SpringBoot使用注解的方式统一返回接口结果集

1.创建一个Result类,包含返回的状态码,返回提示消息和数据结果

package com.dyzwj.zwjsharding.entity;

import lombok.Data;
import lombok.NoArgsConstructor;

import java.io.Serializable;

/**
 * @Title: Result
 * @Description: 接口返回集
 * @Company: caixun
 * @Author: zhengtonghui
 * @Create: Date:2021年08月10日
 */
// 成功结果实体
@Data
public class Result implements Serializable {

    private Integer code;
    private String message;
    private T data;

    public void setResultCode(ResultCode resultCode) {
        this.code = resultCode.code();
    }

    public static Result success() {
        Result result = new Result();
        result.setResultCode(ResultCode.SUCCESS);
        return result;
    }

    public static Result success(T data) {
        Result result = new Result();
        result.setResultCode(ResultCode.SUCCESS);
        result.setCode(ResultCode.SUCCESS.code());
        result.setMessage(ResultCode.SUCCESS.message());
        result.setData(data);
        return result;
    }

    public static Result failure(Integer code, String message) {
        Result result = new Result();
        result.setCode(code);
        result.setMessage(message);
        return result;
    }
}

 2.创建结果状态码枚举类

package com.dyzwj.zwjsharding.entity;

/**
 * @Title: ResultCode
 * @Description: 接口状态码
 * @Company: caixun
 * @Author: ChenCanWen
 * @Create: Date:2021年08月10日
 */
public enum ResultCode {
    /*成功状态码*/
    SUCCESS(1, "成功"),
    SYSTEM_ERROR(400, "系统繁忙,请稍后重试"),
    /*参数错误: 1001-1999 */
    PARAM_IS_INVALID(1001, "参数无效"),
    PARAM_IS_BLANK(1002, "参数为空"),
    PARAM_TYPE_BIND_ERROR(1003, "参数类型错误"),
    PARAM_NOT_COMPLETE(1004, "参数缺失"),
    /*用户错误: 2001-2999*/
    USER_NOT_LOGGED_IN(2001, "用户未登录,访问的路径需要验证,请登录"),
    USER_LOGIN_ERROR(2002, "账号不存在或密码错误"),
    USER_ACCOUNT_FORBIDDEN(2003, "账号已被禁用"),
    USER_NOT_EXIST(2004, "用户不存在"),
    USER_HAS_EXISTED(2005, "用户已存在");

    private Integer code;
    private String message;

    ResultCode(Integer code, String message) {
        this.code = code;
        this.message = message;
    }

    public Integer code() {
        return this.code;
    }

    public String message(){
        return this.message;
    }
}

3.错误结果集

package com.concom.domain;

import lombok.Data;

// 错误结果实体
@Data
public class ErrorResult {
    private Integer code;
    private String message;

    public ErrorResult(Integer code, String message){
        this.code = code;
        this.message = message;
    }
}

 

4.创建注解类 

package com.dyzwj.zwjsharding.annotation;

import java.lang.annotation.*;

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE,ElementType.METHOD})
@Documented
public @interface ResponseResult {
}

5.创建切面类

package com.dyzwj.zwjsharding.aop;

import com.dyzwj.zwjsharding.annotation.ResponseResult;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;

@Aspect
@Component
@Slf4j
public class ResponseResultAop {
    private static final String RESPONSE_RESULT_ANNO = "RESPONSE_RESULT_ANNO";

    //@Around("@within(com.dyzwj.zwjsharding.annotation.ResponseResult)")//这个切点表达式只作用在类上
    @Around("@annotation(com.dyzwj.zwjsharding.annotation.ResponseResult)")//这个切点表达式的作用只用在方法上
    public Object processAop(ProceedingJoinPoint joinPoint)  {
        Object result = null;
        try {
            log.info("开始切入");
            HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
            Class clazz = joinPoint.getTarget().getClass();
            MethodSignature signature = (MethodSignature) joinPoint.getSignature();
            Method method = signature.getMethod();
            if (clazz.isAnnotationPresent(ResponseResult.class)) {
                request.setAttribute(RESPONSE_RESULT_ANNO, clazz.getAnnotation(ResponseResult.class));
            }else if (method.isAnnotationPresent(ResponseResult.class)) {
                request.setAttribute(RESPONSE_RESULT_ANNO, method.getAnnotation(ResponseResult.class));
            }
            result = joinPoint.proceed();
            log.info("目标方法执行完成");
        } catch (Throwable e) {
            log.error("切面执行出错,原因是:{}", e);
        }
        return result;
    }
}

