GVKun编程网logo

使用spring-validation和@RequestParam(required = false)字符串默认值的校验问题

17

在这篇文章中,我们将为您详细介绍使用spring-validation和@RequestParam(required=false)字符串默认值的校验问题的内容。此外,我们还会涉及一些关于@Cookie

在这篇文章中,我们将为您详细介绍使用spring-validation和@RequestParam(required = false)字符串默认值的校验问题的内容。此外,我们还会涉及一些关于@CookieValue,@PathVariable,@RequestBody,@RequestHeader,@RequestParam、@Param @PathVariable @RequestParam @ResponseBody @RequestBody注解说明、@PathVariable,@RequestParam, @RequestBody,@ModelAttribute,@RequestHeader,@CookieValue的区别、@requestparam (required = false) 的作用?的知识,以帮助您更全面地了解这个主题。

本文目录一览:

使用spring-validation和@RequestParam(required = false)字符串默认值的校验问题

使用spring-validation和@RequestParam(required = false)字符串默认值的校验问题

众所周知,使用@RequestParam(required = false) 封装请求参数的时候,如果客户端不提交参数,或者是只声明参数,并不赋值。那么方法的形参值,默认为null(基本数据类型除外)。

一个Controller方法,有2个参数

@GetMapping
public Object update(@RequestParam(value = "number", required = false) Integer number,
				@RequestParam(value = "phone", required = false) String phone) {
	LOGGER.info("number={}, phone={}", number, phone);
	return Message.success(phone);
}

很简单的一个Controller方法。有两个参数,都不是必须的。只是这俩参数的数据类型不同。

// 都不声明参数
http://localhost:8080/test
日志输出:number=null, phone=null

// 都只声明参数,但是不赋值
http://localhost:8080/test?number=&phone=
日志输出出:number=null, phone=

这里可以看出,String类型的参数。在声明,不赋值的情况下。默认值为空字符串。

使用spring-validation遇到@RequestParam(required = false)字符串参数的问题

一个验证手机号码的注解

极其简单,通过正则验证字符串是否是手机号码

import static java.lang.annotation.RetentionPolicy.RUNTIME;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;

import javax.validation.Constraint;
import javax.validation.Payload;
import javax.validation.ReportAsSingleViolation;
import javax.validation.constraints.Pattern;


@Retention(RUNTIME)
@Target(value = { ElementType.FIELD, ElementType.PARAMETER, ElementType.ANNOTATION_TYPE })
@Constraint(validatedBy = {})
@ReportAsSingleViolation
@Pattern(regexp = "^1[3-9]\\d{9}$")
public @interface Phone {
	String message() default "手机号码不正确,只支持大陆手机号码";
	Class<?>[] groups() default {};
	Class<? extends Payload>[] payload() default {};
}

一般这样使用

private static final Logger LOGGER = LoggerFactory.getLogger(TestController.class);

@GetMapping
public Object update(@RequestParam(value = "number", required = false) Integer number,
				@RequestParam(value = "phone", required = false) @Phone String phone) {
	LOGGER.info("number={}, phone={}", number, phone);
	return Message.success(phone);
}

这是一个修改接口,允许用户修改自己的手机号码,但手机号码并不是必须的,允许以空字符串的形式存储在数据库。通俗的说就是,phone参数,要么是一个合法的手机号码。要么是空字符串,或者null。

客户端发起了请求

// 假如用户什么也不输入,清空了 phone 输入框,客户端js序列化表单后提交。
http://localhost:8080/test?number=&phone=

果然得到了异常:
javax.validation.ConstraintViolationException: update.phone: 手机号码不正确,只支持大陆手机号码

很显然,空字符串 "",并不符合手机号码的正则校验。

这种情况就是,在校验规则,和默认值之间,出现了一点点冲突

解决办法

求前端大哥改巴改巴

提交之前,遍历一下请求参数。把空值参数,从请求体中移除。那么后端接收到的形参就是,null。是业务可以接受的数据类型。

修改验证规则

这个也不算难,自己修改一下验证的正则,或者重新实现一个自定义的 ConstraintValidator,允许手机号码为空字符串。但是,也有一个问题,这个注解就不能用在必填的手机号码参数上了。例如:注册业务,因为它的规则是允许空字符串的。

当然,也可以维护多个不同的验证规则注解。

