SpringBoot Map参数校验 自定义异常返回自定义JSON错误&自定义错误注解

lan最近一直在做前后端分离的项目,前端提交的参数很多,用Bean来接前端还要写每个Bean的前缀,索性就直接传参了。我们在controller用一个Map接参。

我看网上很少关于Map接参校验的,我就直接贴代码了。

1、首先是自定义一个异常类

package com.test.validator.exception;

/**
 * @author MrWang
 * @version v1.0
 * @date 2019/02/20
 * @Description
 * 自定义异常
 */
public class TestException extends RuntimeException{
    private String code;
    private String msg;
    private Object data;

    public TestException(String code, String msg, Object data) {
        this.code = code;
        this.msg = msg;
        this.data = data;
    }

    public String getCode() {
        return code;
    }

    public String getMsg() {
        return msg;
    }

    public Object getData() {
        return data;
    }
}

首先这个类必须继承RuntimeException,其次定义你想往前端返回的统一格式。生成构造函数和getset方法。

2、创建全局捕捉异常类

package com.test.validator.exception;

import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;

import java.util.HashMap;
import java.util.Map;

/**
 * @author MrWang
 * @version v1.0
 * @date 2019/02/20
 * @Description
 * 全局捕捉异常处理类
 * @ControllerAdvice注解可以加参数basePackages:指定捕捉异常的包范围
 */
@ControllerAdvice
public class TestControllerAdvice {
    /**
     * 自定义异常处理
     * @param ex
     * @return
     */
    @ResponseBody
    @ExceptionHandler(value = TestException.class)
    public Map myErrorHandler(TestException ex) {
        Map map = new HashMap(3);
        map.put("code", ex.getCode());
        map.put("message", ex.getMsg());
        map.put("data",ex.getData());
        return map;
    }
}

这个类的作用就是捕捉全局异常 然后向前端返回错误信息。

3、自定义校验工具类

package com.test.validator.common;

import cn.hutool.core.lang.Validator;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.StrUtil;
import com.test.validator.exception.TestException;

/**
 * @author MrWang
 * @version v1.0
 * @date 2019/02/20
 * @Description
 * 自定义校验工具类
 */
public class FieldUtils {

    /**
     * 字符串非空校验
     * @param filed 要校验的字段
     * @param message message
     * @param code code
     * @param data data
     */
    public static void stringIsNullCheck(String filed,String message,String code,Object data){
        if (StrUtil.isBlank(filed)){
            throw new TestException(code,message,data);
        }
    }

    /**
     * 数字校验
     * @param filed 要校验的字段
     * @param message message
     * @param code code
     * @param data data
     */
    public static void isNumberCheck(String filed,String message,String code,Object data){
        if (!NumberUtil.isNumber(filed)){
            throw new TestException(code,message,data);
        }
    }

    /**
     * 整数校验
     * @param filed 要校验的字段
     * @param message message
     * @param code code
     * @param data data
     */
    public static void isIntCheck(String filed,String message,String code,Object data){
        if (!NumberUtil.isInteger(filed)){
            throw new TestException(code,message,data);
        }
    }

    /**
     * 邮件校验
     * @param filed 要校验的字段
     * @param message message
     * @param code code
     * @param data data
     */
    public static void isEmailCheck(String filed,String message,String code,Object data){
        if (!Validator.isEmail(filed)){
            throw new TestException(code,message,data);
        }
    }

    /**
     * 手机号校验
     * @param filed 要校验的字段
     * @param message message
     * @param code code
     * @param data data
     */
    public static void isMobileCheck(String filed,String message,String code,Object data){
        if (!Validator.isMobile(filed)){
            throw new TestException(code,message,data);
        }
    }
}

因为是一个测试的小demo,所以就写了几个校验,可以模仿以上的写法往上加。

5、校验层代码

package com.test.validator.service.impl;

import com.test.validator.common.FieldUtils;
import com.test.validator.service.TestService;
import org.springframework.stereotype.Service;

import java.util.Map;

/**
 * @author MrWang
 * @version v1.0
 * @date 2019/02/20
 * @Description
 */
@Service
public class TestServiceImpl implements TestService {
    private static final String CODE = "Y50000";

    @Override
    public Map post(Map<String,String> record) {
        FieldUtils.stringIsNullCheck(record.get("username"),"用户名不能为空",CODE,"");
        FieldUtils.stringIsNullCheck(record.get("password"),"密码不能为空",CODE,"");
        FieldUtils.stringIsNullCheck(record.get("sex"),"性别不能为空",CODE,"");
        FieldUtils.isNumberCheck(record.get("age"),"输入的年龄不合法",CODE,"");
        FieldUtils.isIntCheck(record.get("age2"),"请输入整数",CODE,"");
        FieldUtils.isEmailCheck(record.get("email"),"请输入正确的邮件",CODE,"");
        FieldUtils.isMobileCheck(record.get("mobile"),"请输入正确的手机号",CODE,"");
        //dao逻辑操作
        return record;
    }
}

我们一般都是在service层进行字段校验,可见我们从Map中取出参数后挨个校验参数,如有异常,直接抛掉。是不是比以前的校验清晰多了。

6、实践

我们使用postman对这些参数进行测试校验

 

工具类使用的hutool特别好用,给大家安利一下。这是官网

源码地址

GitHub:https://github.com/chuanzige/springboot_validator

码云:https://gitee.com/QingJiaoWoChuanZiGe/springboot_validator

 

 

2021/01/05更新

结合springboot自定义非空注解 注解类

/**
 * @author whc
 * @version v1.0
 * @date 2020/9/15
 * @Description 字段判空注解
 */

@Target({ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
public @interface FieldsRequire {

    /**
     * 默认 ""
     */
    String message() default "";
}

拦截器类  ServiceException可以参考上边TestException

/**
 * @author whc
 * @version v1.0
 * @date 2020/9/15
 * @Description 拦截@FieldsRequire注解的必填字段校验拦截器
 */

public class FieldsRequireInterceptor implements HandlerInterceptor {

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        if (!(handler instanceof HandlerMethod)) {
            return true;
        }
        List<Map<String,String>> paramsList = getParamsName((HandlerMethod) handler);
        for (Map<String,String> result:paramsList){
            String parameter = request.getParameter(result.get("parameter"));
            if (StrKit.isBlank(parameter)){
                //如果注解没有写message 则以字段名为提示
                throw new ServiceException(ResponseUtil.ERROR_CODE,StrKit.notBlank(result.get("message"))?result.get("message"):result.get("parameter")+"不能为空",null);
            }
        }
        return true;
    }

    /**
     * 获取使用了该注解的参数名称
     */
    private List<Map<String,String>> getParamsName(HandlerMethod handlerMethod) {
        Parameter[] parameters = handlerMethod.getMethod().getParameters();
        List<Map<String,String>> list = new ArrayList<>();
        for (Parameter parameter : parameters) {
            //判断这个参数时候被加入了FieldsRequire的注解
            if(parameter.isAnnotationPresent(FieldsRequire.class)){
                FieldsRequire annotation = parameter.getAnnotation(FieldsRequire.class);
                annotation.message();
                Map<String,String> result = new HashMap<>(8);
                result.put("parameter",parameter.getName());
                result.put("message",annotation.message());
                list.add(result);
            }
        }
        return list;
    }

}

controller层调用即可 

    /**
     *
     * @param code 
     * @return Map<String, Object>
     * @author whc
     */
    @RequestMapping("/login")
    public Map<String, Object> wxLogin(@FieldsRequire(message = "code不能为空") String code) {
        return appletService.wxLogin(code);
    }

 

记得把拦截器注入到配置中哦

  • 3
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
您可以在接口方法的入参前使用`@RequestBody`注解将请求参数绑定到一个对象上,然后在该对象上定义校验规则。当请求参数格式不正确时,Spring会自动抛出`MethodArgumentNotValidException`异常。您可以通过自定义异常处理器来捕获该异常返回相应的错误信息。 以下是一个示例代码: 首先,创建一个用于校验参数对象,例如: ```java public class MyRequest { @NotBlank(message = &quot;参数不能为空&quot;) private String param1; // 其他参数校验规则 // ... // Getter和Setter方法 } ``` 在您的接口方法中使用`@Validated`注解,并将请求参数绑定到上述对象: ```java @PostMapping(&quot;/your-api-endpoint&quot;) public ResponseEntity&lt;?&gt; yourApiMethod(@Validated @RequestBody MyRequest request) { // 参数校验成功,继续处理业务逻辑 // ... return ResponseEntity.ok(&quot;Success&quot;); } ``` 接下来,创建一个全局异常处理器来处理校验失败的情况: ```java @ControllerAdvice public class GlobalExceptionHandler { @ExceptionHandler(MethodArgumentNotValidException.class) public ResponseEntity&lt;?&gt; handleValidationExceptions(MethodArgumentNotValidException ex) { List&lt;String&gt; errors = ex.getBindingResult() .getAllErrors() .stream() .map(DefaultMessageSourceResolvable::getDefaultMessage) .collect(Collectors.toList()); return ResponseEntity.badRequest().body(errors); } } ``` 当请求参数不符合校验规则时,将会返回一个包含错误信息的响应体。 请注意,上述示例使用了`@NotBlank`注解校验参数是否为空。您还可以使用其他注解,如`@NotNull`、`@Min`、`@Max`等来定义更多的校验规则。另外,您还可以自定义校验注解和对应的校验器来实现更复杂的参数校验逻辑。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值