咱們在學習webservice的時候可能就聽過RESTful這麼一個名詞,當時候與SOAP進行對比的…那麼RESTful到底是什麼東東呢???css
RESTful(Representational State Transfer)軟件開發理念,RESTful對http進行很是好的詮釋。java
若是一個架構支持RESTful,那麼就稱它爲RESTful架構…web
如下的文章供咱們瞭解:spring
http://www.ruanyifeng.com/blog/2011/09/restful服務器
綜合上面的解釋,咱們總結一下什麼是RESTful架構:restful
其實通常的架構並不能徹底支持RESTful的,所以,只要咱們的系統支持RESTful的某些功能,咱們通常就稱做爲支持RESTful架構…markdown
非RESTful的http的url:http://localhost:8080/items/editItems.action?id=1&….session
RESTful的url是簡潔的:http:// localhost:8080/items/editItems/1架構
從上面咱們能夠發現,url並無.action後綴的,所以咱們要修改核心分配器的配置mvc
<!-- restful的配置 -->
<servlet>
<servlet-name>springmvc_rest</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<!-- 加載springmvc配置 -->
<init-param>
<param-name>contextConfigLocation</param-name>
<!-- 配置文件的地址 若是不配置contextConfigLocation, 默認查找的配置文件名稱classpath下的:servlet名稱+"-serlvet.xml"即:springmvc-serlvet.xml -->
<param-value>classpath:spring/springmvc.xml</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>springmvc_rest</servlet-name>
<!-- rest方式配置爲/ -->
<url-pattern>/</url-pattern>
</servlet-mapping>
在Controller上使用PathVariable註解來綁定對應的參數
//根據商品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;
}
當DispatcherServlet攔截/開頭的全部請求,對靜態資源的訪問就報錯:咱們須要配置對靜態資源的解析
<!-- 靜態資源 解析 -->
<mvc:resources location="/js/" mapping="/js/**" />
<mvc:resources location="/img/" mapping="/img/**" />
/**
就表示無論有多少層,都對其進行解析,/*
表明的是當前層的全部資源..
在Struts2中攔截器就是咱們當時的核心,原來在SpringMVC中也是有攔截器的
用戶請求到DispatherServlet中,DispatherServlet調用HandlerMapping查找Handler,HandlerMapping返回一個攔截的鏈兒(多個攔截),springmvc中的攔截器是經過HandlerMapping發起的。
實現攔截器的接口:
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"></bean> </mvc:interceptor> <mvc:interceptor> <mvc:mapping path="/**" /> <bean class="cn.itcast.ssm.controller.interceptor.HandlerInterceptor2"></bean> </mvc:interceptor> -->
<mvc:interceptor>
<!-- /**能夠攔截路徑無論多少層 -->
<mvc:mapping path="/**" />
<bean class="cn.itcast.ssm.controller.interceptor.LoginInterceptor"></bean>
</mvc:interceptor>
</mvc:interceptors>
若是兩個攔截器都放行
測試結果:
HandlerInterceptor1...preHandle
HandlerInterceptor2...preHandle
HandlerInterceptor2...postHandle
HandlerInterceptor1...postHandle
HandlerInterceptor2...afterCompletion
HandlerInterceptor1...afterCompletion
總結:
執行preHandle是順序執行。
執行postHandle、afterCompletion是倒序執行
1 號放行和2號不放行
測試結果:
HandlerInterceptor1...preHandle
HandlerInterceptor2...preHandle
HandlerInterceptor1...afterCompletion
總結:
若是preHandle不放行,postHandle、afterCompletion都不執行。
只要有一個攔截器不放行,controller不能執行完成
1 號不放行和2號不放行
測試結果:
HandlerInterceptor1...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";
}
}