HandlerMethodArgumentResolver的简单使用
相关api:
作用:
- SpringMVC解析器用于解析request请求参数并绑定数据到Controller的入参上。
- 自定义一个参数解析器需要实现
HandlerMethodArgumentResolver
接口,重写supportsParameter
和resolveArgument
方法,配置文件中加入resolver配置。 - 如果需要多个解析器同时生效需要在一个解析器中对其他解析器做兼容。
由来:
如果前端对某个不要入参做了加密操作,后端接收到该参数后,都需要进行解密操作。
针对这种需求,首先想到的是filter或者interceptor实现,但是由于HttpServletRequest
对象本身是不提供setParameter()
方法的,因此想要修改request中的参数值为decode后的值是不易达到的。
SpringMVC的HandlerMethodArgumentResolver
,解析器;其功能就是解析request请求参数并绑定数据到Controller的入参上。
实现一个极其简单的参数解析器
具体如何自定义一个参数解析器呢?
其实很简单,一句话——实现HandlerMethodArgumentResolver
接口,重写supportsParameter
和resolveArgument
方法,配置文件中加入resolver配置。
示例代码如下:
自定义注解
/**
* @copyright: Copyright (c) hotel.jd.com All Rights Reserved
* @file: Open.java project: trip-hotel-ebooking
* @creator: feng
* @date: 2018
*/
package com.demo.resolver;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* /**
*
* @description:
* @author: feng
* @requireNo:
* @createdate: 2018
* @lastdate:
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.PARAMETER)
public @interface Open {
String name() default "";
}
自定义解析器实现
public class MyArgumentsResolver implements HandlerMethodArgumentResolver {
/**
* 解析器是否支持当前参数
*/
@Override
public boolean supportsParameter(MethodParameter parameter) {
// 指定参数如果被应用MyParam注解,则使用该解析器。
// 如果直接返回true,则代表将此解析器用于所有参数
return parameter.hasParameterAnnotation(Open.class);
}
/**
* 将request中的请求参数解析到当前Controller参数上
* @param parameter 需要被解析的Controller参数,此参数必须首先传给{@link #supportsParameter}并返回true
* @param mavContainer 当前request的ModelAndViewContainer
* @param webRequest 当前request
* @param binderFactory 生成{@link WebDataBinder}实例的工厂
* @return 解析后的Controller参数
*/
@Override
public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer,
NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception {
return null;
}
}
在springmvc配置解析器
<mvc:annotation-driven>
<mvc:message-converters>
<bean class="org.springframework.http.converter.StringHttpMessageConverter"/>
<bean class="org.springframework.http.converter.support.AllEncompassingFormHttpMessageConverter"/>
<bean class="org.springframework.http.converter.ByteArrayHttpMessageConverter"/>
<bean class="org.springframework.http.converter.BufferedImageHttpMessageConverter"/>
<bean id="fastJsonHttpMessageConverter"
class="com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter4">
<!--加入支持的媒体类型,返回contentType-->
<property name="supportedMediaTypes">
<list>
<value>text/html;charset=UTF-8</value>
<value>application/json;charset=UTF-8</value>
</list>
</property>
</bean>
</mvc:message-converters>
<!--参数转换器-->
<mvc:argument-resolvers>
<bean class="com.jd.trip.hotel.ebooking.resolver.OpenIdHandlerMethodArgumentResolver"/>
</mvc:argument-resolvers>
</mvc:annotation-driven>
具体代码实现:
/**
* @copyright: Copyright (c) hotel.jd.com All Rights Reserved
* @file: OpenIdHandlerMethodArgumentResolver.java project: trip-hotel-ebooking
* @creator: feng
* @date: 2018
*/
package com.demo.resolver;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.MethodParameter;
import org.springframework.util.Base64Utils;
import org.springframework.web.bind.support.WebDataBinderFactory;
import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.method.support.ModelAndViewContainer;
import javax.servlet.http.HttpServletRequest;
/**
* /**
*
* @description:
* @author: feng
* @requireNo:
* @createdate: 2018
* @lastdate:
*/
public class OpenIdHandlerMethodArgumentResolver implements HandlerMethodArgumentResolver {
private static final Logger LOGGER = LoggerFactory.getLogger(OpenIdHandlerMethodArgumentResolver.class);
@Override
public boolean supportsParameter(MethodParameter parameter) {
return parameter.hasParameterAnnotation(Open.class);
}
@Override
public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer, NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception {
LOGGER.info("OpenIdHandlerMethodArgumentResolver:parameter.getParameterType():{}", parameter.getParameterType());
if (parameter.getParameterType().equals(String.class)) {
HttpServletRequest request = webRequest.getNativeRequest(HttpServletRequest.class);
String open = request.getHeader("open");
LOGGER.info("OpenIdHandlerMethodArgumentResolver:openid:{}", open);
String string = new String(Base64Utils.decode(open.getBytes()));
LOGGER.info("OpenIdHandlerMethodArgumentResolver:string:{}", string);
return string;
}
return null;
}
}
controller中代码:
@RequestMapping(value = "getAccountByOpen")
@ResponseBody
public String getAccountByOpenId(@Open String open) {
return open;
}