SpringMVC的基本概念
什麼是MVC
是一種基於兩種形式,一種是C/S架構,也就是客戶端/服務器,
另一種是B/S架構,也就是瀏覽器/服務器. 在JavaEE中,幾乎全是基於B/S架構的開發,
那麼在B/S架構中,系統標準的三層架構包括:表現層,業務層,持久層.
什麼是SpringMVC?
SpringMVC是一種基於java實現的MVC設計模型的請求驅動類型的輕量級WEB框架,爲目前最主流的MVC框架之一,他通過一套註解,讓一個簡單的java類成爲處理請求的控制器,無需實現任何接口.同時還支持RESTful編程風格的請求
MVC設計模型:
M: model 模型 javaBean對象 一般用於封裝數據
V: view 視圖 JSP/Html 一般用於展示數據
C: Controller 控制器 Servlet 一般用於處理程序邏輯
SpringMvc和Struts2:
共同點:
他們都是表現層的框架,都是基於MVC模型編寫的
他們的底層都離不開ServletAPI
他們的處理請求的機制都是一個核心控制器
區別:
SpringMVC的入口是Servlet , Struts2的入口是Filter
SpringMVC是基於方法設計的, Struts2是基於類設計的,Struts2每次執行都會創建一個動作類,而SpringMVC只會創建一個類,執行時調用類中的方法.
SpringMVC更加簡潔,同時還支持JSR303,處理ajax的請求更方便
Struts2的OGNL表達式使頁面的開發效率相比SpringMVC更高,但執行效率並沒有比JSTL提升,尤其是struts2的表單標籤,遠沒有html執行效率高.
SpringMVC搭建環境
在New Module的 Properties屬性添加插件(解決maven項目創建過慢):
Name:archetypeCatalog Value:internal
創建java目錄: java,resource目錄
pom.xml文件
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.7</maven.compiler.source>
<maven.compiler.target>1.7</maven.compiler.target>
<spring.version>5.0.2.RELEASE</spring.version>
</properties>
<!--Spring MVC依賴-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring.version}</version>
</dependency>
web.xml文件配置:
<!-- 前端控制器的配置-->
<servlet>
<servlet-name>dispatcherServlet</servlet-name>
//springmvc提供的類
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<!--加載springmvc.xml配置文件-->
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:springmvc.xml</param-value>
</init-param>
<!--一般servlet只有當發送請求時才創建
配置該參數,只要服務器一啓動,就會創建servlet對象,
servlet對象一創建,就會去加載springmvc.xml文件
-->
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>dispatcherServlet</servlet-name>
<url-pattern>/</url-pattern> / :不管發什麼請求,都會經過servlet
</servlet-mapping>
<!--配置解決中文亂碼的過濾器-->
<filter>
<filter-name>characterEncodingFilter</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>
</filter>
<filter-mapping>
<filter-name>characterEncodingFilter</filter-name>
<url-pattern>/</url-pattern> / :不管發什麼請求,都會經過過濾器
</filter-mapping>
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:mvc="http://www.springframework.org/schema/mvc"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/mvc
https://www.springframework.org/schema/mvc/spring-mvc.xsd
http://www.springframework.org/schema/context
https://www.springframework.org/schema/context/spring-context.xsd">
<!--開啓註解的掃描-->
<context:component-scan base-package="com.tulun"></context:component-scan>
<!--配置視圖解析器-->
<bean id="internalResourceViewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<!--prefix: 文件所在的目錄-->
<property name="prefix" value="/WEB_INF/pages/"/>
<!--文件的後綴名-->
<property name="suffix" value=".jsp"/>
</bean>
<!--開啓SpringMVC框架的註解的支持-->
<mvc:annotation-driven/>
</beans>
index.jsp文件:
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<h3>入門程序</h3>
<a href="hello">入門程序</a>
</body>
</html>
HelloController.java文件:
//控制器的類 ,用來接收請求
@Controller
public class HelloController {
//在方法上面添加請求的映射
//(path="/hello" 那麼以後/hello就是該方法的請求路徑)
@RequestMapping(path = "/hello")
public String sayHello() {
System.out.println("Hello SpringMVC");
//默認返回的值爲當前jsp文件的名字
return "success";
}
}
WEB-INF目錄下添加pages/success.jsp文件:
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<h3>入門成功</h3>
</body>
</html>
運行的步驟
1.導入依賴
2.在web.xml配置前端控制器(在起啓動服務器的時候就加載springmvc.xml文件)
3.在index.jsp文件創建一個鏈接
入門程序
4.在springmvc.xml文件
<!--開啓註解的掃描-->
<context:component-scan base-package="com.tulun"></context:component-scan>
當你點開該鏈接,就會去該包下的類查找index.jsp文件的 的值(也就是類中的方法)
5.找到之後
@RequestMapping(path="/hello")
public String sayHello() {
System.out.println("Hello SpringMVC");
//默認返回的值爲當前jsp文件的名字
return "success";
}
6.接下來在springmvc.xml文件配置視圖解析器
<!--配置視圖解析器-->
<bean id="internalResourceViewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<!--prefix: 文件所在的目錄-->
<property name="prefix" value="/WEB-INF/pages/"/>
<!--文件的後綴名-->
<property name="suffix" value=".jsp"/>
</bean>```
以上兩個配置的意義:就會去在/WEB-INF/pages/目錄下找名字爲success.jsp的文件
所以需要在該目錄下創建該文件success.jsp(例:此處爲成功請求頁面)
常用註解
@RequestMapping註解
用於建立請求URL和處理請求方法之間的對應關係
可以放在方法上,也可以是類
試例:
<a href="controller/testRequestMapping">RequestMapping註解</a>
@RequestMapping(path = "/controller")
public class HelloController {
@RequestMapping(path = "/testRequestMapping")
public String testRequestMapping() {
}
}
屬性:
value和path的作用是一樣的
@RequestMapping(path = "/controller")
public class HelloController {
@RequestMapping(value = "/testRequestMapping")
public String testRequestMapping() {
}
}
method: 請求方式
//method={RequestMethod.POST} 表示該方法的請求必須爲 post 方式 (爲枚舉類型)
@RequestMapping(path = "/testRequestMapping",method={RequestMethod.POST})
public String testRequestMapping() {
}
params: 請求的時候必須傳入一個 username的參數 如果params = {“username=hehe”}傳入的參數必須爲這樣 ?username=hehe
@RequestMapping(path = "/testRequestMapping",params ={"username"})
public String testRequestMapping() {
}
<a href="controller/testRequestMapping?username=haha">RequestMapping註解</a>
@RequestParam:
把請求中指定名稱的參數給控制器中的形參賦值
<a href="anno/testRequestParam?name=haha">RequestParam</a>
@RequestMapping("/testRequestParam")
public String testRequestParam(@RequestParam(value = "name") String username) {
System.out.println("執行了...");
return "success";
}
@RequestBody:
獲取到請求體的內容
<form action="/anno/testRequestBody" method="post">
姓名: <input type="text" name="username"/><br/>
密碼: <input type="text" name="age"/><br/>
<input type="submit" value="提交"/>
</form>
/**
* 獲取到請求體的內容
* @param body
* @return
*/
@RequestMapping("testRequestBody")
public String testRequestBody(@RequestBody String body) {
System.out.println("執行了...");
return "success";
}
@PathVaribale:
和restful風格很像 path="/user/{id}" 傳一個佔位符
RESTful風格URL:
優點:節後清晰,符合標準,易於理解,擴展方便,更利於緩存
原來方式:
UserController類
path="/user/save"
save
path="/user/update"
update
path="/user/findAll"
findAll
restful方式: 根據不同的請求方式,找到方法執行
UserController類
path="/user" post
save
path="/user" put
update
path="/user" get
findAll
path="/user/{id}" get
findById(id)
localhost:8080/user/10 get(請求方式) 查詢的是findById
localhost:8080/user get 查詢的是findAll
@SessionAttribute
anno.jsp文件
<%--SessionAttritubes--%>
<a href="anno/testSessionAttributes">SessionAttributes</a>
<a href="anno/getSessionAttribute">SessionAttributes</a>
<a href="anno/delSessionAttribute">SessionAttributes</a>
AnnoController.java
@SessionAttributes("msg") //將數值存入Session域
public class AnnoController {
/**
* testSessionAttributes註解 向session存值
* @return
*/
@RequestMapping("/testSessionAttribute")
public String testSessionAttributes(Model model) {
System.out.println("testSessionAttributes...");
//將一組鍵值對存入model對象 會存儲到Request域對象中
model.addAttribute("msg","meimei");
return "success";
}
/**
* 獲取值
* @param modelMap
* @return
*/
@RequestMapping("/getSessionAttribute")
public String testGetSessionAttributes(ModelMap modelMap) {
System.out.println("testSessionAttributes...");
String msg = (String)modelMap.get("msg");
System.out.println(msg);
return "success";
}
/**
* 刪除值
* @param sessionStatus
* @return
*/
@RequestMapping("/delSessionAttribute")
public String testDelSessionAttributes(SessionStatus sessionStatus) {
System.out.println("testSessionAttributes...");
//清空Session域
sessionStatus.setComplete();
return "success";
}
}
success.jsp
<!--說明不忽略EL表達式-->
<%@ page contentType="text/html;charset=UTF-8" language="java" isELIgnored="false" %>
${ requestScope }
${ sessionScope }
返回值
response.jsp文件
<a href="user/testString">TestString</a>
<a href="user/testVoid">TestVoid</a>
UserController.java文件
//返回值爲字符串
@RequestMapping(path = "/testString")
public String testString(Model model) {
System.out.println("testString...");
//模擬從數據庫中查詢User對象
User user = new User();
user.setUname("fly");
user.setAge(19);
user.setDate(new Date());
//model存對象
model.addAttribute("user",user); //存入request域
return "success";
}
//返回值爲void 注:如果沒有返回值,會默認去WEB-INF/pages/user/找testVoid.jsp文件
@RequestMapping(path = "/testVoid")
public void testVoid(HttpServletRequest request,HttpServletResponse response) throws Exception {
System.out.println("testVoid...");
//請求轉發 手動轉發不會調用視圖解析器 所以要自己寫路徑
request.getRequestDispatcher("WEB-INF/pages/success.jsp").forward(request,response);
//重定向 會重定向請求index.jsp
response.sendRedirect(request.getContextPath()+"/index.jsp");
//設置中文亂碼
response.setCharacterEncoding("UTF-8");
response.setContentType("text/html;charset=UTF-8");
//會直接進行響應
response.getWriter().println("你好");
}
異常處理
異常處理思路:Controller調用service ,service調用dao,異常都是向上拋出的,最終由DispatcherServlet異常處理器進行異常的處理.
SpringMVC異常處理:在前端控制器配置一個 異常處理器(組件).
1.編寫自定義異常類(做提示信息的)
public class SysException extends Exception{
//存儲提示信息
private String message;
public SysException(String message) {
this.message = message;
}
@Override
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
}
2.編寫異常處理器
public class SysExceptionResolver implements HandlerExceptionResolver {
/**
* 處理異常的業務邏輯
* @param request
* @param response
* @param o
* @param e
* @return
*/
@Override
public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object o, Exception e) {
//獲取異常對象
SysException exception = null;
if(e instanceof SysException) {
exception = (SysException)e;
} else {
exception = new SysException("系統正在維護...");
}
//創建ModelAndView
ModelAndView mv = new ModelAndView();
mv.addObject("errorMsg",exception.getMessage());
//表示往哪去跳轉
mv.setViewName("error");
return mv;
}
}
3.配置異常處理器(跳轉到提示頁面)
<!--配置異常處理器-->
<bean id="sysExceptionResolver" class="com.tulun.exception.SysExceptionResolver"></bean>
SpringMVC攔截器
攔截器是springMVC框架自己的,只有使用了SpringMVC框架後才能用
過濾器是servlet規範中的一部分,任何web項目都可以使用
攔截器只會攔截訪問的控制器(Controller)的方法,如果訪問的是jsp,html,css,image都不會攔截
過濾器是url-pattern中配置了 /* 之後,對所有訪問資源進行攔截
1.編寫攔截器類 實現HandlerInterceptor接口
public class MyInterceptor implements HandlerInterceptor {
/**
* 預處理 在controller方法執行前執行
* @param request
* @param response
* @param handler
* @return true:放行,執行下一個攔截器,如果沒有,執行controller方法
* @throws Exception
*/
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("攔截器執行了....前");
//頁面跳轉
// request.getRequestDispatcher("/WEB-INF/pages/error.jsp").forward(request,response);
return true;
}
/**
* 後處理方法 在controller方法執行後 success.jsp執行之前
* @param request
* @param response
* @param handler
* @param modelAndView
* @throws Exception
*/
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("攔截器執行了....後");
}
/**
* 在success.jsp執行後執行
* @param request
* @param response
* @param handler
* @param ex
* @throws Exception
*/
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
System.out.println("攔截器執行了....最後");
}
}
2.配置攔截器
<!--配置攔截器-->
<mvc:interceptors>
<!--配置攔截器-->
<mvc:interceptor>
<!--要攔截的具體的方法-->
<mvc:mapping path="/user/*"/>
<!--不要攔截的方法
<mvc:exclude-mapping path=""/>-->
<!--配置攔截器對象-->
<bean id="myInterceptor" class="com.tulun.interceptor.MyInterceptor"/>
</mvc:interceptor>
</mvc:interceptors>