关闭

使用HandlerMethodArgumentResolver接口自定义Spring MVC的参数接受规则

2456人阅读 评论(0) 收藏 举报
分类:

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
 在CODE上查看代码片派生到我的代码片
  1. package com.weishubin.springmvc.model;  
  2.   
  3. public class User {  
  4.     private String name;  
  5.     private int age;  
  6.     public String getName() {  
  7.         return name;  
  8.     }  
  9.     public void setName(String name) {  
  10.         this.name = name;  
  11.     }  
  12.     public int getAge() {  
  13.         return age;  
  14.     }  
  15.     public void setAge(int age) {  
  16.         this.age = age;  
  17.     }  
  18.           
  19.     public String toString() {  
  20.         StringBuilder sb = new StringBuilder();  
  21.         sb.append(name);  
  22.         sb.append("-");  
  23.         sb.append(age);  
  24.         return sb.toString();  
  25.     }  
  26. }  

注解类:

[java] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. package com.weishubin.springmvc.listargument;  
  2.   
  3. import java.lang.annotation.Documented;  
  4. import java.lang.annotation.ElementType;  
  5. import java.lang.annotation.Retention;  
  6. import java.lang.annotation.RetentionPolicy;  
  7. import java.lang.annotation.Target;  
  8.   
  9. @Target(ElementType.PARAMETER)  
  10. @Retention(RetentionPolicy.RUNTIME)  
  11. @Documented   
  12. public @interface ListAttribute {  
  13.       
  14. }  

实现了HandlerMethodArgumentResolver接口的参数解析器:

[java] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. package com.weishubin.springmvc.listargument;  
  2.   
  3. import java.util.ArrayList;  
  4. import java.util.List;  
  5.   
  6. import org.springframework.beans.BeanWrapper;  
  7. import org.springframework.beans.PropertyAccessorFactory;  
  8. import org.springframework.core.MethodParameter;  
  9. import org.springframework.web.bind.support.WebDataBinderFactory;  
  10. import org.springframework.web.context.request.NativeWebRequest;  
  11. import org.springframework.web.method.support.HandlerMethodArgumentResolver;  
  12. import org.springframework.web.method.support.ModelAndViewContainer;  
  13.   
  14. import com.weishubin.springmvc.model.User;  
  15.   
  16. public class ListArgumentResolver implements HandlerMethodArgumentResolver {  
  17.   
  18.     public boolean supportsParameter(MethodParameter parameter) {  
  19.         //仅作用于添加了注解ListAttribute的参数  
  20.         return parameter.getParameterAnnotation(ListAttribute.class) != null;  
  21.     }  
  22.   
  23.     public Object resolveArgument(MethodParameter parameter,  
  24.             ModelAndViewContainer mavContainer, NativeWebRequest webRequest,  
  25.             WebDataBinderFactory binderFactory) throws Exception {  
  26.         List<User> users = new ArrayList<User>();  
  27.         String[] names = webRequest.getParameterValues("name");  
  28.         String[] ages = webRequest.getParameterValues("age");  
  29.           
  30.           
  31.         for (int i = 0; i < names.length; i++) {  
  32.             User user = new User();  
  33.             BeanWrapper beanWrapper = PropertyAccessorFactory.forBeanPropertyAccess(user);  
  34.               
  35.             String name = names[i];  
  36.             String age = ages[i];  
  37.             beanWrapper.setPropertyValue("name", name);  
  38.             beanWrapper.setPropertyValue("age", age);  
  39.               
  40.             users.add(user);  
  41.         }  
  42.         return users;  
  43.     }  
  44.   
  45. }  

Controller类:

[java] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. package com.weishubin.springmvc.listargument;  
  2.   
  3. import java.util.List;  
  4.   
  5. import org.springframework.stereotype.Controller;  
  6. import org.springframework.web.bind.annotation.RequestMapping;  
  7. import org.springframework.web.bind.annotation.ResponseBody;  
  8.   
  9. import com.weishubin.springmvc.model.User;  
  10.   
  11. @Controller  
  12. public class ListArgumentController {  
  13.       
  14.     @ResponseBody  
  15.     @RequestMapping("/list")  
  16.     public String argumentResolver(@ListAttribute List<User> list) {  
  17.         StringBuilder b = new StringBuilder();  
  18.         for (User u : list) {  
  19.             b.append(u);  
  20.             b.append("<br/>");  
  21.         }  
  22.         return b.toString();  
  23.     }  
  24. }  

