1. 程式人生 > >SpringMVC的核心技術之一--攔截器

SpringMVC的核心技術之一--攔截器

專案中的應用:比如使用者的登入攔截----------我們可以在prehandle方法中寫我們的業務邏輯程式碼來判斷請求是不是正確的,使用者只有登入過我們的系統之後才可以訪問我們的應用,可以判斷在session會話中有沒有登入資訊,如果有,讓prehandle方法返回true,如果沒有就在會話中返回false,提示使用者登入。

溫故知新:springmvc執行流程:

1.由中央排程器接收請求
2.中央排程器把請求交給了處理器對映器

處理器對映器:是一些類,他們需要實現HandlerMapping介面。
處理器對映器作用:根據請求的資訊,找到處理此請求的處理器物件。
也就是根據some.do

找到MyController.把找到的
MyController物件儲存到 “處理器執行鏈”的物件中。

3.中央排程器把“處理器執行鏈”的處理器物件(MyController),
交給的處理器的介面卡

處理器介面卡:是一些類,需要實現HandlerAdapter介面。
處理器介面卡作用:根據處理器物件找到對應的處理器介面卡物件(根據你的電腦的型號找到適合電源)。
每個處理器介面都有一個介面卡物件

4.中央排程器,根據找到的處理器介面卡。
通過這個處理器介面卡執行處理器方法(呼叫MyController的handlerRequest()方法),
處理器呼叫完成後,會得到ModelAndView(資料和檢視)

5.中央排程器把處理後的ModelAndView交給了檢視解析器

檢視解析器:是一些類,需要實現ViewResovler介面
檢視解析器作用:根據他的字首,字尾,組成檢視的完整路徑, 並建立檢視檔案的對應檢視物件
在框架中, 檢視是用View介面表示的。

==========================================================================
配置式開發中的對映器和介面卡

1.處理器對映器:
org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping
org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping

使用的是 BeanNameUrlHandlerMapping

2.處理器的介面卡
org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter
org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter
org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter

使用的是 SimpleControllerHandlerAdapter , 處理Controller介面的

/****攔截器講解/
攔截器的使用類似servlet中的過濾器(由tomcat建立),而攔截器由SpringMVC建立(在本節中)

22-interceptor:一個攔截器
攔截器攔截使用者的請求, 可以對請求做判斷,處理的。 可以控制請求是否被處理。
攔截器的執行時間點:獲取到處理器的介面卡之後,在處理器方法執行之前,攔截使用者的請求。

攔截器的數量:在一個專案中攔截器可以0-多個。

攔截器是全域性的, 對所有的處理器物件都可以使用。

實現攔截器的步驟:
1.定義類實現攔截器的介面HandlerInterceptor
2.在springmvc的配置檔案中,宣告攔截器的存在,指定攔截器的uri地址。

步驟:
1.新建 web project
2.匯入jar:
1)spring的核心jar:spring-beans.jar,spring-core.jar,spring-context.jar,spring-expression.jar
2)spring-aop.jar
3)web相關的jar:spring-web.jar
4)springmvc的實現jar:spring-webmvc.jar
5)日誌:commons-logging.jar
3.重點:修改web.xml , 註冊springmvc的核心物件:中央排程器DispatherServlet

  1. 中央排程器DispatherServlet是一個Servlet
  2. 中央排程器的作用:1)接收使用者的請求;2)響應處理結果。
  3. 中央排程器也叫做前端控制器(front controller)
    4.新建jsp,發起一個請求。
    定義請求引數 name ,age (使用整數表示年齡)

5.新建控制器物件,是一個普通的java類
1)在類的上面加入註解@Controller,建立處理器物件
2)在類中自定義方法,處理某個請求, 在方法的上面加入@RequestMapping.
方法定義形參 name ,age

6.新建jsp,顯示請求的處理結果

7.定義類實現HandlerInterceptor介面, 實現介面中的三個方法。

8.定義springmvc的配置檔案
1)宣告元件掃描器,指定@Controller註解所在的包名
2)宣告檢視解析器,處理檢視
3)宣告攔截器物件,指定攔截的請求uri

package com.bjpowernode.interceptors;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

//攔截器
public class MyInterceptor implements HandlerInterceptor {

private long btime;
/**
 * preHandle:預處理方法,使用者的請求首先到達此方法。在方法中可以對請求做判斷處理。
 * 
 * 引數:
 *  Object handler:處理器物件
 * 
 * 返回值:boolean
 *  true:請求是能被處理的, 攔截器的所有方法都會執行, afterCompletion也能被執行。
 *  
 *      攔截器MyInterceptor的preHandle()
		執行了MyController的doSome方法
		攔截器MyInterceptor的postHandle()
		攔截器MyInterceptor的afterCompletion()
		
 *  false: 請求不會被處理,到攔截器就截止了。
 *      攔截器MyInterceptor的preHandle()
 *  
 *  
 *  preHandle()可以看做是整個應用的總開關。
 *  
 */
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
		throws Exception {
	btime = System.currentTimeMillis();
	System.out.println("攔截器MyInterceptor的preHandle()");
	return true;
}

