SpringBoot学习

SpringBoot学习

1.创建SpringBoot项目

点击文件->新建->spring Initializr
SpringBoot学习_第1张图片
SpringBoot学习_第2张图片
选择需要的依赖,我这里只选择了Spring Web

SpringBoot学习_第3张图片
选择文件位置
SpringBoot学习_第4张图片
点击完成,创建完毕
SpringBoot学习_第5张图片

2.使用MyBatis

我们先在数据库里创建一个user表,表里的内容如下

SpringBoot学习_第6张图片
在刚才的springboot项目下,引入相关依赖
后面要演示拦截器的例子,所以先不采用前后端分离,方便等下学习


		<dependency>
			<groupId>mysqlgroupId>
			<artifactId>mysql-connector-javaartifactId>
		dependency>
		
		<dependency>
			<groupId>org.mybatis.spring.bootgroupId>
			<artifactId>mybatis-spring-boot-starterartifactId>
			<version>2.2.2version>
		dependency>
		
		<dependency>
			<groupId>org.projectlombokgroupId>
			<artifactId>lombokartifactId>
		dependency>
		
		<dependency>
			<groupId>org.springframework.bootgroupId>
			<artifactId>spring-boot-starter-thymeleafartifactId>
		dependency>

创建实体类User.java

@Data
@NoArgsConstructor
@AllArgsConstructor
public class User {
    private Integer id;
    private String username;
    private String password;
}

dao层:UserDao.java

@Repository 
@Mapper
public interface UserDao {
    User login(User user);
    User getUserByUserName(String username);
    List<User>getUserList();
    Integer getTotal();
    User getUserById(Integer id);
    boolean addUser(User user);
    boolean deleteUserById(Integer id);
}

service层
UserService.java

public interface UserService {
    User login(User user);
    User getUserByUserName(String username);
    List<User> getUserList();
    Integer getTotal();
    User getUserById(Integer id);
    Integer addUser(User user);
    boolean deleteUserById(Integer id);
}

UserServiceImpl.java

@Service
@Slf4j
public class UserServiceImpl implements UserService {
    @Autowired
    private UserDao userDao;
    @Override
    public User login(User user){
        try{
            User res=userDao.login(user);
            return res;
        }catch (Exception e){
            log.error(e.getMessage(),e);
            return null;
        }
    }
    @Override
    public User getUserByUserName(String username) {
        try{
            User user=userDao.getUserByUserName(username);
            return user;
        }catch (Exception e){
            log.error(e.getMessage(),e);
            return null;
        }
    }
    @Override
    public List<User> getUserList() {
        try{
            List<User>list=userDao.getUserList();
            return list;
        }catch (Exception e){
            log.error(e.getMessage(),e);
            return Collections.emptyList();
        }
    }
    @Override
    public Integer getTotal() {
        try{
            Integer total=userDao.getTotal();
            return total;
        }catch (Exception e){
            log.error(e.getMessage(),e);
            return -1;
        }
    }
    @Override
    public User getUserById(Integer id) {
        try{
            User user=userDao.getUserById(id);
            return user;
        }catch (Exception e){
            log.error(e.getMessage(),e);
            return null;
        }
    }
    @Override
    public Integer addUser(User user) {
        try{
            userDao.addUser(user);
            //返回主键id
            return user.getId();
        }catch (Exception e){
            log.error(e.getMessage(),e);
            return -1;
        }
    }
    @Override
    public boolean deleteUserById(Integer id) {
        try{
            return userDao.deleteUserById(id);
        }catch (Exception e){
            log.error(e.getMessage(),e);
            return false;
        }
    }
}

控制层UserController.java

@RestController
@Slf4j
public class UserController {
   @Autowired
    private UserService userService;
   //跳转到主页
   @RequestMapping("/index")
    public ModelAndView index(){
       log.info("跳转到主页=============");
       ModelAndView modelAndView=new ModelAndView();
       modelAndView.setViewName("index");
       return modelAndView;
   }
   //跳转到登录页面
   @RequestMapping("/loginUI")
    public ModelAndView loginUI(){
       log.info("跳转到登录页面============");
       ModelAndView modelAndView=new ModelAndView();
       modelAndView.setViewName("login");
       return modelAndView;
   }
   //登录操作
    @RequestMapping("/login")
    public ModelAndView login(User user){
       log.info("进行登录操作===============");
       ModelAndView modelAndView=new ModelAndView();
        user=userService.login(user);
        if(Objects.isNull(user)){
            modelAndView.setViewName("login");
        }else{
            modelAndView.setViewName("index");
            modelAndView.addObject("user",user);
        }
        return modelAndView;
    }
}

application.yml

server:
  port: 8080