@Phone 验证必须是标准手机号码
@Retention(RUNTIME)
@Target(value = { ElementType.FIELD, ElementType.PARAMETER, ElementType.ANNOTATION_TYPE })
@Constraint(validatedBy = {})
@ReportAsSingleViolation
@Pattern(regexp = "^1[3-9]\\d{9}$")
public @interface Phone {
	String message() default "手机号码不正确,只支持大陆手机号码";
	Class<?>[] groups() default {};
	Class<? extends Payload>[] payload() default {};
}
@PhoneOrEmpty 可以是空字符串或者标准的手机号码
@Retention(RUNTIME)
@Target(value = { ElementType.FIELD, ElementType.PARAMETER, ElementType.ANNOTATION_TYPE })
@Constraint(validatedBy = {})
@ReportAsSingleViolation
@Pattern(regexp = "^(1[3-9]\\d{9})|(.{0})$")  
public @interface PhoneOrEmpty {
	String message() default "手机号码不正确,只支持大陆手机号码";
	Class<?>[] groups() default {};
	Class<? extends Payload>[] payload() default {};
}

好了,这俩可以用在不同的验证地方。唯一的不同就是验证的正则不同。这也是让我觉得不舒服的地方。需要维护两个正则表达式

一种我认为比较"优雅"的方式

还是一样,定义不同的注解来处理不同的验证场景。但是,我并不选择自立门户(单独维护一个正则),而是在@Phone的基础上,进行一个加强

@Retention(RUNTIME)
@Target(value = { ElementType.FIELD, ElementType.PARAMETER })
@Constraint(validatedBy = {})
@ReportAsSingleViolation

@Phone						// 使用已有的@Phone作为校验规则,参数必须是一个合法的手机号码
@Length(max = 0, min = 0)	// 使用Hiberante提供的字符串长度校验规则,在这里,表示惨参数字符串的长度必须:最短0,最长0(就是空字符串)

@ConstraintComposition(CompositionType.OR)	// 核心的来了,这个注解表示“多个验证注解之间的逻辑关系”,这里使用“or”,满足任意即可
public @interface PhoneOrEmpty {
	String message() default "手机号码不正确,只支持大陆手机号码";
	Class<?>[] groups() default {};
	Class<? extends Payload>[] payload() default {};
}

核心的说明,都在上面的注释代码上了。

自定义使用组合Constraint,在原来@Phone的验证规则上,再添加一个 @Length(max = 0, min = 0)规则。使用@ConstraintComposition描述这两个验证规则的逻辑关系。

ConstraintComposition只有一个枚举属性

@Documented
@Target({ ANNOTATION_TYPE })
@Retention(RUNTIME)
public @interface ConstraintComposition {
	/**
	 * The value of this element specifies the boolean operator,
	 * namely disjunction (OR), negation of the conjunction (ALL_FALSE),
	 * or, the default, simple conjunction (AND).
	 *
	 * @return the {@code CompositionType} value
	 */
	CompositionType value() default AND;
}
public enum CompositionType {
	OR,   // 多个验证规则中,只要有一个通过就算验证成功
	AND,  // 多个验证规则中,必须全部通过才算成功(默认)
	ALL_FALSE // 多个验证规则中,必须全部失败,才算通过(少见)
}

试试看

Controller

@GetMapping
public Object update (@RequestParam(value = "number", required = false) Integer number,
				@RequestParam(value = "phone", required = false) @PhoneOrEmpty String phone) {
	LOGGER.info("number={}, phone={}", number, phone);
	return Message.success(phone);
}

空参数:空字符串,是合法的

合法参数:更是合法

非法参数:验证失败

原文:https://springboot.io/t/topic/2312

@CookieValue,@PathVariable,@RequestBody,@RequestHeader,@RequestParam

@CookieValue,@PathVariable,@RequestBody,@RequestHeader,@RequestParam

原文链接:http://blog.sina.com.cn/s/blog_6d3c1ec601017q4l.html


下列参数一般都和@RequestMapping配合使用。

 

A@CookieValue

org.springframework.web.bind.annotation.CookieValue

public @interface CookieValue

Annotation which indicates that a method parameter should be bound to an HTTP cookie. Supported for annotated handler methods in Servlet and Portlet environments.

这个注释表示一个方法参数绑定到一个HTTP cookie。支持ServletPortlet环境。

The method parameter may be declared as type Cookie or as cookie value type (String,int,etc).

这个方法的参数可声明为Cookie类型或String,int等。

A.1@CookieValue的属性

String value

The name of the cookie to bind to.

绑定的cookie名称。

boolean required

Whether the header is required.