/**
 * postHandle:後處理方法,在處理器方法執行後執行的。 特點能夠獲取到處理器方法的返回值。
 *            可以對返回值做處理,修改資料,修改檢視。 做二次處理
 * 引數:
 *  Object handler:處理器物件
 *  ModelAndView mv:處理器方法的返回值
 */
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
		ModelAndView mv) throws Exception {
	System.out.println("攔截器MyInterceptor的postHandle()");
	//修改原來的執行結果,增加資料
	if( mv !=null ){
		//增加資料
		mv.addObject("msg", "postHandle");
		
		//修改檢視
		mv.setViewName("other");
	}
	
}

/**
 * afterCompletion:最後執行的方法, 在方法中可以做資源的回收, 記憶體釋放。
 *                  只有當攔截器的preHander()方法返回true,它才能執行。           
 * 引數:
 *  Object handler:處理器物件
 *  Exception ex:指定程式中的異常物件
 *  
 * 請求處理完成:在檢視處理完成後,認為請求處理完成, afterCompletion方法是在檢視處理完成後執行的。
 */
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
		throws Exception {
	System.out.println("攔截器MyInterceptor的afterCompletion()");
	
	long etime = System.currentTimeMillis();
	System.out.println("請求的處理時長:"+(etime - btime));
	
}

}
/SpringMVC.xml/

<?xml version="1.0" encoding="UTF-8"?>

<!-- 宣告元件掃描器,指定@Controller註解的包名 -->
<context:component-scan base-package="com.bjpowernode.controllers" />

<!-- 宣告檢視解析器物件:框架提供的類, 處理檢視的。
          實現ViewResolver介面的類叫做檢視解析器
 -->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
	<!-- 指定字首:表示檢視檔案的目錄 -->
	<property name="prefix" value="/WEB-INF/jsp/" />
	<!-- 指定字尾:表示檢視檔案的副檔名 -->
	<property name="suffix" value=".jsp" />
</bean>

<!-- 宣告攔截器物件,指定攔截器的uri -->
<mvc:interceptors>
	<!-- 第一個攔截器 -->
	<mvc:interceptor>
		<!-- 攔截的uri -->
		<mvc:mapping path="/**"/>
		<!-- 指定攔截器 -->
		<bean class="com.bjpowernode.interceptors.MyInterceptor" />
	</mvc:interceptor>
</mvc:interceptors>

/**Mycontroller/
package com.bjpowernode.controllers;

import javax.servlet.http.HttpServletRequest;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;

/**

  • @Contorller:建立處理器物件,預設是單例物件
  •     位置:在類的上面
    
  • @RequestMapping:請求對映
  •     value:在類的上面使用,value表示請求地址的公共部分, 我們叫做模組名稱
    

*/
@Controller
@RequestMapping(“test”)
public class MyController {

//自定義方法處理請求。


@RequestMapping(value="some.do")
public ModelAndView doSome( Integer age,String name){
	
	System.out.println("執行了MyController的doSome方法");
	//處理some.do的請求, doSome就相當於 Servlet的doGet
	ModelAndView mv = new ModelAndView();
	//呼叫Service處理業務,將處理結果顯示到檢視
	mv.addObject("myname", name);
	mv.addObject("myage", age);
	//指定檢視
	mv.setViewName("show");
	
	return mv;
}

}
/*web.xml/

<?xml version="1.0" encoding="UTF-8"?> 01-primary index.html index.htm index.jsp default.html default.htm default.jsp myweb org.springframework.web.servlet.DispatcherServlet contextConfigLocation classpath:springmvc.xml
<!-- 在伺服器啟動的時候,建立物件 -->
<load-on-startup>1</load-on-startup>
myweb characterEncodingFilter org.springframework.web.filter.CharacterEncodingFilter encoding utf-8 forceRequestEncoding true
<!-- 強制應答(HttpServletResponse)物件,使用encoding的字元編碼 -->
<init-param>
	<param-name>forceResponseEncoding</param-name>
	<param-value>true</param-value>
</init-param>
characterEncodingFilter /*