配置文件:

[html] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. <mvc:annotation-driven>  
  2.         <mvc:argument-resolvers>  
  3.             <bean class="com.weishubin.springmvc.listargument.ListArgumentResolver"/>  
  4.         </mvc:argument-resolvers>  
  5.     </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代码  收藏代码
  1. import java.lang.annotation.Documented;  
  2. import java.lang.annotation.ElementType;  
  3. import java.lang.annotation.Retention;  
  4. import java.lang.annotation.RetentionPolicy;  
  5. import java.lang.annotation.Target;  
  6.   
  7. @Documented  
  8. @Target({ElementType.PARAMETER})  
  9. @Retention(RetentionPolicy.RUNTIME)  
  10. public @interface CurrentUser {  
  11. }  

Java代码  收藏代码
  1. @RequestMapping(value = "/test1")  
  2. public @ResponseBody String test1(@CurrentUser Long userId) {  
  3.     return userId.toString();  
  4. }  
  5.   
  6. @RequestMapping(value = "/test2")  
  7. public @ResponseBody String test2(@CurrentUser UserDetails userDetails) {  
  8.     return userDetails.toString();  
  9. }  

Java代码  收藏代码
  1. import java.lang.annotation.Annotation;  
  2.   
  3. import org.springframework.core.MethodParameter;  
  4. import org.springframework.web.bind.support.WebDataBinderFactory;  
  5. import org.springframework.web.context.request.NativeWebRequest;  
  6. import org.springframework.web.method.support.HandlerMethodArgumentResolver;  
  7. import org.springframework.web.method.support.ModelAndViewContainer;  
  8.   
  9. import com.github.yingzhuo.mycar2.annotation.CurrentUser;  
  10. import com.github.yingzhuo.mycar2.security.SecurityUtils;  
  11. import com.github.yingzhuo.mycar2.security.UserDetails;  
  12.   
  13. public class CurrentUserHandlerMethodArgumentResolver implements HandlerMethodArgumentResolver {  
  14.   
  15.     @Override  
  16.     public boolean supportsParameter(MethodParameter parameter) {  
  17.         Class<?> klass = parameter.getParameterType();  
  18.         if (klass.isAssignableFrom(UserDetails.class) || klass.isAssignableFrom(Long.class)) {  
  19.             Annotation[] as = parameter.getParameterAnnotations();  
  20.             for (Annotation a : as) {  
  21.                 if (a.annotationType() == CurrentUser.class) {  
  22.                     return true;  
  23.                 }  
  24.             }  
  25.         }  
  26.         return false;  
  27.     }  
  28.   
  29.     @Override  
  30.     public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer, NativeWebRequest webRequest,  
  31.             WebDataBinderFactory binderFactory) throws Exception {  
  32.           
  33.         if ((SecurityUtils.isAuthenticated() || SecurityUtils.isRemembered()) == false) {  
  34.             return null;  
  35.         }  
  36.           
  37.         Class<?> klass = parameter.getParameterType();  
  38.           
  39.         UserDetails userDetails = SecurityUtils.getUserDetails();  
  40.           
  41.         if (klass.isAssignableFrom(UserDetails.class)) {  
  42.             return SecurityUtils.getUserDetails();  
  43.         }  
  44.           
  45.         if (klass.isAssignableFrom(Long.class)) {  
  46.             return userDetails != null ? userDetails.getId() : null;  
  47.         }  
  48.           
  49.         return null;  
  50.     }  
  51. }  

最后,需要配置一下 
Xml代码  收藏代码
  1. <mvc:annotation-driven>  
  2.     <mvc:argument-resolvers>  
  3.         <bean class="xxx.yyy.CurrentUserHandlerMethodArgumentResolver" />  
  4.     </mvc:argument-resolvers>  
  5. </mvc:annotation-driven>  

0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:962119次
    • 积分:14095
    • 等级:
    • 排名:第868名
    • 原创:413篇
    • 转载:211篇
    • 译文:0篇
    • 评论:121条
    博客专栏
    最新评论