第三章:JavaMVC框架之SpringMVC
歡迎檢視Java開發之上帝之眼系列教程,如果您正在為Java後端龐大的體系所困擾,如果您正在為各種繁出不窮的技術和各種框架所迷茫,那麼本系列文章將帶您窺探Java龐大的體系。本系列教程希望您能站在上帝的角度去觀察(瞭解)Java體系。使Java的各種後端技術在你心中模組化;讓你在工作中能將Java各個技術瞭然於心;能夠即插即用。本章我們來一起了解Java的MVC框架之SpringMVC。
Java語言現在應用比較多的MVC框架有SpringMVC,Struts2兩種。本章我們就來講解SpringMVC,對於本篇SpringMVC本篇不會介紹其詳細知識點及具體應用,Spring系列詳細使用和高階應用相關知識都在第四章:Spring專欄進行講解,本篇將會介紹Spring的基礎相關概念,這些基礎概念是很重要的,它就如同蓋房子的基石。本章示例原始碼下載
什麼是MVC?
不可免俗地我還是想在本章開始與大家一起回顧一下什麼是MVC?MVC其實就是一種軟體的設計模式。在開發中並沒有強制我們必須去遵循這種設計模式,但是遵循MVC模式會使我們系統層次更清晰;職責更明確;擴充套件性更強;耦合度降低。
什麼是SpringMVC?
SpringMVC就是一個嚴格遵循MVC設計模式的框架。說其是一個框架,那麼SpringMVC框架中就應該有與Model,View,Controller相對應的元件;分別是Model模型物件,檢視解析器,Controller控制器。
SpringMVC屬於SpringFrameWork的後續產品,SpringMVC對於構建WEB專案而言是可選的,如果你使用Spring框架,你可以選擇使用SpringMVC或者整合其他MVC框架。同時Spring MVC分離了控制器、模型物件、過濾器以及處理程式物件的角色,這種分離讓它們更容易進行定製。
為什麼使用SpringMVC?
- 學習門檻低,容易上手
- SpringMVC繼承了Spring框架的靈活性,容易擴充套件
- Spring將控制器,模型物件,過濾器等分離,使元件之間鬆耦合
- 支援多種檢視
- 輕鬆使用Spring生態下的其他元件
SpringMVC請求流程
- 使用者發起請求到DispatchServlet
- Handler Mapping匹配請求資訊的Handler(匹配條件:請求路徑,方法,header資訊)
- HandlerMapping向DispatchServlet返回handler,返回過程執行攔截器鏈(一系列攔截器Interceptor)
- 請求HandlerAdapter執行Handler
- HandlerAdapter根據Handler型別執行不同的Handler(處理器)
- Handler執行完畢返回給HandlerAdapter(處理器介面卡)ModelAndView物件
- HandlerAdapter將ModelAndView返回給DispatchServlet
- DispatchServlet請求ViewResolver解析ModelAndView
- ViewResolver向DispatchServlet返回View
- DispatchServlet將View和模型資料進行檢視渲染
- DispatchServlet向用戶響應結果
SpringMVC常用元件
前端控制器DispatcherServlet 接受請求,響應結果,相當於轉發器,中央處理器,減少了與其他元件之間的耦合度
處理器對映器HandlerMapping 根據規則查詢需要執行的Handler
處理器介面卡HandlerAdapter 根據Handler型別,尋找相應處理器執行Handler
處理器 Handler 可以實際處理請求的方法,如被@RequestMapping標註的方法
檢視解析器 ViewResolver 進行檢視解析,根據邏輯檢視名解析成真正的檢視(view)
檢視View View是一個介面,實現類支援不同的view型別(jsp,framemark,pdf…)
檔案上傳解析器MultipartResolver 用於處理上傳請求。
SpringMVC基本配置
典型的XML配置方式
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd">
<!--載入資料字典-->
<context:property-placeholder location="classpath:resource.properties"/>
<!--配置預設的Servlet作為靜態資源的Handler-->
<mvc:default-servlet-handler/>
<!-- 註解驅動:作用:替我們自動配置最新版的註解的處理器對映器和處理器介面卡-->
<mvc:annotation-driven/>
<!-- 配置@Controller註解掃描 -->
<context:component-scan base-package="com.jimisun.controller"></context:component-scan>
<!--配置InternalResourceViewResolver檢視解析器解析返回資料-->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="cache" value="false"/>
<property name="prefix" value="/WEB-INF/jsp/"/>
<property name="suffix" value=".jsp"/>
<property name="contentType" value="text/html;charset=UTF-8"/>
</bean>
<!--配置自定義exceptionResolver異常解析器處理異常-->
<bean id="exceptionResolver" class="com.jimisun.exception.MyExceptionResolver"/>
<!--配置檔案上傳-->
<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>
</bean>
<!--配置攔截器-->
<mvc:interceptors>
<mvc:interceptor>
<!--攔截路徑規則-->
<mvc:mapping path="/user/**"/>
<!--排除路徑-->
<mvc:exclude-mapping path="/user/login.html"></mvc:exclude-mapping>
<mvc:exclude-mapping path="/user/register.html"></mvc:exclude-mapping>
<bean id="viewLoginInterceptor" class="com.jimisun.interceptor.ViewLoginInterceptor"></bean>
</mvc:interceptor>
</mvc:interceptors>
</beans>
從Servlet3.0開始,可以完全脫離XML對SpringWeb專案進行配置
/**
* @Author:jimisun
* @Description:
* @Date:Created in 19:42 2018-09-28
* @Modified By:
*/
public class MyWebApplicationInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
@Override
protected Class<?>[] getRootConfigClasses() {
return new Class[]{RootConfig.class};
}
@Override
protected Class<?>[] getServletConfigClasses() {
return new Class[]{WebConfig.class};
}
@Override
protected String[] getServletMappings() {
return new String[]{"/"};
}
}
SpringMVC單元測試
/**
* @Author:jimisun
* @Description:
* @Date:Created in 07:58 2018-09-25
* @Modified By:
*/
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {
"classpath:SpringMvc.xml",
})
public class TestControllerTest {
@Autowired
private TestService testService;
@Test
public void sayhello() {
String test = testService.sayHelloService("test");
System.out.println(test);
}
}
SpringMVC驗證Web請求引數
對於Controller接收到的引數,幾乎在所有情況下我們都需要驗證,SpringMVC開發中常用的驗證方法有兩種,Spring框架定義Validator校驗和JSP-303Bean Validation校驗。
@RequestMapping("sayhello")
public void sayhello(@Validated User user, BindingResult bindingResult) {
if (bindingResult.hasErrors()) {
System.out.println(bindingResult.getFieldError().getDefaultMessage());
} else {
String s = testService.sayHelloService(user.getUsername());
System.out.println(s);
}
Spring在3.1的時候增加了對JSP-303 BeanValidation規範的支援,不僅可以對SpringMVC進行校驗,還可以對Hibernate的物件儲存進行校驗,是一個通用的校驗框架,在開發中我們都是用JSP-303Bean Validation進行校驗,也是個人推薦使用的。
hibernate-validator依賴
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-validator</artifactId>
<version>6.0.4.Final</version>
</dependency>
相關配置
<mvc:annotation-driven validator="validator"/>
<bean id="validator" class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean">
<property name="providerClass" value="org.hibernate.validator.HibernateValidator"/>
<property name="validationMessageSource" ref="messageSource"/>
</bean>
<!-- 校驗錯誤資訊配置檔案 -->
<bean id="messageSource" class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
<!-- 資原始檔名 -->
<property name="basename" value="classpath:validationMessages"/>
<!-- 對資原始檔內容快取時間,單位秒 -->
<property name="fileEncodings" value="GBK"/>
<property name="defaultEncoding" value="GBK"/>
<property name="cacheSeconds" value="120"/>
</bean>
在接收引數時使用@Valid
進行校驗
@RequestMapping("sayhello")
public void sayhello(@Valid User user, BindingResult bindingResult) {
if (bindingResult.hasErrors()) {
System.out.println(bindingResult.getFieldError().getDefaultMessage());
} else {
String s = testService.sayHelloService(user.getUsername());
System.out.println(s);
}
}
使用下面註解對引數進行約束
@Valid 被註釋的元素是一個物件,需要檢查此物件的所有欄位值
@Null 被註釋的元素必須為 null
@NotNull 被註釋的元素必須不為 null
@AssertTrue 被註釋的元素必須為 true
@AssertFalse 被註釋的元素必須為 false
@Min(value) 被註釋的元素必須是一個數字,其值必須大於等於指定的最小值
@Max(value) 被註釋的元素必須是一個數字,其值必須小於等於指定的最大值
@DecimalMin(value) 被註釋的元素必須是一個數字,其值必須大於等於指定的最小值
@DecimalMax(value) 被註釋的元素必須是一個數字,其值必須小於等於指定的最大值
@Size(max, min) 被註釋的元素的大小必須在指定的範圍內
@Digits (integer, fraction) 被註釋的元素必須是一個數字,其值必須在可接受的範圍內
@Past 被註釋的元素必須是一個過去的日期
@Future 被註釋的元素必須是一個將來的日期
@Pattern(value) 被註釋的元素必須符合指定的正則表示式
@Email 被註釋的元素必須是電子郵箱地址
@Length(min=, max=) 被註釋的字串的大小必須在指定的範圍內
@NotEmpty 被註釋的字串的必須非空
@Range(min=, max=) 被註釋的元素必須在合適的範圍內
@NotBlank 被註釋的字串的必須非空
@URL(protocol=,host=, port=, regexp=, flags=) 被註釋的字串必須是一個有效的url
@CreditCardNumber 被註釋的字串必須通過Luhn校驗演算法,銀行卡,信用卡等號碼一般都用Luhn計算合法性
Java開發之上帝之眼系列教程其他文章
勘誤&感謝
本系列文章資料來源很多出自於網際網路和在下本身的見解,受限於個人技術能力水平和其他相關知識的限制,相關見解錯誤或者資料引用錯誤請各位幫助留言校正!引用資料多來自於網際網路,在下在引用前會遵循各位前輩或者博主的引用說明表示感謝,但網際網路資料多是轉發再轉發或存在遺漏請原作者內信聯絡指正。