前言
spring boot 项目中的MVC分层,在controller层我们需要做的是什么,统一项目中的返回格式,统一异常的统一处理,统一错误的返回码。项目中的三个统一息息相关,互相联系。gitee:
https://gitee.com/shen_wen_jia/learning-projects/tree/master/%E7%BB%9F%E4%B8%80%E8%BF%94%E5%9B%9E%E6%A0%BC%E5%BC%8Fresponse
项目架构
1.统一标准返回格式
项目中在controller层出现的各种返回,例:List ,Map<String,Object>。返回的数据多种多样,不方便与前端做一个统一的交互。统一标准返回格式,将各种返回对象分装在自己的BaseResponse当中。主要封装三个对象,code,msg,data。code-返回信息码(主要用来描述错误码)。msg-返回信息描述(主要用来描述错误信息)。data-正确数据/异常信息
Baseresponse的封装:
package com.study.res.comm;
import com.study.res.enums.ErrorEnum;
import javax.management.openmbean.TabularData;
import java.io.Serializable;
/**
* @ClassName BaseResponse
* @Author swj
* @Date 2020/10/10 10:08
*/
public class BaseResponse<T> implements Serializable {
private static final long serialVersionUID = 9211889136173018364L;
/**
* 成功返回码
*/
private static final int SUCCESS_CODE = 200;
/**
* 成功返回信息
*/
private static final String SUCCESS_MSG = "SUCCESS";
/**
* 返回信息标识码
*/
private int code = SUCCESS_CODE;
/**
* 返回信息描述信息
*/
private String msg = SUCCESS_MSG;
/**
* 响应内容-默认为空
*/
private T data = null;
/**
* 返回空的正确返回
* @return
*/
public static BaseResponse retOk(){
return new BaseResponse();
}
/**
* 有内容的成功信息返回
* @param data
* @param <T>
* @return
*/
public static <T> BaseResponse<T> retOk(T data){
BaseResponse<T> baseResponse = new BaseResponse<T>();
baseResponse.setData(data);
return baseResponse;
}
/**
* 失败版本返回 enum 版本
* @param errorEnum
* @return
*/
public static BaseResponse retFail(ErrorEnum errorEnum){
return retFail(errorEnum.getRespCode(),errorEnum.getRespMsg());
}
/**
* 无失败内容返回
* @param code
* @param msg
* @param <T>
* @return
*/
public static <T> BaseResponse<T> retFail(int code,String msg){
BaseResponse<T> response = new BaseResponse<>();
response.setCode(code);
response.setMsg(msg);
return response;
}
/**
* 有失败的返回格式 enum版本
* @param errorEnum
* @param data
* @param <T>
* @return
*/
public static <T> BaseResponse<T> retFail(ErrorEnum errorEnum,T data) {
BaseResponse<T> response = new BaseResponse<>();
response.setCode(errorEnum.getRespCode());
response.setMsg(errorEnum.getRespMsg());
response.setData(data);
return response;
}
/**
* 有失败的返回格式
* @param code
* @param msg
* @param data
* @param <T>
* @return
*/
public static <T> BaseResponse<T> retFail(int code, String msg, T data){
BaseResponse<T> response = new BaseResponse<>();
response.setCode(code);
response.setMsg(msg);
response.setData(data);
return response;
}
public void setData(T data) {
this.data = data;
}
public int getCode() {
return code;
}
public void setCode(int code) {
this.code = code;
}
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
public T getData() {
return data;
}
}
2.统一异常处理
项目中,将会遇到很多的异常,对统一的异常加以处理,统一解决项目当中的各种异常,并且将异常描述信息返回给前端。这里是将异常信息,统一处理,统一加入json返回,而不是spring boot 项目中的默认返回界面 /error
代码中生效的主要有2个注解:
@ControllerAdvice //将本类加入spring管理
@ExceptionHandler(value = WebException.class) //接收需要处理的异常类
自定义异常:
package com.study.res.exception;
/**
* @ClassName WebException
* @Author swj
* @Date 2020/10/10 10:28
*/
public class WebException extends Exception {
public WebException(String msg){
super(msg);
}
}
代码如下:
package com.study.res.controller;
import com.study.res.comm.BaseResponse;
import com.study.res.enums.ErrorEnum;
import com.study.res.exception.WebException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import javax.servlet.http.HttpServletRequest;
/**
* @ClassName UnifyExceptionHandler
* @Author swj
* @Date 2020/10/10 10:32
* controller层的异常统一处理类
*/
@ControllerAdvice
public class UnifyExceptionHandler {
@ResponseBody
@ExceptionHandler(value = WebException.class)
public BaseResponse handleWebException(HttpServletRequest req, WebException e){
return BaseResponse.retFail(ErrorEnum.SYSTEM_EXCEPTION,e);
}
}
3.统一错误返回码
错误标准码的定义,各个公司都不一定,建议按照阿里规范错误返回码来。给出自定义的错误返回码。错误返回enum的使用,主要是结合统一返回格式进行使用,给出固定的项目中的错误返回码,和错误返回描述信息。
代码如下:
package com.study.res.enums;
/**
* @ClassName ErrorEnum
* @Author swj
* @Date 2020/10/10 10:22
*/
public enum ErrorEnum {
DUPLICATE_KEY(1000,"标识符重复"),
DUPLICATE_ROLE_NAME(1001,"角色名重复"),
DUPLICATE_USER_CODE(1002,"用户账号重复"),
USER_NOT_LOGIN(1003,"用户未登录"),
QUESTIONNAIRE_PARAM_IS_NULL(2000,"类型或问题详情为空"),
PARAM_IS_NULL(2001,"参数为空"),
SYSTEM_EXCEPTION(500,"服务器发生异常")
;
private Integer respCode;
private String respMsg;
ErrorEnum(Integer respCode, String respMsg) {
this.respCode = respCode;
this.respMsg = respMsg;
}
public Integer getRespCode() {
return respCode;
}
public String getRespMsg() {
return respMsg;
}
}
4.测试效果
编写controller层代码测试代码相关效果
package com.study.res.controller;
import com.study.res.comm.BaseResponse;
import com.study.res.enums.ErrorEnum;
import com.study.res.exception.WebException;
import com.study.res.pojo.User;
import org.springframework.web.bind.annotation.*;
/**
* @ClassName UserController
* @Author swj
* @Date 2020/10/10 10:08
*/
@RestController
@RequestMapping("/test")
public class UserController {
@GetMapping(value = "/exception")
public BaseResponse get(@RequestParam Integer flag) throws WebException{
if (flag == 0){
throw new WebException("my test");
}else if(flag == 1){
return BaseResponse.retOk();
} else if(flag ==2){
User u = new User();
u.setPassword("swj");
u.setUserName("swj");
return BaseResponse.retOk(u);
}else {
return BaseResponse.retFail(ErrorEnum.DUPLICATE_USER_CODE);
}
}
@PostMapping(value = "/test")
public BaseResponse get(@RequestBody User user) throws WebException{
//假设项目中出现异常,解决相关异常的同时,抛出自己定义的异常
try{
System.out.println(user.toString());
}catch (Exception e){
throw new WebException(e.toString());
}
return BaseResponse.retOk();
}
}
测试结果:
正确结果
错误结果:
异常结果:
路漫漫其修远兮,吾将上下而求索