首页 > 其他分享 >Spring-Boot整合微信登陆、微信支付、邮箱发送、支付宝支付和阿里云短信

Spring-Boot整合微信登陆、微信支付、邮箱发送、支付宝支付和阿里云短信

时间:2023-03-30 15:01:45浏览次数:49  
标签:return String 微信 支付 private Spring import com public


Spring-Boot整合

  • 1. 发送邮件
  • 2. 支付宝支付
  • 3. 阿里云短信
  • 4. 微信登陆
  • 5. 微信支付
  • 6. Swargger2 前后端API接口信息文档
  • 7. ehcache缓存缓存
  • 8. Spring-Boot注解详解
  • 9. 自定义配置文件类

1. 发送邮件

  1. 添加依赖
<dependency>
     <groupId>org.springframework.boot</groupId>
     <artifactId>spring-boot-starter-mail</artifactId>
 </dependency>
  1. 创建 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
  1. 创建配置类
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 
}
  1. 创建工具类
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;
        }
    }
}
  1. 创建 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. 支付宝支付

  1. 引入依赖
<!-- 支付宝支付 -->
<dependency>
    <groupId>com.alipay.sdk</groupId>
    <artifactId>alipay-easysdk</artifactId>
    <version>2.0.1</version>
</dependency>
  1. 创建 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
}
  1. 创建 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);
    }
}
  1. 新增测试页面
<!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. 阿里云短信

  1. 引入依赖
<!-- 发送短信 -->
<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=***
  1. 创建配置类
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
}
  1. 创建工具类
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;
    }
}
  1. 创建 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. 微信登陆

  1. 引入依赖
<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>fastjson</artifactId>
    <version>1.2.31</version>
</dependency>
  1. 创建 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
  1. 创建 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
}
  1. 创建 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();
    }
}
  1. 创建 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. 微信支付

  1. 添加依赖
<dependency>
  <groupId>com.github.wxpay</groupId>
  <artifactId>wxpay-sdk</artifactId>
  <version>0.0.3</version>
</dependency>
  1. 微信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
  1. 创建配置类
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;
    }
}
  1. 定义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);
    }

}
  1. 定义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);
}
  1. 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);
        }
    }

}
  1. 定义通用返回结果集 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接口信息文档

  1. 添加依赖
<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>
  1. 创建 swagger.properties 配置文件
# swagger测试项目
swagger.title=各种登陆
# swagger测试案例
swagger.description=邮箱登陆,短信登陆,微信扫码登陆
# 版本
swagger.version=1.0.0
  1. 创建配置类
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();
    }
}
  1. API类
@Api(tags = "类说明")
 public class TestController {
     @ApiOperation("方法说明")
     public String test(
             @ApiParam(value = "参数说明", required = true)//required 说明是否必需
             @RequestParam String text) {
         return text;
     }
 }
  1. 访问网页查看文档

访问:http://localhost:8080/swagger-ui.html

7. ehcache缓存缓存

  1. 添加依赖
<!-- cache缓存依赖 -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-cache</artifactId>
</dependency>
<dependency>
    <groupId>net.sf.ehcache</groupId>
    <artifactId>ehcache</artifactId>
</dependency>
  1. 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>
  1. 在程序入口 MyAppRun 类中添加注解 @EnableCaching
@EnableCaching
@SpringBootApplication
public class MyAppRun {
    public static void main(String[] args) {
        SpringApplication.run(MyAppRun.class, args);
    }
}
  1. 给需要缓存的方法加注解 (一般在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注解详解

  1. @SpringBootApplication

这个注解是Spring Boot最核心的注解,用在 Spring Boot的主类上,标识这是一个 Spring Boot 应用,用来开启 Spring Boot 的各项能力。实际上这个注解是@Configuration,@EnableAutoConfiguration,@ComponentScan三个注解的组合。由于这些注解一般都是一起使用,所以Spring Boot提供了一个统一的注解@SpringBootApplication。

  1. @EnableAutoConfiguration

允许 Spring Boot 自动配置注解,开启这个注解之后,Spring Boot 就能根据当前类路径下的包或者类来配置 Spring Bean。

如:当前类路径下有 Mybatis 这个 JAR 包,MybatisAutoConfiguration 注解就能根据相关参数来配置 Mybatis 的各个 Spring Bean。

@EnableAutoConfiguration实现的关键在于引入了AutoConfigurationImportSelector,其核心逻辑为selectImports方法,逻辑大致如下:

● 从配置文件META-INF/spring.factories加载所有可能用到的自动配置类;

● 去重,并将exclude和excludeName属性携带的类排除;

● 过滤,将满足条件(@Conditional)的自动配置类返回;

  1. @Configuration

用于定义配置类,指出该类是 Bean 配置的信息源,相当于传统的xml配置文件,一般加在主类上。如果有些第三方库需要用到xml文件,建议仍然通过@Configuration类作为项目的配置主类——可以使用@ImportResource注解加载xml配置文件。

  1. @ComponentScan

组件扫描。让spring Boot扫描到Configuration类并把它加入到程序上下文。

@ComponentScan注解默认就会装配标识了@Controller,@Service,@Repository,@Component注解的类到spring容器中。

  1. @Repository

用于标注数据访问组件,即DAO组件。

使用@Repository注解可以确保DAO或者repositories提供异常转译,这个注解修饰的DAO或者repositories类会被ComponetScan发现并配置,同时也不需要为它们提供XML配置项。

  1. @Service

一般用于修饰service层的组件,修饰服务层

  1. @RestController

用于标注控制层组件(如struts中的action),表示这是个控制器bean,并且是将函数的返回JSON值直接填入HTTP响应体中,是REST风格的控制器;它是@Controller和@ResponseBody的合集。

  1. @Component

泛指组件,当组件不好归类的时候,我们可以使用这个注解进行标注,一般用于实体类。

  1. @Bean

相当于XML中的,放在方法的上面,而不是类,意思是产生一个bean,并交给spring管理。

  1. @AutoWired

byType方式。把配置好的Bean拿来用,完成属性、方法的组装,它可以对类成员变量、方法及构造函数进行标注,完成自动装配的工作。

当加上(required=false)时,就算找不到bean也不报错

  1. @Qualifier

当有多个同一类型的Bean时,可以用@Qualifier(“name”)来指定。与@Autowired配合使用

  1. @Resource(name=“name”,type=“type”)

没有括号内内容的话,默认byName。与@Autowired干类似的事。

  1. @RequestMapping

RequestMapping是一个用来处理请求地址映射的注解;提供路由信息,负责URL到Controller中的具体函数的映射,可用于类或方法上。用于类上,表示类中的所有响应请求的方法都是以该地址作为父路径。

  1. @RequestParam

用于注解Controller里面的方法参数
@RequestParam(defaultValue = “默认值”,required = true) --ture表示参数是必须要的

  1. @PathVariable

前端访问以http://localhost:8080/demo/id方式访问,后端方法参数前面必须加上此注解 public String demo(@PathVariable Integer id)

  1. @Profiles

Spring Profiles提供了一种隔离应用程序配置的方式,并让这些配置只能在特定的环境下生效。

任何@Component或@Configuration都能被@Profile标记,从而限制加载它的时机。

  1. @ConfigurationProperties

Spring Boot可使用注解的方式将自定义的properties文件映射到实体bean中,比如config.properties文件。

9. 自定义配置文件类

  1. 创建新的maven项目

父包名必须和使用它的项目的父包名一样

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-3yFTmBRg-1600694977271)(demo.jpg)]

  1. 导入依赖
