003-maven开发Java脚手架archrtype-技术点说明

一、概述

二、技术点说明

2.1、springboot与mybatisplus整合

  【代码生成器、分页、逻辑删除】参看 代码

2.2、log4j2整合

  参看 代码

2.3、统一响应【统一异常处理】

1、设置统一响应输出类 BaseResponse

package com.aaa.test.response;

import com.aaa.test.enums.ErrorCodeEnum;

/**
 * 统一返回结果
 */
public class BaseResponse<T> {
    /**
     * 返回的data
     * */
    private T data;

    /**
     * 错误码
     * */
    private Integer errorCode;

    /**
     * 错误信息
     * */
    private String errorMsg;

    /**
     * 是否成功
     * */
    private boolean success = false;

    /**
     * 出现异常的构造函数
     * */
    public BaseResponse(ErrorCodeEnum errorCodeEnum) {
        this.errorCode = errorCodeEnum.getErrorCode();
        this.errorMsg = errorCodeEnum.getErrorMsg();
    }

    /**
     * 成功返回的结果
     * */
    public BaseResponse(T data) {
        success = true;
        this.data = data;
    }

    /**
     * 成功返回的结果
     * */
    public BaseResponse(boolean success,ErrorCodeEnum errorCodeEnum,T data) {
        this.success = success;
        this.data = data;
        this.errorCode = errorCodeEnum.getErrorCode();
        this.errorMsg = errorCodeEnum.getErrorMsg();
    }

    public static <T> BaseResponse success(T data) {
        return new BaseResponse(data);
    }
    public static <T> BaseResponse success(ErrorCodeEnum errorCodeEnum) {
        return new BaseResponse(true,errorCodeEnum,null);
    }

    public static BaseResponse fail(ErrorCodeEnum errorCodeEnum) {
        return new BaseResponse(errorCodeEnum);
    }


    public static BaseResponse fail() {
        return new BaseResponse(ErrorCodeEnum.result_exception);
    }

    public T getData() {
        return data;
    }

    public void setData(T data) {
        this.data = data;
    }

    public Integer getErrorCode() {
        return errorCode;
    }

    public void setErrorCode(Integer errorCode) {
        this.errorCode = errorCode;
    }

    public String getErrorMsg() {
        return errorMsg;
    }

    public void setErrorMsg(String errorMsg) {
        this.errorMsg = errorMsg;
    }

    public boolean isSuccess() {
        return success;
    }

    public void setSuccess(boolean success) {
        this.success = success;
    }

    @Override
    public String toString() {
        return "BaseResponse{" +
                "data=" + data +
                ", errorCode='" + errorCode + '\'' +
                ", errorMsg='" + errorMsg + '\'' +
                ", success=" + success +
                '}';
    }
}
View Code

其中用到了错误码 ErrorCodeEnum

package com.aaa.test.enums;

/**
 * 错误代码枚举类
 */
public enum ErrorCodeEnum {
    // 成功类响应
    success(200000, "成功"),
    no_response_data(200001, "没有返回数据"),

    //请求类响应码
    Param_does_not_exist(400001, "查找参数不存在"),
    Param_does_not_correct(400002, "所传参数格式不正确"),
    HttpMediaTypeNotSupportedException(400003, "不支持的Content-type类型"),

    result_exception(600000, "待处理服务端异常"),

    ;

    ErrorCodeEnum(Integer errorCode, String errorMsg) {
        this.errorCode = errorCode;
        this.errorMsg = errorMsg;
    }

    /**
     * 错误码
     */
    private Integer errorCode;

    /**
     * 错误信息
     */
    private String errorMsg;

    public Integer getErrorCode() {
        return errorCode;
    }

    public void setErrorCode(Integer errorCode) {
        this.errorCode = errorCode;
    }

    public String getErrorMsg() {
        return errorMsg;
    }

    public void setErrorMsg(String errorMsg) {
        this.errorMsg = errorMsg;
    }
}
View Code

技术需求

  1、统一响应类支持静态的成功失败方法

  2、错误码,设计应为6位数值类型,其中200000 类别为成功类型,400000为请求类型码,500000为服务端异常,其他大于 600000码为客户自定义码, 

2、Controller编写

  支持controller多种响应参数

    常见类型String,int,Integer、Map、Object、单个类等

    支持使用上述:BaseResponse 包装响应类

    支持使用:ResponseEntity接收类型

  通过统一响应处理返回统一:BaseResponse格式

3、统一响应处理方案 

  编写RestControllerAdvice,对响应,以及异常统一处理

/**
 * 统一返回结果异常处理类
 */
@RestControllerAdvice
public class ResponseResultBodyAdvice implements ResponseBodyAdvice<Object> {
    private final Logger log = LoggerFactory.getLogger(ResponseResultBodyAdvice.class);
    private static final Class<? extends Annotation> ANNOTATION_TYPE = ResponseBody.class;

    /**
     * 判断类或者方法是否使用了 @ResponseResultBody
     */
    @Override
    public boolean supports(MethodParameter returnType, Class<? extends HttpMessageConverter<?>> converterType) {
        return AnnotatedElementUtils.hasAnnotation(returnType.getContainingClass(), ANNOTATION_TYPE) || returnType.hasMethodAnnotation(ANNOTATION_TYPE);
    }

