Java學習筆記——SpringMVC框架
一、註解
@RequestMapping:此註解可以放在方法和類上面,用於用於對映url到控制器類或一個特定的處理程式方法,若用在類上,則此類所有處理請求的方法都以該地址作為父路徑。還有各種屬性
/** * @RequestMapping有8個屬性 * value:訪問路徑,若只有value屬性可以省略不寫value,例@RequestMapping("/t") * method:接受訪問的請求方式有GET、POST、PUT、DELETE等。 * params:是表明處理請求必須的引數 * headers:表明處理請求的請求頭引數 * consumes:指定處理請求的提交內容型別(Content-Type),例如application/json, text/html * produces:指定返回的內容型別,僅當request請求頭中的(Accept)型別中包含該指定型別才返回; * * */ @RequestMapping(value="/t",method=RequestMethod.GET,params={"name","age!=12"}, headers={"Accept-Language=en-US,zh;q=0.8"},consumes={"application/json"},produces={}) public String t(){ System.out.println(2); return "success"; }
@PathVariable
/**
* @PathVariable:SpringMVC向rest風格發展的標誌。
* */
@RequestMapping("/t1/{id}")
public String t1(@PathVariable("id")Integer id){
System.out.println(id);
return "success";
}
@RequestParam
/** * @RequestParam:獲取請求引數 * required設定非必要引數 * defaultValue設定預設引數值 * 注意:若required為false時要把int設定成Integer型別或者設定defaultValue值, * 否則丟擲IllegalStateException異常 * */ @RequestMapping("/t2") public String t2(@RequestParam("id")Integer id, @RequestParam(value="name",required=false/*,defaultValue="0"*/)int name){ System.out.println(id); System.out.println(name); return "success"; }
@RequestHeader
/**
* @RequestHeader:獲取請求頭引數
* */
@RequestMapping("/t3")
public String t3(@RequestHeader(value="Accept-Language")String s1){
System.out.println(s1); //輸出結果為: zh-CN,zh;q=0.8
return "success";
}
@CookieValue
/** * @CookieValue:獲取Cookie各屬性值 * */ @RequestMapping("/t4") public String t4(@CookieValue("JSESSIONID")String s1){ System.out.println(s1); return "success"; }
@SessionAttributes:講資料放到session域裡面
@ModelAttribute:被此註解標記的方法會在每個目標方法執行之前先被呼叫一次!(但內部實行原理較複雜,可以參考尚矽谷SpringMVC第20集)
@ControllerAdvice:修飾處理異常的類。
@ResponseStatus:自定義異常類,可以標註類或者方法上。
@ResponseStatus(reason="異常",value=HttpStatus.NOT_FOUND)
public class FirstException extends RuntimeException{
/**
*
*/
private static final long serialVersionUID = 1L;
}
//@ResponseStatus(reason="異常two",value=HttpStatus.NO_CONTENT)
@RequestMapping("/t12")
public String t12(@RequestParam("num")int num){
System.out.println(1);
if(num==1){
System.out.println(2);
throw new FirstException();
}
System.out.println("FirstException");
return "success";
}
二、SpringMVC的應用
1、SpringMVC支援pojo入參,若一個表單中各個屬性有與之相配的實體類。可以直接將實體類入參,SpringMVC會自動將表單中各個引數封裝到實體類中去。例:
2、增刪改查對應著post、delete、put、get,因為表單只能提交為post和get,使用hidden隱藏域、name=“_method”,新增HiddenHTTPMethodFilter過濾器把post請求轉化為delete或put請求
3、SpringMVC支援原生servletAPI
4、ModelAndView、Map處理模型資料(ModelMap也一樣)
/**
* Map處理模型資料
* */
@RequestMapping("/t6")
public String t6(Map<String, Object> map){
map.put("time", new Date());
return "success";
}
/**
* ModelAndView處理模型資料
* */
@RequestMapping("/t5")
public ModelAndView t5(){
ModelAndView modelAndView=new ModelAndView("success");
modelAndView.addObject("time", new Date());
return modelAndView;
}
5、國際化資源
1、首先要在配置檔案中配置ResourceBundleMessageSource類來處理國際化資原始檔。
2、在src目錄下建立資原始檔
6、WEB-INF下的檔案是不能被直接訪問的,但有時候我們也需要直接訪問一些頁面,例如登入註冊頁面。這是就可以 用<mvc:view-controller path="/q" view-name="q"/>標籤,不過該標籤需要和<mvc:annotation-driven></mvc:annotation-driven>標籤一起用。
<!-- 配置直接轉發頁面 -->
<!-- 可以直接轉發的頁面,無需經過Handler的方法 -->
<mvc:view-controller path="/q" view-name="q"/>
<mvc:annotation-driven></mvc:annotation-driven>
7、 SpringMVC可以自定義檢視,可以整合Excel,jsp等檢視技術。只要配置BeanNameViewResolver類,order值越小,優先順序越高,InternalResourceViewResolver的order為 Integer.MAX_VALUE。檢視類實現View介面。介面return返回值只需寫上檢視類的首字母小寫全稱就可以了。
<!-- 第四步:建立jsp試圖解析器 -->
<bean id="jspResourceViewResolver"
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/jsp/" />
<property name="suffix" value=".jsp" />
</bean>
<bean class="org.springframework.web.servlet.view.BeanNameViewResolver">
<property name="order" value="100"></property>
</bean>
@Component
public class HelloView implements View {
@Override
public String getContentType() {
return "text/html";
}
@Override
public void render(Map<String, ?> model, HttpServletRequest request, HttpServletResponse response)
throws Exception {
response.getWriter().print("hello"+new Date());
}
}
@RequestMapping("/t9")
public String t9(){
System.out.println("t9");
return "helloView";
}
8、SpringMVC重定向可以在return "redirect:/namespace/toController";轉發:return "forward:/namespace/toController";
9、SpringMVC型別轉換自定義轉換類繼承org.springframework.core.convert.converter類,並註冊為Spring成員。
配置ConversionServiceFactoryBean,並在<mvc:annotation-driven>的注入屬性conversion-service,屬性值是ConversionServiceFactoryBean Bean的id值。
10、mvc:annotation-driven 標籤
在配置檔案中配置<mvc:annotation-driven>會自動註冊三個Bean。RequestMappingHandlerMapping與RequestMappingHandlerAdapter兩個Bean,這是Spring MVC為@Controller分發請求所必需的,並且提供了資料繫結支援。
11、資料格式化。時間、數字等可以直接在實體類欄位上面添加註解,時間用@DateTimeFormat、數字用@NumberFormat,若想自定義型別和SpringMVC提供的型別轉換同時生效則要把ConversionServiceFactoryBean換成FormattingConversionServiceFactoryBean。
12、資料校驗,加入jsr 303資料驗證jar包,然後在需要資料驗證的bean類欄位上加上需要驗證的註解。在介面上bean類入參前面要加上@Vaild註解,SpringMVC會自動把錯誤資訊放到BindingResult裡面。
@Min(100)
@NumberFormat(pattern="#,###,###.#")
private Integer id;
@NotEmpty
private String age;
@NotNull
private String name;
@DateTimeFormat(pattern="yyyy-mm-dd")
private Date brith;
@Email
private String Email;
@RequestMapping("/t10")
public String t10(@Valid User user,BindingResult result){
System.out.println(user);
if(result.getErrorCount()>0){
System.out.println("error!");
for(FieldError fieldError:result.getFieldErrors()){
System.out.println(fieldError.getField()+"---"+fieldError.getDefaultMessage());
}
}
return "success";
}
13、返回json資料,加入三個jar包,然後再介面上加上@ResponseBody註解,返回值直接為資料集合。返回值為byte[]陣列可以實現下載的效果。
14、SpringMVC檔案上傳利用 MultipartResolver介面,SpringMVC自身沒有提供上傳實現,利用Apache的commons-fileupload-1.3.1.jar和commons-io-2.4.jar,表單的file名字和入參的@RequestParam的屬性值要一致。
15、SpringMVC攔截器,<mvc:mapping path="/test/*" />可以配置攔截器的作用範圍。攔截器的作用順序跟在配置檔案中的配置順序有關,preHandle方法執行順序是配置檔案中的正序,postHandle和afterCompletion方法的配置檔案中的反序。
public class FirstInterceptor implements HandlerInterceptor{
/**
* 方法在目標方法渲染檢視之後執行方法。
* */
public void afterCompletion(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, Exception arg3)
throws Exception {
System.out.println("FirstInterceptor - "+"afterCompletion");
}
/**
* 方法在目標方法之後,渲染檢視之前執行。
* 入參屬性中有ModelAndView,可以對請求域中的屬性或檢視做出修改。
* */
public void postHandle(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, ModelAndView arg3)
throws Exception {
System.out.println("FirstInterceptor - "+"postHandle");
}
/**
* 方法在目標方法之前執行
* 返回true,後續的攔截器會被繼續執行。
* 返回false,後續的攔截器不會被繼續執行。
* */
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object arg2) throws Exception {
System.out.println("FirstInterceptor - "+"preHandle");
return true;
}
}
<bean id="multipartResolver"
class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<property name="maxUploadSize" value="104857600" />
<property name="maxInMemorySize" value="4096" />
<property name="defaultEncoding" value="UTF-8"></property>
<!-- <property name="uploadTempDir" value="fileUpload/temp"></property> -->
</bean>
若第一個攔截器返回的是true,第二個返回的是false時。
16、SpringMVC異常處理
①、在當前Handler中新增異常處理方法使用@ExceptionHandler註解修飾,並傳入異常類。
②、@ExceptionHandler方法中的入參不可以傳入Map中。若想把異常傳到頁面上則需要用到ModelAndView物件。
③、@ExceptionHandler方法標記的異常有優先順序的問題,與發生的異常匹配度越高優先順序越高。也可以寫專門處理異常的類,使用@ControllerAdvice註解來修飾類,若在當前Handler找不到匹配的異常處理(當前Handler中的@ExceptionHandler方法異常類是發生異常的父類,也會找到當前Handler的方法處理異常,即只有當前Handler沒有與之匹配的異常類才會去找@ControllerAdvice修飾的類處理異常),則會去被@ControllerAdvice修飾的類中找匹配的異常處理方法來處理異常。
@ExceptionHandler(ArithmeticException.class)
public ModelAndView handlerException(Exception ex){
System.out.println(ex);
ModelAndView modelAndView=new ModelAndView("error");
modelAndView.addObject("exception",ex);
return modelAndView;
}
@RequestMapping("/t11")
public String t11(@RequestParam("num")int num){
int i=10/num;
System.out.println(i);
return "success";
}
@ControllerAdvice
public class ExceptionHandler {
@org.springframework.web.bind.annotation.ExceptionHandler(ArithmeticException.class)
public ModelAndView handlerException(Exception ex){
System.out.println("--->>"+ex);
ModelAndView modelAndView=new ModelAndView("error");
modelAndView.addObject("exception",ex);
return modelAndView;
}
}
17、SpringMVC在restfull風格中無法獲取小數點,詳細原因參考。
解決方法有兩種:
1.在佔位符裡新增:.+,。
2.在<mvc:annotation-driven></mvc:annotation-driven>中新增<mvc:path-matching registered-suffixes-only="true"/>
.三、總結
1、SpringMVC執行流程。
一、先用文字描述
1.使用者傳送請求到DispatchServlet
2.DispatchServlet根據請求路徑查詢具體的Handler
3.HandlerMapping返回一個HandlerExcutionChain給DispatchServlet
HandlerExcutionChain:Handler和Interceptor集合
4.DispatchServlet呼叫HandlerAdapter介面卡
5.HandlerAdapter呼叫具體的Handler處理業務
6.Handler處理結束返回一個具體的ModelAndView給介面卡
ModelAndView:model-->資料模型,view-->檢視名稱
7.介面卡將ModelAndView給DispatchServlet
8.DispatchServlet把檢視名稱給ViewResolver檢視解析器
9.ViewResolver返回一個具體的檢視給DispatchServlet
10.填充資料,渲染檢視。
11.展示給使用者
二、畫圖解析
2 、SpringMVC三大元件處理器對映器、處理器介面卡、檢視解析器。
處理器對映器:註解式處理器對映器,對類中標記了@ResquestMapping的方法進行對映,根據@ResquestMapping定義的url匹配@ResquestMapping標記的方法,匹配成功返回HandlerMethod物件給前端控制器。
<!-- 配置處理器對映器 -->
<bean
class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping" />
處理器介面卡:對標記@ResquestMapping的方法進行適配
<!-- 配置處理器介面卡 -->
<bean
class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter" />
解決辦法:
SpringMVC使用<mvc:annotation-driven>自動載入RequestMappingHandlerMapping和RequestMappingHandlerAdapter
可以在springmvc.xml配置檔案中使用<mvc:annotation-driven>替代註解處理器和介面卡的配置。
<!-- 註解驅動 -->
<mvc:annotation-driven />
檢視解析器:檢視解析器使用SpringMVC框架預設的InternalResourceViewResolver,這個檢視解析器支援JSP檢視解析。
<!-- 配置檢視解析器 -->
<bean
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<!-- 配置邏輯檢視的字首 -->
<property name="prefix" value="/WEB-INF/jsp/" />
<!-- 配置邏輯檢視的字尾 -->
<property name="suffix" value=".jsp" />
</bean>
最終jsp實體地址:字首+邏輯檢視名+字尾
3、引數型別推薦使用包裝資料型別,因為基礎資料型別不可以為null。
4、SpringMVC與struts2的不同
- SpringMVC的入口是一個servlet即前端控制器,而struts2入口是一個filter過濾器。
- SpringMVC是基於方法開發(一個url對應一個方法),請求引數傳遞到方法的形參,可以設計為單例或多例(建議單例),struts2是基於類開發,傳遞引數是通過類的屬性,只能設計為多例。
- Struts2採用值棧儲存請求和響應的資料,通過OGNL存取資料, SpringMVC通過引數解析器是將request請求內容解析,並給方法形參賦值,將資料和檢視封裝成ModelAndView物件,最後又將ModelAndView中的模型資料通過request域傳輸到頁面。Jsp檢視解析器預設使用jstl。