spring:
  thymeleaf:
    prefix: classpath:/templates/
    suffix: .html
    mvc:
      view:
        static-path-pattern: /static/**
  datasource:
    username: root
    password: 3fa4d180
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:3306/young?useSSL=false&serverTimezone=UTC
mybatis:
  mapper-locations: classpath:/mapper/*.xml

登录页面:login.html

DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>登录页面title>
head>
<body>
    <form action="/login" method="post">
        <label>
            用户名:<input type="text" name="username" placeholder="请输入用户名"/><br>
        label>
        <label>
            密码:<input type="password" name="password" placeholder="请输入密码"/><br>
        label>
        <input type="submit" value="登录"/>
    form>
body>
html>

主页:index.html

DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>主页title>
head>
<body>
    <h3>登录成功,进入主页h3>
body>
html>

UserDao.xml


DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.young.demo12.dao.UserDao">
    <select id="login" parameterType="com.young.demo12.entity.User" resultType="com.young.demo12.entity.User">
        select *
        from user
        where username=#{username} and password=#{password}
    select>
    <select id="getUserByUserName" parameterType="string" resultType="com.young.demo12.entity.User">
        select *
        from user
        where username=#{username}
    select>
    <select id="getUserList" resultType="com.young.demo12.entity.User">
        select *
        from user
    select>
    <select id="getTotal" resultType="int">
        select count(*)
        from user
    select>
    <insert id="addUser" parameterType="com.young.demo12.entity.User" useGeneratedKeys="true" keyProperty="id">
        insert into
        user(id,username,password)
        values
        (#{id},#{username},#{password})
    insert>
    <delete id="deleteUserById" parameterType="int">
        delete
        from user
        where id=#{id}
    delete>
mapper>

完整文件目录如下:
SpringBoot学习_第7张图片

运行项目
访问:
http://localhost:8080/loginUI
SpringBoot学习_第8张图片
SpringBoot学习_第9张图片
SpringBoot学习_第10张图片

3.拦截器

刚才的项目中,即使我不登录,也可以正常访问首页,这就很不合理了,所以我们需要拦截器来进行拦截
LoginInterceptor.java

public class LoginInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response,Object handle)throws Exception{
        Cookie[]cookies=request.getCookies();
        //cookie为空时,返回false
        if(Objects.isNull(cookies)){
            return false;
        }
        String username=null;
        for(Cookie cookie:cookies){
            if(cookie.getName().equals(LoginConfig.USERCOOKIE)){
                username=cookie.getValue();
                break;
            }
        }
        //cookie过期或不存在相应的cookie,返回false
        if(username==null||username==""){
            return false;
        }
        return true;
    }
}

LoginConfig.java

@Configuration
public class LoginConfig implements WebMvcConfigurer {
    public static String USERCOOKIE="username_cookie";
    @Override
    public void addInterceptors(InterceptorRegistry registry){
    //设置拦截器,拦截index,放行loginUI,login
        registry.addInterceptor(new LoginInterceptor())
                .addPathPatterns("/index")
                .excludePathPatterns("/loginUI","/login");
    }
}

修改UserController的login

//登录操作
    @RequestMapping("/login")
    public ModelAndView login(User user, HttpServletResponse response){
       log.info("进行登录操作===============");
       ModelAndView modelAndView=new ModelAndView();
        user=userService.login(user);
        if(Objects.isNull(user)){
            modelAndView.setViewName("login");
        }else{
            //设置cookie
            Cookie cookie=new Cookie(LoginConfig.USERCOOKIE,user.getUsername());
            //cookie路径
            cookie.setPath("/");
            //cookie存活时间,设置为1h
            cookie.setMaxAge(60*60);
            response.addCookie(cookie);
            modelAndView.setViewName("index");
            modelAndView.addObject("user",user);
        }
        return modelAndView;
    }

SpringBoot学习_第11张图片

运行项目
直接访问主页,被拦截
SpringBoot学习_第12张图片
进行登录
SpringBoot学习_第13张图片
登录成功,跳转到主页
SpringBoot学习_第14张图片
重新访问主页,访问成功,说明cookie生效,免密登录成功
SpringBoot学习_第15张图片
参考文章:springboot拦截器

4.JDBCTemplate

我们在刚才的基础上,进一步整合JDBCTemplate框架,并用它实现增删改查
首先创建一个微信用户表
SpringBoot学习_第16张图片
我们引入相关依赖,来整合JDBCTemplate


		<dependency>
			<groupId>com.alibabagroupId>
			<artifactId>fastjsonartifactId>
			<version>1.2.51version>
		dependency>
		
		<dependency>
			<groupId>org.springframework.bootgroupId>
			<artifactId>spring-boot-starter-jdbcartifactId>
		dependency>

对返回值进行封装
ResultVO.java,注意,这里一定要有get和set方法

public class ResultVO <T>{
    private Integer code;
    private String msg;
    private T data;
    public ResultVO(){
    }
    public ResultVO(Integer code,String msg){
        this.code=code;
        this.msg=msg;
        this.data=null;
    }
    public ResultVO(Integer code,String msg,T data){
        this.code=code;
        this.msg=msg;
        this.data=data;
    }
    public Integer getCode() {
        return code;
    }
    public void setCode(Integer code) {
        this.code = code;
    }
    public String getMsg() {
        return msg;
    }
    public void setMsg(String msg) {
        this.msg = msg;
    }
    public T getData() {
        return data;
    }
    public void setData(T data) {
        this.data = data;
    }
}

返回值处理工具类
ResultVOUtil.java

public class ResultVOUtil {
    public static ResultVO success(){
        return new ResultVO<>(200,"操作成功");
    }
    public static ResultVO success(Object data){
        return new ResultVO<>(200,"操作成功",data);
    }
    public static ResultVO error(Integer code,String msg){
        return new ResultVO<>(code,msg);
    }
}

微信用户实体类WxUser.java

@Data
public class WxUser {
    private Integer id;
    private String openId;
    private String nickName;
    private String avatarUrl;
    @Override
    public String toString(){
        return "WxUser{id="+id+",openId="+openId+",nickName="+nickName+
                ",avatarUrl="+avatarUrl+"}";
    }
}

dao层
WxUserDao.java

public interface WxUserDao {
    Integer addWxUser(WxUser user);
    WxUser getWxUserById(Integer id);
    List<WxUser>getWxUserList();
    Boolean deleteWxUser(Integer id);
}

WxUserDaoImpl.java

@Repository
public class WxUserDaoImpl implements WxUserDao {
    @Autowired
    private JdbcTemplate jdbcTemplate;
    //插入并返回主键
    @Override
    public Integer addWxUser(WxUser user) {
        //sql语句
        String sql="insert into wxuser(openId,nickName,avatarUrl) values(?,?,?)";
//        jdbcTemplate.update(sql,user.getOpenId(),user.getNickName(),user.getAvatarUrl());
        //获取自增主键
        KeyHolder holder=new GeneratedKeyHolder();
        jdbcTemplate.update(connection->{
            PreparedStatement ps=connection.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS);
            ps.setString(1,user.getOpenId());
            ps.setString(2,user.getNickName());
            ps.setString(3,user.getAvatarUrl());
            return ps;
        },holder);
        int id= Objects.requireNonNull(holder.getKey()).intValue();
        return id;
    }
    @Override
    public WxUser getWxUserById(Integer id) {
        String sql="select * from wxuser where id=?";
        List<WxUser>list=jdbcTemplate.query(sql,new Object[]{id},new BeanPropertyRowMapper<>(WxUser.class));
        if(list.size()>0){
            return list.get(0);
        }else{
            return null;
        }
    }
    @Override
    public List<WxUser> getWxUserList() {
        String sql="select * from wxuser";
        List<WxUser>list=jdbcTemplate.query(sql,new BeanPropertyRowMapper<>(WxUser.class));
        return list;
    }
    @Override
    public Boolean deleteWxUser(Integer id) {
        String sql="delete from wxuser where id=?";
        int i= jdbcTemplate.update(sql,new Object[]{id});
        if(i>0){
            return true;
        }else{
            return false;
        }
    }
}

service层
WxUserService.java

public interface WxUserService {
    ResultVO addWxUser(JSONObject jsonObject);
    ResultVO getWxUserById(Integer id);
    ResultVO getWxUserList();
    ResultVO deleteWxUserById(JSONObject jsonObject);
}

WxUserServiceImpl.java

@Service
@Slf4j
public class WxUserServiceImpl implements WxUserService {
    @Autowired
    private WxUserDao wxUserDao;
    @Override
    public ResultVO addWxUser(JSONObject jsonObject) {
        String openId=jsonObject.getString("openId");
        String nickName=jsonObject.getString("nickName");
        String avatarUrl=jsonObject.getString("avatarUrl");
        WxUser wxUser=new WxUser();
        wxUser.setOpenId(openId);
        wxUser.setNickName(nickName);
        wxUser.setAvatarUrl(avatarUrl);
        try{
            Integer id=wxUserDao.addWxUser(wxUser);
            Map<String,Object>res=new HashMap<>();
            res.put("id",id);
            return ResultVOUtil.success(res);
        }catch (Exception e){
            log.error(e.getMessage(),e);
            return ResultVOUtil.error(500,"添加微信用户失败");
        }
    }
    @Override
    public ResultVO getWxUserById(Integer id) {
       try{
           WxUser wxUser=wxUserDao.getWxUserById(id);
           Map<String,Object>res=new HashMap<>();
           res.put("wxUser",wxUser);
           return ResultVOUtil.success(res);
       }catch (Exception e){
           log.error(e.getMessage(),e);
           return ResultVOUtil.error(500,"获取微信用户详情失败");
       }
    }
    @Override
    public ResultVO getWxUserList() {
        try{
            List<WxUser>list=wxUserDao.getWxUserList();
            Map<String,Object>res=new HashMap<>();
            res.put("list",list);
            return ResultVOUtil.success(res);
        }catch (Exception e){
            log.error(e.getMessage(),e);
            return ResultVOUtil.error(500,"获取微信用户列表失败");
        }
    }
    @Override
    public ResultVO deleteWxUserById(JSONObject jsonObject) {
        String idStr=jsonObject.getString("id");
        int id;
        try{
            id=Integer.parseInt(idStr);
        }catch (Exception e){
            log.error(e.getMessage(),e);
            return ResultVOUtil.error(500,"传递的参数类型有误");
        }
        try{
            boolean flag=wxUserDao.deleteWxUser(id);
            if(flag){
                Map<String,Object>res=new HashMap<>();
                res.put("deleteNum",1);
                return ResultVOUtil.success(res);
            }else{
                return ResultVOUtil.error(500,"删除微信用户失败");
            }
        }catch (Exception e){
            log.error(e.getMessage(),e);
            return ResultVOUtil.error(500,"删除微信用户失败");
        }
    }
}

控制层
WxUserController.java

@Slf4j
@RestController
public class WxUserController {
    @Autowired
    private WxUserService wxUserService;
    @RequestMapping(value = "/wxuser/addWxUser",method = RequestMethod.POST)
    public ResultVO addWxUser(@RequestBody JSONObject jsonObject){
        log.info("添加微信用户=================");
        return wxUserService.addWxUser(jsonObject);
    }
    @RequestMapping(value = "/wxuser/getWxUserById",method = RequestMethod.GET)
    public ResultVO getWxUserById(@RequestParam(value = "id",required = true)Integer id){
        log.info("获取微信用户详情===============");
        return wxUserService.getWxUserById(id);
    }
    @RequestMapping(value = "/wxuser/getWxUserList",method = RequestMethod.GET)
    public ResultVO getWxUserList(){
        log.info("获取微信用户列表===============");
        return wxUserService.getWxUserList();
    }
    @RequestMapping(value = "/wxuser/deleteWxUser",method = RequestMethod.DELETE)
    public ResultVO deleteWxUser(@RequestBody JSONObject jsonObject){
        log.info("删除微信用户=================");
        return wxUserService.deleteWxUserById(jsonObject);
    }
}

修改LoginConfig,将微信用户操作放行

@Configuration
public class LoginConfig implements WebMvcConfigurer {
    public static String USERCOOKIE="username_cookie";
    @Override
    public void addInterceptors(InterceptorRegistry registry){
        registry.addInterceptor(new LoginInterceptor())
                .addPathPatterns("/index")
                .excludePathPatterns("/loginUI","/login","/wxuser/**");
    }
}

SpringBoot学习_第17张图片
运行项目,打开postman
添加微信用户
SpringBoot学习_第18张图片
SpringBoot学习_第19张图片
SpringBoot学习_第20张图片
获取微信用户详情
SpringBoot学习_第21张图片
获取微信用户列表:
SpringBoot学习_第22张图片
删除微信用户
SpringBoot学习_第23张图片
参考文章:SpringBoot高级篇JdbcTemplate之数据插入使用姿势详解

4.JWT(json web token)

这里先插入微信小程序背景
SpringBoot学习_第24张图片
在我们刚才的例子中,很明显,即使我没使用微信小程序,只要我调用相应的接口,无论我是不是该小程序的用户,我都可以进行相应的操作,这是不合理的,我们必须采取鉴权,但是使用什么手段鉴权?可能会有人想到用cookie,但是在手机端,是不存在cookie的,而且cookie其实是不安全的,可能会造成用户信息的泄露,而且一些网站会禁用cookie导致我们无法使用cookie进行鉴权。
接下来,于是我们使用JWT来进行鉴权。
因为这里只是演示,并没有真正的小程序,所有也就不写微信登录的接口了,刚才那个WxUserController里的接口也不鉴权了,我们假设微信用户可以进行和帖子相关的操作。
引入依赖:


		<dependency>
			<groupId>com.auth0groupId>
			<artifactId>java-jwtartifactId>
			<version>3.19.2version>
		dependency>

JWT工具类

public class JWTUtil {
    private static final String SECRET="1q2w3e";
    //创造token
    public static String createTokeN(Map<String,String>payload){
        //设置过期时间
        Calendar calendar=Calendar.getInstance();
        calendar.add(Calendar.DATE,7);
        JWTCreator.Builder builder= JWT.create();
        payload.forEach((k,v)->builder.withClaim(k,v));
        return builder.withExpiresAt(calendar.getTime())
                .sign(Algorithm.HMAC256(SECRET));
    }
    //解析token
    public static DecodedJWT resolveToken(String token){
        JWTVerifier jwtVerifier=JWT.require(Algorithm.HMAC256(SECRET)).build();
        DecodedJWT decodedJWT=jwtVerifier.verify(token);
        return decodedJWT;
    }
}

我们增加一个登录的接口,因为只是一个例子,所有登录过程不规范,只是为了方便获取token
WxUserService

public interface WxUserService {
    ResultVO addWxUser(JSONObject jsonObject);
    ResultVO getWxUserById(Integer id);
    ResultVO getWxUserList();
    ResultVO deleteWxUserById(JSONObject jsonObject);
    ResultVO login(JSONObject jsonObject);
}

WxUserServiceImpl

 @Override
    public ResultVO login(JSONObject jsonObject){
        String openId=jsonObject.getString("openId");
        try{
            WxUser wxUser=wxUserDao.getWxUserByOpenId(openId);
            if(Objects.isNull(wxUser)){
                return ResultVOUtil.error(500,"该微信用户不存在");
            }
            Map<String,String>payload=new HashMap<>();
            //将信息存入负载
            payload.put("id",wxUser.getId()+"");
            payload.put("openId",wxUser.getOpenId());
            payload.put("nickName",wxUser.getNickName());
            payload.put("avatarUrl",wxUser.getAvatarUrl());
            payload.put("openId",wxUser.getOpenId());
            //获取用户凭证
            String token= JWTUtil.createTokeN(payload);
            //将用户信息和凭证返回给前端
            Map<String,Object>res=new HashMap<>();
            res.put("token",token);
            res.put("wxUser",wxUser);
            return ResultVOUtil.success(res);
        }catch (Exception e){
            log.error(e.getMessage(),e);
            return ResultVOUtil.error(500,"查找微信用户失败");
        }
    }

WxUserDao

public interface WxUserDao {
    Integer addWxUser(WxUser user);
    WxUser getWxUserById(Integer id);
    List<WxUser>getWxUserList();
    Boolean deleteWxUser(Integer id);
    WxUser getWxUserByOpenId(String openId);
}

WxUserDaoImpl.java

@Repository
public class WxUserDaoImpl implements WxUserDao {
    @Autowired
    private JdbcTemplate jdbcTemplate;
    //插入并返回主键
    @Override
    public Integer addWxUser(WxUser user) {
        //sql语句
        String sql="insert into wxuser(openId,nickName,avatarUrl) values(?,?,?)";
//        jdbcTemplate.update(sql,user.getOpenId(),user.getNickName(),user.getAvatarUrl());
        //获取自增主键
        KeyHolder holder=new GeneratedKeyHolder();
        jdbcTemplate.update(connection->{
            PreparedStatement ps=connection.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS);
            ps.setString(1,user.getOpenId());
            ps.setString(2,user.getNickName());
            ps.setString(3,user.getAvatarUrl());
            return ps;
        },holder);
        int id= Objects.requireNonNull(holder.getKey()).intValue();
        return id;
    }
    @Override
    public WxUser getWxUserById(Integer id) {
        String sql="select * from wxuser where id=?";
        List<WxUser>list=jdbcTemplate.query(sql,new Object[]{id},new BeanPropertyRowMapper<>(WxUser.class));
        if(list.size()>0){
            return list.get(0);
        }else{
            return null;
        }
    }
    @Override
    public List<WxUser> getWxUserList() {
        String sql="select * from wxuser";
        List<WxUser>list=jdbcTemplate.query(sql,new BeanPropertyRowMapper<>(WxUser.class));
        return list;
    }
    @Override
    public Boolean deleteWxUser(Integer id) {
        String sql="delete from wxuser where id=?";
        int i= jdbcTemplate.update(sql,new Object[]{id});
        if(i>0){
            return true;
        }else{
            return false;
        }
    }
    @Override
    public WxUser getWxUserByOpenId(String openId) {
        String sql="select * from wxuser where openId=?";
        List<WxUser>list=jdbcTemplate.query(sql,new Object[]{openId},new BeanPropertyRowMapper<>(WxUser.class));
        if(list.size()>0){
            return list.get(0);
        }else{
            return null;
        }
    }
}

WxUserController.java

 @Override
    public ResultVO login(JSONObject jsonObject){
        String openId=jsonObject.getString("openId");
        try{
            WxUser wxUser=wxUserDao.getWxUserByOpenId(openId);
            Map<String,Object>res=new HashMap<>();
            res.put("wxUser",wxUser);
            return ResultVOUtil.success(res);
        }catch (Exception e){
            log.error(e.getMessage(),e);
            return ResultVOUtil.error(500,"查找微信用户失败");
        }
    }

帖子实体类
Article.java,这里的isDelete是用来判断帖子是否删除的,我们项目中,一般是不会直接将数据删除的,而是通过一个标识来判断数据是否有效

@Data
public class Article {
    private Integer id;
    private WxUser wxUser;
    private String content;
    private Integer isDelete;
}

dao层

@Repository
@Mapper
public interface ArticleDao {
    boolean addArticle(Map<String,Object>map);
    boolean deleteArticle(Map<String,Object>map);
    Article getArticleById(Integer id);
    Integer getTotal();
    List<Article>getArticleList();
}

service层
ArticleService.java

public interface ArticleService {
    ResultVO addArticle(JSONObject jsonObject);
    ResultVO deleteArticle(JSONObject jsonObject);
    ResultVO getArticleById(JSONObject jsonObject);
    ResultVO getArticleList(JSONObject jsonObject);
}

ArticleServiceImpl.java

@Slf4j
@Service
public class ArticleServiceImpl implements ArticleService {
    @Autowired
    private ArticleDao articleDao;
    @Override
    public ResultVO addArticle(JSONObject jsonObject) {
        //获取token和文章信息
        String token=jsonObject.getString("token");
        String content=jsonObject.getString("content");
        String userId=jsonObject.getString("userId");
        //鉴权
        try{
            DecodedJWT decodedJWT= JWTUtil.resolveToken(token);
        }catch(AlgorithmMismatchException e){
            log.error(e.getMessage(),e);
            return ResultVOUtil.error(501,"鉴权算法不一致");
        }catch (SignatureVerificationException e){
            log.error(e.getMessage(),e);
            return ResultVOUtil.error(502,"签名失效");
        }catch (TokenExpiredException e){
            log.error(e.getMessage(),e);
            return ResultVOUtil.error(503,"token已过期");
        }catch (Exception e){
            //返回不同的状态码,帮助前端判断鉴权失败原因
            log.error(e.getMessage(),e);
            return ResultVOUtil.error(504,"微信用户鉴权失败");
        }
        try{
            Map<String,Object>map=new HashMap<>();
            map.put("content",content);
            map.put("userId",userId);
            boolean flag=articleDao.addArticle(map);
            if(flag){
                Map<String,Object>res=new HashMap<>();
                res.put("id",map.get("id"));
                //返回帖子主键
                return ResultVOUtil.success(res);
            }else{
                return ResultVOUtil.error(500,"发布帖子失败");
            }
        }catch (Exception e){
            log.error(e.getMessage(),e);
            return ResultVOUtil.error(500,"发布帖子数据库操作失败");
        }
    }
    @Override
    public ResultVO deleteArticle(JSONObject jsonObject) {
        //获取token和文章信息
        String token=jsonObject.getString("token");
        String id=jsonObject.getString("id");
        //鉴权
        try{
            DecodedJWT decodedJWT= JWTUtil.resolveToken(token);
        }catch(AlgorithmMismatchException e){
            log.error(e.getMessage(),e);
            return ResultVOUtil.error(501,"鉴权算法不一致");
        }catch (SignatureVerificationException e){
            log.error(e.getMessage(),e);
            return ResultVOUtil.error(502,"签名失效");
        }catch (TokenExpiredException e){
            log.error(e.getMessage(),e);
            return ResultVOUtil.error(503,"token已过期");
        }catch (Exception e){
            //返回不同的状态码,帮助前端判断鉴权失败原因
            log.error(e.getMessage(),e);
            return ResultVOUtil.error(504,"微信用户鉴权失败");
        }
        try{
            Map<String,Object>map=new HashMap<>();
           map.put("id",id);
            boolean flag=articleDao.deleteArticle(map);
            if(flag){
                Map<String,Object>res=new HashMap<>();
                res.put("deleteNum",1);
                //返回帖子主键
                return ResultVOUtil.success(res);
            }else{
                return ResultVOUtil.error(500,"删除帖子失败");
            }
        }catch (Exception e){
            log.error(e.getMessage(),e);
            return ResultVOUtil.error(500,"删除帖子数据库操作失败");
        }
    }
    @Override
    public ResultVO getArticleById(JSONObject jsonObject) {
        //获取token和文章信息
        String token=jsonObject.getString("token");
        String idStr=jsonObject.getString("id");
        //鉴权
        try{
            DecodedJWT decodedJWT= JWTUtil.resolveToken(token);
        }catch(AlgorithmMismatchException e){
            log.error(e.getMessage(),e);
            return ResultVOUtil.error(501,"鉴权算法不一致");
        }catch (SignatureVerificationException e){
            log.error(e.getMessage(),e);
            return ResultVOUtil.error(502,"签名失效");
        }catch (TokenExpiredException e){
            log.error(e.getMessage(),e);
            return ResultVOUtil.error(503,"token已过期");
        }catch (Exception e){
            //返回不同的状态码,帮助前端判断鉴权失败原因
            log.error(e.getMessage(),e);
            return ResultVOUtil.error(504,"微信用户鉴权失败");
        }
        int id;
        try{
            id=Integer.parseInt(idStr);
        }catch (Exception e){
            log.error(e.getMessage(),e);
            return ResultVOUtil.error(500,"参数类型有误");
        }
        try{
            Article article=articleDao.getArticleById(id);
            Map<String,Object>res=new HashMap<>();
            res.put("article",article);
            return ResultVOUtil.success(res);
        }catch (Exception e){
            log.error(e.getMessage(),e);
            return ResultVOUtil.error(500,"获取帖子详情失败");
        }
    }
    @Override
    public ResultVO getArticleList(JSONObject jsonObject) {
        //获取token和文章信息
        String token=jsonObject.getString("token");
        //鉴权
        try{
            DecodedJWT decodedJWT= JWTUtil.resolveToken(token);
        }catch(AlgorithmMismatchException e){
            log.error(e.getMessage(),e);
            return ResultVOUtil.error(501,"鉴权算法不一致");
        }catch (SignatureVerificationException e){
            log.error(e.getMessage(),e);
            return ResultVOUtil.error(502,"签名失效");
        }catch (TokenExpiredException e){
            log.error(e.getMessage(),e);
            return ResultVOUtil.error(503,"token已过期");
        }catch (Exception e){
            //返回不同的状态码,帮助前端判断鉴权失败原因
            log.error(e.getMessage(),e);
            return ResultVOUtil.error(504,"微信用户鉴权失败");
        }
        try{
            List<Article>list=articleDao.getArticleList();
            Map<String,Object>res=new HashMap<>();
            res.put("list",list);
            return ResultVOUtil.success(list);
        }catch (Exception e){
            log.error(e.getMessage(),e);
            return ResultVOUtil.error(500,"获取帖子列表数据库操作失败");
        }
    }
}

控制层 ArticleController.java

@Slf4j
@RestController
public class ArticleController {
    @Autowired
    private ArticleService articleService;
    @RequestMapping(value = "/wxuser/addArticle",method = RequestMethod.POST)
    public ResultVO addArticle(@RequestBody JSONObject jsonObject){
        log.info("微信用户发布帖子=================");
        return articleService.addArticle(jsonObject);
    }
    @RequestMapping(value = "/wxuser/deleteArticle",method = RequestMethod.DELETE)
    public ResultVO deleteArticle(@RequestBody JSONObject jsonObject){
        log.info("微信用户删除帖子=================");
        return articleService.deleteArticle(jsonObject);
    }
    @RequestMapping(value = "/wxuser/getArticleById",method = RequestMethod.POST)
    public ResultVO getArticleById(@RequestBody JSONObject jsonObject){
        log.info("微信用户获取帖子详情=================");
        return articleService.getArticleById(jsonObject);
    }
    @RequestMapping(value = "/wxuser/getArticleList",method = RequestMethod.POST)
    public ResultVO getArticleList(@RequestBody JSONObject jsonObject){
        log.info("微信用户获取帖子列表=================");
        return articleService.getArticleList(jsonObject);
    }
}

帖子表
SpringBoot学习_第25张图片

ArticleDao.xml


DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.young.demo12.dao.ArticleDao">
    <resultMap id="articleBean" type="com.young.demo12.entity.Article">
        <id property="id" column="id"/>
        <result property="content" column="content"/>
        <result property="isDelete" column="is_delete"/>
        <association property="wxUser" javaType="com.young.demo12.entity.WxUser">
            <id property="id" column="wid"/>
            <result property="openId" column="openId"/>
            <result property="nickName" column="nickName"/>
            <result property="avatarUrl" column="avatarUrl"/>
        association>
    resultMap>
   <insert id="addArticle" parameterType="map" useGeneratedKeys="true" keyProperty="id">
        insert into article(user_id,content,is_delete)
        values
        (#{userId},#{content},0)
    insert>
    <update id="deleteArticle" parameterType="map">
        update article
        set is_delete=1
        where id=#{id}
    update>
    <select id="getArticleById" parameterType="int" resultMap="articleBean">
        select a.id,a.content,
        a.is_delete,w.id wid,
        w.openId,w.nickName,
        w.avatarUrl
        from article a inner join wxuser w
        on a.user_id=w.id
        where a.is_delete=0
        and a.id=#{id}
    select>
    <select id="getTotal" resultType="int">
        select count(*)
        from article a inner join wxuser w
        on a.user_id=w.id
        where a.is_delete=0
    select>
    <select id="getArticleList" resultMap="articleBean">
        select a.id,a.content,
        a.is_delete,w.id wid,
        w.openId,w.nickName,
        w.avatarUrl
        from article a inner join wxuser w
        on a.user_id=w.id
        where a.is_delete=0
    select>
mapper>

运行
因为刚才我们没有获取token,所以先调用login接口获取token
SpringBoot学习_第26张图片
发布帖子
SpringBoot学习_第27张图片
获取帖子详情
SpringBoot学习_第28张图片
获取帖子列表
SpringBoot学习_第29张图片
删除帖子
SpringBoot学习_第30张图片
参考文章SpringBoot整合JWT

5.AOP

在刚才的例子中,我们发现一个问题,就是帖子操作前都要进行鉴权,鉴权逻辑是一样的,那么我们是不是可以把鉴权代码提取出来,可能有人想到用一个拦截器来拦截,这当然也可以,不过我要介绍的是另一种方法:AOP,aop是SpringBoot的两大核心,另一个核心是loc
我们先引入依赖


		<dependency>
			<groupId>org.springframework.bootgroupId>
			<artifactId>spring-boot-starter-aopartifactId>
		dependency>
	dependencies>

创建一个切入点类,一开始向通过前置通知鉴权,然后如果鉴权失败抛出错误,返回ResultVO来通知前端鉴权失败的原因,但是发现使用afterThrowing要进入方法后抛出错误才会执行,先这样吧,后边看看怎么改

@Aspect
@Component
@Slf4j
public class ArticleAop {
    //切入点,待增强的方法
    @Pointcut("execution(public * com.young.demo12.controller.ArticleController.*(..))")
    //切入点签名
    public void log(){
        log.info("pointCut签名===========");
    }
    //前置通知
    @Before("log()")
    public void doBefore(JoinPoint jp)throws Throwable{
        log.info("前置通知==================");
        //获取请求
        ServletRequestAttributes attributes=(ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request=attributes.getRequest();
        //获取请求头中的token
        String token=request.getHeader("token");
        //验证token
        JWTUtil.resolveToken(token);
    }
}

修改ArticleServiceImpl.java

@Slf4j
@Service
public class ArticleServiceImpl implements ArticleService {
    @Autowired
    private ArticleDao articleDao;
    @Override
    public ResultVO addArticle(JSONObject jsonObject) {
        String content=jsonObject.getString("content");
        String userId=jsonObject.getString("userId");
        try{
            Map<String,Object>map=new HashMap<>();
            map.put("content",content);
            map.put("userId",userId);
            boolean flag=articleDao.addArticle(map);
            if(flag){
                Map<String,Object>res=new HashMap<>();
                res.put("id",map.get("id"));
                //返回帖子主键
                return ResultVOUtil.success(res);
            }else{
                return ResultVOUtil.error(500,"发布帖子失败");
            }
        }catch (Exception e){
            log.error(e.getMessage(),e);
            return ResultVOUtil.error(500,"发布帖子数据库操作失败");
        }
    }
    @Override
    public ResultVO deleteArticle(JSONObject jsonObject) {
        //获取token和文章信息
        String token=jsonObject.getString("token");
        String id=jsonObject.getString("id");
        try{
            Map<String,Object>map=new HashMap<>();
           map.put("id",id);
            boolean flag=articleDao.deleteArticle(map);
            if(flag){
                Map<String,Object>res=new HashMap<>();
                res.put("deleteNum",1);
                //返回帖子主键
                return ResultVOUtil.success(res);
            }else{
                return ResultVOUtil.error(500,"删除帖子失败");
            }
        }catch (Exception e){
            log.error(e.getMessage(),e);
            return ResultVOUtil.error(500,"删除帖子数据库操作失败");
        }
    }
    @Override
    public ResultVO getArticleById(JSONObject jsonObject) {
        //获取token和文章信息
        String token=jsonObject.getString("token");
        String idStr=jsonObject.getString("id");
        int id;
        try{
            id=Integer.parseInt(idStr);
        }catch (Exception e){
            log.error(e.getMessage(),e);
            return ResultVOUtil.error(500,"参数类型有误");
        }
        try{
            Article article=articleDao.getArticleById(id);
            Map<String,Object>res=new HashMap<>();
            res.put("article",article);
            return ResultVOUtil.success(res);
        }catch (Exception e){
            log.error(e.getMessage(),e);
            return ResultVOUtil.error(500,"获取帖子详情失败");
        }
    }
    @Override
    public ResultVO getArticleList(JSONObject jsonObject) {
        //获取token和文章信息
        String token=jsonObject.getString("token");
        try{
            List<Article>list=articleDao.getArticleList();
            Map<String,Object>res=new HashMap<>();
            res.put("list",list);
            return ResultVOUtil.success(list);
        }catch (Exception e){
            log.error(e.getMessage(),e);
            return ResultVOUtil.error(500,"获取帖子列表数据库操作失败");
        }
    }
}

运行,现在我们不行要请求体上加上token,我们把token加在请求头上
SpringBoot学习_第31张图片
然后发布帖子
SpringBoot学习_第32张图片
获取帖子详情
SpringBoot学习_第33张图片

获取帖子列表
SpringBoot学习_第34张图片
删除帖子
SpringBoot学习_第35张图片
我们观察控制台,有打印“前置通知”,说明确实有切入成功
SpringBoot学习_第36张图片
参考文章:如何优雅地在SpringBoot中使用自定义注解,AOP切面统一打印出入参数

6.Redis

在上述情况中,我们每次获取帖子信息都要从数据库获取,这样做开销比较大,我们可以先把数据放入缓存中,然后先从缓存中获取,如果缓存中没有在从数据库获取,所有在这一节,我们引入Redis
引入依赖


		<dependency>
			<groupId>org.springframework.bootgroupId>
			<artifactId>spring-boot-starter-data-redisartifactId>
		dependency>

RedisUtil工具类,因为这里没有设计hash、set等更高级的数据结构,所有我写这个工具类也没有考虑这些的存取

@Slf4j
@Component
public class RedisUtil {
    @Autowired
    private StringRedisTemplate redisTemplate;
    private final String PRE_VALUE="article_";
    public <K,V>void add(K key,V value){
        try{
            if(value!=null){
                String valueStr= JSON.toJSONString(value);
                redisTemplate.opsForValue()
                        .set(PRE_VALUE+key,valueStr);
            }
        }catch (Exception e){
            log.error(e.getMessage(),e);
        }
    }
    public <K,V>void add(K key,V value,long timeout){
        try{
            if(value!=null){
                String valueStr=JSON.toJSONString(value);
                redisTemplate.opsForValue()
                        .set(PRE_VALUE+key,valueStr,timeout, TimeUnit.SECONDS);
            }
        }catch (Exception e){
            log.error(e.getMessage(),e);
        }
    }
    public <K,V> V getObject(K key,Class<V>clazz){
        String value=this.get(key);
        V result=null;
        if(!StringUtils.isEmpty(value)){
            result=JSON.parseObject(value,clazz);
        }
        return result;
    }
    public <K,V>List<V> getList(K key,Class<V>clazz){
        String value=this.get(key);
        List<V>result= Collections.emptyList();
        if(!StringUtils.isEmpty(value)){
            result=JSON.parseArray(value,clazz);
        }
        return result;
    }
    public <K> String get(K key){
        String value;
        try{
            value=redisTemplate.opsForValue()
                    .get(PRE_VALUE+key);
        }catch (Exception e){
            log.error(e.getMessage(),e);
            throw new RuntimeException("从Redis获取失败");
        }
        return value;
    }
    public <K> void delete(K key){
        redisTemplate.delete(PRE_VALUE+key);
    }
    public <K>boolean expire(K key,long timeout){
        return redisTemplate.expire(PRE_VALUE+key,timeout, TimeUnit.SECONDS);
    }
    public <K> long getExpire(K key){
        return redisTemplate.getExpire(PRE_VALUE+key);
    }
}

修改ArticleServiceImpl.java

@Slf4j
@Service
public class ArticleServiceImpl implements ArticleService {
    @Autowired
    private ArticleDao articleDao;
    @Autowired
    private RedisUtil redisUtil;
    @Autowired
    private WxUserDao wxUserDao;
    @Override
    public ResultVO addArticle(JSONObject jsonObject) {
        String content=jsonObject.getString("content");
        String userId=jsonObject.getString("userId");
        try{
            Map<String,Object>map=new HashMap<>();
            map.put("content",content);
            map.put("userId",userId);
            boolean flag=articleDao.addArticle(map);
            if(flag){
                Article article=new Article();
                               String idStr=String.valueOf(map.get("id"));

                int id=Integer.parseInt(idStr);
                article.setId(id);
                article.setContent(content);
                article.setIsDelete(0);
                //获取微信用户
                WxUser wxUser=wxUserDao.getWxUserById(Integer.parseInt(userId));
                article.setWxUser(wxUser);
                //添加到redis缓存中
                redisUtil.add(article.getId(),article);
                //更新缓存
                resetCache();
                Map<String,Object>res=new HashMap<>();
                res.put("id",map.get("id"));
                //返回帖子主键
                return ResultVOUtil.success(res);
            }else{
                return ResultVOUtil.error(500,"发布帖子失败");
            }
        }catch (Exception e){
            log.error(e.getMessage(),e);
            return ResultVOUtil.error(500,"发布帖子数据库操作失败");
        }
    }
    @Override
    public ResultVO deleteArticle(JSONObject jsonObject) {
        //获取token和文章信息
        String token=jsonObject.getString("token");
        String id=jsonObject.getString("id");
        try{
            Map<String,Object>map=new HashMap<>();
           map.put("id",id);
            boolean flag=articleDao.deleteArticle(map);
            if(flag){
                //删除缓存
                redisUtil.delete(id);
                //重载缓存
                resetCache();
                Map<String,Object>res=new HashMap<>();
                res.put("deleteNum",1);
                //返回帖子主键
                return ResultVOUtil.success(res);
            }else{
                return ResultVOUtil.error(500,"删除帖子失败");
            }
        }catch (Exception e){
            log.error(e.getMessage(),e);
            return ResultVOUtil.error(500,"删除帖子数据库操作失败");
        }
    }
    @Override
    public ResultVO getArticleById(JSONObject jsonObject) {
        //获取token和文章信息
        String token=jsonObject.getString("token");
        String idStr=jsonObject.getString("id");
        int id;
        try{
            id=Integer.parseInt(idStr);
        }catch (Exception e){
            log.error(e.getMessage(),e);
            return ResultVOUtil.error(500,"参数类型有误");
        }
        try{
            //先从缓存中获取
            Article article=redisUtil.getObject(id,Article.class);
            if(!Objects.isNull(article)){
                            log.info("从缓存中获取==============");

                Map<String,Object>res=new HashMap<>();
                res.put("article",article);
                return ResultVOUtil.success(res);
            }
            article=articleDao.getArticleById(id);
            //添加到缓存中
            redisUtil.add(article.getId(),article);
            //重载缓存
            resetCache();
            Map<String,Object>res=new HashMap<>();
            res.put("article",article);
            return ResultVOUtil.success(res);
        }catch (Exception e){
            log.error(e.getMessage(),e);
            return ResultVOUtil.error(500,"获取帖子详情失败");
        }
    }
    @Override
    public ResultVO getArticleList(JSONObject jsonObject) {
        //获取token和文章信息
        String token=jsonObject.getString("token");
        try{
            //先从缓存中获取
            List<Article>list=redisUtil.getList("ALL",Article.class);
            if(!Objects.isNull(redisUtil)&&list.size()>0){
                            log.info("从缓存中获取==============");

                Map<String,Object>res=new HashMap<>();
                res.put("list",list);
                return ResultVOUtil.success(list);
            }
            list=articleDao.getArticleList();
            //添加到缓存
            redisUtil.add("ALL",list);
            Map<String,Object>res=new HashMap<>();
            res.put("list",list);
            return ResultVOUtil.success(list);
        }catch (Exception e){
            log.error(e.getMessage(),e);
            return ResultVOUtil.error(500,"获取帖子列表数据库操作失败");
        }
    }
    //重置缓存
    private void resetCache(){
        try{
            List<Article>list=articleDao.getArticleList();
            redisUtil.add("ALL",list);
        }catch (Exception e){
            log.error(e.getMessage(),e);
        }
    }
}

修改application.yml

server:
  port: 8080
spring:
  redis:
    host: 127.0.0.1
    port: 6379
    timeout: 300000
    jedis:
      pool:
        max-active: 8
        min-idle: 0
        max-idle: 8
        max-wait: -1
  thymeleaf:
    prefix: classpath:/templates/
    suffix: .html
    mvc:
      view:
        static-path-pattern: /static/**
  datasource:
    username: root
    password: *******
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:3306/young?useSSL=false&serverTimezone=UTC
mybatis:
  mapper-locations: classpath:/mapper/*.xml

运行前先打开redis
SpringBoot学习_第37张图片
运行
SpringBoot学习_第38张图片
SpringBoot学习_第39张图片
SpringBoot学习_第40张图片
查看控制台SpringBoot学习_第41张图片
打开RedisDesktopManager,确实有刚才添加的缓存
SpringBoot学习_第42张图片

7.配置多环境application.yml

在实际开发中,我们一般都是在本地环境测试,测试没问题再部署到服务器上,现在我们演示配置多个环境
修改applicatio.yml

spring:
  profiles:
    active: dev

application-dev.yml

server:
  port: 8003
spring:
  redis:
    host: 127.0.0.1
    port: 6379
    timeout: 300000
    jedis:
      pool:
        max-active: 8
        min-idle: 0
        max-idle: 8
        max-wait: -1
  thymeleaf:
    prefix: classpath:/templates/
    suffix: .html
    mvc:
      view:
        static-path-pattern: /static/**
  datasource:
    username: root
    password: 3fa4d180
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:3306/young?useSSL=false&serverTimezone=UTC
mybatis:
  mapper-locations: classpath:/mapper/*.xml

application-prod.yml

server:
  port: 8003
spring:
  redis:
    host: 127.0.0.1
    port: 6379
    timeout: 300000
    password:******
    jedis:
      pool:
        max-active: 8
        min-idle: 0
        max-idle: 8
        max-wait: -1
  thymeleaf:
    prefix: classpath:/templates/
    suffix: .html
    mvc:
      view:
        static-path-pattern: /static/**
  datasource:
    username: root
    password: ******
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://192.168.137.128/young?useSSL=false&serverTimezone=UTC
mybatis:
  mapper-locations: classpath:/mapper/*.xml

运行
SpringBoot学习_第43张图片
本地没问题,我们修改application.yml

spring:
  profiles:
    active: prod

因为没钱买服务器,这里用虚拟机来模拟,先将项目打包
打开虚拟机,使用Xftp传输文件
SpringBoot学习_第44张图片
打开navicat,同步一下数据库
运行jar包
SpringBoot学习_第45张图片
先在虚拟机访问
SpringBoot学习_第46张图片
SpringBoot学习_第47张图片
本地访问
SpringBoot学习_第48张图片
打开postman
SpringBoot学习_第49张图片
SpringBoot学习_第50张图片

8.HttpClient

在实际开发中,有时候我们会遇到一些要求,就是在项目中发送http请求获取内容,这里我仿照微信小程序登录的流程,来整合HttpClient
我们先创建另一个SpringBoot项目,用来模拟被请求的服务
WxLoginController.java

@RestController
public class WxLoginController {
    @RequestMapping(value="/user/wxLogin",method = RequestMethod.GET)
    public String wxLogin(@RequestParam(value = "code",required = true)String code){
        System.out.println(code);
        return UUID.randomUUID().toString();
    }
}

在我们原本的项目里,导入依赖


		<dependency>
			<groupId>org.apache.httpcomponentsgroupId>
			<artifactId>httpclientartifactId>
			<version>4.5.13version>
		dependency>

HttpClientUtil 工具类

public class HttpClientUtil {
    //编码格式
    private static final String ENCODING = "UTF-8";
    //连接超时
    private static final int CONNECT_TIMEOUT = 5000;
    //请求连接超时
    private static final int CONNECT_REQUEST_TIMEOUT = 5000;
    //socket套接字超时
    private static final int SOCKET_TIMEOUT = 5000;
    public static ResultVO doGet(String url) throws Exception {
        return doGet(url, null, null);
    }
    public static ResultVO doGet(String url, Map<String, String> params) throws Exception {
        return doGet(url, null, params);
    }
    public static ResultVO doGet(String url, Map<String, String> headers, Map<String, String> params) throws Exception {
        //创建HttpClient
        CloseableHttpClient httpClient = HttpClientBuilder.create().build();
        //创建访问地址
        URIBuilder uriBuilder = new URIBuilder(url);
        if(params!=null&&params.size()>0){
            params.forEach((k, v) -> uriBuilder.setParameter(k, v));
        }
        //创建http对象
        HttpGet httpGet = new HttpGet(uriBuilder.build());
        //配置
        RequestConfig requestConfig = RequestConfig.custom()
                .setConnectTimeout(CONNECT_TIMEOUT)
                .setConnectionRequestTimeout(CONNECT_REQUEST_TIMEOUT)
                .setSocketTimeout(SOCKET_TIMEOUT).build();
        httpGet.setConfig(requestConfig);
        //设置请求头
        packageHeader(headers, httpGet);
        //创建httpResponse对象
        CloseableHttpResponse httpResponse = null;
        try {
            //执行请求
            return getHttpClientResult(httpResponse, httpClient, httpGet);
        } finally {
            //释放资源
            release(httpResponse, httpClient);
        }
    }

    public static ResultVO doPost(String url) throws Exception {
        return doPost(url, null, null);
    }

    public static ResultVO doPost(String url, Map<String, String> params) throws Exception {
        return doPost(url, null, params);
    }

    public static ResultVO doPost(String url, Map<String, String> headers, Map<String, String> params) throws Exception {
        //创建httpClient
        CloseableHttpClient httpClient = HttpClientBuilder.create().build();
        //创建http对象
        HttpPost httpPost = new HttpPost(url);
        //配置
        RequestConfig requestConfig = RequestConfig.custom()
                .setConnectTimeout(CONNECT_TIMEOUT)
                .setConnectionRequestTimeout(CONNECT_REQUEST_TIMEOUT)
                .setSocketTimeout(SOCKET_TIMEOUT).build();
        //设置请求头
        packageHeader(headers, httpPost);
        //封装请求参数
        if (params != null) {
            List<NameValuePair> list = new ArrayList<>();
            params.forEach((k, v) -> list.add(new BasicNameValuePair(k, v)));
            //设置请求体
            httpPost.setEntity(new UrlEncodedFormEntity(list, ENCODING));
        }
        //获取响应结果
        CloseableHttpResponse httpResponse = null;
        try {
            return getHttpClientResult(httpResponse, httpClient, httpPost);
        } finally {
            release(httpResponse, httpClient);
        }
    }
    //封装头部
    public static void packageHeader(Map<String, String> headers, HttpRequestBase httpMethod) {
        if (headers != null) {
            headers.forEach((k, v) -> httpMethod.setHeader(k, v));
        }
    }
    //获取响应结果
    public static ResultVO getHttpClientResult(CloseableHttpResponse httpResponse,CloseableHttpClient httpClient,HttpRequestBase httpMethod)throws Exception{
        httpResponse=httpClient.execute(httpMethod);
        if(httpResponse!=null&&httpResponse.getStatusLine()!=null){
            String content="";
            if(httpResponse.getEntity()!=null){
                content= EntityUtils.toString(httpResponse.getEntity(),ENCODING);
            }
            return new ResultVO(httpResponse.getStatusLine().getStatusCode(),"获取成功",content);
        }
        return new ResultVO(HttpStatus.SC_INTERNAL_SERVER_ERROR,"请求失败");
    }
    //释放资源
    public static void release(CloseableHttpResponse httpResponse,CloseableHttpClient httpClient)throws Exception{
        if(httpResponse!=null){
            httpResponse.close();
        }
        if(httpClient!=null){
            httpClient.close();
        }
    }
}

修改WxUserController

@RequestMapping(value = "/wxuser/verify",method = RequestMethod.GET)
    public ResultVO verify(@RequestParam(value = "code",required = true)String code){
        log.info("发送请求获取openId==================");
        try{
           ResultVO resultVO=HttpClientUtil.doGet("http://localhost:8080/user/wxLogin?code="+code);
            System.out.println(resultVO.getData());
            return resultVO;
        }catch (Exception e){
            log.error(e.getMessage(),e);
            return ResultVOUtil.error(500,"获取失败");
        }
    }

将两个项目都运行起来
SpringBoot学习_第51张图片

你可能感兴趣的:(笔记,spring,boot,java,学习)