    /**
     * 当类或者方法使用了 @ResponseResultBody 就会调用这个方法
     */
    @Override
    public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType, Class<? extends HttpMessageConverter<?>> selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) {
        // 避免已经返回基础类型 多次转换
        if (body instanceof BaseResponse) {
            return body;
        }
        return BaseResponse.success(body);
    }

    /**
     * 提供对标准Spring MVC异常的处理
     *
     * @param ex      the target exception
     * @param request the current request
     */
    @ExceptionHandler(Exception.class)
    public final ResponseEntity<BaseResponse<?>> exceptionHandler(Exception ex, WebRequest request) {
        log.error("ExceptionHandler: {}", ex.getMessage());
        HttpHeaders headers = new HttpHeaders();
        if (ex instanceof HttpMediaTypeNotSupportedException) {
            // 针对 返回String 类型 需要客户端设置Content-type 为application/json
            return this.handleResultException(new ResultException(ErrorCodeEnum.HttpMediaTypeNotSupportedException),
                    headers, request);
        } else if (ex instanceof ResultException) {
            return this.handleResultException((ResultException) ex, headers, request);
        }
        //TODO: 这里可以自定义其他的异常拦截
        return this.handleException(ex, headers, request);
    }

    /**
     * 对ResultException类返回返回结果的处理
     */
    protected ResponseEntity<BaseResponse<?>> handleResultException(ResultException ex, HttpHeaders headers, WebRequest request) {
        BaseResponse<?> body = BaseResponse.fail((ex.getErrorCodeEnum()));
        HttpStatus status = null;
        if (ex.getErrorCodeEnum().getErrorCode().intValue() >= 500000) {
            status = HttpStatus.INTERNAL_SERVER_ERROR;
        } else if (ex.getErrorCodeEnum().getErrorCode().intValue() >= 400000) {
            status = HttpStatus.BAD_REQUEST;
        }
        return this.handleExceptionInternal(ex, body, headers, status, request);
    }

    /**
     * 异常类的统一处理
     */
    protected ResponseEntity<BaseResponse<?>> handleException(Exception ex, HttpHeaders headers, WebRequest request) {
        BaseResponse<?> body = BaseResponse.fail();
        HttpStatus status = HttpStatus.INTERNAL_SERVER_ERROR;
        return this.handleExceptionInternal(ex, body, headers, status, request);
    }

    /**
     * org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler
     * handleExceptionInternal(java.lang.Exception, java.lang.Object, org.springframework.http.HttpHeaders,
     * org.springframework.http.HttpStatus, org.springframework.web.context.request.WebRequest)
     * <p>
     * A single place to customize the response body of all exception types.
     * <p>The default implementation sets the {@link WebUtils#ERROR_EXCEPTION_ATTRIBUTE}
     * request attribute and creates a {@link ResponseEntity} from the given
     * body, headers, and status.
     */
    protected ResponseEntity<BaseResponse<?>> handleExceptionInternal(
            Exception ex, BaseResponse<?> body, HttpHeaders headers, HttpStatus status, WebRequest request) {
        if (HttpStatus.INTERNAL_SERVER_ERROR.equals(status)) {
            request.setAttribute(WebUtils.ERROR_EXCEPTION_ATTRIBUTE, ex, WebRequest.SCOPE_REQUEST);
        }
        return new ResponseEntity<>(body, headers, status);
    }
}
View Code

  上述在返回String类型,以及Object等类型或者为空时会出现类型转换异常。做以下处理:

  1、配置WebMvcConfigurer,将 MappingJackson2HttpMessageConverter

/旧版本 WebMvcConfigurerAdapter  spring5弃用了 WebMvcConfigurerAdapter
@Configuration
public class WebMvcConfig  implements WebMvcConfigurer {
    @Override
    public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
        //提到最前面 ,主要为了处理基础类型时 XXX not cast String type 类似问题,结合请求类型必须为application/json
        // 提前使用MappingJackson2HttpMessageConverter 处理 避免使用 StringHttpMessageConverter处理 String类型
        converters.add(0,new MappingJackson2HttpMessageConverter());
    }
}
View Code

    主要作用://提到最前面 ,主要为了处理基础类型时 XXX not cast String type 类似问题,结合请求类型必须为application/json

        // 提前使用MappingJackson2HttpMessageConverter 处理 避免使用 StringHttpMessageConverter处理 String类型

  2、编写controller级别aop,主要作用处理,对象为null,以及String为null,转换为BaseResponse时的类型转换异常

/**
 * 统一结果处理切面, 注意返回时 null 时候 处理
 */
@Aspect
@Component
public class ResponseAspect {
    @Around("execution(* com.aaa.test.controller..*(..))")
    public Object controllerProcess(ProceedingJoinPoint pjd) throws Throwable {
        Object result = pjd.proceed();
        // 是null特殊处理
        if (result == null) {
            try {
                MethodSignature signature = (MethodSignature) pjd.getSignature();
                Class returnType = signature.getReturnType();
                if("java.lang.Object".equals(returnType.getName())){
                    // object 使用此方式
                    return BaseResponse.success(result);
                }else if("java.lang.String".equals(returnType.getName())){
                    // 字符串 初始化一个新的返回
                    return returnType.newInstance();
                }
                //其他默认 返回
                return result;
            }catch (Exception ex){
                ex.printStackTrace();
            }
        }
        return result;
    }
}
View Code

猜你喜欢

转载自www.cnblogs.com/bjlhx/p/11780672.html