自定义数据绑定---HandlerMethodArgumentResolver

介绍

      前面几节我们介绍了spring MVC的几种常见的数据绑定的方法,可以灵活地获取用户请求中的参数,例如@PathVariable,@ModelAttribute,@RequestParam等这些数据绑定注解,有了这些注解,我们可以很方便的去获取参数,但是偶尔我们需要自定义的去进行数据绑定,Spring一直遵循开闭原则,可以让使用者自定义去做自己的事情,今天我们一起浅析一下HandlerMethodArgumentResolver



认识HandlerMethodArgumentResolver,我们可以看下HandlerMethodArgumentResolver的继承关系图

我们可以很清楚的看到我们常见的几个数据绑定的annotation的具体实现都是实现了HandlerMethodArgumentResolver这个接口,我们可以先尝试一下写一个demo,自定义annotation绑定一个数据

首先我们新建一个annotation-----CurrentUser  默认只能注解参数,且运行时有效:

[java]  view plain  copy
  1. package org.study.lyncc.web.resolver.annotation;  
  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. @Target({ElementType.PARAMETER})  
  9. @Retention(RetentionPolicy.RUNTIME)  
  10. @Documented  
  11. public @interface CurrentUser {  
  12.   
  13.       
  14.     String value() default "";  
  15.   
  16. }  
我们按照他的定义,自定义一个CurrentUserHandlerMethodArgumentResolver实现HandlerMethodArgumentResolver:

[java]  view plain  copy
  1. package org.study.lyncc.web.resolver;  
  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. import org.study.lyncc.web.entity.User;  
  9. import org.study.lyncc.web.resolver.annotation.CurrentUser;  
  10.   
  11. public class CurrentUserHandlerMethodArgumentResolver implements HandlerMethodArgumentResolver{  
  12.   
  13.     public boolean supportsParameter(MethodParameter parameter) {  
  14.         return parameter.hasParameterAnnotation(CurrentUser.class);  
  15.     }  
  16.   
  17.     public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer,  
  18.             NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception {  
  19.         return new User(1,"lyncc");  
  20.     }  
  21.   
  22. }  

这边只是一个简单的demo,默认返回一个user,这样,我们写个controller来测试一下

[java]  view plain  copy
  1. package org.study.lyncc.web.controller;  
  2.   
  3. import org.springframework.stereotype.Controller;  
  4. import org.springframework.web.bind.annotation.RequestMapping;  
  5. import org.springframework.web.servlet.ModelAndView;  
  6. import org.study.lyncc.web.entity.User;  
  7. import org.study.lyncc.web.resolver.annotation.CurrentUser;  
  8.   
  9. @Controller  
  10. @RequestMapping(value="/data/binding")  
  11. public class CostomDataBindingController {  
  12.       
  13.     @RequestMapping(value="/test")  
  14.     public ModelAndView costomData(@CurrentUser User u){  
  15.         System.out.println(u.getUsername());  
  16.         ModelAndView mav = new ModelAndView("session");  
  17.         return mav;  
  18.     }  
  19.   
  20. }  
我们写了一个测试方法,costomData中间的入参是User,前面加了我们自定义的注解@CurrentUser,这样此处的User应该就是我们在CurrentUserHandlerMethodArgumentResolver中resolveArgument方法返回的对象了

不过我们还需要让spring容器加载我们自定义的数据绑定的类CurrentUserHandlerMethodArgumentResolver,我们修改一下我们spring mvc的配置文件spring-servlet.xml

[html]  view plain  copy
  1. <beans xmlns="http://www.springframework.org/schema/beans"  
  2.        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
  3.        xmlns:p="http://www.springframework.org/schema/p"  
  4.        xmlns:context="http://www.springframework.org/schema/context"  
  5.        xmlns:mvc="http://www.springframework.org/schema/mvc"  
  6.        xsi:schemaLocation="  
  7.        http://www.springframework.org/schema/beans  
  8.        http://www.springframework.org/schema/beans/spring-beans.xsd  
  9.        http://www.springframework.org/schema/context  
  10.        http://www.springframework.org/schema/context/spring-context.xsd  
  11.        http://www.springframework.org/schema/mvc  
  12.        http://www.springframework.org/schema/mvc/spring-mvc.xsd">  
  13.          
  14.      <!-- 基于注解驱动 -->  
  15.     <mvc:annotation-driven>  
  16.        <mvc:argument-resolvers>    
  17.             <bean class="org.study.lyncc.web.resolver.CurrentUserHandlerMethodArgumentResolver"/>    
  18.         </mvc:argument-resolvers>    
  19.     </mvc:annotation-driven>  
  20.       
  21.     <!-- 默认spring的扫描包, 此处指定处理扫描org.study.lyncc.web.controller包下的类有@Controller注解的-->  
  22.      <context:component-scan base-package="org.study.lyncc.web.controller" >  
  23.         <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller" />   
  24.     </context:component-scan>    
  25.       
  26.     <!-- 静态资源的处理 -->  
  27.     <mvc:resources mapping="/fonts/**" location="/WEB-INF/fonts/"/>  
  28.     <mvc:resources mapping="/js/**" location="/WEB-INF/js/"/>  
  29.   
  30.      <!--视图解析器  -->  
  31.     <bean id="viewResolver"    
  32.         class="org.springframework.web.servlet.view.InternalResourceViewResolver">    
  33.         <property name="prefix" value="/WEB-INF/jsp/"></property>    
  34.         <property name="suffix" value=".jsp"></property>    
  35.     </bean>   
  36.       
  37. </beans>  
在<mvc:annotation-driven>中加入我们的自定义的类的全路径

启动spring mvc 浏览器中输入:http://localhost:8080/spring-mvc/data/binding/test,发现在控制台中正常打印了



好了,我们再举一个例子,加入我们的url是http://localhost:8080/spring-mvc/data/binding/custom?names=lyncc,fly,ted&ids=1,2,3,我们想要在后台直接获取一个List<User>

也就说我们可以提前转化

同样我们定义一个annotation

[java]  view plain  copy
  1. package org.study.lyncc.web.resolver.annotation;  
  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.   
  10. @Target({ElementType.PARAMETER})  
  11. @Retention(RetentionPolicy.RUNTIME)  
  12. @Documented  
  13. public @interface ManyUser {  
  14.   
  15.     String value() default "";  
  16. }  
ManyUserHandlerMethodArgumentResolver

[java]  view plain  copy
  1. package org.study.lyncc.web.resolver;  
  2.   
  3. import java.util.ArrayList;  
  4. import java.util.List;  
  5.   
  6. import org.springframework.core.MethodParameter;  
  7. import org.springframework.web.bind.support.WebDataBinderFactory;  
  8. import org.springframework.web.context.request.NativeWebRequest;  
  9. import org.springframework.web.method.support.HandlerMethodArgumentResolver;  
  10. import org.springframework.web.method.support.ModelAndViewContainer;  
  11. import org.study.lyncc.web.entity.User;  
  12. import org.study.lyncc.web.resolver.annotation.ManyUser;  
  13.   
  14. public class ManyUserHandlerMethodArgumentResolver implements HandlerMethodArgumentResolver{  
  15.   
  16.     public boolean supportsParameter(MethodParameter parameter) {  
  17.         return parameter.hasParameterAnnotation(ManyUser.class);  
  18.     }  
  19.   
  20.     public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer,  
  21.             NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception {  
  22.         List<User> users = new ArrayList<User>();  
  23.         String names = (String)webRequest.getParameter("names");  
  24.         String ids = (String)webRequest.getParameter("ids");  
  25.         if(null != names && null != ids){  
  26.             String[] nameStrs = names.trim().split(",");  
  27.             String[] idStrs = ids.trim().split(",");  
  28.             for(int i = 0;i<nameStrs.length;i++){  
  29.                 User user = new User(Integer.parseInt(idStrs[i]), nameStrs[i]);  
  30.                 users.add(user);  
  31.             }  
  32.         }  
  33.         return users;  
  34.     }  
  35.   
  36. }  

测试controller

[java]  view plain  copy
  1. package org.study.lyncc.web.controller;  
  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.servlet.ModelAndView;  
  8. import org.study.lyncc.web.entity.User;  
  9. import org.study.lyncc.web.resolver.annotation.CurrentUser;  
  10. import org.study.lyncc.web.resolver.annotation.ManyUser;  
  11.   
  12. @Controller  
  13. @RequestMapping(value="/data/binding")  
  14. public class CostomDataBindingController {  
  15.       
  16.     @RequestMapping(value="/test")  
  17.     public ModelAndView costomData(@CurrentUser User u){  
  18.         System.out.println(u.getUsername());  
  19.         ModelAndView mav = new ModelAndView("session");  
  20.         return mav;  
  21.     }  
  22.       
  23.     @RequestMapping(value="/custom")  
  24.     public ModelAndView customData1(@ManyUser List<User> users){  
  25.         if(null != users && !users.isEmpty()){  
  26.             for(User u : users){  
  27.                 System.out.println(u);  
  28.             }  
  29.         }  
  30.         ModelAndView mav = new ModelAndView("session");  
  31.         return mav;  
  32.     }  
  33.   
  34.       
  35. }  
别忘记修改spring-servlet.xml

[html]  view plain  copy
  1. <mvc:annotation-driven>  
  2.      <mvc:argument-resolvers>    
  3.           <bean class="org.study.lyncc.web.resolver.CurrentUserHandlerMethodArgumentResolver"/>  
  4.           <bean class="org.study.lyncc.web.resolver.ManyUserHandlerMethodArgumentResolver"/>    
  5.       </mvc:argument-resolvers>    
  6.   </mvc:annotation-driven>  
启动项目,输入http://localhost:8080/spring-mvc/data/binding/custom?names=lyncc,fly,ted&ids=1,2,3







评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值