一 SpringMVC簡介
SpringMVC是Spring提供的一個強大而靈活的Web框架 借助于注解 SpringMVC提供了幾乎是POJO的開發模式 使得控制器的開發和測驗更加簡單
二 SpringMVC優點
1. 角色劃分清晰
2. 分工明確 而且擴展相當靈活
3. 和Spring其它框架無縫集成 是其它Web框架所不具備的
4. 功能強大的資料驗證 格式化 系結機制
5. 約定大于配置的契約式編程支持 基于注解的零配置支持等等
三 SpringMVC框架核心

DispatcherServlet 前端控制器
用戶請求到達前端控制器 它就相當于MVC模式中的C DispatcherServlet是整個流程控制的中心 由它呼叫其它組件處理用戶的請求 DispatcherServlet的存在降低了組件之間的耦合性
HandlerMapping 處理器映射器
SpringMVC三大組件之一 HandlerMapping負責根據用戶請求URL找到Handler即處理器 SpringMVC提供了不同的映射器實作不同的映射方式 比如組態檔方式 實作介面方式 注解方式等等
Handler 處理器
Handler是繼DispatcherServlet前端控制器的后端控制器 在DispatcherServlet的控制下Handler對具體的用戶請求進行處理 由于Handler涉及到具體的用戶業務請求 所以一般情況需要程式員根據業務需求開發Handler
HandlAdapter 處理器配接器
SpringMVC三大組件之一 通過HandlerAdapter對處理器進行執行 這是配接器模式的應用 通過擴展配接器可以對更多型別的處理器進行執行
ViewResolver 視圖決議器
SpringMVC三大組件之一 ViewResolver負責將處理結果生成View視圖 ViewResolver首先根據邏輯視圖名決議成物理視圖名即具體的頁面地址 再生成View視圖物件 最后對View進行渲染將處理結果通過頁面展示給用戶
View 視圖
SpringMVC提供了很多View視圖型別的支持 比如FreemarkerView PDFView等等 最常用的視圖就是JSP 一般情況下需要通過頁面標簽或頁面模版技術將模型資料通過頁面展示給用戶 需要程式員根據業務需求開發具體的頁面
四 SpringMVC初體驗
1. 新建一個Maven專案
pom.xml
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.hy.springmvc</groupId> <artifactId>springmvc-demo</artifactId> <version>1.0-SNAPSHOT</version> <packaging>war</packaging> <!-- 定義依賴版本號 --> <properties> <javax.servlet-api.version>4.0.1</javax.servlet-api.version> <jsp-api.version>2.0</jsp-api.version> <jstl.version>1.2</jstl.version> <spring.version>5.0.5.RELEASE</spring.version> <jackson-databind.version>2.9.5</jackson-databind.version> <commons-fileupload.version>1.3.3</commons-fileupload.version> </properties> <!-- 管理jar版本號 --> <dependencyManagement> <dependencies> <!-- servlet --> <dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> <version>${javax.servlet-api.version}</version> <scope>provided</scope> </dependency> <!-- jsp --> <dependency> <groupId>javax.servlet</groupId> <artifactId>jsp-api</artifactId> <version>${jsp-api.version}</version> <scope>provided</scope> </dependency> <!-- jstl --> <dependency> <groupId>jstl</groupId> <artifactId>jstl</artifactId> <version>${jstl.version}</version> </dependency> <!-- spring --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-beans</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-jdbc</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-aspects</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-jms</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context-support</artifactId> <version>${spring.version}</version> </dependency> <!-- jackson(spring mvc need) --> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> <version>${jackson-databind.version}</version> </dependency> <!-- fileupload(spring mvc need) --> <dependency> <groupId>commons-fileupload</groupId> <artifactId>commons-fileupload</artifactId> <version>${commons-fileupload.version}</version> </dependency> </dependencies> </dependencyManagement> <dependencies> <!-- servlet --> <dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> <scope>provided</scope> </dependency> <!-- jsp --> <dependency> <groupId>javax.servlet</groupId> <artifactId>jsp-api</artifactId> <scope>provided</scope> </dependency> <!-- jstl --> <dependency> <groupId>jstl</groupId> <artifactId>jstl</artifactId> </dependency> <!-- spring --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-beans</artifactId> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-jdbc</artifactId> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-aspects</artifactId> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-jms</artifactId> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context-support</artifactId> </dependency> <!-- jackson(spring mvc need) --> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> </dependency> <!-- fileupload(spring mvc need) --> <dependency> <groupId>commons-fileupload</groupId> <artifactId>commons-fileupload</artifactId> </dependency> </dependencies> <build> <plugins> <!-- 編譯 --> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>3.7.0</version> <configuration> <source>1.8</source> <target>1.8</target> <encoding>UTF-8</encoding> </configuration> </plugin> <!-- tomcat7 --> <plugin> <groupId>org.apache.tomcat.maven</groupId> <artifactId>tomcat7-maven-plugin</artifactId> <version>2.2</version> <configuration> <port>8080</port> <path>/</path> <uriEncoding>UTF-8</uriEncoding> </configuration> </plugin> </plugins> </build> </project>
2. 新建webapp檔案夾及子檔案夾和web.xml

