springMvc中提供了很多好用的参数绑定的方式方法,那枚举呢?
或者参数的值是一个json字符串的时候?
你是怎么处理的?
下面我就给大家分享一下我的处理方式。
普通的枚举类型,比如单列值的那种:one ,two... 。
这种事不需要特殊处理的,我们是可以直接接收值并绑定数据的。
要是下面这种枚举类型呢?
而且我们的参数传递的是:0,1这种数字,方法参数是枚举类型。
spring还能帮我们自动绑定参数嘛?
public?enum?StatusEnum?{
????online(1),
????offline(0);
????private?Integer?value;
????StatusEnum(Integer?value)?{
????????this.value?=?value;
????}
????public?Integer?getValue()?{
????????return?value;
????}
}
这时候spring就无法自动帮我们绑定参数了,报如下错误:
@Target({ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public?@interface?EnumParam?{
????String?value()?default?"";
????/**
?????*?赋值调用方法
?????*?如果为空,默认调用name()方法
?????*?该方法必须是一个不含参数的方法,否则将会调用失败
?????*
?????*?@return
?????*/
????String?valueMethod()?default?"";
}
user?statusNo=1
?。getUser(@EnumParam(value="statusNo") int status)
?或者?getUser(@EnumParam() int statusNo)
valueOf()
” 方法。StatusEnum的getValue()
方法。核心代码:
//?1
public?class?EnumParamArgumentResolver?implements?HandlerMethodArgumentResolver?{
????@Override
????public?boolean?supportsParameter(MethodParameter?parameter)?{
????????return?parameter.hasParameterAnnotation(EnumParam.class);
????}
????@Override
????public?Object?resolveArgument(MethodParameter?parameter,?ModelAndViewContainer?mavContainer,?NativeWebRequest?webRequest,?WebDataBinderFactory?binderFactory)?throws?Exception?{
????????//?2?
????????EnumParam?annotation?=?parameter.getParameterAnnotation(EnumParam.class);
????????Object?object?=?null;
????????if?(annotation?!=?null)?{
????????????String?parameterName?=?annotation.value();
????????????//?3
????????????if?(!StringUtils.hasText(parameterName))?{
????????????????parameterName?=?annotation.name();
????????????}
????????????if?(!StringUtils.hasText(parameterName))?{
????????????????parameterName?=?parameter.getParameterName();
????????????}
????????????String?value?=?webRequest.getParameter(parameterName);
????????????if?(StringUtils.hasText(value))?{
????????????????//?4?
????????????????Class<?>?objectType?=?parameter.getParameterType();
????????????????String?method?=?Objects.equals(annotation.valueMethod(),?"")???"valueOf"?:?annotation.valueMethod();
????????????????Object[]?enumConstants?=?objectType.getEnumConstants();
????????????????//?如果方法没了就?抛出异常
????????????????Method?declaredMethod?=?objectType.getDeclaredMethod(method);
????????????????try?{
????????????????????for?(Object?enumConstant?:?enumConstants)?{
????????????????????????//?5
????????????????????????Object?invoke?=?method.equals("valueOf")???declaredMethod.invoke(enumConstant,?enumConstant.toString())?:?declaredMethod.invoke(enumConstant);
????????????????????????if?(invoke?!=?null)?{
????????????????????????????if?(Convert.toStr(invoke).equals(Convert.toStr(value)))?{
????????????????????????????????object?=?enumConstant;
????????????????????????????????break;
????????????????????????????}
????????????????????????}
????????????????????}
????????????????}?catch?(Exception?e)?{
????????????????????log.error("参数enum转换失败:{}.{}[{}]",?parameter.getContainingClass().getName(),?parameter.getMethod().getName(),?parameterName);
????????????????????object?=?null;
????????????????}
????????????}
????????????mavContainer.addAttribute(parameterName,?object);
????????}
????????return?object;
????}
}
EnumParamArgumentResolver
)实现 spring mvc的扩展接口HandlerMethodArgumentResolver
。EnumParam
?注解,如果是则进行解析。EnumParam.value()
?的值并进行赋值给parameterName
。mavContainer.addAttribute(parameterName, object);
然后返回。以上就是实现枚举参数解析器的全部步骤。
方法示例:
请求示例:
我们有时候可能会遇到这种请求:
“
localhost:8088/prt/jsonParams?user={"age":12,"id":"1","name":"凹凸曼"}
?那么这种我们可能一般都是使用String接收,然后在调用转JSON的API进行处理。可是这种代码每个方法都去写的话,太不优雅了。毕竟:「温柔永不落伍, 优雅永不过时 」 。
@Target({ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public?@interface?JsonParam?{
????String?value()?default?""
????Class<?>?objectType()?default?JsonParam.class;
}
value()
?: value用于绑定请求参数和方法参数名一致时的对应关系。和 EnumParam中的value定义差不多。objectType()
?: 当参数是数组对象时,赋值属性。核心代码:
public?class?JsonParamArgumentResolver?implements?HandlerMethodArgumentResolver?{
????@Override
????public?boolean?supportsParameter(MethodParameter?parameter)?{
????????return?parameter.hasParameterAnnotation(?JsonParam.class?);
????}
????@Override
????public?Object?resolveArgument(MethodParameter?parameter,?ModelAndViewContainer?mavContainer,?NativeWebRequest?webRequest,?WebDataBinderFactory?binderFactory)?throws?Exception?{
????????JsonParam?annotation?=?parameter.getParameterAnnotation(?JsonParam.class?);
????????Object?object?=?null;
????????if?(annotation?!=?null)?{
????????????String?parameterName?=?annotation.value();
????????????if?(StringUtils.isBlank(?parameterName?))?{
????????????????parameterName?=?annotation.name();
????????????}
????????????if?(StringUtils.isBlank(?parameterName?))?{
????????????????parameterName?=?parameter.getParameterName();
????????????}
????????????String?value?=?webRequest.getParameter(?parameterName?);
????????????if?(StringUtils.isNotBlank(?value?))?{
????????????????//?2
????????????????Class<?>?objectType?=?annotation.objectType();
????????????????try?{
????????????????????if?(objectType?!=?JsonParam.class)?{
????????????????????????object?=?JSON.parseArray(?value,?objectType?);
????????????????????}?else?{
????????????????????????object?=?JSON.parseObject(?value,?parameter.getParameterType()?);
????????????????????}
????????????????}?catch?(Exception?e)?{
????????????????????LoggerFactory.getLogger(?JsonParamArgumentResolver.class?)
????????????????????????????.error(?"参数Json转换失败:"?+?parameter.getContainingClass().getName()?+?"."?+?parameter.getMethod().getName()?+?"["?+?parameterName?+?"]"?);
????????????????????object?=?null;
????????????????}
????????????}
????????????//this.validate(?parameter,?mavContainer,?object,?parameterName?);
????????????mavContainer.addAttribute(?parameterName,?object?);
????????}
????????return?object;
????}
}
以上就是实现Json参数解析器的全部步骤。
普通对象方法示例:
请求示例:
数组对象方法示例:
请求示例:
一般我们普通的参数我们无需加任何额外的注解标记,spring既可以给我们自定绑定参数。
这种,当我们的请求参数与方法参数不一致时可以使用@RequestParam
如下:
在Controller方法的参数前面添加@PathVariable
注解,将路径参数的值绑定到对应的参数上。
如下:
在Controller方法的参数前面添加@RequestBody
注解,将请求体的值绑定到对应的参数上 。
“注意这种模式不支持:
Content-Type: application/x-www-form-urlencoded
或?Content-Type: application/x-www-form
的请求。
在Controller方法的参数前面添加@ModelAttribute
注解,将表单参数的值绑定到对应的参数上。同上这种模式不支持?Content-Type: application/json
的请求。
springBoot+tomcat报错:Invalid character found in the request target [...]. The valid characters are defined in RFC 7230 and RFC 3986
原因是:SpringBoot 2.0.0 以上都采用内置tomcat8.0以上版本,而tomcat8.0以上版本遵从RFC规范添加了对Url的特殊字符的限制,url中只允许包含英文字母(a-zA-Z
)、数字(0-9
)、-_.~
四个特殊字符以及保留字符(?! * ’ ( ) ; : @ & = + $ , / ? # [ ]
?) (26*2+10+4+18=84
)这84个字符,请求中出现了{}
大括号或者[]
,所以tomcat报错。
处理办法:在application.yml配置文件中如下配置:
server:
?tomcat:
????relaxed-path-chars:?['|','{','}','[',']']
????relaxed-query-chars:?['|','{','}','[',']']?
最后说一句(求关注!别白嫖!)
如果这篇文章对您有所帮助,或者有所启发的话,求一键三连:点赞、转发、在看。
关注公众号:woniuxgg,在公众号中回复:笔记??就可以获得蜗牛为你精心准备的java实战语雀笔记,回复面试、开发手册、有超赞的粉丝福利!
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。