6. 写一个类继承ResponseBodyAdvice重写supports()和beforeBodyWrire()方法,该类需要使用@RestControllerAdvice注解和@RestControllerAdvice注解,并将其放入IOC容器交给spring进行管理,这个类就是在将数据返回给DispathchServlet对视图进行渲渲染前对body进行重写,当supports方法返回true的时候,该方法才会去执行beforeBodyWrite()方法,对返回的body进行重写

package com.dyzwj.zwjsharding.handler;

import com.dyzwj.zwjsharding.annotation.ResponseResult;
import com.dyzwj.zwjsharding.entity.ErrorResult;
import com.dyzwj.zwjsharding.entity.Result;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.MethodParameter;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;

import javax.servlet.http.HttpServletRequest;

@Component
@Slf4j
@RestControllerAdvice
public class ResponseResultAdvice implements ResponseBodyAdvice {
    private static final String RESPONSE_RESULT_ANNO="RESPONSE_RESULT_ANNO";
    /**
     * 获取请求中是否有包装注解标记,没有直接返回,如果有则需要重写返回体
     */
    @Override
    public boolean supports(MethodParameter methodParameter, Class> converterType) {
        ServletRequestAttributes sra = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = sra.getRequest();
        // 获取请求是否有包装标记
        ResponseResult responseResultAnn = (ResponseResult) request.getAttribute(RESPONSE_RESULT_ANNO);
        return responseResultAnn == null ? false : true;
    }

    /**
     * 重写返回体
     */
    @Override
    public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType,
                                  Class> selectedConverterType, ServerHttpRequest request,
                                  ServerHttpResponse response) {
        log.info("进入返回体处理");
        if (body instanceof ErrorResult) {
            ErrorResult errorResult = (ErrorResult) body;
            return Result.failure(errorResult.getCode(), errorResult.getMessage());
        }
        return Result.success(body);
    }

}

 7.控制器,用来发送请求,调用业务层获取数据,注意自定义注解是用在类上还是用在方法上,如果用在类上的话,则aop中的切点表达式使用的是@Around(@within("xxx.xx.class")),如果用在方法上则切点表达式为@Around(@annotation("xxxx.xxx.class"))

package com.dyzwj.zwjsharding.controller;

import com.dyzwj.zwjsharding.annotation.ResponseResult;
import com.dyzwj.zwjsharding.entity.User;
import com.dyzwj.zwjsharding.service.UserService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.util.List;

@RestController
@RequestMapping("/user")
@Slf4j
public class UserController {
    @Autowired
    private UserService userService;

    @GetMapping(value = "/findAll")
    @ResponseResult
    public List findAll() {
        return userService.findAll();
    }

    @GetMapping(value = "/findById/{id}")
    public User listUserByID(@PathVariable("id") long id) {
       return userService.findById(id);
    }

    @PostMapping(value = "/saveOrUpdate")
    public boolean updateOrInsertUser(@RequestBody User user) {
        if (user == null) {
            log.info("参数不对:{}", user);
        }
        User user1 = userService.findById(user.getId());
        if(user1!=null) {
            return userService.updateUser(user);
        }else{
            return userService.saveUser(user);
        }
    }
    @DeleteMapping(value = "/deleteUser/{id}")
    public int deleteUser(@PathVariable("id")long id){
        return userService.deleteUser(id);
    }
    @GetMapping(value = "/getAll")
    public List getAll(){
        return userService.list();
    }
}

8.业务接口层

package com.dyzwj.zwjsharding.service;

import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.service.IService;
import com.dyzwj.zwjsharding.entity.User;
import com.dyzwj.zwjsharding.exception.CustomException;

import java.util.List;

public interface UserService extends IService {
    List findAll();

    User findById(long id) throws CustomException;

    boolean updateUser(User user);