<dependencies>
    <dependency>
        <groupId>org.springframework.boot<groupId>
        <artifactId>spring-boot-autoconfigure<artifactId>
        <version>2.1.6.RELEASE</version>
    </dependency>
</dependencies>
  1. 创建 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;
    }
}
  1. 创建 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;
    }
}
  1. 创建 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;
    }
}
  1. 使用install 上传到本地

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-UApmpn37-1600694977272)(install.jpg)]

  1. 在需要使用的项目里导入依赖
<dependency>
    <groupId>com.ddz</groupId>
    <artifactId>myconfig</artifactId>
    <version>1.0-SNAPSHOT</version>
</dependency>
  1. application.yml里面添加属性
myhello:
  msg: ddz
  1. 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;
    }
}


标签:return,String,微信,支付,private,Spring,import,com,public
From: https://blog.51cto.com/loveddz/6159593

相关文章

  • SpringCloud常见问题描述
    1什么是SpringCloudSpringcloud流应用程序启动器是基于SpringBoot的Spring集成应用程序,提供与外部系统的集成。SpringcloudTask,一个生命周期短暂的微服务框......
  • 搭建微信小程序开发环境
    有2种开发工具可供选择:一、微信小程序开发者工具别的不说,代码编辑区真的太小了,很不方便,我们略过。二、VisualCode通过官网下载,如果下载的很慢,或者没有反应,可以尝试把a......
  • SpringBoot 项目使用 Sa-Token 完成登录认证
    一、设计思路对于一些登录之后才能访问的接口(例如:查询我的账号资料),我们通常的做法是增加一层接口校验:如果校验通过,则:正常返回数据。如果校验未通过,则:抛出异常,告知其需......
  • SpringBoot中集成Redis实现对redis中数据的解析和存储
    场景SpringBoot中操作springredis的工具类:https://blog.csdn.net/BADAO_LIUMANG_QIZHI/article/details/108335645上面讲的操作redis的工具类,但是对于redis的集成并没......
  • Spring
    Springhttps://start.spring.io/ Gradle相当于mavenSpring分为2.x和3.xsnapshot正在开发的快照版本,较为不稳定M2:第二个里程碑,而后会转换为snapshot,最后变为release......
  • SpringBoot——更换Tomcat服务器为 Jetty 服务器
    Jetty服务器(可能会用到)Jetty比Tomcat更轻量级,可拓展性更强(相较于Tomcat),谷歌应用引擎(GAE)已经全面切换为Jetty首先要启动Jetty服务器 --> 到nexus.exe文件夹中cmd输......
  • springboot获取小程序二维码图片
    获取小程序二维码前需要获取小程序的token。这个不赘述了。获取小程序二维码官方文档上找到2个处理的Api接口。经测试,现有一个能用的 https://api.weixin.qq.com/wxa/ge......
  • Spring常见问题描述
    1渊源 原型在200210由RodJohnson发布的书中体现,后来在200403spring1.0版本发布,201709spring5.0发布,(1)springioc 控制反转,管理容器中的bean,主要使用di依赖注入实现。......
  • 应用汇推国内首家信用卡应用内支付解决方案“微支付”
    随着智能手机用户的大量增长,用户对手机支付的方式,以及手机支付所能涉及的领域的认识都在改变。最早的时候,手机支付基本用于收费短信、铃声下载等项目,但随着购买应用增值......
  • spring-boot-devtools 热部署造成的类加载问题
    如果你的项目在IDE中出现了像下面这些奇怪的错误objectisnotaninstanceofdeclaringclass//对象不是声明类的实例java.lang.ClassCastException:com.exam......