Default is true,leading to an exception being thrown in case the header is missing in the request. Switch this to false if you prefer a null in case of the missing header.

Head是否需要。默认是true,请求中头丢失将抛出一个异常。False,请求中头丢失将返回null

Alternatively,provide a defaultValue,which implicitly sets this flag to false.

因此,提供一个defaultValue

String defaultValue

The default value to use as a fallback. Supplying a default value implicitly sets required() to false.

requiredfalse,请求中头丢失将返回这个值。

B@PathVariable

Annotation which indicates that a method parameter should be bound to a URI template variable. Supported for RequestMapping annotated handler methods in Servlet environments.

    这个参数指出方法的一个参数绑定到一个URI template变量。在Servlet环境中的被@RequestMapping注释的处理器方法。

B.1@PathVariable的属性

value

The URI template variable to bind to.

绑定URI template变量。

举例说明

@Controller

public class HelloWorldController {    @RequestMapping("/helloWorld/{userId}")

public String helloWorld(ModelMap model,@PathVariable("userId") String userId) {

       model.addAttribute("attributeName",userId);

       return "helloWorld";

    }

}

URI template变量和方法的参数名称一样时,可以省略value的定义,@PathVariable达到同样的效果。

 

C@RequestBody

Annotation which indicates that a method parameter should be bound to the web request body. Supported for annotated handler methods in Servlet environments.

这个注释它指示一个方法的参数绑定到一个web请求的body。它支持Servlet环境中的注释处理器方法。

class HelloWorldController {

    "/hello.do")   

    public String helloWorld(Model model,100);font-size:10pt;">@RequestBody String reqBody) {

"message",reqBody);

    }

}

这时这个参数reqBody的值是请求页面的form表单的所有值。

 

D@ RequestHeader

Annotation which indicates that a method parameter should be bound to a web request header. Supported for annotated handler methods in Servlet and Portlet environments.

这个注释它指示一个方法的参数绑定到一个web请求的头信息。它支持ServletPortlet环境中的注释处理器方法。

D.1@ RequestHeader的属性

String defaultValue

The default value to use as a fallback.

默认返回值。

Boolean required

Whether the header is required.

是否需要header

String value

The name of the request header to bind to.

绑定的请求头名称。

@RequestHeader("Accept") String info) {

ottom:5px;border:0px;list-style:none;line-height:21px;color:rgb(70, info);

这时这个参数info将获得请求的Accept头信息。

E@RequestParam

org.springframework.web.bind.annotation.RequestParam

Annotation which indicates that a method parameter should be bound to a web request parameter. Supported for annotated handler methods in Servlet and Portlet environments.

这个参数指出一个方法的参数应绑定到一个web请求的参数。支持ServletPortlet环境下注释处理器的方法。

E.1@RequestParam的属性

E.1.1value

The name of the request parameter to bind to.

绑定的请求参数的名称。

@RequestParam(value="abc")等同于@RequestParam("abc")

E.1.2required

Whether the parameter is required.

是否需要参数。

Default is true,leading to an exception thrown in case of the parameter missing in the request. Switch this to false if you prefer a null in case of the parameter missing.

默认为true,若请求中没有参数会导致抛出一个异常。若设置为false,若请求中没有参数就会返回null

Alternatively,which implicitly sets this flag to false.

required=false时,最好设置一个defaultValue默认值。

@RequestParam(value = "abc",required=false)

E.1.3defaultValue

The default value to use as a fallback. Supplying a default value implicitly sets required() to false.

required=false时,设定默认值。

"/a")

"/b")