    boolean saveUser(User user);

    int deleteUser(long id);
}

9.业务实现类

package com.dyzwj.zwjsharding.service.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.dyzwj.zwjsharding.entity.User;
import com.dyzwj.zwjsharding.exception.CustomException;
import com.dyzwj.zwjsharding.mapper.UserMapper;
import com.dyzwj.zwjsharding.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;

@Service
public class UserServiceImpl extends ServiceImpl implements UserService {
    @Autowired
    private UserMapper userMapper;
    @Override
    public List findAll() {
        return userMapper.selectAll();
    }

    @Override
    public User findById(long id) throws CustomException{
        if(id==0){
            throw new CustomException("id不能为0");
        }
        return userMapper.findById(id);
    }

    @Override
    public boolean updateUser(User user) {
        return userMapper.updateUser(user);
    }

    @Override
    public boolean saveUser(User user) {
        return userMapper.saveUser(user);
    }

    @Override
    public int deleteUser(long id) {
        return userMapper.deleteById(id);
    }

}

10.数据访问层

package com.dyzwj.zwjsharding.mapper;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.dyzwj.zwjsharding.entity.User;
import org.apache.ibatis.annotations.*;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Repository;

import java.util.List;

@Repository
public interface UserMapper extends BaseMapper {


    @Insert("insert into t_user(nickname,password,age,sex,birthday) values(#{nickname},#{password},#{age},#{sex},#{birthday})")
    int insert(User user);

    @Delete("delete from t_user")
    int delete();


    @Select("select * from t_user")
    List selectAll();

    @Select("select * from t_user where id=#{id}")
    User findById(long id);

    @Update("update t_user set nickname=#{nickname},password=#{password},age=#{age},sex=#{sex},birthday=now() where id=#{id}")
    boolean updateUser(User user);

    @Insert("insert into t_user(nickname,password,age,sex,birthday) values(#{nickname},#{password},#{age},#{sex},#{birthday})")
    boolean saveUser(User user);
}

11.访问结果 ,数据比较多,暂未截完整图

SpringBoot使用注解的方式统一返回接口结果集_第1张图片

  12.实体类

package com.dyzwj.zwjsharding.entity;

import com.baomidou.mybatisplus.annotation.TableName;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.Date;

@Data
@TableName(value = "t_user")
public class User {

    private long id;
    private String nickname;
    private String password;
    private Integer age;
    private Integer sex;
    @JsonFormat(pattern="yyyy-MM-dd HH:mm:ss",timezone="GMT+8")
    private Date birthday;
}

13.依赖

 
        
            org.springframework.boot
            spring-boot-starter-web
        
        
            org.springframework.boot
            spring-boot-starter-aop
        
        
        
            mysql
            mysql-connector-java
        
        
            com.alibaba
            druid
            1.2.8
        
        
            com.alibaba
            fastjson
            1.2.78
        
        
            com.baomidou
            mybatis-plus-boot-starter
            3.3.1.tmp
        
        

        
            org.apache.shardingsphere
            sharding-jdbc-spring-boot-starter
            4.0.0-RC1
        
        

        
            org.projectlombok
            lombok
        
        
            org.springframework.boot
            spring-boot-starter-test
            test
        
    

14.配置application.propertis文件

server:
  port: 8089
spring:
  application:
    name: boot-student
  datasource:
    url: jdbc:mysql://localhost:3306/db3?useUnicode=true&characterEncoding=utf-8
    driver-class-name: com.mysql.jdbc.Driver
    username: root
    password: west151211
mybatis-plus:
  mapper-locations: classpath:/mapper/*Mapper.xml
  type-aliases-package: com.concom.domain
  configuration:
    map-underscore-to-camel-case: true
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl #开启SQL语句打印

15.SQL语句

CREATE TABLE `t_user` (
  `id` int(10) NOT NULL AUTO_INCREMENT,
  `user_name` varchar(20) DEFAULT NULL,
  `user_sex` varchar(6) DEFAULT NULL,
  `user_age` int(10) DEFAULT NULL,
  `user_telphone` varchar(11) DEFAULT NULL,
  `login_time` timestamp NULL DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8;

你可能感兴趣的:(spring,boot,java)