實現(xiàn)(POST,GET)傳參自動轉(zhuǎn)換成Json對象,所有參數(shù)為Json格式然后再Base64加密
Spring Request詳解:
Spring 的DispatcherServlet 實現(xiàn)了Servlet方法体斩,來處理一次請求
DispatcherServlet主要是執(zhí)行了兩個方法doService(HttpServletRequest request, HttpServletResponse response)晚伙,doDispatch(HttpServletRequest request, HttpServletResponse response)
在doDispatch方法中
// Determine handler for the current request.
mappedHandler = getHandler(processedRequest);
獲取當前請求的handler,也就是獲取到執(zhí)行當前request的bean拷窜。
HandlerMapping有多個實現(xiàn)开皿,具體的還需自己看下實現(xiàn)
// Determine handler adapter for the current request.
HandlerAdapterha = getHandlerAdapter(mappedHandler.getHandler());
獲取到當前請求的HandlerAdapter
protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
for (HandlerMapping hm : this.handlerMappings) {
if (logger.isTraceEnabled()) {
logger.trace(
"Testing handler map [" + hm + "] in DispatcherServlet with name '" + getServletName() + "'");
}
HandlerExecutionChain handler = hm.getHandler(request);
if (handler != null) {
return handler;
}
}
return null;
}
獲取ha.supports(handler) 返回為true的HandlerAdapter
eg.
如果這個bean實現(xiàn)了HttpRequestHandler接口則返回HttpRequestHandlerAdapter
@Override
public boolean supports(Object handler) {
return (handler instanceof HttpRequestHandler);
}
如果這個bean實現(xiàn)了Controller接口則返回SimpleControllerHandlerAdapter
@Override
public boolean supports(Object handler) {
return (handler instanceof Controller);
}
目前常用的方式是通過@Controller、@RequestMapping和Spring配置中添加<context:component-scan/>
此時使用的是RequestMappingHandlerAdapter
RequestMappingHandlerAdapter 主要實現(xiàn)了請求參數(shù)的封裝處理篮昧,返回參數(shù)的封裝處理赋荆,支持注入argumentResolvers、returnValueHandlers懊昨、messageConverters等來實現(xiàn)擴展
RequestMappingHandlerAdapter.invokeHandlerMethod.invokeAndHandle.invokeForRequest.getMethodArgumentValues
if (this.argumentResolvers.supportsParameter(parameter)) {
try {
args[i] = this.argumentResolvers.resolveArgument(
parameter, mavContainer, request, this.dataBinderFactory);
continue;
}
catch (Exception ex) {
if (logger.isDebugEnabled()) {
logger.debug(getArgumentResolutionErrorMessage("Error resolving argument", i), ex);
}
throw ex;
}
}
首先會調(diào)用argumentResolver的supportsParameter判斷是否可用窄潭,然后再執(zhí)行resolveArgument方法
SpecialArgumentsResolver,自定義argumentResolver
通過上面我們可以發(fā)現(xiàn)酵颁,基于自定義注解實現(xiàn)Json的參數(shù)傳遞嫉你,需要實現(xiàn)自定的argumentResolver并注入到RequestMappingHandlerAdapter中
- 實現(xiàn)自定義Json注解
/**
* Created by zhaoqi on 2016/5/5.
*/
@Target(ElementType.PARAMETER)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Json {
Class[] types() default java.lang.Object.class;
String path() default "";
}
- spring配置文件增加自定義argumentResolver
注意,如果是注入的argumentResolver躏惋,會覆蓋默認的argumentResolver幽污。
<!--RequestMappingHandlerAdapter加入自定義ArgumentsResolver-->
<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter">
<property name="synchronizeOnSession" value="true" />
<property name="argumentResolvers">
<list>
<bean class="com.zhaoqi.component.annotation.SpecialArgumentsResolver"/>
</list>
</property>
<property name="messageConverters">
<list>
<ref bean="stringConverter" />
<ref bean="jsonConverter" />
</list>
</property>
</bean>
如果不想覆蓋默認的argumentResolver,請注入customArgumentResolvers簿姨。
// Custom arguments
if(getCustomArgumentResolvers() !=null) {
resolvers.addAll(getCustomArgumentResolvers());
}
- 實現(xiàn)SpecialArgumentsResolver
/**
* Created by zhaoqi on 2016/5/6.
*/
public class SpecialArgumentsResolver implements HandlerMethodArgumentResolver {
@Resource
DotaJsonHttpMessageConverter dotaJsonHttpMessageConverter;
@Override
public boolean supportsParameter(MethodParameter parameter) {
return parameter.hasParameterAnnotation(Json.class);
}
@Override
public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer, NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception {
return this.readArguments(webRequest, parameter, parameter.getGenericParameterType());
}
private Object readArguments(NativeWebRequest webRequest, MethodParameter parameter, Type genericParameterType) {
HttpServletRequest servletRequest = webRequest.getNativeRequest(HttpServletRequest.class);
ServletServerHttpRequest inputMessage = new ServletServerHttpRequest(servletRequest);
Object arg =null;
try {
// get方式取queryString
if (servletRequest.getMethod().equals(RequestMappingHandlerAdapter.METHOD_GET)) {
// base64解碼
String decodedQueryString = new String(Base64Utils.decodeFromString(servletRequest.getQueryString()));
return JsonUtil.toObject(decodedQueryString, Class.forName(genericParameterType.getTypeName()));
}
// Json注解使用dotaJsonHttpMessageConverter讀取參數(shù)
arg = dotaJsonHttpMessageConverter.readInternal(Class.forName(genericParameterType.getTypeName()), inputMessage);
if (null == arg) {
throw new HttpMessageNotReadableException("Required request body is missing: " +
parameter.getMethod().toGenericString());
}
} catch (IOException | ClassNotFoundException e) {
//
}
return arg;
}
}
實際使用
@RequestMapping("/sayHi")
@ResponseBody
public ResponseVo getFeedback(@Json HelloRequest hello){
ResponseVo responseVo = new ResponseVo();
responseVo.setMsg("success");
responseVo.setData(hello.getHello());
return responseVo;
}
好處
- 目前前端頁面調(diào)用后臺接口距误,GET和POST的參數(shù)形式不一樣。GET方式是將參數(shù)拼接在url中扁位,而POST是可以直接傳Json對象的
后臺通過使用@Json注解准潭,可以實現(xiàn)GET和POST參數(shù)的統(tǒng)一,如果需要切換請求方式域仇,無需重新拼裝參數(shù) - 本例采用的為base64加密刑然,實際可以根據(jù)情況自行使用加密方式⊙臭ぃ可以偽裝請求的參數(shù)闰集,增強安全性