1。Springmvc架構
2。Springmvc元件
三大元件:處理器對映器,處理器介面卡,檢視解析器
處理器對映器:註解式處理器對映器,對類中標記了@ResquestMapping的方法進行對映,根據@ResquestMapping定義的url匹配@ResquestMapping標記的方法,匹配成功返回HandlerMethod物件給前端控制器。
class=“org。springframework。web。servlet。mvc。method。annotation。RequestMappingHandlerMapping” />
處理器介面卡:對標記@ResquestMapping的方法進行適配
class=“org。springframework。web。servlet。mvc。method。annotation。RequestMappingHandlerAdapter” />
解決辦法:
SpringMVC使用自動載入RequestMappingHandlerMapping和RequestMappingHandlerAdapter
可以在springmvc。xml配置檔案中使用替代註解處理器和介面卡的配置。
檢視解析器:檢視解析器使用SpringMVC框架預設的InternalResourceViewResolver,這個檢視解析器支援JSP檢視解析。
class=“org。springframework。web。servlet。view。InternalResourceViewResolver”>
最終jsp物理地址:字首+邏輯檢視名+字尾
3。引數繫結
引數型別推薦使用包裝資料型別,因為基礎資料型別不可以為null
整形:Integer、int
字串:String
單精度:Float、float
雙精度:Double、double
布林型:Boolean、boolean
說明:對於布林型別的引數,請求的引數值為true或false。或者1或0
請求url:
http://localhost:8080/xxx。action?id=2&status=false
處理器方法:
public String editItem(Model model,Integer id,Boolean status)
3。1簡單引數的繫結(@RequestParam)
當請求的引數名稱和處理器形參名稱一致時會將請求引數與形參進行繫結,若不一致,就需要@RequestParam
value:引數名字,即入參的請求引數名字,如value=“itemId”表示請求的引數 區中的名字為itemId的引數的值將傳入
required:是否必須,預設是true,表示請求中一定要有相應的引數,否則將報錯
TTP Status 400 - Required Integer parameter ‘XXXX’ is not present
defaultValue:預設值,表示如果請求中沒有同名引數時的預設值
public String queryItemById(@RequestParam(value = “itemId”, required = true, defaultValue = “1”) Integer id,ModelMap modelMap) {}
這裡需要傳入的是id,實際傳入的是itemId,需要用@RequestParam轉換一下
3。2pojo引數繫結
如果提交的引數很多,或者提交的表單中的內容很多的時候,可以使用簡單型別接受資料,也可以使用pojo接收資料,但是pojo物件中的屬性名和表單中input的name屬性一致。
3。3自定義引數繫結
由於日期資料有很多種格式,springmvc沒辦法把字串轉換成日期型別。所以需要自定義引數繫結
一般使用註解驅動載入處理器介面卡,可以在此標籤上進行配置
//Converter,>
//S:source,需要轉換的源的型別
//T:target,需要轉換的目標型別
public class DateConverter implements Converter{,>
@Override
public Date convert(String source) {
try {
// 把字串轉換為日期型別
SimpleDateFormat simpleDateFormat = new SimpleDateFormat(“yyy-MM-dd HH:mm:ss”);
Date date = simpleDateFormat。parse(source);
return date;
} catch (ParseException e) {
// TODO Auto-generated catch block
e。printStackTrace();
}
// 如果轉換異常則返回空
return null;
}
}
3。3高階引數繫結
3。3。1繫結陣列
3。3。2將資料繫結到list集合
將pojo放入list集合中,注意:接收List型別的資料必須是pojo的屬性,如果方法的形參為ArrayList型別無法正確接收到資料
4。RequestMapping
4。1url路徑對映
@RequestMapping(value=“item”)或@RequestMapping(“/item”),value的值是陣列,可以將多個url對映到同一個方法
4。2請求方法的限定
限定GET方法
@RequestMapping(method = RequestMethod。GET)
如果透過POST訪問則報錯:
HTTP Status 405 - Request method ‘POST’ not supported
例如:
@RequestMapping(value = “itemList”,method = RequestMethod。POST)
限定POST方法
@RequestMapping(method = RequestMethod。POST)
如果透過GET訪問則報錯:
HTTP Status 405 - Request method ‘GET’ not supported
GET和POST都可以
@RequestMapping(method = {RequestMethod。GET,RequestMethod。POST})
5。Controller返回值
5。1Redirect重定向
Contrller方法返回字串可以重定向到一個url地址
// 重定向後瀏覽器位址列變更為重定向的地址,
// 重定向相當於執行了新的request和response,所以之前的請求引數都會丟失
// 如果要指定請求引數,需要在重定向的url後面新增 ?itemId=1 這樣的請求引數
return “redirect:/itemEdit。action?itemId=” + item。getId();
5。2Forward轉發
Controller方法執行後繼續執行另一個Controller方法
// 修改商品成功後,繼續執行另一個方法
// 使用轉發的方式實現。轉發後瀏覽器位址列還是原來的請求地址,
// 轉發並沒有執行新的request和response,所以之前的請求引數都存在
return “forward:/itemEdit。action”;
6。異常處理器
springmvc在處理請求過程中出現異常資訊交由異常處理器進行處理,自定義異常處理器可以實現一個系統的異常處理邏輯。
系統的dao、service、controller出現都透過throws Exception向上丟擲,最後由springmvc前端控制器交由異常處理器進行異常處理
6。1自定義異常類
為了區別不同的異常,通常根據異常型別進行區分,這裡我們建立一個自定義系統異常。
如果controller、service、dao丟擲此類異常說明是系統預期處理的異常資訊。
public class MyException extends Exception {
// 異常資訊
private String message;
public MyException() {
super();
}
public MyException(String message) {
super();
this。message = message;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this。message = message;
}
}
6。2自定義異常處理器
public class CustomHandleException implements HandlerExceptionResolver {
@Override
public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler,
Exception exception) {
// 定義異常資訊
String msg;
// 判斷異常型別
if (exception instanceof MyException) {
// 如果是自定義異常,讀取異常資訊
msg = exception。getMessage();
} else {
// 如果是執行時異常,則取錯誤堆疊,從堆疊中獲取異常資訊
Writer out = new StringWriter();
PrintWriter s = new PrintWriter(out);
exception。printStackTrace(s);
msg = out。toString();
}
// 把錯誤資訊發給相關人員,郵件,簡訊等方式
// 返回錯誤頁面,給使用者友好頁面顯示錯誤資訊
ModelAndView modelAndView = new ModelAndView();
modelAndView。addObject(“msg”, msg);
modelAndView。setViewName(“error”);
return modelAndView;
}
}
在springmvc。xml中新增:
id=“customHandleException” class=“cn。itcast。ssm。exception。CustomHandleException”/>
7。上傳圖片
7。1配置虛擬路徑
在tomcat上配置圖片虛擬目錄,在tomcat下conf/server。xml中新增:
訪問http://localhost:8080/pic即可訪問D:\develop\upload\temp下的圖片。
也可以透過eclipse配置,如下圖:
複製一張圖片到存放圖片的資料夾,使用瀏覽器訪問
測試效果,如下圖:
7。2jar包以及檢視解析器
在springmvc。xml中配置檔案上傳解析器
class=“org。springframework。web。multipart。commons。CommonsMultipartResolver”>
7。3圖片上傳程式碼示例
@RequestMapping(“updateItem”)
public String updateItemById(Item item, MultipartFile pictureFile) throws Exception {
// 圖片上傳
// 設定圖片名稱,不能重複,可以使用uuid
String picName = UUID。randomUUID()。toString();
// 獲取檔名
String oriName = pictureFile。getOriginalFilename();
// 獲取圖片字尾
String extName = oriName。substring(oriName。lastIndexOf(“。”));
// 開始上傳
pictureFile。transferTo(new File(“C:/upload/image/” + picName + extName));
// 設定圖片名到商品中
item。setPic(picName + extName);
// ——————————————————————-
// 更新商品
this。itemService。updateItemById(item);
return “forward:/itemEdit。action”;
}
8。Json資料互動
8。1@RequestBody
@RequestBody註解用於讀取http請求的內容(字串),透過springmvc提供的HttpMessageConverter介面將讀到的內容(json資料)轉換為java物件並繫結到Controller方法的引數上。
@RequestBody註解實現接收http請求的json資料,將json資料轉換為java物件進行繫結
8。2@ResponseBody
@ResponseBody註解用於將Controller的方法返回的物件,透過springmvc提供的HttpMessageConverter介面轉換為指定格式的資料如:json,xml等,透過Response響應給客戶端
@ResponseBody註解實現將Controller方法返回java物件轉換為json響應給客戶端。
8。3Json請求,Json響應(jackson)
如果需要springMVC支援json,必須加入json的處理jar
8。4Json轉換器
如果不使用註解驅動,就需要給處理器介面卡配置json轉換器
在springmvc。xml配置檔案中,給處理器介面卡加入json轉換器:
9。RESTful支援
9。1資源操作
傳統方式操作資源
http://127。0。0。1/item/queryItem。action?id=1 查詢,GET
http://127。0。0。1/item/saveItem。action 新增,POST
http://127。0。0。1/item/updateItem。action 更新,POST
http://127。0。0。1/item/deleteItem。action?id=1 刪除,GET或POST
使用RESTful操作資源
http://127。0。0。1/item/1 查詢,GET
http://127。0。0。1/item 新增,POST
http://127。0。0。1/item 更新,PUT
http://127。0。0。1/item/1 刪除,DELETE
9。2從url上獲取引數(@PathVariable)
@RequestMapping(“item/{id}”)
@ResponseBody
public Item queryItemById(@PathVariable() Integer id) {}
{xxx}叫做佔位符,請求的URL可以是“item /1”或“item/2”
使用(@PathVariable() Integer id)獲取url上的資料
如果@RequestMapping中表示為“item/{id}”,id和形參名稱一致,@PathVariable不用指定名稱。如果不一致,例如“item/{ItemId}”則需要指定名稱@PathVariable(“itemId”)
注意兩個區別
1。 @PathVariable是獲取url路徑上資料的。@RequestParam獲取靜態的url請求引數的(包括post表單提交)
1。 @Controller
2。 @RequestMapping(“/owners/{ownerId}”)
3。 public class RelativePathUriTemplateController {
4。
5。 @RequestMapping(“/pets/{petId}”)
6。 public void findPet(@PathVariable String ownerId, @PathVariable String petId, Model model) {
7。 // implementation omitted
8。 }
9。 }
上面程式碼把URI template 中變數 ownerId的值和petId的值,繫結到方法的引數上。若方法引數名稱和需要繫結的uri template中變數名稱不一致,需要在@PathVariable(“name”)指定uri template中的名稱
2。 如果加上@ResponseBody註解,就不會走檢視解析器,不會返回頁面,目前返回的json資料。如果不加,就走檢視解析器,返回頁面
9。3最佳實踐
9。3。1響應設計
錯誤2點:
第一違反了僅僅用來傳輸資料的原則,status:200不是響應狀態碼,一般稱之為業務狀態碼。
第二違反了拿來就用的原則,資料被包裝了2層
9。3。2指定響應屬性欄位
如介紹,按需提取,需要什麼就提取什麼,而不是全部提取。例如:根據id查詢使用者資訊,可能我就需要使用者名稱稱就行,但是結果卻返回跟使用者相關的所有資訊,
包括年齡,性別等。。。。,這都不是我想要的資料,我僅僅需要姓名而已。
9。3。3http的響應狀態碼
9。4操作資源時注意更新和刪除
9。4。1更新操作
預設情況下,PUT請求是無法提交表單資料的,需要在web。xml中新增過濾器解決:
HttpMethodFilter
org。springframework。web。filter。HttpPutFormContentFilter
HttpMethodFilter
/*
9。4。2刪除操作
需要在web。xml中新增過濾器解決DELETE請求無法提交表單資料的問題:
將POST請求轉化為DELETE或者是PUT
要用_method指定真正的請求引數
——>
HiddenHttpMethodFilter
org。springframework。web。filter。HiddenHttpMethodFilter
HiddenHttpMethodFilter
/*
10。攔截器
10。1自定義攔截器類
public class HandlerInterceptor1 implements HandlerInterceptor {
// controller執行後且檢視返回後呼叫此方法
// 這裡可得到執行controller時的異常資訊
// 這裡可記錄操作日誌
@Override
public void afterCompletion(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, Exception arg3)
throws Exception {
System。out。println(“HandlerInterceptor1。。。。afterCompletion”);
}
// controller執行後但未返回檢視前呼叫此方法
// 這裡可在返回使用者前對模型資料進行加工處理,比如這裡加入公用資訊以便頁面顯示
@Override
public void postHandle(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, ModelAndView arg3)
throws Exception {
System。out。println(“HandlerInterceptor1。。。。postHandle”);
}
// Controller執行前呼叫此方法
// 返回true表示繼續執行,返回false中止執行
// 這裡可以加入登入校驗、許可權攔截等
@Override
public boolean preHandle(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2) throws Exception {
System。out。println(“HandlerInterceptor1。。。。preHandle”);
// 設定為true,測試使用
return true;
}
}
10。2攔截器配置
在springmvc。xml中配置攔截器
總結:
preHandle按攔截器定義順序呼叫
postHandler按攔截器定義逆序呼叫
afterCompletion按攔截器定義逆序呼叫
postHandler在攔截器鏈內所有攔截器返成功呼叫
afterCompletion只有preHandle返回true才呼叫
10。3攔截器應用案例
判斷使用者是否登入
Jsp頁面
<%@ page language=“java” contentType=“text/html; charset=UTF-8”
pageEncoding=“UTF-8”%>
Insert title here
使用者名稱:
密碼:
登入的controller
@Controller
@RequestMapping(“user”)
public class UserController {
/**
* 跳轉到登入頁面
*
* @return
*/
@RequestMapping(“toLogin”)
public String toLogin() {
return “login”;
}
/**
* 使用者登入
*
* @param username
* @param password
* @param session
* @return
*/
@RequestMapping(“login”)
public String login(String username, String password, HttpSession session) {
// 校驗使用者登入
System。out。println(username);
System。out。println(password);
// 把使用者名稱放到session中
session。setAttribute(“username”, username);
return “redirect:/item/itemList。action”;
}
}
攔截器的編寫
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object arg2) throws Exception {
// 從request中獲取session
HttpSession session = request。getSession();
// 從session中獲取username
Object username = session。getAttribute(“username”);
// 判斷username是否為null
if (username != null) {
// 如果不為空則放行
return true;
} else {
// 如果為空則跳轉到登入頁面
response。sendRedirect(request。getContextPath() + “/user/toLogin。action”);
}
return false;
}
在springmvc。xml配置攔截器
<!—— 配置商品被攔截器攔截 ——>
<!—— 配置具體的攔截器 ——>
11。springmvc與struts2不同
1、 springmvc的入口是一個servlet即前端控制器,而struts2入口是一個filter過濾器。
2、 springmvc是基於方法開發(一個url對應一個方法),請求引數傳遞到方法的形參,可以設計為單例或多例(建議單例),struts2是基於類開發,傳遞引數是透過類的屬性,只能設計為多例。
3、 Struts採用值棧儲存請求和響應的資料,透過OGNL存取資料, springmvc透過引數解析器是將request請求內容解析,並給方法形參賦值,將資料和檢視封裝成ModelAndView物件,最後又將ModelAndView中的模型資料透過request域傳輸到頁面。Jsp檢視解析器預設使用jstl。
12。springmvc和mybatis整合
需要的jar包:
1。 spring(包括springmvc)
2。 mybatis
3。 mybatis-spring整合包
4。 資料庫驅動
第三方連線池。
Dao層:
1、SqlMapConfig。xml,空檔案即可,但是需要檔案頭。
2、applicationContext-dao。xml
a) 資料庫連線池
b) SqlSessionFactory物件,需要spring和mybatis整合包下的。
c) 配置mapper檔案掃描器。
Service層:
1、applicationContext-service。xml包掃描器,掃描@service註解的類。
2、applicationContext-trans。xml配置事務。
Controller層:
1、Springmvc。xml
a) 包掃描器,掃描@Controller註解的類。
b) 配置註解驅動
c) 配置檢視解析器
Web。xml檔案:
1、配置spring
配置前端控制器