java项目流程

项目框架

参数校验

why

在日常的接口开发中,为了防止非法参数对业务造成影响,经常需要对接口的参数做校验

what

springboot validator参数校验遵循jsr-303规范(java specification requests)

example

@Data
public class NestClass {
    private String name;

    @NotNull(message = "参数不能为空")
    @Valid
    private Company company;

    @Min(value = 5,message = "男性每天工作不得低于5小时",groups = Male.class)
    @Min(value = 10,message = "女性每天工作不得低于10小时",groups = Female.class)
    private Integer workTime;

    @Data
    public static class Company{
        @Min(value = 10,message = "年龄最小不能小于10岁")
        private Integer age;
    }
    public interface Male{}

    public interface Female{}
}
@LogAspect
@PostMapping("nested")
@CosmoController
public String selectNested(@RequestBody @Validated(NestClass.Male.class) NestClass nestClass){
    log.info("com.example.demo.controller-->getNested::nestClass = [{}]",nestClass);
    return "1234";

}

这个例子中包含普通、分组、嵌套校验。

分组校验

使用场景:同一个对象在不同场景的需求不同。

workTime字段根据male和female进行了不同的要求,可以通过male和female类根据场景进行应用。

嵌套校验

当对象中还包含对象时对内部对象进行使用,上述例子中对NestClass对象中的Company对象的age字段进行校验

异常处理

全局异常处理,异常情况被拦截,给予特殊响应封装

@RestControllerAdvice
@Slf4j
@CosmoController
public class GlobalExceptionHandler {

    @ExceptionHandler(ConstraintViolationException.class)
    public BaseResult getConstraintViolationException(ConstraintViolationException e){
        log.info("com.example.demo.exception-->getConstraintViolationException::e = [{}]",e.getMessage());
        return new BaseResult(ResultEnum.ARGUMENTS_NOT_VALIDATE,e.getMessage());
    }


    /**
    **@author xuweiqiang
    *@time 2023/3/15 16:52
    *校验异常进入此方法
    **/
    @ExceptionHandler(MethodArgumentNotValidException.class)
    public BaseResult getMethodArgumentNotValidException(MethodArgumentNotValidException e){
        log.info("com.example.demo.exception-->getMethodArgumentNotValidException::e = [{}]",e.getMessage());
        BindingResult bindingResult = e.getBindingResult();
        List<ObjectError> allErrors = bindingResult.getAllErrors();
        log.info("allErrors:{}",allErrors);
        StringBuffer stringBuffer = new StringBuffer();
        allErrors.forEach(error -> stringBuffer.append(error.getDefaultMessage()));
        return new BaseResult(ResultEnum.ARGUMENTS_NOT_VALIDATE,stringBuffer);
    }
    @ExceptionHandler(BindingException.class)
    public BaseResult getBindException(BindingException e){
        log.info("com.example.demo.exception-->getBindException::e = [{}]",e);
        return new BaseResult(ResultEnum.ARGUMENTS_NOT_VALIDATE,e.getMessage());
    }

    @ExceptionHandler(BusinessException.class)
    public BaseResult getBusinessException(BusinessException e){
        log.info("进入BusinessException的异常处理页面,BusinessException:{}",e.getMessage());
        return BaseResult.failure(e.getErrorMessage(),e.getErrorCode());
    }

    @ExceptionHandler(Exception.class)
    public BaseResult getException(Exception e){
        log.info("进入Exception的异常处理页面,exception:{}",e.getMessage());
        return BaseResult.failure(ResultEnum.SERVER_ERROR,e.getMessage());
    }

    /**
     * 后端无法正常解析前端传来的json
     * @param e
     * @return
     */
    @ExceptionHandler(HttpMessageNotReadableException.class)
    public BaseResult getHttpMessageNotReadableException(HttpMessageNotReadableException e){
        log.info("com.example.demo.exception-->getHttpMessageNotReadableException::e = [{}]",e);
        return BaseResult.failure(ResultEnum.HTTP_MESSAGE_NOT_READABLE,e.getMessage());
    }

}

响应封装

正常响应的封装,通过support方法可以指定哪类接口要进行封装。

响应封装的逻辑,异常处理页面的方法直接返回,正常页面的响应封装一层。

@RestControllerAdvice
@Slf4j
public class ResponseInterceptorHandler implements ResponseBodyAdvice {
    @Override
    public boolean supports(MethodParameter returnType, Class converterType) {
        log.info("进入supports方法");
        boolean annotationPresent = returnType.getMethod().isAnnotationPresent(CosmoController.class) || returnType.getDeclaringClass().isAnnotationPresent(CosmoController.class);
        return annotationPresent;
    }

    @Override
    public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType, Class selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) {
        log.info("进入beforeBodyWrite方法");
        log.info("body的内容为:{}",body);

        //如果是BaseResult类,应该就是进入异常处理页面,被封装处理过,所以异常处理页面可以直接返回
        if(body instanceof BaseResult){
            return body;
        }
        //String类型一定要序列化才能返回,不然报错
        if(body instanceof String){
            return FastJsonUtils.bean2Json(BaseResult.success((String)body));

        }
        //正常结果,封装一层返回
        return BaseResult.success(body);
    }
}

总结

前端数据以json方式进入后端,后端首先对参数进行校验,校验成功进入代码逻辑,最后将结果进行封装响应。中途出现任何异常都会被全局异常处理拦截。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值