使用HandlerMethodArgumentResolver接口自定义Spring MVC的参数接受规则
2016-05-30 13:43
931 查看
1.自定义Spring MVC接受List参数
SpringMVC3.1引入了HandlerMethodArgumentResolver接口,spring调用该接口实现Controller的参数装配。HandlerMethodArgumentResolver实现类中会调用DataBinder,Converter等。常用的该接口实现类有:
ServletModelAttributeMethodProcessor:实体类的组装用它实现。
RequestParamMethodArgumentResolver:基本数据类型如String用它实现。
在我学习过程中,发现对List类型的参数SpringMVC没有提供默认实现。我参照Spring的示例 通过实现 HandlerMethodArgumentResolver接口,实现对List参数的组装。
示例中用到的Model类:
[java] view
plain copy
package com.weishubin.springmvc.model;
public class User {
private String name;
private int age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append(name);
sb.append("-");
sb.append(age);
return sb.toString();
}
}
注解类:
[java] view
plain copy
package com.weishubin.springmvc.listargument;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(ElementType.PARAMETER)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface ListAttribute {
}
实现了HandlerMethodArgumentResolver接口的参数解析器:
[java] view
plain copy
package com.weishubin.springmvc.listargument;
import java.util.ArrayList;
import java.util.List;
import org.springframework.beans.BeanWrapper;
import org.springframework.beans.PropertyAccessorFactory;
import org.springframework.core.MethodParameter;
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 com.weishubin.springmvc.model.User;
public class ListArgumentResolver implements HandlerMethodArgumentResolver {
public boolean supportsParameter(MethodParameter parameter) {
//仅作用于添加了注解ListAttribute的参数
return parameter.getParameterAnnotation(ListAttribute.class) != null;
}
public Object resolveArgument(MethodParameter parameter,
ModelAndViewContainer mavContainer, NativeWebRequest webRequest,
WebDataBinderFactory binderFactory) throws Exception {
List<User> users = new ArrayList<User>();
String[] names = webRequest.getParameterValues("name");
String[] ages = webRequest.getParameterValues("age");
for (int i = 0; i < names.length; i++) {
User user = new User();
BeanWrapper beanWrapper = PropertyAccessorFactory.forBeanPropertyAccess(user);
String name = names[i];
String age = ages[i];
beanWrapper.setPropertyValue("name", name);
beanWrapper.setPropertyValue("age", age);
users.add(user);
}
return users;
}
}
Controller类:
[java] view
plain copy
package com.weishubin.springmvc.listargument;
import java.util.List;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import com.weishubin.springmvc.model.User;
@Controller
public class ListArgumentController {
@ResponseBody
@RequestMapping("/list")
public String argumentResolver(@ListAttribute List<User> list) {
StringBuilder b = new StringBuilder();
for (User u : list) {
b.append(u);
b.append("<br/>");
}
return b.toString();
}
}
配置文件:
[html] view
plain copy
<mvc:annotation-driven>
<mvc:argument-resolvers>
<bean class="com.weishubin.springmvc.listargument.ListArgumentResolver"/>
</mvc:argument-resolvers>
</mvc:annotation-driven>
2.对接受的参数进行Base64解密处理
1.自定义注解import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; /** * Description: <br/> * Tsp请求,入参自动Base64转码注解 * @date 2016年4月8日 下午4:26:14 * */ @Target(ElementType.PARAMETER) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface TspRequestBase64 { }
2.定义对使用注解的入参处理
import java.io.InputStreamReader; import java.nio.charset.Charset; import javax.servlet.http.HttpServletRequest; import org.apache.commons.codec.binary.Base64; import org.apache.commons.lang3.StringUtils; import org.springframework.core.MethodParameter; import org.springframework.http.HttpInputMessage; import org.springframework.http.MediaType; import org.springframework.http.server.ServletServerHttpRequest; import org.springframework.util.FileCopyUtils; 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 com.alibaba.fastjson.JSONObject; import com.xx.movie.confirmation.common.annotation.TspRequestBase64; /** * Description: <br/> * Tsp服务,入参进行Base64自动转码 * @date 2016年4月8日 下午3:46:41 * */ public class TspRequestBase64Resolver implements HandlerMethodArgumentResolver { private Charset defaultCharset = Charset.forName("UTF-8"); public boolean supportsParameter(MethodParameter parameter) { return parameter.hasParameterAnnotation(TspRequestBase64.class); } public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer, NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception { HttpServletRequest request = webRequest.getNativeRequest(HttpServletRequest.class); HttpInputMessage message = new ServletServerHttpRequest(request); Charset charset = this.getContentCharset(message.getHeaders().getContentType()); String body = FileCopyUtils.copyToString(new InputStreamReader(request.getInputStream(), charset)); //如果是GET请求,body应该是空,重新获取 if (StringUtils.isEmpty(body)) { body = request.getQueryString(); } byte[] content = null; if(body != null && body.length() > 0){ if (Base64.isBase64(body)) { content = Base64.decodeBase64(body); } else { content = body.getBytes(charset); } } return (content == null) ? null : JSONObject.parseObject(content, parameter.getParameterType()); } //获取charset public Charset getContentCharset(MediaType mediaType) { if (mediaType != null && mediaType.getCharSet() != null) { return mediaType.getCharSet(); } else { return this.defaultCharset; } } }
3.配置spring-mvc.xml文件
<!-- 启用spring mvc 注解 --> <mvc:annotation-driven> <mvc:argument-resolvers> <!-- aop解析TspRequest注解 --> <beans:bean class="com.xx.movie.confirmation.common.util.TspRequestBase64Resolver"></beans:bean> <beans:bean class="com.xx.nfbird.web.argument.JsonMapperArgumentResolver"></beans:bean> <!-- pagination --> <beans:bean class="com.xx.nfbird.web.argument.PaginationArgumentResolver"></beans:bean> </mvc:argument-resolvers> </mvc:annotation-driven>
4.Spring MVC中使用
@RequestMapping(value = "/order/take", method = RequestMethod.POST) @ResponseJson(translate = true) public SeqId orderOccupy(@TspRequestBase64 OrderOccupyRequestVo occupyVo) throws Exception {
解析:
传入的参数必须是Base64位加密之后的,在Spring MVC接受到参数后,回先进行参数的解码
3.使用Shiro+HanderMethodArgumentResolver在入参时,获取安全上下文
为@RequestMapping标注的方法扩展传入的参数。以shiro为例,扩展一个标注,@CurrentUser,只要有这个标注,就可以在shiro的安全上下文中取出适当的对象直接从参数传入,request响应函数。
Java代码
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Documented
@Target({ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
public @interface CurrentUser {
}
Java代码
@RequestMapping(value = "/test1")
public @ResponseBody String test1(@CurrentUser Long userId) {
return userId.toString();
}
@RequestMapping(value = "/test2")
public @ResponseBody String test2(@CurrentUser UserDetails userDetails) {
return userDetails.toString();
}
Java代码
import java.lang.annotation.Annotation;
import org.springframework.core.MethodParameter;
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 com.github.yingzhuo.mycar2.annotation.CurrentUser;
import com.github.yingzhuo.mycar2.security.SecurityUtils;
import com.github.yingzhuo.mycar2.security.UserDetails;
public class CurrentUserHandlerMethodArgumentResolver implements HandlerMethodArgumentResolver {
@Override
public boolean supportsParameter(MethodParameter parameter) {
Class<?> klass = parameter.getParameterType();
if (klass.isAssignableFrom(UserDetails.class) || klass.isAssignableFrom(Long.class)) {
Annotation[] as = parameter.getParameterAnnotations();
for (Annotation a : as) {
if (a.annotationType() == CurrentUser.class) {
return true;
}
}
}
return false;
}
@Override
public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer, NativeWebRequest webRequest,
WebDataBinderFactory binderFactory) throws Exception {
if ((SecurityUtils.isAuthenticated() || SecurityUtils.isRemembered()) == false) {
return null;
}
Class<?> klass = parameter.getParameterType();
UserDetails userDetails = SecurityUtils.getUserDetails();
if (klass.isAssignableFrom(UserDetails.class)) {
return SecurityUtils.getUserDetails();
}
if (klass.isAssignableFrom(Long.class)) {
return userDetails != null ? userDetails.getId() : null;
}
return null;
}
}
最后,需要配置一下
Xml代码
<mvc:annotation-driven>
<mvc:argument-resolvers>
<bean class="xxx.yyy.CurrentUserHandlerMethodArgumentResolver" />
</mvc:argument-resolvers>
</mvc:annotation-driven>
相关文章推荐
- 希尔排序算法(Java语言)
- java 集合框架(1)奠定基础的接口和Collection
- Java中的面向接口编程
- 附 5 springboot之配置文件
- 动态连通性问题
- 安卓 报错 Check the Eclipse log for stack trace.
- hdu2091JAVA
- Java - PAT - 1022. D进制的A+B (20)
- 《Spring实战》学习笔记-第八章:使用Spring Web Flow
- java gc总结
- struts上传文件限制
- 插入排序算法(Java语言)
- JAVA模式设计-开放/关闭原则
- 枚举,注解,实体类,单元测试,反射对象字段------------举例使用
- 微博短链接的生成算法(Java版本)
- Java设计模式之单例模式的写法
- java中四种线程池的使用
- scala的Eclpise开发和helloworld
- myeclipse中项目名有红叉,但项目中文件没有报错的解决办法
- Springmvc 拦截器