项目父工程及其子模块
版本控制
在父工程的pom中添加版本依赖信息。基础配置,后面会陆续完善
pom.xml<properties> <java.version>11</java.version> <spring.boot.version>2.7.8</spring.boot.version> <reflections.version>0.9.11</reflections.version> <fastjson.version>2.0.32</fastjson.version> <leadnew-common.version>0.0.1-SNAPSHOT</leadnew-common.version> <leadnew-model.version>0.0.1-SNAPSHOT</leadnew-model.version> <spring.cloud.version>Hoxton.SR10</spring.cloud.version> </properties>
<dependencyManagement> <dependencies> <dependency> <groupId>com.swx</groupId> <artifactId>leadnews-common</artifactId> <version>${leadnew-common.version}</version> </dependency> <dependency> <groupId>com.swx</groupId> <artifactId>leadnews-model</artifactId> <version>${leadnew-model.version}</version> </dependency>
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>${spring.cloud.version}</version> <type>pom</type> <scope>import</scope> </dependency> <dependency> <groupId>org.reflections</groupId> <artifactId>reflections</artifactId> <version>${reflections.version}</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> <exclusions> <exclusion> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-logging</artifactId> </exclusion> </exclusions> <version>${spring.boot.version}</version> </dependency> <dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> <version>${fastjson.version}</version> </dependency> </dependencies> </dependencyManagement>
|
异常和返回结果统一处理
添加依赖信息
在leadnews-common
模块中添加如下的依赖信息
pom.xml<dependencies> <dependency> <groupId>com.swx</groupId> <artifactId>leadnews-model</artifactId> </dependency> <dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-api</artifactId> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-simple</artifactId> </dependency> </dependencies>
|
在leadnews-model
模块中添加如下的依赖信息
pom.xml<dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> </dependency>
|
创建实体类和枚举类
在leadnews-model
模块中创建包com.swx.model.common.dto
和com.swx.model.common.enums
创建消息提示枚举
enums.ResultCodeEnumpublic enum ResultCodeEnum {
SUCCESS(20000, "成功"), TOKEN_INVALID(50, "无效TOKEN"), TOKEN_EXPIRE(51, "TOKEN已过期"), TOKEN_REQUIRE(50, "TOKEN是必须的"), SERVER_ERROR(500, "服务器内部错误"), PARAM_REQUIRE(501, "缺少参数"), PARAM_INVALID(502, "无效参数"), PARAM_TIMAGE_FORMAT_ERROR(503, "图片格式有误"), DATA_EXIST(1000, "数据已经存在"), AP_USER_DATA_NOT_EXIST(1001, "ApUser数据不存在"), DATA_NOT_EXIST(1002, "数据不存在"), NO_OPERATOR_AUTH(3000, "无权操作"), NEED_ADMIN(3001, "需要管理员权限");
private Integer code; private String message;
private ResultCodeEnum(Integer code, String message) { this.code = code; this.message = message; }
public Integer code() { return this.code; } public String message() { return this.message; } }
|
创建返回结果实体类
dto.R
@Data public class R implements Serializable {
private static final long serialVersionUID = 1L;
private Integer code;
private String message;
private Object data;
public R() {
}
public R(ResultCodeEnum resultCode, Object data) { this.code = resultCode.code(); this.message = resultCode.message(); this.data = data; }
private void setResultCode(ResultCodeEnum resultCode) { this.code = resultCode.code(); this.message = resultCode.message(); }
public static R success() { R result = new R(); result.setResultCode(ResultCodeEnum.SUCCESS); return result; } public static R success(Object data) { R result = new R(); result.setResultCode(ResultCodeEnum.SUCCESS); result.setData(data); return result; }
public static R fail(Integer code, String message) { R result = new R(); result.setCode(code); result.setMessage(message); return result; } public static R fail(ResultCodeEnum resultCode) { R result = new R(); result.setResultCode(resultCode); return result; } }
|
创建返回分页结果实体类
dto.PageR
@Data public class PageR extends R implements Serializable { private static final long serialVersionUID = 1L;
private Integer current; private Integer size; private Integer total;
public PageR() {
}
public PageR(Integer current, Integer size, Integer total) { this.current = current; this.size = size; this.total = total; } }
|
创建错误结果实体类
dto.ErrorResult
public class ErrorResult {
private Integer code;
private String message;
private String exception;
public Integer getCode() { return code; }
public void setCode(Integer code) { this.code = code; }
public String getMessage() { return message; }
public void setMessage(String message) { this.message = message; }
public String getException() { return exception; }
public void setException(String exception) { this.exception = exception; }
public static ErrorResult fail(ResultCodeEnum resultCode, Throwable e, String message) { ErrorResult errorResult = ErrorResult.fail(resultCode, e); errorResult.setMessage(message); return errorResult; }
public static ErrorResult fail(ResultCodeEnum resultCode, Throwable e) { ErrorResult errorResult = new ErrorResult(); errorResult.setCode(resultCode.code()); errorResult.setMessage(resultCode.message()); errorResult.setException(e.getClass().getName()); return errorResult; } public static ErrorResult fail(Integer code, String message) { ErrorResult errorResult = new ErrorResult(); errorResult.setCode(code); errorResult.setMessage(message); return errorResult; } }
|
创建自定义异常类
dto.BizExceptionpublic class BizException extends RuntimeException {
private Integer code;
private String message;
public BizException() { super(); }
public BizException(ResultCodeEnum resultCode) { super(resultCode.message()); this.code = resultCode.code(); this.message = resultCode.message(); }
public BizException(ResultCodeEnum resultCode, Throwable cause) { super(resultCode.message(), cause); this.code = resultCode.code(); this.message = resultCode.message(); }
public BizException(String message) { super(message); this.code = -1; this.message = message; }
public BizException(Integer code, String message) { super(message); this.code = code; this.message = message; }
public BizException(Integer code, String message, Throwable cause) { super(message, cause); this.code = code; this.message = message; }
@Override public synchronized Throwable fillInStackTrace() { return this; }
public Integer getCode() { return code; }
public void setCode(Integer code) { this.code = code; }
@Override public String getMessage() { return message; }
public void setMessage(String message) { this.message = message; } }
|
创建自定义注解
使用注解的Controller自动统一封装
在leadnews-common
模块中创建com.swx.common.exception
,并在该包下创建annotation
包
创建自定义注解类
annotation.ResponseResult@Retention(RetentionPolicy.RUNTIME) @Target({ ElementType.TYPE, ElementType.METHOD}) @Documented public @interface ResponseResult {
}
|
创建拦截器
在com.swx.common.exception
下创建interceptor
包
拦截器会拦截添加了自定义注解的类或者方法,完成统一封装
interceptor.ResponseResultInterceptor@Component public class ResponseResultInterceptor implements HandlerInterceptor { public static final String RESPONSE_RESULT_ANN = "RESPONSE-RESULT-ANN";
@Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { if (handler instanceof HandlerMethod) { final HandlerMethod handlerMethod = (HandlerMethod) handler; final Class<?> clazz = handlerMethod.getBeanType(); final Method method = handlerMethod.getMethod(); if (clazz.isAnnotationPresent(ResponseResult.class)) { request.setAttribute(RESPONSE_RESULT_ANN, clazz.getAnnotation(ResponseResult.class)); } else if (method.isAnnotationPresent(ResponseResult.class)) { request.setAttribute(RESPONSE_RESULT_ANN, method.getAnnotation(ResponseResult.class)); } } return true; } }
|
注册拦截器
在com.swx.common.exception
下创建config
包
config.WebAppConfig@Configuration public class WebAppConfig implements WebMvcConfigurer {
@Override public void addInterceptors(InterceptorRegistry registry) { ResponseResultInterceptor interceptor = new ResponseResultInterceptor(); registry.addInterceptor(interceptor); WebMvcConfigurer.super.addInterceptors(registry); } }
|
异常和返回值处理类
在com.swx.common.exception
下创建handler
包
创建全局异常处理类
handler.GlobalExceptionHandler
@RestControllerAdvice public class GlobalExceptionHandler { private static final Logger logger = LoggerFactory.getLogger("GlobalExceptionHandler.class");
@ExceptionHandler(BizException.class) public ErrorResult bizExceptionHandler(BizException e, HttpServletRequest request) { logger.error("发生业务异常!原因是: {}", e.getMessage()); return ErrorResult.fail(e.getCode(), e.getMessage()); }
@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR) @ExceptionHandler(Throwable.class) public ErrorResult handlerThrowable(Throwable e, HttpServletRequest request) { logger.error("发生未知异常!原因是: ", e); ErrorResult error = ErrorResult.fail(ResultCodeEnum.SERVER_ERROR, e); return error; }
@ExceptionHandler(BindException.class) public ErrorResult handleBindExcpetion(BindException e, HttpServletRequest request) { logger.error("发生参数校验异常!原因是:",e); ErrorResult error = ErrorResult.fail(ResultCodeEnum.PARAM_INVALID, e, e.getAllErrors().get(0).getDefaultMessage()); return error; }
@ExceptionHandler(MethodArgumentNotValidException.class) public ErrorResult handleMethodArgumentNotValidException(MethodArgumentNotValidException e, HttpServletRequest request) { logger.error("发生参数校验异常!原因是:",e); ErrorResult error = ErrorResult.fail(ResultCodeEnum.PARAM_INVALID,e,e.getBindingResult().getAllErrors().get(0).getDefaultMessage()); return error; } }
|
创建返回值处理类
handler.ResponseResultHandler
@ControllerAdvice public class ResponseResultHandler implements ResponseBodyAdvice<Object> {
public static final String RESPONSE_RESULT_ANN = "RESPONSE-RESULT-ANN";
@Override public boolean supports(MethodParameter arg0, Class<? extends HttpMessageConverter<?>> arg1) { ServletRequestAttributes sra = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes(); HttpServletRequest request = sra.getRequest(); ResponseResult responseResultAnn = (ResponseResult) request.getAttribute(RESPONSE_RESULT_ANN); return responseResultAnn == null ? false : true; }
@Override public Object beforeBodyWrite(Object body, MethodParameter arg1, MediaType arg2, Class<? extends HttpMessageConverter<?>> arg3, ServerHttpRequest arg4, ServerHttpResponse arg5) { if (body instanceof ErrorResult) { ErrorResult error = (ErrorResult) body; return R.fail(error.getCode(), error.getMessage()); } else if (body instanceof R) { return (R) body; } else if (body instanceof String) { return body; } return R.success(body); } }
|
自动装配
在 leadnews-common
模块的resources
包下创建META-INF
目录,目录中创建spring.factories
文件,内容如下,当其他模块引入该模块时,会自动装配指定的类
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ com.swx.common.exception.config.WebAppConfig, \ com.swx.common.exception.handler.GlobalExceptionHandler, \ com.swx.common.exception.handler.ResponseResultHandler
|
测试
在 leadnews-service
模块中添加如下依赖信息
pom.xml<dependencies> <dependency> <groupId>com.swx</groupId> <artifactId>leadnews-common</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> </dependencies>
|
创建com.swx.service
包,并在该包下创建启动类
ServiceApplication@SpringBootApplication public class ServiceApplication { public static void main(String[] args) { SpringApplication.run(ServiceApplication.class, args); } }
|
创建controller
包,并创建测试Controller,内容如下:
controller.TestController@ResponseResult @RestController @RequestMapping("/test") public class TestController {
@GetMapping("") public Map<String, String> test() { HashMap<String, String> data = new HashMap<>(); data.put("data", "01"); return data; } }
|
- 使用了自定义的
@ResponseResult
注解,该类下的方法返回值会被统一处理
使用浏览器访问:http://localhost:8080/test
{"code":20000,"message":"成功","data":{"data":"01"}}
|