1. 程式人生 > 實用技巧 >springMVC學習(七)RESTful API和攔截器

springMVC學習(七)RESTful API和攔截器

RESTful API

RESTful結構:

  • 每一個URI代表一種資源;

  • 客戶端和伺服器之間,傳遞這種資源的某種表現層;

  • 客戶端通過四個HTTP動詞,對伺服器端資源進行操作,實現"表現層狀態轉化"

非RESTful的http的url:http://localhost:8080/items/editItems.action?id=1&….

RESTful的url是簡潔的:http:// localhost:8080/items/editItems/1

RESTful結構開發步驟:

  • 更改DispatcherServlet的配置,修改web.xml的url匹配模式

 <servlet-mapping>
<servlet-name>DispatcherServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
  • 配置對靜態資源的解析,當DispatcherServlet攔截/開頭的所有請求,對靜態資源的訪問就報錯,新增靜態資源配置

  <!-- 靜態資源 解析 -->
<mvc:resources location="/js/" mapping="/js/**" />
<mvc:resources location="/img/" mapping="/img/**" />

/**就表示不管有多少層,都對其進行解析,/*代表的是當前層的所有資源

  • 在Controller上使用PathVariable註解來繫結對應的引數

@PathVariable 可以將URL中佔位符引數{xx}繫結到處理器類的方法形參中@PathVariable(“xx“),兩個引數名必須相同

  //根據商品id檢視商品資訊rest介面
//@RequestMapping中指定restful方式的url中的引數,引數需要用{}包起來
//@PathVariable將url中的{}中的引數和形參進行繫結
@RequestMapping("/viewItems/{id}")
public @ResponseBody ItemsCustom viewItems(@PathVariable("id") Integer id) throws Exception{
//呼叫 service查詢商品資訊
ItemsCustom itemsCustom = itemsService.findItemsById(id);
return itemsCustom;
}

springMVC攔截器

使用者請求到DispatherServlet中,DispatherServlet呼叫HandlerMapping查詢Handler,HandlerMapping返回一個攔截鏈(多個攔截),springmvc中的攔截器是通過HandlerMapping發起的

開發步驟:

  • 自定義攔截器,實現 HandlerInterceptor

public class HandlerInterceptor1 implements HandlerInterceptor {
//在執行handler之前來執行的
//用於使用者認證校驗、使用者許可權校驗
@Override
public boolean preHandle(HttpServletRequest request,
HttpServletResponse response, Object handler) throws Exception {
System.out.println("HandlerInterceptor1...preHandle");
//如果返回false表示攔截,不繼續執行handler;如果返回true表示放行
return false;
}
//在執行handler返回modelAndView之前來執行
//如果需要向頁面提供一些公用 的資料或配置一些檢視資訊,使用此方法實現 從modelAndView入手
@Override
public void postHandle(HttpServletRequest request,
HttpServletResponse response, Object handler,
ModelAndView modelAndView) throws Exception {
System.out.println("HandlerInterceptor1...postHandle");
}
//執行handler之後執行此方法
//作系統統一異常處理,進行方法執行效能監控,在preHandle中設定一個時間點,在afterCompletion設定一個時間,兩個時間點的差就是執行時長
//實現 系統統一日誌記錄
@Override
public void afterCompletion(HttpServletRequest request,
HttpServletResponse response, Object handler, Exception ex)
throws Exception {
System.out.println("HandlerInterceptor1...afterCompletion");
}
}
  • 配置攔截器

  <!--攔截器 -->
<mvc:interceptors>
<!--多個攔截器,順序執行 -->
<mvc:interceptor>
<mvc:mapping path="/**" />
<bean class="cn.itcast.ssm.controller.interceptor.HandlerInterceptor1"/>
</mvc:interceptor>
<mvc:interceptor>
<mvc:mapping path="/**" />
<bean class="cn.itcast.ssm.controller.interceptor.HandlerInterceptor2"/>
</mvc:interceptor>

<mvc:interceptor>
<!-- /**可以攔截路徑不管多少層 -->
<mvc:mapping path="/**" />
<bean class="cn.itcast.ssm.controller.interceptor.LoginInterceptor"/>
</mvc:interceptor>
</mvc:interceptors>
  • 攔截器鏈是按配置的攔截器順序執行,執行preHandle是順序執行。執行postHandle、afterCompletion是倒序執行

  • 如果preHandle不放行,postHandle、afterCompletion都不執行。只要有一個攔截器不放行,controller不能執行完成

  • 只有前邊的攔截器preHandle方法放行,下邊的攔截器的preHandle才執行。

日誌攔截器或異常攔截器要求

  • 將日誌攔截器或異常攔截器放在攔截器鏈中第一個位置,且preHandle方法放行

身份認證

攔截器

public class LoginInterceptor implements HandlerInterceptor {

//在執行handler之前來執行的
//用於使用者認證校驗、使用者許可權校驗
@Override
public boolean preHandle(HttpServletRequest request,
HttpServletResponse response, Object handler) throws Exception {

//得到請求的url
String url = request.getRequestURI();

//判斷是否是公開 地址
//實際開發中需要公開 地址配置在配置檔案中
//...
if(url.indexOf("login.action")>=0){
//如果是公開 地址則放行
return true;
}

//判斷使用者身份在session中是否存在
HttpSession session = request.getSession();
String usercode = (String) session.getAttribute("usercode");
//如果使用者身份在session中存在放行
if(usercode!=null){
return true;
}
//執行到這裡攔截,跳轉到登陸頁面,使用者進行身份認證
request.getRequestDispatcher("/WEB-INF/jsp/login.jsp").forward(request, response);

//如果返回false表示攔截不繼續執行handler,如果返回true表示放行
return false;
}
//在執行handler返回modelAndView之前來執行
//如果需要向頁面提供一些公用 的資料或配置一些檢視資訊,使用此方法實現 從modelAndView入手
@Override
public void postHandle(HttpServletRequest request,
HttpServletResponse response, Object handler,
ModelAndView modelAndView) throws Exception {
System.out.println("HandlerInterceptor1...postHandle");

}
//執行handler之後執行此方法
//作系統 統一異常處理,進行方法執行效能監控,在preHandle中設定一個時間點,在afterCompletion設定一個時間,兩個時間點的差就是執行時長
//實現 系統 統一日誌記錄
@Override
public void afterCompletion(HttpServletRequest request,
HttpServletResponse response, Object handler, Exception ex)
throws Exception {
System.out.println("HandlerInterceptor1...afterCompletion");
}

}

Controller

@Controller
public class LoginController {
//使用者登陸提交方法
@RequestMapping("/login")
public String login(HttpSession session, String usercode,String password)throws Exception{

//呼叫service校驗使用者賬號和密碼的正確性
//..

//如果service校驗通過,將使用者身份記錄到session
session.setAttribute("usercode", usercode);
//重定向到商品查詢頁面
return "redirect:/items/queryItems.action";
}

//使用者退出
@RequestMapping("/logout")
public String logout(HttpSession session)throws Exception{

//session失效
session.invalidate();
//重定向到商品查詢頁面
return "redirect:/items/queryItems.action";
}
}