1.使用背景
Web項目中需要判斷http接口用戶Post上來的數據是否合法,如果不合法要另做處理,用戶Post上來的數據是Json形式的,我們用了@RequestBody標記自動將json形式的提交封裝為一個Model對象,這樣一來,我們就不能判斷在自動封裝過程中是否出現了異常,此時便想起了springMVC中的interceptor,用於處理請求之前,做一些處理,我們可以取消@RequestBody標記,然后在interceptor中取得請求體,檢查是否符合json要求,即是不是一個valid interceptor,但是這里出現了一個問題:
httpServletRequest的請求內容,只能被讀取一次,在interceptor中讀取了的話,在controller中便不能讀取了,解決方式是,讀取到的請求內容存起來,然后在controller中直接使用。
這里用到了interceptor的一種,HandlerInterceptor,可以寫一個小例子來記一下是怎么使用的!
2.HandlerInterceptor概述
在SpringMVC 中定義一個Interceptor是比較非常簡單,主要有兩種方式:
第一種:實現HandlerInterceptor 接口,或者是繼承實現了HandlerInterceptor 接口的類,例如HandlerInterceptorAdapter;
第二種:實現Spring的WebRequestInterceptor接口,或者是繼承實現了WebRequestInterceptor的類。
現在主要結合一個例子說一下第一種方式:實現HandlerInterceptor接口。
HandlerInterceptor接口主要定義了三個方法:
1. boolean preHandle (HttpServletRequest request, HttpServletResponse response, Object handle)方法:該方法將在請求處理之前進行調用,只有該方法返回true,才會繼續執行后續的Interceptor和Controller,當返回值為true 時就會繼續調用下一個Interceptor的preHandle 方法,如果已經是最后一個Interceptor的時候就會是調用當前請求的Controller方法;
2.void postHandle (HttpServletRequest request, HttpServletResponse response, Object handle, ModelAndView modelAndView)方法:該方法將在請求處理之后,DispatcherServlet進行視圖返回渲染之前進行調用,可以在這個方法中對Controller 處理之后的ModelAndView 對象進行操作。
3.void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handle, Exception ex)方法:該方法也是需要當前對應的Interceptor的preHandle方法的返回值為true時才會執行,該方法將在整個請求結束之后,也就是在DispatcherServlet 渲染了對應的視圖之后執行。用於進行資源清理。
3.簡單的一個例子:
1.xml需要配置:兩種配置方式(對所有的請求記性攔截,對特定的請求進行攔截)
<mvc:interceptors>
<!--對所有的請求記性攔截-->
<!--<beans:bean class="com.sunp.common.interceptor.Myinterceptor"/>-->
<!--對特定的請求進行攔截-->
<mvc:interceptor>
<mapping path="/kfc/brands/brand1/*"/>
<beans:bean class="com.sunp.common.interceptor.Myinterceptor"/>
</mvc:interceptor>
</mvc:interceptors>
2.interceptors類
package com.sunp.common.interceptor;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.mkyong.common.model.Shop;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.BufferedReader;
import java.io.IOException;
/** * Created by hzsunpeng on 2016/6/14. */
public class Myinterceptor implements HandlerInterceptor {
public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o) throws Exception {
System.out.println("preHandle run!");
return true;
}
public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception {
System.out.println("postHandle run!");
}
public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception {
System.out.println("afterCompletion run!");
}
}
3.controller類(為了使用@Controller @PathVariable @ResponseBody注釋等需要加一些配置文件,這里不再列出)
package com.sunp.common.controller;
import com.sunp.common.model.Shop;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletRequest;
/** * Created by hzsunpeng on 2016/6/7. */
@Controller
@RequestMapping("/kfc/brands")
public class JSONController {
@RequestMapping(value = "/brand1/{name}",method = RequestMethod.GET)
public @ResponseBody Shop getShopInJSON(@PathVariable String name)
{
Shop sp = new Shop();
sp.setName(name);
sp.setStaffName(new String[]{"Staffname1","Staffname2"});
System
return sp;
}
//測試用
@RequestMapping(value = "/json",method = RequestMethod.POST)
public String index(HttpServletRequest request)
{
return "index";
}
}
4.model Shop類
package com.sunp.common.model;
import java.io.Serializable;
/** * Created by hzsunpeng on 2016/6/7. */
public class Shop implements Serializable {
private String name;
private String[] staffName;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String[] getStaffName() {
return staffName;
}
public void setStaffName(String[] staffName) {
this.staffName = staffName;
}
}
運行結果:
控制台輸出: