Spring-Boot整合
- 1. 发送邮件
- 2. 支付宝支付
- 3. 阿里云短信
- 4. 微信登陆
- 5. 微信支付
- 6. Swargger2 前后端API接口信息文档
- 7. ehcache缓存缓存
- 8. Spring-Boot注解详解
- 9. 自定义配置文件类
1. 发送邮件
- 添加依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-mail</artifactId>
</dependency>
- 创建 mail.properties 配置文件
mail.host=smtp.qq.com
#邮箱地址
mail.username=*****@qq.com
#邮箱授权码
mail.password=********
#是否启用加密
mail.smtpAuth=true
#
mail.smtpStarttlsEnable=true
mail.smtpStarttlsRequired=true
mail.defaultEncoding=UTF-8
- 创建配置类
package com.example.demo1.config;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.PropertySource;
import org.springframework.stereotype.Component;
/**
* 邮箱类
*/
@Component
//配置属性文件
@PropertySource("classpath:mail.properties")
//说明配置文件属性的头部
@ConfigurationProperties(prefix = "mail")
public class MailConfig {
private String host;
private String username;
private String password;
private String smtpAuth;
private String smtpStarttlsEnable;
private String smtpStarttlsRequired;
private String defaultEncoding;
//getter and setter
}
- 创建工具类
package com.example.demo1.utils;
import com.example.demo1.config.MailConfig;
import org.springframework.mail.SimpleMailMessage;
import org.springframework.mail.javamail.JavaMailSenderImpl;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import java.util.Properties;
@Component
public class MailUtils {
@Resource
private MailConfig mailConfig;
/**
* 邮箱发送方法
*
* @param to 收信人
* @param title 邮箱标题
* @param content 邮箱内容
*/
public boolean sendMail(String to, String title, String content) {
try {
//邮箱消息对象
SimpleMailMessage simpleMailMessage = new SimpleMailMessage();
simpleMailMessage.setFrom(mailConfig.getUsername());//发送人
simpleMailMessage.setTo(to);//收件人
simpleMailMessage.setSubject(title);//邮箱标题
simpleMailMessage.setText(content);//邮箱内容
//邮箱发送对象
JavaMailSenderImpl javaMailSender = new JavaMailSenderImpl();
javaMailSender.setUsername(mailConfig.getUsername());
javaMailSender.setHost(mailConfig.getHost());
javaMailSender.setPassword(mailConfig.getPassword());
javaMailSender.setDefaultEncoding(mailConfig.getDefaultEncoding());
Properties properties = new Properties();
properties.setProperty("mail.smtp.auth", mailConfig.getSmtpAuth());
properties.setProperty("mail.smtp.starttls.enable", mailConfig.getSmtpStarttlsEnable());
properties.setProperty("mail.smtp.starttls.required", mailConfig.getSmtpStarttlsRequired());
javaMailSender.setJavaMailProperties(properties);
//实现发送邮箱
javaMailSender.send(simpleMailMessage);
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
}
- 创建 MailController
package com.example.demo1.controller;
import com.alibaba.fastjson.JSONObject;
import com.example.demo1.pojo.Test;
import com.example.demo1.service.TestService;
import com.example.demo1.utils.MailUtils;
import com.example.demo1.utils.RandomUtils;
import com.example.demo1.utils.RedisUtils;
import com.example.demo1.utils.TokenUtils;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;
@Api(tags = "邮箱登陆")
@RestController
@RequestMapping("test")
public class MailController {
@Resource
private MailUtils mailUtils;
@Resource
private RedisUtils redisUtils;
@Resource
private TestService testService;
@Resource
private TokenUtils tokenUtils;
/* 发送验证码 */
@ApiOperation("发送验证码")
@GetMapping("/sendmail")
public Object sendMail(@ApiParam(value = "请求头", required = true) HttpServletRequest request) {
Map<String, Object> dto = new HashMap<>();
String to = request.getHeader("to");
//判断是否已经发送过验证码
String code = redisUtils.get(to);
if (code != null) {
dto.put("msg", "验证码10分钟内有效");
dto.put("code", 6000);
return dto;
}
//生产随机数
Integer ran = RandomUtils.genNumByLen(6);
String title = "登陆";
String content = "验证码" + ran + ",5分钟内有效";
//发送验证码
if (mailUtils.sendMail(to, title, content)) {
// 把验证码保存到redis中
redisUtils.set(to, ran.toString(), 300, TimeUnit.SECONDS);
dto.put("msg", "发送成功");
dto.put("code", 2);
return dto;
}
dto.put("msg", "发送失败");
dto.put("code", -2);
return dto;
}
/* 邮箱登陆 */
@ApiOperation("邮箱登陆")
@GetMapping("/maillogin")
public Object mailLogin(HttpServletRequest request) {
String to = request.getHeader("to");
String code = request.getHeader("code");
Map<String, Object> dto = new HashMap<>();
//从redis中获取验证吗
String rCode = redisUtils.get(to);
if (!rCode.equals(code)) {
dto.put("msg", "验证码错误");
dto.put("code", 0);
return dto;
}
//判断用户是否存在
Test test = testService.getUserByEmail(to);
if (test == null) {//新用户
test = new Test();
test.setCode(to);
//添加用户到数据库
/* --------------------- 添加并获取id ------------- */
if (!testService.addUser(test)) {
dto.put("msg", "登陆失败");
dto.put("code", -1);
return dto;
}
}
//生成token
String token = tokenUtils.getToken("Mail-", test.getId(), RandomUtils.genNumByLen(6));
//把token存入redis中 30分钟有效
redisUtils.set(token, JSONObject.toJSONString(test), 30 * 60, TimeUnit.SECONDS);
dto.put("msg", "登陆成功");
dto.put("code", 1);
dto.put("token", token);
return dto;
}
/**
* 用于测试token的替换
*
* @param request 请求对象
* @return
*/
@ApiOperation("用于测试token的替换")
@GetMapping("getUser")
public Object getUser(@ApiParam(value = "请求对象") HttpServletRequest request) {
Map<String, Object> dto = new HashMap<>();
String token = request.getHeader("token");
//判断token存在
if (!redisUtils.hasKey(token)) {
dto.put("msg", "token失效");
dto.put("code", -3);
return dto;
}
//把redis转换成对象
Test test = JSONObject.parseObject(redisUtils.get(token), Test.class);
token = tokenUtils.replaceToken(token, "Mail-", test);
dto.put("msg", "token有效");
dto.put("code", 3);
dto.put("token", token);
return dto;
}
}
2. 支付宝支付
- 引入依赖
<!-- 支付宝支付 -->
<dependency>
<groupId>com.alipay.sdk</groupId>
<artifactId>alipay-easysdk</artifactId>
<version>2.0.1</version>
</dependency>
- 创建 AliPayConfig 配置类
package com.example.demo1.config;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.PropertySource;
import org.springframework.stereotype.Component;
@Component
@PropertySource("classpath:alipay.properties")
@ConfigurationProperties("alipay")
public class AliPayConfig {
private String protocol;
private String gatewayHost;
private String signType;
private String appId;
private String merchantPrivateKey;
private String notifyUrl;
private String returnUrl;
private String encryptKey;
private String alipayPublicKey;
private String successUrl;
// getter and setter
}
- 创建 AliPayUtils 工具类
package com.example.demo1.utils;
import com.alipay.easysdk.factory.Factory;
import com.alipay.easysdk.factory.Factory.Payment;
import com.alipay.easysdk.kernel.Config;
import com.alipay.easysdk.kernel.util.ResponseChecker;
import com.alipay.easysdk.payment.page.models.AlipayTradePagePayResponse;
import com.example.demo1.config.AliPayConfig;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import java.util.Map;
/**
* 阿里支付工具类
*/
@Component
public class AliPayUtils {
@Resource
private AliPayConfig aliPayConfig;
public AliPayConfig getAliPayConfig() {
return aliPayConfig;
}
/**
* 支付
*
* @param sunject 项目名称
* @param payNo 订单号
* @param amount 支付金额
* @return
*/
public String toPcPay(String sunject, String payNo, String amount) {
String result = "";
// 1. 设置参数(全局只需设置一次)
Factory.setOptions(getOptions());
try {
// 2. 发起API调用
AlipayTradePagePayResponse response = Payment.Page().pay(sunject, payNo, amount, aliPayConfig.getReturnUrl());
// 3. 处理响应或异常
if (ResponseChecker.success(response)) {
result = response.body;
System.out.println("调用成功");
} else {
System.err.println("调用失败,原因:" + response.body);
}
} catch (Exception e) {
System.err.println("调用遭遇异常,原因:" + e.getMessage());
throw new RuntimeException(e.getMessage(), e);
}
return result;
}
private Config getOptions() {
Config config = new Config();
config.protocol = aliPayConfig.getProtocol();
config.gatewayHost = aliPayConfig.getGatewayHost();
config.signType = aliPayConfig.getSignType();
config.appId = aliPayConfig.getAppId();
config.merchantPrivateKey = aliPayConfig.getMerchantPrivateKey();
config.encryptKey = aliPayConfig.getEncryptKey();
config.notifyUrl = aliPayConfig.getNotifyUrl();
config.alipayPublicKey = aliPayConfig.getAlipayPublicKey();
return config;
}
/**
* 验签
*
* @param parameters
* @return
* @throws Exception
*/
public Boolean verify(Map<String, String> parameters) throws Exception {
return Factory.Payment.Common().verifyNotify(parameters);
}
}
- 新增测试页面
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>支付测试页</title>
</head>
<body>
<form action="/test/alipay" method="POST">
<label for="subject">项目名:</label>
<input type="text" name="subject">
<br>
<label for="payno">订单号:</label>
<input type="text" name="payno">
<br>
<label for="amount">订单金额:</label>
<input type="text" name="amount">
<br>
<input type="submit" value="支付">
</form>
</body>
</html>
3. 阿里云短信
- 引入依赖
<!-- 发送短信 -->
<dependency>
<groupId>com.aliyun</groupId>
<artifactId>aliyun-java-sdk-core</artifactId>
<version>4.5.3</version>
</dependency>
2.创建ssm.properties配置文件
#此处替填写'AccessKey ID'
sms.accessKeyId=**************
#此处填写'AccessKey Secret'
sms.secret=**************
# 最近服务器地点
sms.RegionId=cn-hangzhou
sms.domain=dysmsapi.aliyuncs.com
sms.version=2017-05-25
sms.action=SendSms
#此处替换为'签名名称'
sms.signName=**
#此处替换为'模版CODE'
sms.templateCode=***
- 创建配置类
package com.example.demo1.config;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.PropertySource;
import org.springframework.stereotype.Component;
@Component
@PropertySource("classpath:ssm.properties")
@ConfigurationProperties(prefix = "sms")
public class AliyunSSMConfig {
private String accessKeyId;
private String secret;
private String RegionId;
private String domain;
private String version;
private String action;
private String signName;
private String templateCode;
//getter and setter
}
- 创建工具类
package com.example.demo1.utils;
import com.alibaba.fastjson.JSONObject;
import com.aliyuncs.CommonRequest;
import com.aliyuncs.CommonResponse;
import com.aliyuncs.DefaultAcsClient;
import com.aliyuncs.IAcsClient;
import com.aliyuncs.exceptions.ClientException;
import com.aliyuncs.exceptions.ServerException;
import com.aliyuncs.http.MethodType;
import com.aliyuncs.profile.DefaultProfile;
import com.example.demo1.config.AliyunSSMConfig;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
@Component
public class AliyunSMSUtils {
@Resource
private AliyunSSMConfig aliyunSSMConfig;
/**
* 发送短信
*
* @param phone 手机号
* @param code 验证码
*/
public boolean sendMessage(String phone, String code) {
DefaultProfile profile = DefaultProfile.getProfile(aliyunSSMConfig.getRegionId(),
aliyunSSMConfig.getAccessKeyId(), aliyunSSMConfig.getSecret());
//客服端对象
IAcsClient client = new DefaultAcsClient(profile);
//请求对象
CommonRequest request = new CommonRequest();
//请求方式
request.setSysMethod(MethodType.POST);
request.setSysDomain(aliyunSSMConfig.getDomain());
request.setSysVersion(aliyunSSMConfig.getVersion());
//具体操作
request.setSysAction(aliyunSSMConfig.getAction());
request.putQueryParameter("RegionId", aliyunSSMConfig.getRegionId());
request.putQueryParameter("PhoneNumbers", phone);
request.putQueryParameter("SignName", aliyunSSMConfig.getSignName());
request.putQueryParameter("TemplateCode", aliyunSSMConfig.getTemplateCode());
// 参数 和模板里的格式一样
request.putQueryParameter("TemplateParam", "{\"code\":\"" + code + "\"}");
try {
//响应对象
CommonResponse response = client.getCommonResponse(request);
System.out.println(response.getData());
// 获取状态码 (固定)
String status = JSONObject.parseObject(response.getData()).get("Code").toString();
return "OK".equals(status);
} catch (ServerException e) {
e.printStackTrace();
} catch (ClientException e) {
e.printStackTrace();
}
return false;
}
}
- 创建 AliyunController
package com.example.demo1.controller;
import com.alibaba.fastjson.JSONObject;
import com.example.demo1.pojo.Test;
import com.example.demo1.service.TestService;
import com.example.demo1.utils.MailUtils;
import com.example.demo1.utils.RandomUtils;
import com.example.demo1.utils.RedisUtils;
import com.example.demo1.utils.TokenUtils;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;
@Api(tags = "邮箱登陆")
@RestController
@RequestMapping("test")
public class MailController {
@Resource
private MailUtils mailUtils;
@Resource
private RedisUtils redisUtils;
@Resource
private TestService testService;
@Resource
private TokenUtils tokenUtils;
/* 发送验证码 */
@ApiOperation("发送验证码")
@GetMapping("/sendmail")
public Object sendMail(@ApiParam(value = "请求头", required = true) HttpServletRequest request) {
Map<String, Object> dto = new HashMap<>();
String to = request.getHeader("to");
//判断是否已经发送过验证码
String code = redisUtils.get(to);
if (code != null) {
dto.put("msg", "验证码10分钟内有效");
dto.put("code", 6000);
return dto;
}
//生产随机数
Integer ran = RandomUtils.genNumByLen(6);
String title = "登陆";
String content = "验证码" + ran + ",5分钟内有效";
//发送验证码
if (mailUtils.sendMail(to, title, content)) {
// 把验证码保存到redis中
redisUtils.set(to, ran.toString(), 300, TimeUnit.SECONDS);
dto.put("msg", "发送成功");
dto.put("code", 2);
return dto;
}
dto.put("msg", "发送失败");
dto.put("code", -2);
return dto;
}
/* 邮箱登陆 */
@ApiOperation("邮箱登陆")
@GetMapping("/maillogin")
public Object mailLogin(HttpServletRequest request) {
String to = request.getHeader("to");
String code = request.getHeader("code");
Map<String, Object> dto = new HashMap<>();
//从redis中获取验证吗
String rCode = redisUtils.get(to);
if (!rCode.equals(code)) {
dto.put("msg", "验证码错误");
dto.put("code", 0);
return dto;
}
//判断用户是否存在
Test test = testService.getUserByEmail(to);
if (test == null) {//新用户
test = new Test();
test.setCode(to);
//添加用户到数据库
/* --------------------- 添加并获取id ------------- */
if (!testService.addUser(test)) {
dto.put("msg", "登陆失败");
dto.put("code", -1);
return dto;
}
}
//生成token
String token = tokenUtils.getToken("Mail-", test.getId(), RandomUtils.genNumByLen(6));
//把token存入redis中 30分钟有效
redisUtils.set(token, JSONObject.toJSONString(test), 30 * 60, TimeUnit.SECONDS);
dto.put("msg", "登陆成功");
dto.put("code", 1);
dto.put("token", token);
return dto;
}
/**
* 用于测试token的替换
*
* @param request 请求对象
* @return
*/
@ApiOperation("用于测试token的替换")
@GetMapping("getUser")
public Object getUser(@ApiParam(value = "请求对象") HttpServletRequest request) {
Map<String, Object> dto = new HashMap<>();
String token = request.getHeader("token");
//判断token存在
if (!redisUtils.hasKey(token)) {
dto.put("msg", "token失效");
dto.put("code", -3);
return dto;
}
//把redis转换成对象
Test test = JSONObject.parseObject(redisUtils.get(token), Test.class);
token = tokenUtils.replaceToken(token, "Mail-", test);
dto.put("msg", "token有效");
dto.put("code", 3);
dto.put("token", token);
return dto;
}
}
4. 微信登陆
- 引入依赖
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.31</version>
</dependency>
- 创建 wxlogin.properties 配置文件
wxlogin.openUrl=https://open.weixin.qq.com/connect/qrconnect
wxlogin.appid=*********
# 回调地址 接收用户信息的Url
wxlogin.redirectUri=http://localhost:8080/test/wechat/callback
wxlogin.responseType=code
wxlogin.scope=snsapi_login
wxlogin.state=STATE#wechat_redirect
# 再去微信服务器拿token的url
wxlogin.accessTokenUrl=https://api.weixin.qq.com/sns/oauth2/access_token
wxlogin.secret=********
wxlogin.grantType=authorization_code
# 获取微信用户的信息
wxlogin.userInfoUrl=https://api.weixin.qq.com/sns/userinfo
- 创建 WxLoginConfig 配置类
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.PropertySource;
import org.springframework.stereotype.Component;
/**
* 微信登陆配置文件类
*/
@Component
@ConfigurationProperties(prefix = "wxlogin")
@PropertySource("classpath:wxlogin.properties")
public class WxLoginConfig {
private String appid;
private String redirectUri;
private String responseType;
private String scope;
private String state;
private String openUrl;
private String accessTokenUrl;
private String secret;
private String grantType;
private String userInfoUrl;
//getter and serter
}
- 创建 UrlUtils 工具类
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
/**
* 微信登陆Url工具类
*/
public class UrlUtils {
/**
* 获取url网址返回的数据内容
*
* @param urlStr
* @return
*/
public static String loadURL(String urlStr) {
try {
URL url = new URL(urlStr);
//连接网址对象
HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
// 连接方式
urlConnection.setRequestMethod("GET");
urlConnection.connect();
//获取返回的输入流
InputStream inputStream = urlConnection.getInputStream();
//把输入流转换成字符串
String responseStr = ConvertToString(inputStream);
return responseStr;
} catch (IOException e) {
e.printStackTrace();
return null;
}
}
/**
* 输入流转换成字符串
* @param inputStream
* @return
*/
private static String ConvertToString(InputStream inputStream) {
InputStreamReader inputStreamReader = new InputStreamReader(inputStream);
BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
StringBuilder result = new StringBuilder();
String line = null;
try {
while ((line = bufferedReader.readLine()) != null) {
result.append(line + "\n");
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
inputStreamReader.close();
inputStream.close();
bufferedReader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return result.toString();
}
}
- 创建 WxLoginController API接口
import com.alibaba.fastjson.JSONObject;
import com.example.demo1.config.WxLoginConfig;
import com.example.demo1.utils.RandomUtils;
import com.example.demo1.utils.RedisUtils;
import com.example.demo1.utils.TokenUtils;
import com.example.demo1.utils.UrlUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;
@RestController
@RequestMapping("/test")
public class WxLoginController {
@Resource
private WxLoginConfig wxLoginConfig;
@Resource
private RedisUtils redisUtils;
@Resource
private TokenUtils tokenUtils;
/**
* 显示微信登陆扫码界面
*
* @param response
* @throws Exception
*/
@RequestMapping("/wechat/login")
public void wechat(HttpServletResponse response) throws Exception {
// 构建获取二维码的URL
StringBuffer wxsb = new StringBuffer(wxLoginConfig.getOpenUrl());
wxsb.append("?appid=" + wxLoginConfig.getAppid());
wxsb.append("&redirect_uri=" + wxLoginConfig.getRedirectUri());
wxsb.append("&response_type=" + wxLoginConfig.getResponseType());
wxsb.append("&scope=" + wxLoginConfig.getScope());
wxsb.append("&state=" + wxLoginConfig.getState());
response.sendRedirect(wxsb.toString());
}
/**
* 用户手机确认后回调函数
*
* @param code
* @throws Exception
*/
@RequestMapping("/wechat/callback")
public Object callback(String code) throws Exception {
Map<String, Object> dto = new HashMap<>();
// 构造请求URL
StringBuffer wxsb = new StringBuffer(wxLoginConfig.getAccessTokenUrl());
wxsb.append("?appid=" + wxLoginConfig.getAppid());
wxsb.append("&secret=" + wxLoginConfig.getSecret());
wxsb.append("&code=" + code);
wxsb.append("&grant_type=" + wxLoginConfig.getGrantType());
// 发送请求并获取accessToken和opendId
String resp = UrlUtils.loadURL(wxsb.toString());
JSONObject jsonObject = JSONObject.parseObject(resp);
String accessToken = jsonObject.getString("access_token");
String openId = jsonObject.getString("openid");
// 构造获取用户信息的URL
StringBuffer usb = new StringBuffer(wxLoginConfig.getUserInfoUrl());
usb.append("?access_token=" + accessToken);
usb.append("&openid=" + openId);
// 发送请求并获取用户信息
String userInfo = UrlUtils.loadURL(usb.toString());
JSONObject userObject = JSONObject.parseObject(userInfo);
if (userObject == null) {
dto.put("msg", "微信登陆失败");
dto.put("code", -4);
return dto;
}
//生产token
String token = tokenUtils.getToken("WX-", 1, RandomUtils.genNumByLen(6));
redisUtils.set(token, JSONObject.toJSONString(userObject), 30 * 60, TimeUnit.SECONDS);
dto.put("msg", "微信登陆成功");
dto.put("code", 4);
dto.put("token", token);
return dto;
}
}
5. 微信支付
- 添加依赖
<dependency>
<groupId>com.github.wxpay</groupId>
<artifactId>wxpay-sdk</artifactId>
<version>0.0.3</version>
</dependency>
- 微信app支付参数配置
#服务器域名地址
server.service-domain = http://127.0.0.1:8080
#微信app支付
pay.wxpay.app.appID = "你的appid"
pay.wxpay.app.mchID = "你的商户id"
pay.wxpay.app.key = "你的api秘钥,不是appSecret"
#从微信商户平台下载的安全证书存放的路径、我放在resources下面,切记一定要看看target目录下的class文件下有没有打包apiclient_cert.p12文件
pay.wxpay.app.certPath = static/cert/wxpay/apiclient_cert.p12
#微信支付成功的异步通知接口
pay.wxpay.app.payNotifyUrl=${server.service-domain}/api/wxPay/notify
- 创建配置类
import com.github.wxpay.sdk.WXPayConfig;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
import java.io.InputStream;
/**
* 配置我们自己的信息
*/
@Component
@ConfigurationProperties(prefix = "pay.wxpay.app")
public class WxPayAppConfig implements WXPayConfig {
/**
* appID
*/
private String appID;
/**
* 商户号
*/
private String mchID;
/**
* API 密钥
*/
private String key;
/**
* API证书绝对路径 (本项目放在了 resources/cert/wxpay/apiclient_cert.p12")
*/
private String certPath;
/**
* HTTP(S) 连接超时时间,单位毫秒
*/
private int httpConnectTimeoutMs = 8000;
/**
* HTTP(S) 读数据超时时间,单位毫秒
*/
private int httpReadTimeoutMs = 10000;
/**
* 微信支付异步通知地址
*/
private String payNotifyUrl;
/**
* 微信退款异步通知地址
*/
private String refundNotifyUrl;
/**
* 获取商户证书内容(这里证书需要到微信商户平台进行下载)
*
* @return 商户证书内容
*/
@Override
public InputStream getCertStream() {
InputStream certStream =getClass().getClassLoader().getResourceAsStream(certPath);
return certStream;
}
public String getAppID() {
return appID;
}
public void setAppID(String appID) {
this.appID = appID;
}
public String getMchID() {
return mchID;
}
public void setMchID(String mchID) {
this.mchID = mchID;
}
public String getKey() {
return key;
}
public void setKey(String key) {
this.key = key;
}
public String getCertPath() {
return certPath;
}
public void setCertPath(String certPath) {
this.certPath = certPath;
}
public int getHttpConnectTimeoutMs() {
return httpConnectTimeoutMs;
}
public void setHttpConnectTimeoutMs(int httpConnectTimeoutMs) {
this.httpConnectTimeoutMs = httpConnectTimeoutMs;
}
public int getHttpReadTimeoutMs() {
return httpReadTimeoutMs;
}
public void setHttpReadTimeoutMs(int httpReadTimeoutMs) {
this.httpReadTimeoutMs = httpReadTimeoutMs;
}
public String getPayNotifyUrl() {
return payNotifyUrl;
}
public void setPayNotifyUrl(String payNotifyUrl) {
this.payNotifyUrl = payNotifyUrl;
}
public String getRefundNotifyUrl() {
return refundNotifyUrl;
}
public void setRefundNotifyUrl(String refundNotifyUrl) {
this.refundNotifyUrl = refundNotifyUrl;
}
}
- 定义controller
在调用微信服务接口进行统一下单之前,
1、为保证安全性,建议验证数据库是否存在订单号对应的订单。
package com.annaru.upms.payment.controller;
import com.annaru.common.result.ResultMap;
import com.annaru.upms.payment.service.WxPayService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpServletRequest;
@Api(tags = "微信支付接口管理")
@RestController
@RequestMapping("/wxPay")
public class WxPayController{
@Autowired
private WxPayService wxPayService;
/**
* 统一下单接口
*/
@ApiOperation(value = "统一下单", notes = "统一下单")
@GetMapping("/unifiedOrder")
public ResultMap unifiedOrder(
@ApiParam(value = "订单号") @RequestParam String orderNo,
@ApiParam(value = "订单金额") @RequestParam double amount,
@ApiParam(value = "商品名称") @RequestParam String body,
HttpServletRequest request) {
try {
// 1、验证订单是否存在
// 2、开始微信支付统一下单
ResultMap resultMap = wxPayService.unifiedOrder(orderNo, orderNo, body);
return resultMap;//系统通用的返回结果集,见文章末尾
} catch (Exception e) {
logger.error(e.getMessage());
return ResultMap.error("运行异常,请联系管理员");
}
}
/**
* 微信支付异步通知
*/
@RequestMapping(value = "/notify")
public String payNotify(HttpServletRequest request) {
InputStream is = null;
String xmlBack = "<xml><return_code><![CDATA[FAIL]]></return_code><return_msg><![CDATA[报文为空]]></return_msg></xml> ";
try {
is = request.getInputStream();
// 将InputStream转换成String
BufferedReader reader = new BufferedReader(new InputStreamReader(is));
StringBuilder sb = new StringBuilder();
String line = null;
while ((line = reader.readLine()) != null) {
sb.append(line + "\n");
}
xmlBack = wxPayService.notify(sb.toString());
} catch (Exception e) {
logger.error("微信手机支付回调通知失败:", e);
} finally {
if (is != null) {
try {
is.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return xmlBack;
}
@ApiOperation(value = "退款", notes = "退款")
@PostMapping("/refund")
public ResultMap refund(@ApiParam(value = "订单号") @RequestParam String orderNo,
@ApiParam(value = "退款金额") @RequestParam double amount,
@ApiParam(value = "退款原因") @RequestParam(required = false) String refundReason){
return wxPayService.refund(orderNo, amount, refundReason);
}
}
- 定义service接口
package com.annaru.upms.payment.service;
import com.annaru.common.result.ResultMap;
/**
* 微信支付服务接口
*/
public interface WxPayService {
/**
* @Description: 微信支付统一下单
* @param orderNo: 订单编号
* @param amount: 实际支付金额
* @param body: 订单描述
* @Author:
* @Date: 2019/8/1
* @return
*/
ResultMap unifiedOrder(String orderNo, double amount, String body) ;
/**
* @Description: 订单支付异步通知
* @param notifyStr: 微信异步通知消息字符串
* @Author:
* @Date: 2019/8/1
* @return
*/
String notify(String notifyStr) throws Exception;
/**
* @Description: 退款
* @param orderNo: 订单编号
* @param amount: 实际支付金额
* @param refundReason: 退款原因
* @Author: XCK
* @Date: 2019/8/6
* @return
*/
ResultMap refund(String orderNo, double amount, String refundReason);
}
- service实现类
package com.annaru.upms.payment.service.impl;
import com.alibaba.dubbo.config.annotation.Reference;
import com.annaru.common.result.ResultMap;
import com.annaru.common.util.HttpContextUtils;
import com.annaru.upms.payment.config.WxPayAppConfig;
import com.annaru.upms.payment.service.WxPayService;
import com.annaru.upms.service.IOrderPaymentService;
import com.github.wxpay.sdk.WXPay;
import com.github.wxpay.sdk.WXPayUtil;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.HashMap;
import java.util.Map;
@Service
public class WxPayServiceImpl implements WxPayService {
private final Logger logger = LoggerFactory.getLogger(WxPayServiceImpl.class);
@Reference
private IOrderPaymentService orderPaymentService;
@Autowired
private WxPayAppConfig wxPayAppConfig;
@Override
public ResultMap unifiedOrder(String orderNo, double amount, String body) {
Map<String, String> returnMap = new HashMap<>();
Map<String, String> responseMap = new HashMap<>();
Map<String, String> requestMap = new HashMap<>();
try {
WXPay wxpay = new WXPay(wxPayAppConfig);
requestMap.put("body", body); // 商品描述
requestMap.put("out_trade_no", orderNo); // 商户订单号
requestMap.put("total_fee", String.valueOf((int)(amount*100))); // 总金额
requestMap.put("spbill_create_ip", HttpContextUtils.getIpAddr()); // 终端IP
requestMap.put("trade_type", "APP"); // App支付类型
requestMap.put("notify_url", wxPayAppConfig.getPayNotifyUrl()); // 接收微信支付异步通知回调地址
Map<String, String> resultMap = wxpay.unifiedOrder(requestMap);
//获取返回码
String returnCode = resultMap.get("return_code");
String returnMsg = resultMap.get("return_msg");
//若返回码为SUCCESS,则会返回一个result_code,再对该result_code进行判断
if ("SUCCESS".equals(returnCode)) {
String resultCode = resultMap.get("result_code");
String errCodeDes = resultMap.get("err_code_des");
if ("SUCCESS".equals(resultCode)) {
responseMap = resultMap;
}
}
if (responseMap == null || responseMap.isEmpty()) {
return ResultMap.error("获取预支付交易会话标识失败");
}
// 3、签名生成算法
Long time = System.currentTimeMillis() / 1000;
String timestamp = time.toString();
returnMap.put("appid", wxPayAppConfig.getAppID());
returnMap.put("partnerid", wxPayAppConfig.getMchID());
returnMap.put("prepayid", responseMap.get("prepay_id"));
returnMap.put("noncestr", responseMap.get("nonce_str"));
returnMap.put("timestamp", timestamp);
returnMap.put("package", "Sign=WXPay");
returnMap.put("sign", WXPayUtil.generateSignature(returnMap, wxPayAppConfig.getKey()));//微信支付签名
return ResultMap.ok().put("data", returnMap);
} catch (Exception e) {
logger.error("订单号:{},错误信息:{}", orderNo, e.getMessage());
return ResultMap.error("微信支付统一下单失败");
}
}
@Override
public String notify(String notifyStr) {
String xmlBack = "<xml><return_code><![CDATA[FAIL]]></return_code><return_msg><![CDATA[报文为空]]></return_msg></xml> ";
try {
// 转换成map
Map<String, String> resultMap = WXPayUtil.xmlToMap(notifyStr);
WXPay wxpayApp = new WXPay(wxPayAppConfig);
if (wxpayApp.isPayResultNotifySignatureValid(resultMap)) {
String returnCode = resultMap.get("return_code"); //状态
String outTradeNo = resultMap.get("out_trade_no");//商户订单号
String transactionId = resultMap.get("transaction_id");
if (returnCode.equals("SUCCESS")) {
if (StringUtils.isNotBlank(outTradeNo)) {
/**
* 注意!!!
* 请根据业务流程,修改数据库订单支付状态,和其他数据的相应状态
*
*/
logger.info("微信手机支付回调成功,订单号:{}", outTradeNo);
xmlBack = "<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>";
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
return xmlBack;
}
@Override
public ResultMap refund(String orderNo, double amount, String refundReason){
if(StringUtils.isBlank(orderNo)){
return ResultMap.error("订单编号不能为空");
}
if(amount <= 0){
return ResultMap.error("退款金额必须大于0");
}
Map<String, String> responseMap = new HashMap<>();
Map<String, String> requestMap = new HashMap<>();
WXPay wxpay = new WXPay(wxPayAppConfig);
requestMap.put("out_trade_no", orderNo);
requestMap.put("out_refund_no", UUIDGenerator.getOrderNo());
requestMap.put("total_fee", "订单支付时的总金额,需要从数据库查");
requestMap.put("refund_fee", String.valueOf((int)(amount*100)));//所需退款金额
requestMap.put("refund_desc", refundReason);
try {
responseMap = wxpay.refund(requestMap);
} catch (Exception e) {
e.printStackTrace();
}
String return_code = responseMap.get("return_code"); //返回状态码
String return_msg = responseMap.get("return_msg"); //返回信息
if ("SUCCESS".equals(return_code)) {
String result_code = responseMap.get("result_code"); //业务结果
String err_code_des = responseMap.get("err_code_des"); //错误代码描述
if ("SUCCESS".equals(result_code)) {
//表示退款申请接受成功,结果通过退款查询接口查询
//修改用户订单状态为退款申请中或已退款。退款异步通知根据需求,可选
//
return ResultMap.ok("退款申请成功");
} else {
logger.info("订单号:{}错误信息:{}", orderNo, err_code_des);
return ResultMap.error(err_code_des);
}
} else {
logger.info("订单号:{}错误信息:{}", orderNo, return_msg);
return ResultMap.error(return_msg);
}
}
}
- 定义通用返回结果集 ResultMap
package com.annaru.common.result;
import org.apache.http.HttpStatus;
import java.util.HashMap;
import java.util.Map;
/**
* @Description 通用返回结果集
* @Author
* @Date 2018/6/12 15:13
*/
public class ResultMap extends HashMap<String, Object> {
public ResultMap() {
put("state", true);
put("code", 0);
put("msg", "success");
}
public static ResultMap error(int code, String msg) {
ResultMap r = new ResultMap();
r.put("state", false);
r.put("code", code);
r.put("msg", msg);
return r;
}
public static ResultMap error(String msg) {
return error(HttpStatus.SC_INTERNAL_SERVER_ERROR, msg);
}
public static ResultMap error() {
return error(HttpStatus.SC_INTERNAL_SERVER_ERROR, "未知异常,请联系管理员");
}
public static ResultMap ok(String msg) {
ResultMap r = new ResultMap();
r.put("msg", msg);
return r;
}
public static ResultMap ok(Map<String, Object> par) {
ResultMap r = new ResultMap();
r.putAll(par);
return r;
}
public static ResultMap ok() {
return new ResultMap();
}
public ResultMap put(String key, Object value) {
super.put(key, value);
return this;
}
}
6. Swargger2 前后端API接口信息文档
- 添加依赖
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2artifactId>
<version>2.9.2</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-uiartifactId>
<version>2.9.2</version>
</dependency>
- 创建 swagger.properties 配置文件
# swagger测试项目
swagger.title=各种登陆
# swagger测试案例
swagger.description=邮箱登陆,短信登陆,微信扫码登陆
# 版本
swagger.version=1.0.0
- 创建配置类
package com.example.demo1.config;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;
@Configuration//配置类
@PropertySource("classpath:swagger.properties")
@ConfigurationProperties("swagger")
@EnableSwagger2
public class SwaggerConfig {
private String title;
private String description;
private String version;
//getter and setter
@Bean
public Docket createRestApi() {
return new Docket(DocumentationType.SWAGGER_2).apiInfo(apiInfo())
.select()
.apis(RequestHandlerSelectors.any())
.paths(PathSelectors.any()).build();
}
public ApiInfo apiInfo() {
return new ApiInfoBuilder()
.title(this.title)
.description(this.description)
.version(this.version).build();
}
}
- API类
@Api(tags = "类说明")
public class TestController {
@ApiOperation("方法说明")
public String test(
@ApiParam(value = "参数说明", required = true)//required 说明是否必需
@RequestParam String text) {
return text;
}
}
- 访问网页查看文档
访问:http://localhost:8080/swagger-ui.html
7. ehcache缓存缓存
- 添加依赖
<!-- cache缓存依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-cache</artifactId>
</dependency>
<dependency>
<groupId>net.sf.ehcache</groupId>
<artifactId>ehcache</artifactId>
</dependency>
- resources 文件下添加 ehcache.xml 配置文件
<?xml version="1.0" encoding="UTF-8"?>
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="http://ehcache.org/ehcache.xsd" updateCheck="false">
<!--
磁盘存储:将缓存中暂时不使用的对象,转移到硬盘,类似于Windows系统的虚拟内存
path:指定在硬盘上存储对象的路径
path可以配置的目录有:
user.home(用户的家目录)
user.dir(用户当前的工作目录)
java.io.tmpdir(默认的临时目录)
ehcache.disk.store.dir(ehcache的配置目录)
绝对路径(如:d:\\ehcache)
查看路径方法:String tmpDir = System.getProperty("java.io.tmpdir");
-->
<diskStore path="java.io.tmpdir"/>
<!--
defaultCache:默认的缓存配置信息,如果不加特殊说明,则所有对象按照此配置项处理
maxElementsInMemory:设置了缓存的上限,最多存储多少个记录对象
eternal:代表对象是否永不过期 (指定true则下面两项配置需为0无限期)
timeToIdleSeconds:最大的发呆时间 /秒
timeToLiveSeconds:最大的存活时间 /秒
overflowToDisk:是否允许对象被写入到磁盘
说明:下列配置自缓存建立起600秒(10分钟)有效 。
在有效的600秒(10分钟)内,如果连续120秒(2分钟)未访问缓存,则缓存失效。
就算有访问,也只会存活600秒。
-->
<defaultCache maxElementsInMemory="10000" eternal="false" timeToIdleSeconds="600"
timeToLiveSeconds="600" overflowToDisk="true"/>
<cache name="cache" maxElementsInMemory="10000" eternal="false" timeToIdleSeconds="120"
timeToLiveSeconds="600" overflowToDisk="true"/>
</ehcache>
- 在程序入口 MyAppRun 类中添加注解 @EnableCaching
@EnableCaching
@SpringBootApplication
public class MyAppRun {
public static void main(String[] args) {
SpringApplication.run(MyAppRun.class, args);
}
}
- 给需要缓存的方法加注解 (一般在service实现类上)
- @Cacheable(value=”accountCache”)
当调用这个方法的时候,会先从一个名叫 accountCache的缓存中查询,如果没有,则执行实际的方法(即查询数库),并将执行的结果存入缓存中,否则返回缓存中的象。这里的缓存中的 key 就是参数 userName,value 是ehcache.xml 文件里定义的<cache>的name属性值,不设置就是默认
- @CachePut 作用和配置方法:
@CachePut 的作用 主要针对方法配置,能够根据方法的请求参数对其结果进行缓存,和 @Cacheable 不同的是,它每次都会触发真实方法的调用,多数用于数据的更新。
@CachePut 注释,这个注释可以确保方法被执行,同时方法的返回值也被记录到缓存中,实现缓存与数据库的同步更新。
- @CacheEvict 作用和配置方法
@CachEvict 的作用 主要针对方法配置,能够根据一定的条件对缓存进行清空,多用于删除数据
- @CacheConfig
所有的@Cacheable()里面都有一个value=“xxx”的属性,这显然如果方法多了,写起来也是挺累的,如果可以一次性声明完 那就省事了, 所以,有了@CacheConfig这个配置,@CacheConfig is a class-level annotation that allows to share the cache names,如果你在你的方法写别的名字,那么依然以方法的名字为准。
@CacheConfig("books")
public class BookRepositoryImpl implements BookRepository {
@Cacheable
public Book findBook(ISBN isbn) {...}
}
- @Caching
有时候我们可能组合多个Cache注解使用;比如用户新增成功后,我们要添加id–>user;username—>user;email—>user的缓存;此时就需要@Caching组合多个注解标签了。
@Caching(put = {
@CachePut(value = "user", key = "#user.id"),
@CachePut(value = "user", key = "#user.username"),
@CachePut(value = "user", key = "#user.email")
})
public User save(User user) {
8. Spring-Boot注解详解
- @SpringBootApplication
这个注解是Spring Boot最核心的注解,用在 Spring Boot的主类上,标识这是一个 Spring Boot 应用,用来开启 Spring Boot 的各项能力。实际上这个注解是@Configuration,@EnableAutoConfiguration,@ComponentScan三个注解的组合。由于这些注解一般都是一起使用,所以Spring Boot提供了一个统一的注解@SpringBootApplication。
- @EnableAutoConfiguration
允许 Spring Boot 自动配置注解,开启这个注解之后,Spring Boot 就能根据当前类路径下的包或者类来配置 Spring Bean。
如:当前类路径下有 Mybatis 这个 JAR 包,MybatisAutoConfiguration 注解就能根据相关参数来配置 Mybatis 的各个 Spring Bean。
@EnableAutoConfiguration实现的关键在于引入了AutoConfigurationImportSelector,其核心逻辑为selectImports方法,逻辑大致如下:
● 从配置文件META-INF/spring.factories加载所有可能用到的自动配置类;
● 去重,并将exclude和excludeName属性携带的类排除;
● 过滤,将满足条件(@Conditional)的自动配置类返回;
- @Configuration
用于定义配置类,指出该类是 Bean 配置的信息源,相当于传统的xml配置文件,一般加在主类上。如果有些第三方库需要用到xml文件,建议仍然通过@Configuration类作为项目的配置主类——可以使用@ImportResource注解加载xml配置文件。
- @ComponentScan
组件扫描。让spring Boot扫描到Configuration类并把它加入到程序上下文。
@ComponentScan注解默认就会装配标识了@Controller,@Service,@Repository,@Component注解的类到spring容器中。
- @Repository
用于标注数据访问组件,即DAO组件。
使用@Repository注解可以确保DAO或者repositories提供异常转译,这个注解修饰的DAO或者repositories类会被ComponetScan发现并配置,同时也不需要为它们提供XML配置项。
- @Service
一般用于修饰service层的组件,修饰服务层
- @RestController
用于标注控制层组件(如struts中的action),表示这是个控制器bean,并且是将函数的返回JSON值直接填入HTTP响应体中,是REST风格的控制器;它是@Controller和@ResponseBody的合集。
- @Component
泛指组件,当组件不好归类的时候,我们可以使用这个注解进行标注,一般用于实体类。
- @Bean
相当于XML中的,放在方法的上面,而不是类,意思是产生一个bean,并交给spring管理。
- @AutoWired
byType方式。把配置好的Bean拿来用,完成属性、方法的组装,它可以对类成员变量、方法及构造函数进行标注,完成自动装配的工作。
当加上(required=false)时,就算找不到bean也不报错
- @Qualifier
当有多个同一类型的Bean时,可以用@Qualifier(“name”)来指定。与@Autowired配合使用
- @Resource(name=“name”,type=“type”)
没有括号内内容的话,默认byName。与@Autowired干类似的事。
- @RequestMapping
RequestMapping是一个用来处理请求地址映射的注解;提供路由信息,负责URL到Controller中的具体函数的映射,可用于类或方法上。用于类上,表示类中的所有响应请求的方法都是以该地址作为父路径。
- @RequestParam
用于注解Controller里面的方法参数
@RequestParam(defaultValue = “默认值”,required = true) --ture表示参数是必须要的
- @PathVariable
前端访问以http://localhost:8080/demo/id方式访问,后端方法参数前面必须加上此注解 public String demo(@PathVariable Integer id)
- @Profiles
Spring Profiles提供了一种隔离应用程序配置的方式,并让这些配置只能在特定的环境下生效。
任何@Component或@Configuration都能被@Profile标记,从而限制加载它的时机。
- @ConfigurationProperties
Spring Boot可使用注解的方式将自定义的properties文件映射到实体bean中,比如config.properties文件。
9. 自定义配置文件类
- 创建新的maven项目
父包名必须和使用它的项目的父包名一样
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-3yFTmBRg-1600694977271)(demo.jpg)]
- 导入依赖
<dependencies>
<dependency>
<groupId>org.springframework.boot<groupId>
<artifactId>spring-boot-autoconfigure<artifactId>
<version>2.1.6.RELEASE</version>
</dependency>
</dependencies>
- 创建 SayHelloProperties 配置文件属性类
package com.ddz.config;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
/**
* 属性类、从配置文件中读取属性并赋值
*/
@Component
@ConfigurationProperties(prefix = "myhello")
public class SayHelloProperties {
private String msg;
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
}
- 创建 SayHello 核心事件类
- 所有的具体功能都在这里完成
package com.ddz.config;
/**
* 核心事件类完成具体功能
* 返回信息
*/
public class SayHello {
private String inMsg;
public String sayHello() {
return "信息:" + inMsg;
}
public String getInMsg() {
return inMsg;
}
public void setInMsg(String inMsg) {
this.inMsg = inMsg;
}
}
- 创建 SayHelloAutoConfiguation 整合类
- 负责整合属性类和核心事件类
package com.ddz.config;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import javax.annotation.Resource;
/**
* 整合类
*/
@Configuration
@EnableConfigurationProperties({SayHelloProperties.class})
@ConditionalOnClass(SayHello.class)
@ConditionalOnProperty(prefix = "myhello", value = "enabled", matchIfMissing = true)
public class SayHelloAutoConfiguation {
@Autowired
private SayHelloProperties sayHelloProperties;
@Bean
@ConditionalOnMissingBean(SayHello.class)
public SayHello creatSayHello() {
SayHello sayHello = new SayHello();
sayHello.setInMsg(sayHelloProperties.getMsg());
return sayHello;
}
}
- 使用install 上传到本地
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-UApmpn37-1600694977272)(install.jpg)]
- 在需要使用的项目里导入依赖
<dependency>
<groupId>com.ddz</groupId>
<artifactId>myconfig</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
- 在 application.yml里面添加属性
myhello:
msg: ddz
- 在 Controller 里面使用注解就能使用
package com.ddz.controller;
import com.ddz.config.SayHello;
import com.ddz.config.SayHelloAutoConfiguation;
import com.ddz.entity.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
@RestController
@CrossOrigin //解决跨域
public class UserController {
@Resource
private User user;
@Autowired
private SayHello sayHello; //自定义配置文件事件处理类
@GetMapping("/show")
public User show() {
System.out.println(sayHello.sayHello());
return user;
}
}