第一章 学习SpringMVC的切入点 如何切入MVC: ①SpringMVC是JavaWeb的延续 ②MVC(重点是Controller) ③拦截器
Controller : Controller的作用——依据用户发送的请求 ①调用相应的Model ②跳转响应的View
DispatcherServlet: 前端控制器是SpringMVC中心枢纽,它负责协调和控制整个请求处理流程,确保请求能够被正确地处理并生成相应的响应。
处理乱码
文件的上传和下载
拦截器
异常处理器
SpringMVC工作原理
SSM框架如何整合
第二章 其他 第一节 REST风格的CRUD 传统风格的CRUD(Create, Read, Update, Delete) 功能 URL 请求方式 增 /insertEmp POST 删 /deleteEmp?empId=1001 GET(因为拼接地址栏) 改 /updateEmp POST 查 /selectEmp?empId=1001 GET
功能 URL 请求方式 增 /emp POST 删 /emp/1001 DELETE 改 /emp PUT 查 /emp/1001 GET
REST风格CRUD优势 如何实现PUT&DELETE提交方式在web.xml中 注册过滤器HiddenHttpMethodFilter 1 2 3 4 5 6 7 8 9 10 <filter > <filter-name > HiddenHttpMethodFilter</filter-name > <filter-class > org.springframework.web.filter.HiddenHttpMethodFilter</filter-class > </filter > <filter-mapping > <filter-name > HiddenHttpMethodFilter</filter-name > <url-pattern > /*</url-pattern > </filter-mapping >
设置表单的提交方式为POST ➕第一个input标签的name为_method, value为PUT 或 DELETE 1 2 3 4 5 <form th:action ="@{/emp}" method ="post" > <input type ="hidden" name ="_method" value ="put" > <input type ="submit" name ="提交" /> </form >
REST风格的URL都一样, 如何区分???依据提交方式来区分, 不同的提交方式跳转不同的Controller方法 第二节 加载静态资源<mvc:annotation-driven/> 问题引入: ①我们发现如果直接通过重定向, 且文件, 路径都正确, 但还是无法404, 其问题可能是未加载静态资源 ②DefaultServlet是Servlet用于加载静态资源的类, 它往往是全部拦截的<url-pattern>/</url-pattern>③但由于我们在web.xml中设置的<url-pattern>/</url-pattern>是SpringMVC的DispatcherServlet, 此时就会使得DefaultServlet无效, 从而导致静态资源无法加载 解决方法: 在springmvc.xml中加上<mvc:default-servlet-handler/>即可 注意⚠️: 使用后会导致@Controller注解无法识别, 加上<mvc:annotation-driven/>可以解决 1 2 3 4 5 <mvc:default-servlet-handler > </mvc:default-servlet-handler > <mvc:annotation-driven > </mvc:annotation-driven >
第三章 Hello SpringMVC 第二节 STEP2: Pom.xml配置 SpringMVC的视图层使用Thymeleaf实现的, 所以得配置①Thymeleaf和②Spring-webmvc两个包, 但又因为Tomcat还得一个③servlet-api 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 <dependency > <groupId > org.springframework</groupId > <artifactId > spring-webmvc</artifactId > <version > 5.3.1</version > </dependency > <dependency > <groupId > org.thymeleaf</groupId > <artifactId > thymeleaf-spring5</artifactId > <version > 3.0.12.RELEASE</version > </dependency > <dependency > <groupId > javax.servlet</groupId > <artifactId > javax.servlet-api</artifactId > <version > 4.0.1</version > <scope > provided</scope > </dependency >
第三节 STEP3: web.xml配置 创建DispatcherServlet Servlet 为DispatcherServlet初始化参数 设置创建DispatcherServlet优先级(Servlet的生命周期默认是有请求才会创建对象, 当SpringMVC要求服务器(Tomcat)一启动就创建, 所以要用<load-on-starup>标签设置其优先级) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 <servlet > <servlet-name > DispatcherServlet</servlet-name > <servlet-class > org.springframework.web.servlet.DispatcherServlet</servlet-class > <init-param > <param-name > contextConfigLocation</param-name > <param-value > classpath:springmvc.xml</param-value > </init-param > <load-on-startup > 1</load-on-startup > </servlet > <servlet-mapping > <servlet-name > DispatcherServlet</servlet-name > <url-pattern > /</url-pattern > </servlet-mapping >
第四节 STEP4: springmvc.xml配置 配置视图解析器本质上就是==配置Thymeleaf==, 其最核心的是==前后缀==, 注意⚠️需要手动要改 关于为什么WEB-INF下的资源可以被访问到 ①因为SpringMVC or Thymeleaf 默认都是转发 ②WEB-INF是服务器的私有目录, 无法从浏览器的请求中获取 ③转发本质上是服务器内部发生的跳转 ④重定向是浏览器发送请求给服务器 其他: HTML超链接<a>是通过GET方式提交的, <form>默认也是GET方式提交 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 <context:component-scan base-package ="com.mts" /> <bean id ="viewResolver" class ="org.thymeleaf.spring5.view.ThymeleafViewResolver" > <property name ="characterEncoding" value ="UTF-8" /> <property name ="templateEngine" > <bean class ="org.thymeleaf.spring5.SpringTemplateEngine" > <property name ="templateResolver" > <bean class ="org.thymeleaf.spring5.templateresolver.SpringResourceTemplateResolver" > <property name ="characterEncoding" value ="UTF-8" /> <property name ="prefix" value ="/WEB-INF/pages/" /> <property name ="suffix" value =".html" /> </bean > </property > </bean > </property > </bean >
第五节 STEP5:编写请求处理器 @Controller 1 2 3 4 5 6 7 8 9 10 @Controller public class HelloController { @RequestMapping("/") public String toIndex () { return "index" ; } }
第四章 Controller 第一节 Request—如何对应请求URL 4.1.1 方式一: 使用视图控制器<mvc:view-controller> 语法: <mvc:view-controller path="/" view-name="index"/> springmvc.xml中配置 属性 作用 path URL地址栏 view-name 指定的视图(html文件等)
注意⚠️: 使用后会导致@Controller无法识别, 在springmvc.xml中加上<mvc:annotation-driven/>可以解决 示例代码: 1 2 3 4 5 6 <mvc:view-controller path ="/" view-name ="index" /> <mvc:annotation-driven />
4.1.2 方式二: 使用@RequestMapping 语法: @RequestMapping 类/方法上增加 属性 类型 作用 value/path String[] 设置URL信息, 可以写多个(String[ ]) method String[] 为当前URL【类或方法】设置请求方式【POST、DELETE、PUT、GET等】 params String[] 为当前URL设置请求参数, 如果URL中未携带 报错400 headers String[] 为当前URL设置请求头信息, 如URL中未携带相应请求头 报错404
注意⚠️:①有@GetMapping等注解, 等同于@RequestMapping(value=”/emps”, method = RequestMethod.GET); ②这个注解可以用在类上, 比如类上为(“/people”), 方法上为(“/student”), URL=>/people/student; ③这个支持Ant风格的路径: /?, /*, /**分别匹配 任意一个字符, 任意多字符, 多层路径; ④params属性 case1 :params = "lastName" URL: ….?lastName=Lisi case2 :params = "lastName=MTS" URl:必须是 ….?lastName=MTS才行 示例代码: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 @RequestMapping( // 可以通过/saveEmp或/insertEmp来跳转这个方法 value = {"/saveEmp","/insertEmp"}, // 只能通过GET的提交方式来跳转这个方法 method = RequestMethod.GET, // URL中必须携带lastName这个参数, 且值必须是lisi params = "lastName=lisi", // 请求头中Accept的值必须是(包括)application/json才能跳转这个方法 headers = "Accept=application/json" ) public String saveEmpTest () { System.out.println("添加员工信息!!!!" ); return SUCCESS; }
第二节 Request—如何获取请求参数 4.2.1 地址栏拼接风格的URL@RequestParam 语法: ①对于名字一致的=>直接入参相同名字即可 且 支持POJO ; ②名字不一致的=>需要用@RequestParam指定参数的前面 属性 作用 value/name String 设置占位符中的参数名 required Boolean 设置当前参数是否必须入参【默认值:true】 如果必须入参但没入=>报错; 不必须且没入=>装配null值
! 关于@RequestParam这个注解注意可以不加@RequestParam这个注解(当名字相同时) 如果加了, 这个注解required的参数默认是true, 所以前端不传就是400; 可以设为false解决这个问题, 建议:如果名称相同, 就不要加了; 如果因为名称不同加了,请把required改为false 示例代码: 普通参数 1 2 3 4 <a th:href ="@{/getRequestNormalParam(username='MTS', password='12341', age=4, money=59.6)}" > *地址栏拼接*的request信息</a > <br >
1 2 3 4 5 6 7 8 9 10 11 @RequestMapping("/getRequestNormalParam") public String getRequestMsgNormal (String username, String password, Integer age, @RequestParam("money") Double salary) { System.out.println("username = " + username); System.out.println("password = " + password); System.out.println("age = " + age); System.out.println("salary = " + salary); return SUCCESS; }
1 2 3 4 5 6 public class Student { String studentName; Integer studNum; Character sex; }
1 2 3 <a th:href ="@{/getRequestPojoParam(studentName='Tom', studNum=23443, otherMsg='太厉害啦!')}" > 获取pojo</a >
1 2 3 4 5 6 7 8 9 @RequestMapping("/getRequestPojoParam") public String getRequestMsgPojo (Student student, String otherMsg) { System.out.println("student = " + student); System.out.println("otherMsg = " + otherMsg); return SUCCESS; }
4.2.2 REST风格的URL@PathVariable 语法: ①对于名字一致的=>自动; ②名字不一致的=>需要用@PathVariable指定 位置: ①直接入参相同名字即可; ②参数的前面 属性: 同上 示例代码: 1 <a th:href ="@{/getRequestNormalParam/1001}" > *REST风格*的request信息</a > <br >
1 2 3 4 5 6 @RequestMapping("/getRequestNormalParam/{deptId}") public String getRequestMsgREST (@PathVariable("deptId") Integer id) { System.out.println(id); return SUCCESS; }
第三节 Request—如何处理请求 语法: @RequestHeader("想要获取的在请求头中的属性名称") 这种只能获取单个, 如果想获取全部的请求头可以用HttpEntity<T>入参(见下) 属性: 同上 示例代码: 1 <a th:href ="@{/getHeaderMsg}" > 获取请求头的信息</a >
1 2 3 4 5 6 7 8 @RequestMapping("/getHeaderMsg") public String getHeaderMsg (@RequestHeader("User-Agent") String userAgent, @RequestHeader("Host") String host) { System.out.println("userAgent = " + userAgent); System.out.println("host = " + host); return SUCCESS; }
4.3.2 获取请求体的内容@RequsetBody HttpEntity<T> 方式一: 使用注解@RequsetBody放在参数前面语法: @RequsetBody 属性: required 默认是true, 就是如果请求体中没有内容, 页面报错400, 改为false就不会报错; 注意⚠️:请求体👉的是隐藏的, 所以要用POST提交表单 示例代码: 1 2 3 4 5 6 <form th:action ="@{/useRequestBody}" method ="post" > lastName:<input type ="text" name ="lastName" /> <br > password:<input type ="text" name ="password" /> <input type ="submit" value ="使用@RequsetBody注解获取request体" /> </form >
1 2 3 4 5 @RequestMapping("/useRequestBody") public String useRequestBody (@RequestBody String body) { System.out.println("body = " + body); return SUCCESS; }
方式二: 使用HttpEntity<T>作为入参变量 1 2 3 4 5 6 <form th:action ="@{/useHttpEntity}" method ="post" > lastName:<input type ="text" name ="lastName" /> <br > password:<input type ="text" name ="password" /> <input type ="submit" value ="使用@RequsetBody注解获取request体" /> </form >
1 2 3 4 5 6 @RequestMapping("/useHttpEntity") public String useHttpEntity (HttpEntity<String> httpEntity) { System.out.println("请求头:" +httpEntity.getHeaders()); System.out.println("请求体:" +httpEntity.getBody()); return SUCCESS; }
第四节 Repond—跳转到相应的视图 【面向用户】
从Controller传回DispatchServlet的, 无论String, View的返回值🔙, 最后都会封装为ModelAndView类型 其中Model保存数据, View保存视图 4.4.1 方式一: 使用String返回 1 2 3 4 @RequestMapping("/success") public String toSuccess () { return "success" ; }
4.4.2 方式二: 使用ModelAndView返回ModelAndView 1 2 3 4 5 6 7 8 @RequestMapping("/modelAndViewRespond") public ModelAndView moduleAndViewRespond () { ModelAndView modelAndView = new ModelAndView (); modelAndView.addObject("username" , "Tom" ); modelAndView.setViewName("success" ); return modelAndView; }
第五节 Repond—返回JSON格式或流【面向前端开发人员】 4.5.1 返回流直接打印在页面中@ResponseBody
语法:@ResponseBody, 方法只能返回String类型 位置: 书写在class类上面【当前类所有方法,均返回文本,不跳转页面】or 书写在方法上面 1 2 3 <h2 > 使用@ResponseBody注解的方式🔙获取响应体</h2 > <h3 > 响应体, 可以理解为在页面上展示文字</h3 > <a th:href ="@{/responseBody}" > 跳转</a >
1 2 3 4 5 6 @ResponseBody @RequestMapping("/responseBody") public String responseBody (HttpServletRequest request, HttpServletResponse response) { return "HelloWord" ; }
4.5.2 返回JSON格式的页面信息@ResponseBody
语法: @ResponseBody配置了JSON相关jar包后, 可以返回任意Object类型的数据, 这些数据都会以JOSN页面(content-type=application/json;charset=UTF-8) 的形式返回 步骤STEP1: 配置pom.xml导入jackson-databind jar包 1 2 3 4 5 6 <dependency > <groupId > com.fasterxml.jackson.core</groupId > <artifactId > jackson-databind</artifactId > <version > 2.12.3</version > </dependency >
STEP2: 在springmvc.xml中添加<mvc:annotation-driven/> STEP3: 在添加了@ResponseBody注解的类or方法上使用 1 2 <h2 > 转换为Json格式</h2 > <a th:href ="@{/toJson}" > 跳转</a >
1 2 3 4 5 6 @ResponseBody @RequestMapping("/toJson") public Employee toJson () { Employee employee = new Employee ("Tom" , "[email protected] " , 23.3 ); return employee; }
第六节 Repond—如何向Request域中存值 4.6.1 方式一: 使用原生servlet-api 1 2 3 4 5 6 7 8 9 10 11 12 13 14 @RequestMapping("/success") public String toSuccess (HttpServletRequest request, HttpServletResponse response) { request.setAttribute("key" , "value" ); request.getSession().setAttribute("key" , "value" ); request.getServletContext().setAttribute("key" , "value" ); Cookie cookie = new Cookie ("key" , "value" ); response.addCookie(cookie); return "success" ; }
4.6.2 方式二: ModelAndView作为返回值 1 2 3 4 5 6 7 8 @RequestMapping("/modelAndViewRespond") public ModelAndView moduleAndViewRespond () { ModelAndView modelAndView = new ModelAndView (); modelAndView.addObject("username" , "Tom" ); modelAndView.setViewName("success" ); return modelAndView; }
4.6.3 方式三: 使用Map, Model, ModelMap入参 1 2 3 4 5 6 7 8 @RequestMapping("/mapRespond") public String mapRespond (Map<String, Object> map, Model model, ModelMap modelMap) { map.put("password" , 123412 ); model.addAttribute("gender" , "♂" ); modelMap.addAttribute("class" , "1001" ); return "success" ; }
第七节 Repond—响应的方式 4.7.1 转发 4.7.2 重定向 语法: return “**redirect:/**xxx.html”; 注意⚠️: 重新向用的不是Thymeleaf所以**不能只传递逻辑路径, ** redirect:/中的/会被解析为servletContext; 1 2 3 4 5 @RequestMapping("/redirectToSuccess") public String redirectToSuccess () { return "redirect:/pages2/success.html" ; }
1 2 <!-springmvc.xml---> <mvc:view-controller path ="/redirectToSuccess" view-name ="redirect:/pages2/success.html" />
第五章 处理请求和响应乱码 第一节 实现SpringMVC处理请求和响应乱码CharacterEncodingFilter 思路: SpringMVC处理源码和JavaWeb我们手动处理的思路一致, 都是写个Filter设置字符编码集 步骤: 在web.xml中创建这个CharacterEncodingFilter并设置参数 注意⚠️: 必须是第一过滤器位置 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 <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 > <init-param > <param-name > forceRequestEncoding</param-name > <param-value > true</param-value > </init-param > </filter > <filter-mapping > <filter-name > CharacterEncodingFilter</filter-name > <url-pattern > /*</url-pattern > </filter-mapping >
第六章 文件的上传和下载 第一节 实现文件下载ResponseEntity<T>
6.1.1 STEP1: 编写Controller STEP1: 获取文件的以字节数组byte[]的形式 STEP2: 设置响应头 STEP3: 创建ResponseEntity并设置状态码 1 2 3 4 5 <h1 > 文件下载</h1 > <a th:href ="@{/downloadFile(filename='chang(2).mp4')}" > "chang(2).mp4"</a > <br > <a th:href ="@{/downloadFile(filename='cover.png')}" > "cover.png"</a > <br > <a th:href ="@{/downloadFile(filename='遗留问题.md')}" > "遗留问题.md"</a >
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 @RequestMapping("/downloadFile") public ResponseEntity<byte []> downloadFile(HttpServletRequest request, String filename) { ResponseEntity<byte []> responseEntity = null ; String fileRealPath = request.getServletContext(). getRealPath("WEB-INF/download/" + filename); try (InputStream inputStream = new FileInputStream (fileRealPath)) { byte [] bytes = new byte [inputStream.available()]; inputStream.read(bytes); HttpHeaders headers = new HttpHeaders (); headers.add("Content-Disposition" , "attachment;filename=" + filename); headers.setContentDispositionFormData("attachment" , new String (filename.getBytes("utf-8" ), "ISO-8859-1" )); responseEntity = new ResponseEntity <>(bytes, headers, HttpStatus.OK); } catch (Exception e) { System.out.println(e); } return responseEntity; }
第二节 实现文件上传MultipartFile 6.2.1 STEP1: 配置pom.xml 1 2 3 4 5 <dependency > <groupId > commons-fileupload</groupId > <artifactId > commons-fileupload</artifactId > <version > 1.4</version > </dependency >
6.2.2 STEP2: 在springmvc.xml中创建并配置CommonsMultipartResolve解析器 注意⚠️: 这个<bean>的id必需是multipartResolver 1 2 3 4 5 6 <bean id ="multipartResolver" class ="org.springframework.web.multipart.commons.CommonsMultipartResolver" > <property name ="defaultEncoding" value ="utf-8" > </property > </bean >
6.2.3 STEP3: 准备文件上传的HTML表单(三必须) 表单提交方式 必须为POST表单属性 必须有enctype=multipart/form-data表单内容 必须包含文件域【type=file】1 2 3 4 5 6 7 <form th:action ="@{/uploadFile}" method ="post" enctype ="multipart/form-data" > 上传文件: <input type ="file" name ="userUploadFile" /> <input type ="submit" name ="提交" /> </form >
6.2.4 STEP4: 编写Controller STEP1: 获取目标文件的原文件名称 STEP2: 获取目标文件需要保存的地址 STEP3: 将用户目标文件移动到需要保存的位置 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 @RequestMapping("/uploadFile") public String uploadFile (MultipartFile userUploadFile, HttpServletRequest request) throws IOException { System.out.println(userUploadFile); String filename = userUploadFile.getOriginalFilename(); String savePath = request.getServletContext().getRealPath("/WEB-INF/upload/" ) + "/" + filename; userUploadFile.transferTo(new File (savePath)); return "success" ; }
第三节 优化文件上传 6.3.1 允许同名文件上传 1 2 UUID uuid = UUID.randomUUID(); String savePath = request.getServletContext().getRealPath("/WEB-INF/upload/" ) + "/" + uuid + filename;
1 2 3 long l = System.currentTimeMillis();String savePath = request.getServletContext().getRealPath("/WEB-INF/upload/" ) + "/" + l + filename;
6.3.2 文件上传大小 位置: STEP2的springmvc.xml CommonsMultipartResolver 语法: maxUploadSize; 单位为byte1 KB = 1024 bytes 1 MB = 1024 KB = 1,048,576 bytes 1 GB = 1024 MB = 1,073,741,824 bytes 1 2 3 4 5 6 7 <bean id ="multipartResolver" class ="org.springframework.web.multipart.commons.CommonsMultipartResolver" > <property name ="defaultEncoding" value ="utf-8" > </property > <property name ="maxUploadSize" value ="102400" > </property > </bean >
第七章 拦截器
第一节 SpringMVC拦截器 语法: 实现HandlerInterceptor接口+spingmvc.xml中装配; 实现拦截器两种方式 实现接口:Handlerinterceptor 继承适配器类:HandlerinterceptorAdapter 过时!辨析: 拦截器与过滤器区别 名称 归属 作用 执行时机及次数 Filter web服务器组件 过滤Servlet请求 1.Servlet前 2.Servlet后 Interceptor SpringMVC框架组件 拦截Controller请求 1.Servlet之后, Controller之前 2.Controller之后, Servlet之前执行 3.DispatcherServlet之后
多个拦截器的执行流程 关于拦截器preHandle()方法返回值对拦截器的影响 【对于某一个拦截器来说, 遵循以下规定(所有前面加上”当前”两个字)】 preHandle() postHandle() afterCompletion() 返回True ①在其之后如果没有返回false的preHandle()就会执行,否则不执行 ②如果有期间Controller有异常, 不会执行 一定执行 返回false 不执行 不执行
第二节 实现SpringMVC拦截器 HandlerInterceptor 7.2.1 STEP1: 实现HandlerInterceptor接口, 并重写其三个方法 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 @Component public class TestInterceptor1 implements HandlerInterceptor { @Override public boolean preHandle (HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { System.out.println("TestInterceptor11111=>preHandle()" ); return false ; } @Override public void postHandle (HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { System.out.println("TestInterceptor11111=>postHandle()" ); } @Override public void afterCompletion (HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { System.out.println("TestInterceptor11111=>afterCompletion()" ); } }
7.2.2 STEP2: 在springmvc.xml中装配<mvc:interceptors> 1 2 3 4 5 6 7 8 <mvc:interceptors > <mvc:interceptor > <mvc:mapping path ="/interceptor_page" /> <ref bean ="testInterceptor1" /> </mvc:interceptor > </mvc:interceptors >
1 2 3 4 5 6 7 8 9 10 11 12 <mvc:interceptors > <mvc:interceptor > <mvc:mapping path ="/interceptor_page" /> <ref bean ="testInterceptor1" /> </mvc:interceptor > <mvc:interceptor > <mvc:mapping path ="/interceptor_page" /> <ref bean ="testInterceptor2" /> </mvc:interceptor > </mvc:interceptors >
1 2 3 4 5 <mvc:interceptors > <ref bean ="testInterceptor1" /> </mvc:interceptors >
第八章 异常处理器 SpringMVC中有两个异常处理器实现类
DefaultHandleExceptionResolver:默认异常处理器,默认开启,可以支持10+多种异常处理 SimpleMappingExceptionResolver: 自定义异常处理, ==将指定的异常映射到指定页面== 第一节 实现SpringMVC异常处理器SimpleMappingExceptionResolver 语法: SimpleMappingExceptionResolver类中有两个关键成员变量private Properties exceptionMappings;是配置xxx异常=>跳转xxx页面的private String exceptionAttribute;异常信息的key会放到request域中(默认名字是exception) 注意⚠️: 配置后任意Controller中出现对应的问题都会跳转 8.1.1 STEP1: 在springmvc.xml中装配SimpleMappingExceptionResolver 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 <bean id ="simpleMappingExceptionResolver" class ="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver" > <property name ="exceptionMappings" > <props > <prop key ="java.lang.ArithmeticException" > error_page</prop > <prop key ="java.lang.NullPointerException" > error_page</prop > </props > </property > <property name ="exceptionAttribute" value ="ex" > </property > </bean >
8.1.2 STEP2: 可以①跳转到指定页面 ②在页面中获取错误信息 1 2 3 4 5 6 7 8 9 10 11 12 <!DOCTYPE html > <html lang ="en" xmlns:th ="http://www.thymeleaf.org" > <head > <meta charset ="UTF-8" > <title > 异常处理器</title > </head > <body > <h1 > 异常处理器</h1 > 异常信息: <p th:text ="${ex}" > 异常信息s</p > </body > </html >
第九章 SpringMVC工作原理
请求【浏览器向服务器发送请求,携带URL (/testSpringMVCWorking) 】 通过DispatcherServlet加载SpringMVC容器对象,从而加载Controller【请求处理器】加载三个对象【HandlerMapping、 HandlerExecutionChain、HandlerAdapter】 第一节 SpringMVC工作原理1【URL不存在】 判断URL是否存在【不存在】 第二节 SpringMVC工作原理2 【URL存在】 判断URL是否存在【存在】 执行Interceptor【拦截器】第一个方法【preHandle()】 1 2 3 4 if (!mappedHandler.applyPreHandle(processedRequest, response)) { return ; }
执行Controller 【请求处理器】中的相应方法【处理请求,做出响应】 1 2 3 mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
判断Controller中是否存在异常存在异常通过HandlerExceptionResolver异常处理器处理异常, 并返回ModelAndView 不存在异常Controller返回ModelAndView 触发拦截器第二个方法【postHandle()】 通过ViewResolver 【视图解析器对象】将View 【视图对象】从ModelAndView中解析出来 1 2 3 4 5 6 7 8 9 if (this .viewResolvers != null ) { for (ViewResolver viewResolver: this .viewResolvers) { view view = viewResolver.resolveviewName(viewName, locale); if (view != null ) { return view; } } }
View对象开始渲染视图 执行拦截器第三个方法【afterCompletion()】 1 2 3 4 5 if (mappedHandler != null ) { mappedHandler.triggerAftercompletion(request, response, null ); }
响应 第十章 SSM框架整合 第一节 Spring+SpringMVC整合步骤 10.1.1 导入jar包 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 <dependency > <groupId > org.springframework</groupId > <artifactId > spring-webmvc</artifactId > <version > 5.3.1</version > </dependency > <dependency > <groupId > org.thymeleaf</groupId > <artifactId > thymeleaf-spring5</artifactId > <version > 3.0.12.RELEASE</version > </dependency > <dependency > <groupId > javax.servlet</groupId > <artifactId > javax.servlet-api</artifactId > <version > 4.0.1</version > <scope > provided</scope > </dependency >
10.1.2 配置文件 web.xml注册CharacterEncodingFilter,解决请求乱码问题 注册HiddenHttpMethodFilter,支持PUT&DELETE提交【REST风格】 注册DispatcherServlet 【前端控制器】,管理springMVC容器对象 注册一个上下文参数【contextConfigLocation】 ,设置applicationContext.xml配置文件路径 注册ContextLoaderListener,管理spring容器对象 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 <filter > <filter-name > CharacterEncodingFilter</filter-name > <filter-class > org.springframework.web.filter.CharacterEncodingFilter </filter-class > </filter > <filter-mapping > <filter-name > CharacterEncodingFilter</filter-name > <url-pattern > /*</url-pattern > </filter-mapping > <filter > <filter-name > HiddenHttpMethodFilter</filter-name > <filter-class > org.springframework.web.filter.HiddenHttpMethodFilter</filter-class > </filter > <filter-mapping > <filter-name > HiddenHttpMethodFilter</filter-name > <url-pattern > /*</url-pattern > </filter-mapping > <servlet > <servlet-name > DispatcherServlet</servlet-name > <servlet-class > org.springframework.web.servlet.DispatcherServlet</servlet-class > <init-param > <param-name > contextConfigLocation</param-name > <param-value > classpath:springmvc.xml</param-value > </init-param > <load-on-startup > 1</load-on-startup > </servlet > <servlet-mapping > <servlet-name > DispatcherServlet</servlet-name > <url-pattern > /</url-pattern > </servlet-mapping > <context-param > <param-name > contextConfigLocation</param-name > <param-value > classpath:applicationContext.xml</param-value > </context-param > <listener > <listener-class > org.springframework.web.context.ContextLoaderListener </listener-class > </listener >
springmvc.xml开启组件扫描【只扫描Controller层】 装配视图解析器 装配视图控制器【view-controller】 装配default-servlet-handler,解决静态资源加载问题 装配annotation-driven,解决后续问题 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 <context:component-scan base-package ="com.mts" > <context:exclude-filter type ="annotation" expression ="org.springframework.stereotype.Controller" /> </context:component-scan > <bean id ="thymeleafViewResolver" class ="org.thymeleaf.spring5.view.ThymeleafViewResolver" > <property name ="characterEncoding" value ="UTF-8" /> <property name ="templateEngine" > <bean class ="org.thymeleaf.spring5.SpringTemplateEngine" > <property name ="templateResolver" > <bean class ="org.thymeleaf.spring5.templateresolver.SpringResourceTemplateResolver" > <property name ="characterEncoding" value ="UTF-8" /> <property name ="prefix" value ="WEB-INF/pages" /> <property name ="suffix" value =".html" /> </bean > </property > </bean > </property > </bean > <mvc:view-controller path ="/index" view-name ="index" /> <mvc:default-servlet-handler /> <mvc:annotation-driven />
applicationContex.xml 1 2 3 4 <context:component-scan base-package ="com.mts" > <context:exclude-filter type ="annotation" expression ="org.springframework.stereotype.Controller" /> </context:component-scan >
第二节 Spring+Mybatis整合步骤 10.2.1 导入jar包 spring的jar包 mybatis的jar包 spring与mybatis整合jar包 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 <dependency > <groupId > org.springframework</groupId > <artifactId > spring-jdbc</artifactId > <version > 5.3.1</version > </dependency > <dependency > <groupId > org.springframework</groupId > <artifactId > spring-orm</artifactId > <version > 5.3.1</version > </dependency > <dependency > <groupId > org.springframework</groupId > <artifactId > spring-aspects</artifactId > <version > 5.3.1</version > </dependency >
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 <dependency > <groupId > com.alibaba</groupId > <artifactId > druid</artifactId > <version > 1.1.10</version > </dependency > <dependency > <groupId > mysql</groupId > <artifactId > mysql-connector-java</artifactId > <version > 8.0.26</version > </dependency > <dependency > <groupId > org.mybatis</groupId > <artifactId > mybatis</artifactId > <version > 3.5.7</version > </dependency > <dependency > <groupId > com.github.pagehelper</groupId > <artifactId > pagehelper</artifactId > <version > 5.1.8</version > </dependency >
1 2 3 4 5 6 <dependency > <groupId > org.mybatis</groupId > <artifactId > mybatis-spring</artifactId > <version > 2.0.6</version > </dependency >
10.2.2 配置文件 applicationContex.xml开启组件扫描【排除Controller层】 加载外部属性文件【db.properties】 装配数据源【DruidDataSource】 装配事务管理器【DataSourceTransactionManager】 开启声明式事务管理注解支持 装配SqlSessionFactoryBean,管理SqlSessionFactory 装配MapperScannerConfigurer,管理Mapper代理对象 1 2 3 4 5 6 7 8 9 10 11 12 13 14 db.driverClassName =com.mysql.cj.jdbc.Driver db.url =jdbc:mysql://localhost:3306/test_mybatis?serverTimezone=UTC db.username =root db.password =root db.initialSize =10 db.maxActive =50 db.minIdle =5 db.maxWait =5000
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 <context:component-scan base-package ="com.mts" > <context:exclude-filter type ="annotation" expression ="org.springframework.stereotype.Controller" /> </context:component-scan > <context:property-placeholder location ="classpath:db.properties" /> <bean class ="com.alibaba.druid.pool.DruidDataSource" id ="dataSource" > <property name ="driverClassName" value ="${db.driverClassName}" /> <property name ="url" value ="${db.url}" /> <property name ="username" value ="${db.username}" /> <property name ="password" value ="${db.password}" /> <property name ="initialSize" value ="${db.initialSize}" /> <property name ="maxActive" value ="${db.maxActive}" /> <property name ="minIdle" value ="${db.minIdle}" /> <property name ="maxWait" value ="${db.maxWait}" /> </bean > <bean class ="org.springframework.jdbc.datasource.DataSourceTransactionManager" id ="transactionManager" > <property name ="dataSource" ref ="dataSource" /> </bean > <tx:annotation-driven transaction-manager ="transactionManager" /> <bean id ="sqlSessionFactory" class ="org.mybatis.spring.SqlSessionFactoryBean" > <property name ="dataSource" ref ="dataSource" > </property > <property name ="configLocation" value ="classpath:mybatis-config.xml" > </property > <property name ="typeAliasesPackage" value ="com.mts.pojo" > </property > <property name ="mapperLocations" value ="classpath:mapper/*.xml" > </property > </bean > <mybatis-spring:scan base-package ="com.mts.mapper" />
mybatis-config.xmlsettings 标签 pluggins 标签 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 <?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "https://mybatis.org/dtd/mybatis-3-config.dtd" > <configuration > <settings > <setting name ="mapUnderscoreToCamelCase" value ="true" /> <setting name ="lazyLoadingEnabled" value ="true" /> </settings > <plugins > <plugin interceptor ="com.github.pagehelper.PageInterceptor" > </plugin > </plugins > </configuration >
第一节 Spring+SpringMVC整合步骤 10.1.1 导入jar包 10.1.2 配置文件 web.xml * 注册CharacterEncodingFilter,解决请求乱码问题 * 注册HiddenHttpMethodFilter,支持PUT&DELETE提交【REST风格】 * 注册DispatcherServlet 【前端控制器】,管理springMVC容器对象 * 注册一个上下文参数【contextConfigLocation】 ,设置applicationContext.xml配置文件路径 * 注册ContextLoaderListener,管理spring容器对象 springmvc.xml * 开启组件扫描【只扫描Controller层】 * 装配视图解析器 * 装配视图控制器【view-controller】 * 装配default-servlet-handler,解决静态资源加载问题 * 装配annotation-driven,解决后续问题 applicationContex.xml * 开启组件扫描【排除Controller层】 第二节 Spring+Mybatis整合步骤 10.2.1 导入jar包 spring的jar包 mybatis的jar包 spring与mybatis整合jar包 10.2.2 配置文件 applicationContex.xml * 开启组件扫描【排除Controller层】 * 加载外部属性文件【db.properties】 * 装配数据源【DruidDataSource】 * 装配事务管理器【DataSourceTransactionManager】 * 开启声明式事务管理注解支持 * 装配SqlSessionFactoryBean,管理SqlSessionFactory * 装配MapperScannerConfigurer,管理Mapper代理对象 mybatis-config.xml * settings 标签 * pluggins 标签