您的位置:首页 > 编程语言 > Java开发

使用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>  
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: