SpringMVC 通過註解進行引數注入
使用SpringMVC已經有好長一段時間,SpringMVC最獨特的方法莫過於對引數的封裝進行注入(在方法上面直接寫引數進行自動注入),但是一直沒深入到裡面瞭解其細節,最近在一個專案中看到java註解結合SpringMVC對引數進行注入,感覺特別不錯。
眾所周知,在方法中能對基本資料型別,Http物件,物件型別進行封裝。這個過程是如何實現的呢?SpringMVC3.0提供HandlerMethodArgumentResolver這個介面。通過Spring呼叫該介面,在controller中對引數進行拼裝。
HandlerMethodArgumentResolver的實現類有很多,既然他是介面,它的實現類很多:
常用的該介面實現類有:
ServletModelAttributeMethodProcessor:實體類的組裝用它實現。
RequestParamMethodArgumentResolver:基本資料型別如String用它實現。
這個說明SpringMVC這個框架對它進行的實現,也可以直接實現,本文章就是講解如何繼承該類對資料進行封裝成我們想要的型別的。
完成這一程序需要三個操作結合:
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; @Documented @Target({ElementType.PARAMETER}) @Retention(RetentionPolicy.RUNTIME) public @interface CurrentUser { String getValue() default "feng"; }
@Documented
@Target({ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
public @interface CurrentGood {
這裡我寫了2個註解類,分別是當前使用者和當前商品類,商品使用者裡面有個屬性預設值是feng。關於註解的作用,舉一個例子:http://www.apkbus.com/android-138762-1-1.html,註解作用:1.起到表示 2.通過反射獲取註解類上繫結的資料
2.完成HandlerMethodArgumentResolver的實現
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;
public class CurrentUserHandlerMethodArgumentResolver implements HandlerMethodArgumentResolver {
@Override
public boolean supportsParameter(MethodParameter parameter) {
if(parameter.hasParameterAnnotation(CurrentUser.class)) {
System.out.println("sss");
return true;
}
return false;
}
@Override
public Object resolveArgument(MethodParameter parameter,
ModelAndViewContainer mavContainer, NativeWebRequest webRequest,
WebDataBinderFactory binderFactory) throws Exception {
CurrentUser currentUserAnnotation = parameter.getParameterAnnotation(CurrentUser.class);
System.out.println(currentUserAnnotation.getValue());
return 8;
}
}
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;
public class CurrentGoodsHandlerMethodArgumentResolver implements HandlerMethodArgumentResolver {
@Override
public boolean supportsParameter(MethodParameter parameter) {
if(parameter.hasParameterAnnotation(CurrentGood.class)) {
System.out.println("sss");
return true;
}
return false;
}
@Override
public Object resolveArgument(MethodParameter parameter,
ModelAndViewContainer mavContainer, NativeWebRequest webRequest,
WebDataBinderFactory binderFactory) throws Exception {
CurrentGood parameterAnnotation = parameter.getParameterAnnotation(CurrentGood.class);
System.out.println(parameterAnnotation);
return 8;
}
}
同樣,HandlerMethodArgumentResolver的實現我也寫了兩個,關於這個類裡面的2個方法在後面說明.
3.在SpringMVC的配置檔案進行配置
<mvc:annotation-driven>
<mvc:argument-resolvers>
<bean class="com.keweisoft.kdp.web.annotation.CurrentUserHandlerMethodArgumentResolver" />
<bean class="com.keweisoft.kdp.web.annotation.CurrentGoodsHandlerMethodArgumentResolver"></bean>
</mvc:argument-resolvers>
</mvc:annotation-driven>
該配置要放在SpringMVC配置檔案 <mvc:annotation-driven /> 上面,才能生效。
/-------------------------------------------------------Controller-----------------------------------------------------------------------------------------------/
@Controller
@RequestMapping("/myTest")
public class TestController extends BaseController {
@RequestMapping("/forward")
public String testForawrd(@CurrentUser Integer id, @CurrentGood String name) {
System.out.println("aaaaaa");
return "index";
}
@RequestMapping("/user")
public String testUser(@CurrentUser Integer id) {
System.out.println("aaaaaa");
return "index";
}
@RequestMapping("/good")
public String testUser(@CurrentGood String name) {
System.out.println("aaaaaa");
return "index";
}
}
這個是Controller裡面有三個方法。
1、先說/myTest/user 這個mapper對映:
當訪問這個對映的時候,會依次執行SpringMVC配置檔案中的這兩個Bean。
<mvc:argument-resolvers>
<bean class="com.keweisoft.kdp.web.annotation.CurrentUserHandlerMethodArgumentResolver" />
<bean class="com.keweisoft.kdp.web.annotation.CurrentGoodsHandlerMethodArgumentResolver"></bean>
</mvc:argument-resolvers>
先執行suportParameter這個方法,若返回false則執行執行testUser中的這個方法,此時引數值是不會封裝進去的。若返回true,則回則這個類個的resolveArgument這個方法,返回的值會賦值給testUser中的這個引數。
2、/myTest/good
同上一樣,會依次執行SpringMVC配置檔案中的這兩個Bean。
3、/myTest/forward
沒一個@註解就會讀取bean裡面的方法,因此會呼叫四次這個Bean。
總結:若Controller中需要接受的型別是List<User>
則在resolveArgument這個方法中返回一個List<User>物件即可!