在使用spring mvc时,因为接口参数用到了泛型,如果不处理,有泛型的参数就是空。因此考虑自定义HandlerMethodArgumentResolver ,统一转换参数。
1.首先定义HandlerMethodArgumentResolver
public class CloudMethodArgumentsResolver implements HandlerMethodArgumentResolver {
/*
* (non-Javadoc)
*
* @see
* org.springframework.web.method.support.HandlerMethodArgumentResolver#
* resolveArgument(org.springframework.core.MethodParameter,
* org.springframework.web.method.support.ModelAndViewContainer,
* org.springframework.web.context.request.NativeWebRequest,
* org.springframework.web.bind.support.WebDataBinderFactory)
*/
@Override
public Object resolveArgument(MethodParameter parameter,
ModelAndViewContainer mavContainer, NativeWebRequest webRequest,
WebDataBinderFactory binderFactory) throws Exception {
// Req<T>
Type type = parameter.getGenericParameterType();
// 带data
Map<String, String[]> paramMap = webRequest.getParameterMap();
String[] reqParam = paramMap.get("data");
if(reqParam == null || reqParam.length == 0){
throw new MyException("9999", "data参数为空");
}
String reqStr = reqParam[0];
reqStr = URLDecoder.decode(reqStr, "utf-8");
Req req = JSON.parseObject(reqStr, type);
try{
ValidateUtils.validate(req.getHeader());
ValidateUtils.validate(req.getBody());
}catch(MyException e){
throw new MyException(e.getErrcode(), e.getErrInfo(), req.getHeader());
}
return req;
// 不带data
/*
String tmp;
String[] val;
Type[] params = ((ParameterizedType) type).getActualTypeArguments();
Class clazz = (Class) params[0];
for (Iterator<String> itr = webRequest.getParameterNames(); itr.hasNext();) {
tmp = (itr.next());
String fieldName = tmp;
String secondFiledName = "";
int arrBeginIndex = tmp.indexOf("[");
int arrEndIndex = tmp.indexOf("]");
if(arrBeginIndex != -1 && arrEndIndex != -1){
fieldName = tmp.substring(0, arrBeginIndex);
secondFiledName = tmp.substring(arrBeginIndex+1, arrEndIndex);
}
Field field = FieldUtils.getDeclaredField(o.getClass(), fieldName, true);
Object obj = field.get(o);
if(obj == null){
if(type != null){
obj = clazz.newInstance();
}else{
Class cla = field.getDeclaringClass();
obj = cla.newInstance();
}
FieldUtils.writeField(field, o, obj, true);
}
val = webRequest.getParameterValues(tmp.toString());
if(!"".equals(secondFiledName)){
Field[] fields = o.getClass().getDeclaredFields();
for(int i = 0; i < fields.length; i++){
Class clazz2 = fields[i].getType();
if(clazz2.isAssignableFrom(clazz)){
clazz2 = clazz;
}
System.out.println(clazz2);
System.out.println(secondFiledName);
Field seconedField = FieldUtils.getDeclaredField(clazz2, secondFiledName, true);
if(seconedField != null){
System.out.println(val[0]);
FieldUtils.writeField(seconedField, obj, val[0], true);
}
}
}else{
FieldUtils.writeField(field, obj, val[0], true);
}
}
return o;*/
}
/*
* (non-Javadoc)
*
* @see
* org.springframework.web.method.support.HandlerMethodArgumentResolver#
* supportsParameter(org.springframework.core.MethodParameter)
*/
@Override
public boolean supportsParameter(MethodParameter parameter) {
// 只对有ReqModel注解的参数处理
return parameter.hasParameterAnnotation(ReqModel.class);}
}
2.定义配置文件
<mvc:annotation-driven>
<mvc:message-converters register-defaults="true">
<bean class="com.test.framework.convertor.UTF8StringHttpMessageConverter"/>
<bean id="fastJsonHttpMessageConverter"
class="com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter">
<property name="supportedMediaTypes">
<list>
<value>application/json;charset=UTF-8</value>
</list>
</property>
<property name="features">
<list>
<value>DisableCircularReferenceDetect</value>
<value>QuoteFieldNames</value>
<value>WriteDateUseDateFormat</value>
</list>
</property>
</bean>
</mvc:message-converters>
<mvc:argument-resolvers>
<bean class="com.test.controller.CloudMethodArgumentsResolver"></bean>
</mvc:argument-resolvers>
</mvc:annotation-driven>
纠结的是,刚开始,不是按照此种方式配置,导致返回数据乱码,也就是说UTF8StringHttpMessageConverter没有生效。
以下就是刚开始的错误配置:
<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter">
<property name="synchronizeOnSession" value="true" />
<property name="customArgumentResolvers">
<list>
<bean class="com.test.controller.CloudMethodArgumentsResolver" />
</list>
</property>
</bean>
<!-- 主要作用于@Controller,激活该模式 下面是一种简写形式,完全可以手动配置替代这种简写形式; 它会自动注册DefaultAnnotationHandlerMapping与AnnotationMethodHandlerAdapter
两个bean, 是spring MVC为@Controllers分发请求所必须的 -->
<mvc:annotation-driven>
<mvc:message-converters register-defaults="true">
<bean class="com.test.framework.convertor.UTF8StringHttpMessageConverter"/>
<bean id="fastJsonHttpMessageConverter"
class="com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter">
<property name="supportedMediaTypes">
<list>
<value>application/json;charset=UTF-8</value>
</list>
</property>
<property name="features">
<list>
<value>DisableCircularReferenceDetect</value>
<value>QuoteFieldNames</value>
<value>WriteDateUseDateFormat</value>
</list>
</property>
</bean>
</mvc:message-converters>
</mvc:annotation-driven>
在这种情况下,必须将RequestMappingHandlerAdapter移动到mvc:annotation-driven标签上,不然RequestMappingHandlerAdapter会不生效。
3. controller参数
@ResponseBody
@RequestMapping("test")
public String test(@ReqModel Req<Test> req)
4.Req类部分内容
public class Req<T> implements java.io.Serializable{
private ReqHeader header = new ReqHeader();
private T body;
。。。。。。
}