SpringMVC入門級知識點簡單總結
SpringMVC是Spring框架的一個模組,是一個基於MVC的web框架。
流程:
1,向伺服器傳送的http request請求被DispatcherServerlet捕獲。
2,DispatcherServerlet根據xml檔案中的配置或註解對請求的URL進行解析,得到uri(請求資源識別符號)。然後根據uri呼叫HandlerMapping,獲得處理該請求的Handler和Handler對應的攔截器,最後以HandlerExecutionChain物件的形式返回。
3,DispatcherServerlet根據獲得的Handler選擇一個合適的HandlerAdapter去執行該Handler。
4,HandlerAdapter提取request中的模型資料,填充Handler入參,執行Handler(也稱為Controller)。
5,Handler(Controller)執行完後,向HandlerAdapter返回一個ModelAndView物件,HandlerAdapter再向DispatcherServerlet返回一個ModelAndView物件。
6,根據返回的ModelAndView,DispatcherServerlet請求一個合適的ViewResolver(必須已經註冊到Spring容器中)去進行檢視解析,然後ViewResolver向DispatcherServerlet返回一個真正的檢視View(jsp)。
7,DispatcherServerlet通過Model解析出ModelAndView中的引數進行解析,最終展現完整的view並通過Http response返回給客戶端。
整個過程我們只需編碼Handler和jsp,在WEB-INF/web.xm中配置DispatcherServerlet
前臺post提交亂碼問題如何解決:
可以在web.xml中配置過濾器解決
SpringMVC攔截器
定義攔截器要實現HandlerInterceptor介面,並實現其三個方法:
boolean preHandle:返回值為false表示攔截,true表示放行,在進入Handler方法前執行,可用於身份認證等
void postHandle:執行於進入Handler方法之後和返回ModelAndView之前。其形參中包含ModelAndView,可以用其返回公用的模型資料(公用導航選單欄)給檢視,或者指定統一的返回檢視
void afterCompletion:在Handler方法執行完後執行,可用於統一日記管理,統一異常處理等。
攔截器是根據具體對映器進行配置的,它配置於某個對映器中,也就是說經由某個HandlerMaping對映成功的Handler可以使用該攔截器。
攔截器的執行規律(假如配置三個):
1,三個攔截器同時放行的情況下,preHandle方法的執行順序是:1,2,3。postHandel和afterCompletion方法的執行順序是3,2,1。
2,不過只要三個攔截器中有一個進行攔截,那麼其後面的攔截器的preHandle方法不會執行,而且三個攔截器的postHandle都不會執行,三個攔截器中執行過preHandle並且返回true的會執行afterCompletion方法。
SpringMVC引數繫結
1,預設引數繫結
可以在controller的形參上直接定義以下預設型別的引數,SpringMVC就會自動繫結。
HttpServletRequest
HttpServletResponse
HttpSession
Model/ModelMap物件:model是個介面ModelMap是個介面實現類,作用和ModelAndView類似,是將Model資料填充到request域。
2,簡單引數繫結
引數名得和前臺傳入的值名稱一樣,如若不同得加上@RequestParam
3,POJO型別引數繫結
需要前臺input標籤的name屬性值和POJO中引數名稱一致。若需要傳入date型別的值,則需要轉換。
轉換可以是在前臺用date型別的input,然後在POJO中加上註解@DateTimeFormat(pattern = "yyyy-MM-dd")
注意此種轉換後,存入資料庫的不是yyyy-MM-dd形式,在前臺展示的時候需要controller轉換下傳入前端。
還可以定義一個轉換器類,繼承Converter介面,在實現的convert方法裡將傳入的String型別引數用SimpleDadteFormat轉換為date型別。做好後,在servlet配置檔案中,開啟轉換器和介面卡的那行程式碼中加入轉換器宣告,然後加入轉換器的bean就可以。
如何繫結包裝的POJO型別(POJO裡有另一個POJO):
1,用HttpserverletRequest接收(原始而通用)
2,直接讓包裝型別的POJO接收
重點說第二種:很簡單,直接在前臺將input的name值,設定為另一個POJO的引數名.引數名即可。
4,集合型別的繫結
1)陣列的繫結:例如前臺同時傳入一連串的ID讓後臺批量刪除
前臺:
Controller
2)list的繫結:例如前臺同時傳入一連串的商品資訊提交修改
封裝的POJO類,裡定義一個list屬性。前臺jsp中對每個item的命名方式是包裝類中的list屬性名+下標+對應list中的POJO屬性名,然後controller中直接讓POJO接收即可
3)Map的繫結
Public classQueryVo {
private Map<String,Student> itemInfo = new HashMap<String,Student>();
//get/set方法..
}
<tr>
<td>學生資訊:</td>
<td>
姓名:<inputtype="text"name="itemInfo['name']"/>
年齡:<inputtype="text"name="itemInfo['price']"/>
.. .. ..
</td>
</tr>
SpringMVC異常處理:
思路:dao、service、controller層一層層將異常丟擲,最終由前端控制器交給全域性異常處理器處理。
springMVC中自帶的簡單異常處理器
SimpleMappingExceptionResolver:實現了HandlerExceptionResolver介面。需要在SpringMVC.xml檔案中配置該處理器。
自定義全域性異常處理器:
處理思路:
1,繼承HandlerexceptionResolver介面,解析出異常型別。
2,如果該異常型別是系統自定義的異常,直接取出異常資訊,在錯誤介面顯示。
3,如果該異常型別不是系統自定義的異常,構造出一個自定義的異常型別(資訊為“未知錯誤”)
4,在SpringMVC.xml中配置。
@ExceptionHandler註解實現異常處理
首先寫個baseController類,並在類中使用@ExceptionHandler註解宣告異常處理的方法
public class BaseController {
@ExceptionHandler
public String exp(HttpServletRequest request, Exception ex) {
//異常處理
//......
}
}
然後所有需要處理異常的controller都繼承這個類,不需要配置什麼東西,但是程式碼有侵入性。
SpringMVC和前臺的json互動
SpringMVC和前臺主要有兩種互動形式
一種是key/value一種是json
首先準備載入json所需要的jar包,SpringMVC3和SpringMVC4有所差別
SpringMVC4是:
我專案中用的是gson和fastjson
第二件事是配置json轉換器如果使用註解驅動形式:
<mvc:annotation-driven/>則不用其他配置了。
具體互動時:如果前臺傳入json則後臺controller使用@RequestBody接收前臺的json串,用@ResponseBody將bean轉換為json並返回json。
如果前臺請求的事key/value則後臺只需要用@ResponseBody返回json即可。
檔案上傳常用元件有兩個cos fileupload和commons fileupload
Spring已經完全集成了這兩種元件,使用Commonsfileupload的較多一些
首先整合兩個jar包
其次前臺傳入的時候需要註明,form表單需要註明enctype=”multipart/form-data”屬性
在後臺的springMVC中註明multipartfile解析器
<!--上傳檔案 -->
<bean id="multipartResolver"
class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<property name="defaultEncoding" value="utf-8" />
<!-- 最大記憶體大小 -->
<property name="maxInMemorySize" value="1024000" />
<!-- 最大檔案大小,-1為不限制大小 -->
<property name="maxUploadSize" value="-1" />
</bean>
這樣,一旦某個Request是MultipartRequest,它就會首先被MultipartResolver處理。
然後再轉發相應的controller。
在具體的controller中將HttpservletRequest轉型為MultipartHttservletRequest,就能非常方便的得到檔名和檔案內容。最後呼叫其transferTo(newFile);即可儲存到本地。
如果想將前臺傳入的圖片轉換為縮圖,則不需要藉助第三方軟體,jdk標準庫就包含了影象處理API。
1. public static void createPreviewImage(String srcFile, String destFile) {
2. try {
3. File fi = new File(srcFile); // src
4. File fo = new File(destFile); // dest
5. BufferedImage bis = ImageIO.read(fi);
6. int w = bis.getWidth();
7. int h = bis.getHeight();
8. double scale = (double) w / h;
9. int nw = IMAGE_SIZE; // final int IMAGE_SIZE = 120;
10. int nh = (nw * h) / w;
11. if (nh > IMAGE_SIZE) {
12. nh = IMAGE_SIZE;
13. nw = (nh * w) / h;
14. }
15. double sx = (double) nw / w;
16. double sy = (double) nh / h;
17. transform.setToScale(sx, sy);
18. AffineTransformOp ato = new AffineTransformOp(transform, null);
19. BufferedImage bid = new BufferedImage(nw, nh,
20. BufferedImage.TYPE_3BYTE_BGR);
21. ato.filter(bis, bid);
22. ImageIO.write(bid, " jpeg ", fo);
23. } catch (Exception e) {
24. e.printStackTrace();
25. throw new RuntimeException(
26. " Failed in create preview image. Error: "
27. + e.getMessage());
28. }
29. }