相关api:
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配置解析器
text/html;charset=UTF-8
application/json;charset=UTF-8
具体代码实现:
/**
* @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 MyArgumentsResolver implements HandlerMethodArgumentResolver {
private static final Logger LOGGER = LoggerFactory.getLogger(MyArgumentsResolver.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;
}