SpringMVC(8) - 處理器對映
在以前的Spring版本中,使用者需要在Web應用程式上下文中定義一個或多個HandlerMapping bean,以將傳入的Web請求對映到適當的處理器。通過引入帶註解的控制器,就不需要像之前那樣定義了,因為RequestMappingHandlerMapping會自動在所有@Controller bean上查詢@RequestMapping註解。但是,請記住,從AbstractHandlerMapping擴充套件的所有HandlerMapping類都具有以下可用於自定義其行為的屬性:
攔截器:使用的攔截器列表
defaultHandler:當此處理器對映未找到匹配的處理器時使用的預設處理器。
order:基於order屬性的值(參考org.springframework.core.Ordered介面),Spring對上下文中可用的所有處理程式對映進行排序,並應用第一個匹配的處理器。
alwaysUseFullPath:如果為true,則Spring使用當前Servlet上下文中的完整路徑來查詢適當的處理器序。如果為false(預設值),則使用當前Servlet對映中的路徑。例如,如果使用 /testing/* 對映Servlet並且將alwaysUseFullPath屬性設定為true,則使用 /testing/viewPage.html,而如果該屬性設定為false,則使用/viewPage.html。
urlDecode:從Spring 2.5開始,預設為true。如果希望比較編碼路徑,將此標誌設定為false。但是,HttpServletRequest始終以解碼形式暴露Servlet路徑。請注意,Servlet路徑與編碼路徑相比是不匹配的。
以下示例顯示如何配置攔截器:
<beans>
<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping">
<property name="interceptors">
<bean class="example.MyInterceptor"/>
</property>
</bean>
<beans>
1. 使用HandlerInterceptor攔截請求
Spring的處理器對映機制包括處理器攔截器,當想要將特定功能應用於某些請求(例如,檢查認證資訊)時,它們很有用。
位於處理器對映中的攔截器必須從org.springframework.web.servlet.HandlerInterceptor。該介面定義了三種方法,這三種方法應該提供足夠的靈活性來進行各種預處理和後處理,方法如下:
在執行實際處理程式之前呼叫preHandle(..)
執行處理程式後呼叫postHandle(..)
完成請求完成後呼叫afterCompletion(..)
preHandle(..)方法返回一個布林值。可以使用此方法來中斷或繼續執行鏈的處理。當此方法返回true時,處理程式執行鏈將繼續;當它返回false時,DispatcherServlet假定攔截器本身已處理請求(例如,呈現了適當的檢視),並且不繼續執行執行鏈中的其他攔截器和實際處理器。
可以使用interceptors屬性配置攔截器,該屬性存在於從AbstractHandlerMapping擴充套件的所有HandlerMapping類中。示例:
<beans>
<bean id="handlerMapping" class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping">
<property name="interceptors"www.hjshidpt.com>
<list>
<ref bean=www.yigouyule2.cn"officeHoursInterceptor"/>
</list>
</property>
</bean>
<bean id="officeHoursInterceptor" class="www".michenggw.com"samples.TimeBasedAccessInterceptor">
<property name="openingTime"www.gcyl152.com value="www.gcyl159.com 9"/>
<property name="closingTime" value="18"/>
</bean>
</beans>
TimeBasedAccessInterceptor攔截此對映處理的任何請求。如果當前時間不在辦公時間,則會將使用者重定向到靜態HTML檔案,例如,只能在辦公時間訪問該網站。
package samples;
public class TimeBasedAccessInterceptor extends HandlerInterceptorAdapter {
private int openingTime;
private int closingTime;
public void setOpeningTime(int openingTime) {
this.openingTime = openingTime;
}
public void setClosingTime(int www.mcyllpt.com closingTime) {
this.closingTime = closingTime;
}
public boolean preHandle(HttpServletRequest request, HttpServletResponse response,
Object handler)www.furggw.com throws Exception {
Calendar cal = Calendar.getInstance();
int hour = cal.get(HOUR_OF_DAY);
if (openingTime <= hour && hour < closingTime) {
return true;
}
response.sendRedirect("http://host.com/outsideOfficeHours.html");
return false;
}
}
注:使用RequestMappingHandlerMapping時,實際的處理器是HandlerMethod的一個例項,它標識將被呼叫的特定控制器方法。
如上例,Spring介面卡類HandlerInterceptorAdapter使擴充套件HandlerInterceptor介面變得更容易。
提示:在上面的示例中,配置的攔截器將應用於使用帶註解的控制器方法處理的所有請求。如果要縮小攔截器應用的URL路徑,可以使用MVC名稱空間或MVC Java配置,或者宣告型別為MappedInterceptor的bean例項來執行此操作。
請注意,HandlerInterceptor的postHandle方法並不總是非常適合與@ResponseBody和ResponseEntity方法一起使用。在這種情況下,HttpMessageConverter在呼叫postHandle之前寫入並提交響應,這使得無法更改響應,例如新增響應頭。相反,應用程式可以實現ResponseBodyAdvice並將其宣告為@ControllerAdvice bean或直接在RequestMappingHandlerAdapter上配置它。