springmvc的底層是Servlet,以Servlet為核心,接收請求,處理請求,顯示處理結果給使用者。
DispatcherServlet 是框架一個Servlet物件,負責接收請求,響應處理結果。
DispatcherServlet 他的父類別是HttpServlet
M:Model,模型層,指工程中的JavaBean,作用是處理資料
V:View,檢視層,指工程中的html或jsp等頁面,作用是與使用者進行互動,展示資料
C:Controller,控制層,指工程中的servlet,作用是接收請求和響應瀏覽器
MVC的處理模式是:使用者通過檢視層(View)將資料傳送給伺服器的控制層(Controller),控制層通過呼叫業務層在呼叫資料層去獲取資料, 然後再將請求處理的結果返回給View檢視層,最後檢視層渲染資料響應給瀏覽器。
<!-- 新增註解掃描器 -->
<context:component-scan base-package="com.meteor.controller"/>
<!-- 新增檢視解析器 -->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<!-- 設定字首 -->
<property name="prefix" value="/admin/"/>
<!-- 設定字尾 -->
<property name="suffix" value=".jsp"/>
</bean>
<!-- 註冊SpringMVC框架 -->
<servlet>
<servlet-name>springmvc</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<!-- 填寫springmvx.xml組態檔的名稱,讓它去讀取 -->
<param-value>classpath:springmvc.xml</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>springmvc</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<!--註冊Spring框架,目的就是啟動spring容器-->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:applicationContext_*.xml</param-value>
</context-param>
<!--新增中文編碼過濾器
private String encoding;
private boolean forceRequestEncoding;
private boolean forceResponseEncoding;
-->
<filter>
<filter-name>encode</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
<init-param>
<param-name>forceRequestEncoding</param-name>
<param-value>true</param-value>
</init-param>
<init-param>
<param-name>forceResponseEncoding</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>encode</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
可以放在類的上面,相當於多加了一層路徑
可以放在方法上面,表示請求的路徑
value可以預設不寫,method預設是GET請求
引數最好使用包裝型別,例如Integer,能接收空值情況,接收的是null
@RequestMapping(value = "/some.do", method= RequestMethod.GET)
public ModelAndView doSome() {
接收請求引數:
@RequestMapping("/hello/{name}/{age}")
public String one(@PathVariable String name,@PathVariable Integer age) {
return "main";
}
@RequestMapping("/hello")
public String one(@RequestParam("name") String uname,@RequestParam("age") Integer uage) {
return "main";
}
@RequestMapping("/hello")
public String one(HttpServletRequest request) {
String name = request.getParameter("name");
int age = Integer.parseInt(request.getParameter("age"));
return "main";
}
@RequestMapping(value = "/test/receive-property.do")
public ModelAndView doPropertyParam(User user) {
String:使用者端資源的地址,自動拼裝字首和字尾,還可以遮蔽自動拼接字串,可以指定返回路徑
Object:返回json格式的物件,自動將物件或者集合轉為json,使用jackson工具進行轉換,必須新增jackson依賴,一般用於ajax
void:無返回值,一般用於ajax請求
基本資料型別,用於ajax請求
ModelAndView:返回資料和檢視物件,用的較少
當我們採用ajax方式請求的時候,需要設定註解驅動<mvc:annotation-driven/>
,並且在類上加入@ResponseBody
,也可以使用@RestController
,它是@Controller
+ @ResponseBody
HttpMessageConverter介面:
//把物件轉為json
ObjectMapper om = new ObjectMapper();
String json = om.writeValueAsString(student);
System.out.println("json=" + json);
mvc:annotation-driven
加入這個標籤後,springmvc專案啟動後,會建立HttpMessageConveter
介面的7個實現類物件。包括StringHttpMessageConveter
和 Mappingjackson2HttpMessageConverter
請求轉發的url位址列是不變的
轉發使用forward
這個時候會清空我們的檢視解析器設定,需要我們自己寫明白具體的路徑
@RequestMapping("/other")
public String other() {
System.out.println("存取了other");
return "main";
}
@RequestMapping("/two")
public String two() {
System.out.println("請求轉發action跳轉");
// forward:這組字串可以遮蔽字首和字尾的拼接
return "forward:/other.do";
}
重定向的url是改變的,並且變得是最終請求的地址url
重定向無法攜帶資料,並且需要使用redirect
,也要寫明路徑名稱
@RequestMapping("/three")
public String three() {
System.out.println("這是重定向頁面");
return "redirect:/admin/main.jsp";
}
@RequestMapping("/four")
public String four() {
System.out.println("這是重定向action");
return "redirect:/other.do";
}
HttpServletRequest
HttpServletResponse
HttpSession
Model
Map
ModelMap
Model、Map、ModelMap和HttpServletRequest 一樣,使用請求作用域進行資料傳遞,所以伺服器跳轉必須是請求轉發。
由於我們的中央排程器設定的是 "/":
使用 "/" 導致中央排程器是預設的 default servlet
需要處理靜態資源和其他的為對映請求。 預設中央排程器沒有處理靜態資源的控制器物件,所以靜態資源都是404.
some.do這個請求有MyController物件,所以能存取。
如果專案中,中央排程器設定了"/",動態資源能存取,靜態資源不能存取,需要處理靜態資源的存取工作。
註解式方法:
<!--宣告註解驅動
default-servlet-handler和@RequestMapping使用有衝突
-->
<mvc:annotation-driven />
<!--宣告靜態資源的第一種處理方式
建立DefaultServletHttpRequestHandler處理靜態資源。
DefaultServletHttpRequestHandler把接收的靜態資源的地址,轉發給tomcat的default
優點:解決方式簡單
缺點:依賴tomcat伺服器提供的能力
-->
<mvc:default-servlet-handler />
匯入靜態資源法:
在springmvc組態檔中加入一個 mvc:resources標籤,框架會建立ResourceHttpRequestHandler控制器物件,使用這個物件處理靜態資源的存取,不依賴tomcat伺服器。推薦使用!
一句話設定靜態資源
<mvc:resources mapping="/static/**" location="/static/" />
WEB-INF目錄下的資源無法通過瀏覽器的url直接存取。都是通過controller的請求轉發進行存取
但是這樣也並不安全,因為我可以把它的請求路徑記住,所以我們就需要用到了攔截器
攔截器的定義:
建立類實現攔截器介面 HandlerInterceptor,實現介面中的方法3個
preHandle():在請求被處理之前進行操作
postHandle():在請求被處理之後,但結果還沒有渲染前進行操作,可以改變響應結果
afterCompletion:所有的請求響應結束後執行善後工作,清理物件、關閉資源、最終處理
在springmvc的組態檔中,宣告攔截器物件,並置頂攔截的url地址
<!-- 註冊攔截器 -->
<mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path="/**"/>
<!-- 設定放行的請求 -->
<mvc:exclude-mapping path="/shouLogin"/>
<mvc:exclude-mapping path="/login"/>
<!-- 設定具體的攔截器實現功能類 -->
<bean class="com.meteor.interceptor.LoginInterceptor"/>
</mvc:interceptor>
</mvc:interceptors>
//攔截器
public class MyInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("preHandle先處理");
return true;
}
}
多個攔截器的時候也採用的是責任鏈設計模式,和我們JavaWeb部分的Filter過濾器一樣,可以跳轉到我的Tomcat深入淺出文章去了解一下
先執行過濾器、在執行中央排程器、最後才是攔截器。
一般攔截器都是用作登入攔截
框架使用的是集中的例外處理。把各個Controller中丟擲的異常集中到一個地方處理。處理異常的叫做例外處理器。
@ControllerAdvice:放在類的上面,表示這個類中有異常的處理方法。相當於aop中的@Aspect
@ExceptionHandler:放在方法的上面,表示此方法可以處理某個型別的異常。當異常發生時,執行這個方法。
@ControllerAdvice
public class GlobalExceptionHandler {
//定義處理異常的方法,當異常發生後,執行這個方法
/**
*處理NameException型別的異常
* 引數:
* @ExceptionHandler: 表示Controller丟擲的異常物件
* 屬性: value 異常的型別
*/
@ExceptionHandler(value = NameException.class)
public ModelAndView doNameException(Exception e) {
//給使用者友好的提示
ModelAndView mv = new ModelAndView();
mv.addObject("tips","姓名只能是zs");
mv.setViewName("nameError");
return mv;
}
}
我們需要把java物件放到容器裡,我們現在有兩個容器
Spring容器:管理service和dao等物件的,是業務層物件的容器。
SpringMVC容器:管理控制器controller物件的,是檢視層物件。
Spring容器建立: 在web.xml中宣告了ContextLoaderListener
,這個功能是框架寫好的,建立spring容器物件WebApplicationContext
。在建立WebApplicationContext
的時,就讀取了spring的組態檔,當遇到bean
標籤的時候就將service、dao等物件建立好放到容器中。
SpringMVC容器建立: SpringMVC是Spring的子容器,它是用於將pojo實體類的物件建立出來的,操作的是Controller層
application_mapper.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"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">
<!-- 讀取屬性檔案-->
<context:property-placeholder location="classpath:jdbc.properties"/>
<!-- 設定資料來源-->
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
<property name="driverClassName" value="${jdbc.driverClassName}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</bean>
<!-- 設定SqlSessionFactoryBean-->
<bean class="org.mybatis.spring.SqlSessionFactoryBean">
<!--設定資料來源-->
<property name="dataSource" ref="dataSource"/>
<!-- 設定SqlMapConfig.xml核心組態檔-->
<property name="configLocation" value="classpath:SqlMapConfig.xml"/>
<!--註冊實體類-->
<property name="typeAliasesPackage" value="com.meteor.pojo"/>
</bean>
<!-- 註冊mapper.xml檔案-->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="com.meteor.mapper"/>
</bean>
</beans>
application_service.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:tx="http://www.springframework.org/schema/tx"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd">
<!--新增包掃描-->
<context:component-scan base-package="com.meteor.service.impl"></context:component-scan>
<!--新增事務管理器-->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<!--切記切記:設定資料來源-->
<property name="dataSource" ref="dataSource"></property>
</bean>
<!--設定事務切面-->
<tx:advice id="myadvice" transaction-manager="transactionManager">
<tx:attributes>
<tx:method name="*select*" read-only="true"/>
<tx:method name="*find*" read-only="true"/>
<tx:method name="*serach*" read-only="true"/>
<tx:method name="*get*" read-only="true"/>
<tx:method name="*insert*" propagation="REQUIRED"/>
<tx:method name="*add*" propagation="REQUIRED"/>
<tx:method name="*save*" propagation="REQUIRED"/>
<tx:method name="*set*" propagation="REQUIRED"/>
<tx:method name="*update*" propagation="REQUIRED"/>
<tx:method name="*change*" propagation="REQUIRED"/>
<tx:method name="*modify*" propagation="REQUIRED"/>
<tx:method name="*delete*" propagation="REQUIRED"/>
<tx:method name="*drop*" propagation="REQUIRED"/>
<tx:method name="*remove*" propagation="REQUIRED"/>
<tx:method name="*clear*" propagation="REQUIRED"/>
<tx:method name="*" propagation="SUPPORTS"/>
</tx:attributes>
</tx:advice>
<!--設定切入點+繫結-->
<aop:config>
<aop:pointcut id="mycut" expression="execution(* com.meteor.service.impl.*.*(..))"></aop:pointcut>
<aop:advisor advice-ref="myadvice" pointcut-ref="mycut"></aop:advisor>
</aop:config>
</beans>
springmvc.xml
//新增包掃描
<context:component-scan base-package="com.meteor.controller"/>
//便於使用ajax
<mvc:annotation-driven/>