web.xml
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" version="3.1"> <!-- 處理POST提交亂碼 --> <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> <!-- 前端控制器 --> <servlet> <servlet-name>spring-mvc</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <init-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:/spring-mvc.xml</param-value> </init-param> <!-- 配置SpringMVC啟動時機 1. 第一次被訪問時啟動 值為負數 2. 隨著容器啟動而啟動 值為0或正數 --> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>spring-mvc</servlet-name> <!-- 攔截所有(不包含jsp 包含js png css...) --> <url-pattern>/</url-pattern> </servlet-mapping> </web-app>
3. 創建jsp webapp/WEB-INF/jsp/index.jsp webapp/WEB-INF/jsp/success.jsp webapp/WEB-INF/jsp/exception.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>Title</title> <script type="text/javascript" src="http://code.jquery.com/jquery-1.4.1.min.js"></script> <script type="text/javascript"> var param = '{"name":"祎哥哥", "age":18}'; function json() { $.ajax({ url: "${pageContext.request.contextPath}/test/postBody", data: param, contentType: "application/json;charset=UTF-8", type: "post", dataType: "json", success: function (data) { alert(data.name + ", " + data.age); } }); } </script> </head> <body> <h3>初體驗</h3> ${message}<br/><br/> <a href="${pageContext.request.contextPath}/test/forward">轉發</a><br/><br/> <a href="${pageContext.request.contextPath}/test/redirect">重定向</a><br/><br/> <a href="${pageContext.request.contextPath}/test/error">例外處理</a><br/><br/> <a href="${pageContext.request.contextPath}/test/get?name=hy&age=18">GET請求 /test/get?name=hy&age=18</a><br/><br/> <a href="${pageContext.request.contextPath}/test/getPath/黃祎">GET請求 /test/getPath/黃祎</a><br/><br/> <p>普通表單 普通型別引數系結 List型別引數系結</p> <form action="${pageContext.request.contextPath}/test/postList" method="post"> 姓名 <input type="text" name="name"/><br/> 年齡 <input type="text" name="age"/><br/> 愛好 <input type="checkbox" name="hobby" value="1"/>紅中 <input type="checkbox" name="hobby" value="2"/>發財 <input type="checkbox" name="hobby" value="3"/>白板<br/> <input type="submit" value="提交"/> </form> <p>普通表單 普通型別引數系結 陣列型別引數系結</p> <form action="${pageContext.request.contextPath}/test/postArray" method="post"> 姓名 <input type="text" name="name"/><br/> 年齡 <input type="text" name="age"/><br/> 愛好 <input type="checkbox" name="hobby" value="1"/>紅中 <input type="checkbox" name="hobby" value="2"/>發財 <input type="checkbox" name="hobby" value="3"/>白板<br/> <input type="submit" value="提交"/> </form> <p>普通表單 Model型別引數系結</p> <form action="${pageContext.request.contextPath}/test/postModel" method="post"> 姓名 <input type="text" name="name"/><br/> 年齡 <input type="text" name="age"/><br/> 愛好 <input type="checkbox" name="hobby" value="1"/>紅中 <input type="checkbox" name="hobby" value="2"/>發財 <input type="checkbox" name="hobby" value="3"/>白板<br/> <input type="submit" value="提交"/> </form> <p>檔案表單 單檔案</p> <form action="${pageContext.request.contextPath}/test/postSingleFile" enctype="multipart/form-data" method="post"> 姓名 <input type="text" name="name"/><br/> 檔案 <input type="file" name="file"/><br/> <input type="submit" value="提交"/> </form> <p>檔案表單 多檔案</p> <form action="${pageContext.request.contextPath}/test/postMoreFile" enctype="multipart/form-data" method="post"> 姓名 <input type="text" name="name"/><br/> 檔案 <input type="file" name="file"/> <input type="file" name="file"/><br/> <input type="submit" value="提交"/> </form> <input type="button" value="請求體是json格式字串" onclick="json()"/> </body> </html>
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>Title</title> </head> <body> <h3>成功了</h3> ${user.toString()} </body> </html>
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>Title</title> </head> <body> <h3>出錯了</h3> ${error.toString()} </body> </html>
4. 配置常量 resources/resource.properties
### 常量 ###
NAME=HUANGYI
5. 創建組態檔 resources/spring-mvc.xml
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:context="http://www.springframework.org/schema/context" xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.2.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.2.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.2.xsd"> <!-- 引入組態檔 --> <context:property-placeholder location="classpath:*.properties" /> <!-- 掃描的位置 --> <context:component-scan base-package="com.hy.springmvc.controller" /> <!-- 注解驅動 --> <mvc:annotation-driven /> <!-- 檔案上傳實作類 id名稱必須固定 --> <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver"> <!-- 默認編碼 --> <property name="defaultEncoding" value="UTF-8" /> <!-- 檔案上傳大小(單位B) 5M = 5 * 1024 * 1024 --> <property name="maxUploadSize" value="5242880" /> </bean> <!-- 視圖決議器 --> <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <!-- 邏輯視圖前綴 --> <property name="prefix" value="/WEB-INF/jsp" /> <!-- 邏輯視圖后綴 --> <property name="suffix" value=".jsp" /> </bean> <!-- 加載靜態資源 --> <mvc:default-servlet-handler /> <!-- 攔截器 --> <mvc:interceptors> <mvc:interceptor> <!-- 攔截所有 --> <mvc:mapping path="/**" /> <bean class="com.hy.springmvc.interceptor.Interceptor" /> </mvc:interceptor> <!-- 多個攔截器 攔截器會順序執行 --> <!--<mvc:interceptor>--> <!--<mvc:mapping path="/**" />--> <!--<bean />--> <!--</mvc:interceptor>--> </mvc:interceptors> <!-- 例外處理器 --> <bean class="com.hy.springmvc.exception.HttpErrorResolver" /> </beans>
6. 創建物體類 com.hy.springmvc.model.User com.hy.springmvc.model.HttpError
public class User { private String name; private Integer age; private Integer[] hobby; public String getName() { return name; } public void setName(String name) { this.name = name; } public Integer getAge() { return age; } public void setAge(Integer age) { this.age = age; } public Integer[] getHobby() { return hobby; } public void setHobby(Integer[] hobby) { this.hobby = hobby; } @Override public String toString() { return "User{" + "name='" + name + '\'' + ", age=" + age + ", hobby=" + Arrays.toString(hobby) + '}'; } }
public class HttpError extends Exception { private int code; private String message; public HttpError() {} public HttpError(int code, String message) { this.code = code; this.message = message; } public int getCode() { return code; } public void setCode(int code) { this.code = code; } @Override public String getMessage() { return message; } public void setMessage(String message) { this.message = message; } @Override public String toString() { return "HttpError{" + "code=" + code + ", message='" + message + '\'' + '}'; } }
7. 創建攔截器 com.hy.springmvc.interceptor.Interceptor
public class Interceptor implements HandlerInterceptor { // Controller執行前呼叫此方法 // 回傳true繼續執行 回傳false中止執行 // 這里可加入登錄校驗 權限攔截等 @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { System.out.println(" ========== preHandle ========== "); // 放行 return true; } // Controller執行后 且未回傳視圖前 呼叫此方法 // 這里可在回傳用戶前對模型資料進行加工處理 比如這里加入公用資訊以便頁面顯示 @Override public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) {} // Controller執行后 且視圖回傳后 呼叫此方法 // 這里可得到執行Controller時的例外資訊 // 這里可記錄操作日志 @Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {} }
8. 創建例外處理器 com.hy.springmvc.exception.HttpErrorResolver
public class HttpErrorResolver implements HandlerExceptionResolver { @Override public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object o, Exception e) { // Object o 發生例外的具體位置 System.out.println("resolveException = " + o.toString()); // 寫日志記錄 發郵件提醒 if (System.currentTimeMillis() % 2 == 0) { /** 有視圖 **/ HttpError error = e instanceof HttpError ? (HttpError) e : new HttpError(-1, "未知例外"); ModelAndView view = new ModelAndView(); view.addObject("error", error); view.setViewName("/exception"); return view; } else { /** 無視圖 **/ HttpError error = e instanceof HttpError ? (HttpError) e : new HttpError(-1, "未知例外"); try { response.setContentType("text/html;charset=UTF-8"); //解決回傳中的中文亂碼 PrintWriter writer = response.getWriter(); writer.write(error.toString()); writer.close(); } catch (IOException e1) { e1.printStackTrace(); } return null; } } }
9. 創建控制器 com.hy.springmvc.controller.TestController
@Controller @RequestMapping("/test") public class TestController { @Value("${NAME}") private String NAME; /** * @param model Model * @param accept @RequestHeader 獲取指定請求頭的值 * @return 資源路徑 */ @RequestMapping("/index") public String index(Model model, @RequestHeader("Accept") String accept) { model.addAttribute("message", NAME + " " + accept); return "/index"; } /** * 轉發 * @return Mapping路徑 */ @RequestMapping("/forward") public String forward() { return "forward:index"; } /** * 重定向 * @return Mapping路徑 */ @RequestMapping("/redirect") public String redirect() { return "redirect:index"; } /** * 例外處理 * @return 資源路徑 */ @RequestMapping("/error") public String error() { int i = 1 / 0; //模擬例外 return "/index"; } /** * @RequestMapping 作用在類上=第一級訪問目錄 作用在方法上=第二級訪問目錄 * path=指定請求路徑 path=指定請求方法 params=指定限制請求引數的條件 headers=指定限制請求頭的條件 * @param model Model * @param name 普通型別引數系結 * @param age @RequestParam 把請求中指定名稱的引數傳遞給控制器中形參賦值 * name=請求引數中的名稱 required=請求引數中是否必須提供此引數 defaultValue=https://www.cnblogs.com/huangyi-427/p/默認值 * @return 資源路徑 */ @RequestMapping(path = "/get", method = RequestMethod.GET) public String get(Model model, String name, @RequestParam(name = "age", required = true, defaultValue = "https://www.cnblogs.com/huangyi-427/p/0") Integer age) { User user = new User(); user.setName(name); user.setAge(age); model.addAttribute("user", user); return "/success"; } /** * @param model Model * @param name @PathVariable 系結url中的占位符 * @return 資源路徑 */ @GetMapping("/getPath/{name}") public String getPath(Model model, @PathVariable String name) { User user = new User(); user.setName(name); model.addAttribute("user", user); return "/success"; } /** * @ResponseBody 將方法的回傳值 以特定格式寫入到回應體 * @param name 普通型別引數系結 * @param age 普通型別引數系結 * @param hobby List型別引數系結 必須添加@RequestParam * @return json格式字串 */ @PostMapping("/postList") @ResponseBody public User postList(String name, Integer age, @RequestParam List<Integer> hobby) { Integer[] array = hobby.toArray(new Integer[0]); User user = new User(); user.setName(name); user.setAge(age); user.setHobby(array); return user; } /** * @param name 普通型別引數系結 * @param age 普通型別引數系結 * @param hobby 陣列型別引數系結 * @return json格式字串 */ @PostMapping("/postArray") @ResponseBody public User postArray(String name, Integer age, Integer[] hobby) { User user = new User(); user.setName(name); user.setAge(age); user.setHobby(hobby); return user; } /** * @param user Model型別引數系結 * @return json格式字串 */ @PostMapping("/postModel") @ResponseBody public User postModel(User user) { return user; } /** * @param request HttpServletRequest * @param name 普通型別引數系結 * @param file 單檔案 * @return json格式字串 * @throws Exception 例外 */ @PostMapping("/postSingleFile") @ResponseBody public User postSingleFile(HttpServletRequest request, String name, MultipartFile file) throws Exception { String path = saveFile(request, file); User user = new User(); user.setName(name + ", " + path); return user; } /** * @param request HttpServletRequest * @param name 普通型別引數系結 * @param file 多檔案 * @return json格式字串 * @throws Exception 例外 */ @PostMapping("/postMoreFile") @ResponseBody public User postMoreFile(HttpServletRequest request, String name, MultipartFile[] file) throws Exception { StringBuilder builder = new StringBuilder(); if (null != file && 0 != file.length) { for (MultipartFile multipartFile : file) { String path = saveFile(request, multipartFile); builder.append(" ").append(path); } } User user = new User(); user.setName(name + "," + builder.toString()); return user; } /** * @param user @RequestBody 用于獲取請求體的內容 * @return json格式字串 */ @PostMapping("/postBody") @ResponseBody public User postBody(@RequestBody User user) { return user; } private String saveFile(HttpServletRequest request, MultipartFile file) throws Exception { if (null != file && !file.isEmpty()) { String fileName = UUID.randomUUID().toString().replace("-", ""); //檔案名 String originalFilename = file.getOriginalFilename(); String substring = originalFilename.substring(originalFilename.lastIndexOf(".")); String path = request.getServletContext().getRealPath("/upload") + "/" + fileName + substring; file.transferTo(new File(path)); return path; } return ""; } }
啟動專案 訪問 http://localhost:8080/test/index
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/80809.html
標籤:Java