ottom:5px;border:0px;list-style:none;line-height:21px;color:rgb(70,@RequestParam("a") String abc) {

ottom:5px;border:0px;list-style:none;line-height:21px;color:rgb(70,abc);

 

F@ResponseBody

Annotation which indicates that a method return value should be bound to the web response body. Supported for annotated handler methods in Servlet environments.

这个注释它指示一个方法的返回值应该绑定到一个web响应的body中。它支持Servlet环境中的注释处理器方法。

应用@ResponseBody将会跳过视图处理,而是调用合适HttpMessageConverter,将返回值写入输出流。

@ResponseBody

public String helloWorld() {

或者这样定义

"/a/b")

public @ResponseBody String helloWorld() {

这时访问/a/b时,不是返回一个view名为helloWorld的视图,而是作出一个响应,其内容为helloWorld


@Param @PathVariable @RequestParam @ResponseBody @RequestBody注解说明

@Param @PathVariable @RequestParam @ResponseBody @RequestBody注解说明

@Param主要是用来注解dao类中方法的参数,在不使用@Param注解的时候,函数的参数只能为一个,并且在查询语句取值时只能用#{},且其所属的类必须为Javabean,而使用@Param注解则可以使用多个参数,在查询语句中使用时可以使用#{}或者${}

 

@PathVariable用于将请求URL中的模板变量映射到功能处理方法的参数上,http://127.0.0.1:8040/findById/1-->>@GetMapping("/findById/{id}")      参数不能为空

 

@RequestParam注解主要有哪些参数:

value:参数名字,即入参的请求参数名字,如username表示请求的参数区中的名字为username的参数的值将传入;

 

required:是否必须,默认是true,表示请求中一定要有相应的参数,否则将报404错误码;

 

defaultValue:默认值,表示如果请求中没有同名参数时的默认值,例如:

 

public List<EasyUITreeNode> getItemTreeNode(@RequestParam(value="id",defaultValue="0")long parentId)

 

@ResponseBody将响应的结果转为json格式

 

@RequestBody将请求参数转为json格式

@PathVariable,@RequestParam, @RequestBody,@ModelAttribute,@RequestHeader,@CookieValue的区别

@PathVariable,@RequestParam, @RequestBody,@ModelAttribute,@RequestHeader,@CookieValue的区别

@RequestMapping(value="/owners/{ownerId}/pets/{petId}/edit", method = RequestMethod.POST)  
public String processSubmit(@ModelAttribute Pet pet) {  
     
}

请求路径上有个id的变量值,可以通过@PathVariable来获取  @RequestMapping(value = "/page/{id}", method = RequestMethod.GET)  
@RequestParam用来获得静态的URL请求入参     spring注解时action里用到。

简介:

handler method 参数绑定常用的注解,我们根据他们处理的Request的不同内容部分分为四类:(主要讲解常用类型)

A、处理requet uri 部分(这里指uri template中variable,不含queryString部分)的注解:   @PathVariable;

B、处理request header部分的注解:   @RequestHeader, @CookieValue;

C、处理request body部分的注解:@RequestParam,  @RequestBody;

D、处理attribute类型是注解: @SessionAttributes, @ModelAttribute;

 

1、 @PathVariable 

当使用@RequestMapping URI template 样式映射时, 即 someUrl/{paramId}, 这时的paramId可通过 @Pathvariable注解绑定它传过来的值到方法的参数上。

示例代码:

@Controller  
@RequestMapping("/owners/{ownerId}")  
public class RelativePathUriTemplateController {  
  
  @RequestMapping("/pets/{petId}")  
  public void findPet(@PathVariable String ownerId, @PathVariable String petId, Model model) {      
    // implementation omitted   
  }  
}

上面代码把URI template 中变量 ownerId的值和petId的值,绑定到方法的参数上。若方法参数名称和需要绑定的uri template中变量名称不一致,需要在@PathVariable("name")指定uri template中的名称。

2、 @RequestHeader、@CookieValue

@RequestHeader 注解,可以把Request请求header部分的值绑定到方法的参数上。

示例代码:

这是一个Request 的header部分:

  1. Host                    localhost:8080  
  2. Accept                  text/html,application/xhtml+xml,application/xml;q=0.9  
  3. Accept-Language         fr,en-gb;q=0.7,en;q=0.3  
  4. Accept-Encoding         gzip,deflate  
  5. Accept-Charset          ISO-8859-1,utf-8;q=0.7,*;q=0.7  
  6. Keep-Alive              300  
  1. @RequestMapping("/displayHeaderInfo.do")  
    public void displayHeaderInfo(@RequestHeader("Accept-Encoding") String encoding,  
                                  @RequestHeader("Keep-Alive") long keepAlive)  {  
    }

上面的代码,把request header部分的 Accept-Encoding的值,绑定到参数encoding上了, Keep-Alive header的值绑定到参数keepAlive上。

@CookieValue 可以把Request header中关于cookie的值绑定到方法的参数上。

例如有如下Cookie值:

  1. JSESSIONID=415A4AC178C59DACE0B2C9CA727CDD84 

参数绑定的代码:

@RequestMapping("/displayHeaderInfo.do")  
public void displayHeaderInfo(@CookieValue("JSESSIONID") String cookie)  {  
}

即把JSESSIONID的值绑定到参数cookie上。


3、@RequestParam, @RequestBody

@RequestParam 

A) 常用来处理简单类型的绑定通过Request.getParameter() 获取的String可直接转换为简单类型的情况( String--> 简单类型的转换操作由ConversionService配置的转换器来完成);因为使用request.getParameter()方式获取参数,所以可以处理get 方式中queryString的值,也可以处理post方式中 body data的值

B)用来处理Content-Type: 为 application/x-www-form-urlencoded编码的内容,提交方式GET、POST;

