1. 程式人生 > >SpringMVC 通過註解進行引數注入

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>物件即可!