基于Springboot搭建java项目(七)——请求的传参和注意事项

以下的传参方式只针对post传参进行分析,put和delete的传参方式可以参考post请求,get请求的传参就是接在URL后面,下面几种方式接收参数对get请求来说都是一样的。

1、直接用属性接收参数

    @RequestMapping("/ginseng")
    public void login1(@RequestParam(value = "name" , required = false,defaultValue = "zhangsan",name = "name") String userName ,String passWord) {
        log.info("传参结果" + userName + passWord);
    }

@RequestMapping可以接收GET,POST,PUT,DELETE请求

1.1、@RequestParam的使用

valuename:这两个属性是针对传参的参数设置别名,这两个属性只要设置一个就行,效果是等效的。

required:传参的必须性,默认为true,必传,如果没有传这个参数就会报Required request parameter ‘name’ for method parameter type String is not present的错误

defaultValue:设置默认的值,设置默认值之后,required为false时不传参也不会报错

不使用@RequestParam注解:类似于passWord的传参,为非必传参数,默认值为null,参数名为属性名(passWord)

1.2、Post请求的传参方式

针对直接用属性来接收参数的情况GET请求只需注意传参的key和接收参数的别名保持一致即可

Post请求常见的传参方式接受 form-data和x-www-for-urlencoded的传参方式,注意传参的key和接收参数的别名保持一致。

2、用对象接受参数

package com.it520.bookkeepingweb.request;
import lombok.Data;
@Data
public class LoginRequest {
    /**
     * 用户名
     */
    private String userName;
    /**
     * 密码
     */
    private String passWord;

}

    @RequestMapping("/ginseng")
    public void login1(LoginRequest request) {
        log.info("传参结果" + request.toString());
    }

针对直接用属性来接收参数的情况GET请求只需注意传参的key和接收参数的别名保持一致即可

Post请求常见的传参方式接受 form-data和x-www-for-urlencoded的传参方式,注意传参的key和接收参数的别名保持一致。

3、@RequestBody对象接受参数

   @RequestMapping("/ginseng")
    public void login1(@RequestBody LoginRequest request) {
        log.info("传参结果" + request.toString());
    }

在接受参数的对象前面加上了@RequestBody的注解,就能够使POST请求的传参方式支持JSON格式的传参,这种方式也是POST请求最推荐的传参方式。

4、@Vaild数据校验

4.1、@Vaild的依赖

首先,我们在 Maven 配置中引入 @valid 的依赖:

如果你是 springboot 项目,那么可以不用引入了,已经引入了,他就存在于最核心的 web 开发包里面。

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
    <version>2.0.5.RELEASE</version>
</dependency>

如果你不是 springboot 项目,那么引入下面依赖即可:

<dependency>
    <groupId>javax.validation</groupId>
    <artifactId>validation-api</artifactId>
    <version>1.1.0.Final</version>
</dependency>
<dependency>
    <groupId>org.hibernate</groupId>
    <artifactId>hibernate-validator</artifactId>
    <version>5.4.1.Final</version>
</dependency>
4.2、@Vaild的使用

第一步,在controller类接收参数的对象前面加上@Vaild的注解

    @RequestMapping("/ginseng")
    public void login1(@Valid LoginRequest request) {
        log.info("传参结果" + request.toString());
    }

第二步,在接收请求的类的属性上添加注解

package com.it520.bookkeepingweb.request;
import lombok.Data;

import javax.validation.constraints.NotNull;

@Data
public class LoginRequest {
    /**
     * 用户名
     */
    @NotNull(message = "用户名不能为null")
    private String userName;
    /**
     * 密码
     */
    private String passWord;
}

@Null
限制只能为null

@NotNull
限制必须不为null

@AssertFalse
限制必须为false

@AssertTrue
限制必须为true

@DecimalMax(value)
限制必须为一个不大于指定值的数字

@DecimalMin(value)
限制必须为一个不小于指定值的数字

@Digits(integer,fraction)
限制必须为一个小数,且整数部分的位数不能超过integer,小数部分的位数不能超过fraction

@Future
限制必须是一个将来的日期

@Max(value)
限制必须为一个不大于指定值的数字

@Min(value)
限制必须为一个不小于指定值的数字

@Past
限制必须是一个过去的日期

@Pattern(value)
限制必须符合指定的正则表达式

@Size(max,min)
限制字符长度必须在min到max之间

@Past
验证注解的元素值(日期类型)比当前时间早

@NotEmpty
验证注解的元素值不为null且不为空(字符串长度不为0、集合大小不为0)

@NotBlank
验证注解的元素值不为空(不为null、去除首位空格后长度为0),不同于@NotEmpty,@NotBlank只应用于字符串且在比较时会去除字符串的空格

@Email
验证注解的元素值是Email,也可以通过正则表达式和flag指定自定义的email格式

注意,不要错用了异常类型,比如在int上不可用@size

4.3、全局异常处理

全局异常处理能够对自定义的错误能够体现在返回结果中

第一步:自定义返回结果的封装类

package com.it520.bookkeepingweb.web.result;

import com.it520.bookkeepingcommon.constant.ErrorCodeEnum;
import lombok.Data;

@Data
public class BaseResult {

    private Integer errorCode = 0;

    private String errorMessage = "success";

    private Object data;

    public BaseResult() {
    }

    //自定义报错信息
    public BaseResult (Integer errorCode , String errorMessage){
        this.errorCode = errorCode;
        this.errorMessage = errorMessage;
    }

    //从枚举中获取报错信息
    public BaseResult (ErrorCodeEnum errorCodeEnum){
        this.errorCode = errorCodeEnum.getErrorCode();
        this.errorMessage = errorCodeEnum.getChErrorMessage();
    }

    public void packageErrorMessage(ErrorCodeEnum errorCodeEnum){
        this.errorCode = errorCodeEnum.getErrorCode();
        this.errorMessage = errorCodeEnum.getChErrorMessage();
    }
}

自定义错误枚举

package com.it520.bookkeepingcommon.constant;

public enum ErrorCodeEnum {
    ERRORCODE000(0 , "成功" ,"success"),
    ERRORCODE001(1 , "登陆失败" ,"login fail"),
    ERRORCODE002(2 , "参数异常" ,"ill param")
    ;
    private final Integer errorCode;
    private final String chErrorMessage;
    private final String enErrorMessage;

    ErrorCodeEnum(Integer errorCode, String errorChMessage, String errorZhMessage) {
        this.errorCode = errorCode;
        this.chErrorMessage = errorChMessage;
        this.enErrorMessage = errorZhMessage;
    }

    public Integer getErrorCode() {
        return errorCode;
    }

    public String getChErrorMessage() {
        return chErrorMessage;
    }

    public String getEnErrorMessage() {
        return enErrorMessage;
    }
}

自定义异常处理器

package com.it520.bookkeepingweb.config;


import com.it520.bookkeepingcommon.constant.ErrorCodeEnum;
import com.it520.bookkeepingweb.web.result.BaseResult;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.validation.BindException;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.validation.ObjectError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.MissingServletRequestParameterException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;

import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;
import java.util.List;
import java.util.Set;

@Slf4j
@RestControllerAdvice
public class GlobalExceptionHandler {

    /**
     * 忽略参数异常处理器
     *
     * @param e 忽略参数异常
     * @return ResponseResult
     */
    @ExceptionHandler(value = MissingServletRequestParameterException.class)
    public BaseResult parameterMissingExceptionHandler(MissingServletRequestParameterException e) {
        log.error("", e);
        return new BaseResult(ErrorCodeEnum.ERRORCODE002.getErrorCode(), "请求参数 " + e.getParameterName() + " 不能为空");
    }

    /**
     * 缺少请求体异常处理器
     *
     * @param e 缺少请求体异常
     * @return ResponseResult
     */
    @ExceptionHandler(value = HttpMessageNotReadableException.class)
    public BaseResult parameterBodyMissingExceptionHandler(HttpMessageNotReadableException e) {
        log.error("", e);
        return new BaseResult(ErrorCodeEnum.ERRORCODE002.getErrorCode(), "参数体不能为空");
    }

    /**
     * 参数效验异常处理器
     *
     * @param e 参数验证异常
     * @return BaseResult
     */
    @ExceptionHandler(value =MethodArgumentNotValidException.class)
    public BaseResult parameterExceptionHandler(MethodArgumentNotValidException e) {
        log.error("", e);
        // 获取异常信息
        BindingResult exceptions = e.getBindingResult();
        // 判断异常中是否有错误信息,如果存在就使用异常中的消息,否则使用默认消息
        if (exceptions.hasErrors()) {
            List<ObjectError> errors = exceptions.getAllErrors();
            if (!errors.isEmpty()) {
                // 这里列出了全部错误参数,按正常逻辑,只需要第一条错误即可
                FieldError fieldError = (FieldError) errors.get(0);
                return new BaseResult(ErrorCodeEnum.ERRORCODE002.getErrorCode(), fieldError.getDefaultMessage());
            }
        }
        return new BaseResult(ErrorCodeEnum.ERRORCODE002);

    }

    /**
     * 参数效验异常处理器
     *
     * @param e 参数验证异常
     * @return BaseResult
     */
    @ExceptionHandler(value =BindException.class)
    public BaseResult bindExceptionHandler(BindException e) {
        log.error("", e);
        // 获取异常信息
        StringBuilder errorMsg = new StringBuilder();
        BindingResult exceptions = e.getBindingResult();
        // 判断异常中是否有错误信息,如果存在就使用异常中的消息,否则使用默认消息
        for (FieldError fieldError : exceptions.getFieldErrors()) {
            errorMsg.append("参数:")
                    .append(fieldError.getField())
                    .append("错误:")
                    .append(fieldError.getDefaultMessage())
                    .append(" ");
        }
        return new BaseResult(ErrorCodeEnum.ERRORCODE002.getErrorCode() , errorMsg.toString());
    }

    /**
     * 参数转换异常
     *
     * @param e 参数验证异常
     * @return BaseResult
     */
    @ExceptionHandler(value =ConstraintViolationException.class)
    public BaseResult constraintViolationExceptionHandler(ConstraintViolationException e) {
        log.error("", e);
        // 获取异常信息
        StringBuilder errorMessage = new StringBuilder();
        Set<ConstraintViolation<?>> constraintViolations = e.getConstraintViolations();
        for (ConstraintViolation<?> constraintViolation : constraintViolations) {
            errorMessage.append(constraintViolation.getMessageTemplate()).append("\\n");
        }
        return new BaseResult(ErrorCodeEnum.ERRORCODE002.getErrorCode() , String.valueOf(errorMessage));
    }

    /**
     * 参数转换异常
     *
     * @param e 参数验证异常
     * @return BaseResult
     */
    @ExceptionHandler(value =ClassCastException.class)
    public BaseResult classCastExceptionHandler(ClassCastException e) {
        log.error("", e);
        // 获取异常信息
        String errorMessage = e.getMessage();
        return new BaseResult(ErrorCodeEnum.ERRORCODE002.getErrorCode() , errorMessage);
    }


}

异常处理器常见的三大异常

ConstraintViolationException:不符合验证规则时触发
BindException:使用form data方式调用接口,校验异常抛出 BindException
MethodArgumentNotValidException:使用 json 请求体调用接口,校验异常会抛出此错误
相对于其他的错误,可以从控制台报错的情况中对该错误进行处理,同时也可以使用Exception对其他不想处理的错误进行处理。

当在异常处理器中同时使用了Exception和ConstraintViolationException时,如果验证器触发了ConstraintViolationException,就只会执行ConstraintViolationException所在的处理方法,而不会调用Exception处理方法,所以异常处理器会优先处理已经有所指明的异常,只有在异常处理器中没有对该异常进行声明的情况下才会执行Exception所在的异常处理方法。

对这个有更深的了解可以参考这篇文章https://blog.csdn.net/qq_45515182/article/details/125766858

这篇文章对@Valid的使用以及异常处理做了很好的解答

java实现HTTP接口的各种传参方式的实现可以参考我的文章https://blog.csdn.net/m0_46616045/article/details/126130783

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值