C) 该注解有两个属性: value、required; value用来指定要传入值的id名称,required用来指示参数是否必须绑定;

示例代码:

@Controller  
@RequestMapping("/pets")  
@SessionAttributes("pet")  
public class EditPetForm {  
    @RequestMapping(method = RequestMethod.GET)  
 public String setupForm(@RequestParam("petId") int petId, ModelMap model) {  
       Pet pet = this.clinic.loadPet(petId);  
   model.addAttribute("pet", pet);  
   return "petForm";  
   }

@RequestBody

该注解常用来处理Content-Type: 不是application/x-www-form-urlencoded编码的内容,例如application/json, application/xml等;

它是通过使用HandlerAdapter 配置的HttpMessageConverters来解析post data body,然后绑定到相应的bean上的。

因为配置有FormHttpMessageConverter,所以也可以用来处理 application/x-www-form-urlencoded的内容,处理完的结果放在一个MultiValueMap<String, String>里,这种情况在某些特殊需求下使用,详情查看FormHttpMessageConverter api;

示例代码:

<span>@RequestMapping(value = "/something", method = RequestMethod.PUT)  
public void handle(@RequestBody String body, Writer writer) throws IOException {  
  writer.write(body);  
}  </span>

4、@SessionAttributes, @ModelAttribute

@SessionAttributes:

该注解用来绑定HttpSession中的attribute对象的值,便于在方法中的参数里使用。

该注解有value、types两个属性,可以通过名字和类型指定要使用的attribute 对象;

示例代码:

@Controller  
@RequestMapping("/editPet.do")  
@SessionAttributes("pet")  
public class EditPetForm {  
    // ...   
}

@ModelAttribute

该注解有两个用法,一个是用于方法上,一个是用于参数上;

用于方法上时:  通常用来在处理@RequestMapping之前,为请求绑定需要从后台查询的model;

用于参数上时: 用来通过名称对应,把相应名称的值绑定到注解的参数bean上;要绑定的值来源于:

A) @SessionAttributes 启用的attribute 对象上;

B) @ModelAttribute 用于方法上时指定的model对象;

C) 上述两种情况都没有时,new一个需要绑定的bean对象,然后把request中按名称对应的方式把值绑定到bean中。


用到方法上@ModelAttribute的示例代码:

// Add one attribute   
// The return value of the method is added to the model under the name "account"   
// You can customize the name via @ModelAttribute("myAccount")   
  
@ModelAttribute  
public Account addAccount(@RequestParam String number) {  
    return accountManager.findAccount(number);  
}
这种方式实际的效果就是在调用@RequestMapping的方法之前,为request对象的model里put(“account”, Account);

用在参数上的@ModelAttribute示例代码:

@RequestMapping(value="/owners/{ownerId}/pets/{petId}/edit", method = RequestMethod.POST)  
public String processSubmit(@ModelAttribute Pet pet) {  
     
}

首先查询 @SessionAttributes有无绑定的Pet对象,若没有则查询@ModelAttribute方法层面上是否绑定了Pet对象,若没有则将URI template中的值按对应的名称绑定到Pet对象的各属性上。

@requestparam (required = false) 的作用?

@requestparam (required = false) 的作用?

不传值后台也不会报错,但是如果 @requestparam (required = false) 的括号中指定了基本数据类型,例如 (@requestparam (value = ''num'' required = false)  int num) 这个时候如果不传值是会报错的,因为不传值就赋 null, 但是 int 类型不能为 null, 解决办法,修改成 Integer 即可

关于使用spring-validation和@RequestParam(required = false)字符串默认值的校验问题的介绍现已完结,谢谢您的耐心阅读,如果想了解更多关于@CookieValue,@PathVariable,@RequestBody,@RequestHeader,@RequestParam、@Param @PathVariable @RequestParam @ResponseBody @RequestBody注解说明、@PathVariable,@RequestParam, @RequestBody,@ModelAttribute,@RequestHeader,@CookieValue的区别、@requestparam (required = false) 的作用?的相关知识,请在本站寻找。

本文标签: