资料来源:https://www.bilibili.com/video/BV1WD4y1D7kz?p=1

第一章 SpringMVC基础介绍

1、SpringMVC的引言

为了使Spring可插入的MVC架构,SpringFrameWork在Spring基础上开发SpringMVC框架,从而在使用Spring进行WEB开发时可以选择使用Spring的SpringMVC框架作为web开发的控制器框架
image-20210806111138086.png

2、为什么是SpringMVC

  • 可以和spring框架无缝整合
  • 运行效率高于struts2框架
  • 注解式开发更高效

    3、SpringMVC的特点

    SpringMVC 轻量级,典型MVC框架,在整个MVC架构中充当控制器框架,相对于之前学习的struts2框架,SpringMVC运行更快,其注解式开发更高效灵活

    4、SpringMVC与Struts2运行流程对比

    2.springmvc的运行流程和struts运行流程对比.png
    image-20210806112456495.png

    第二章 环境搭建

    1、引入相关依赖

    1. <dependency>
    2. <groupId>org.springframework</groupId>
    3. <artifactId>spring-core</artifactId>
    4. <version>4.3.2.RELEASE</version>
    5. </dependency>
    6. <dependency>
    7. <groupId>org.springframework</groupId>
    8. <artifactId>spring-context</artifactId>
    9. <version>4.3.2.RELEASE</version>
    10. </dependency>
    11. <dependency>
    12. <groupId>org.springframework</groupId>
    13. <artifactId>spring-context-support</artifactId>
    14. <version>4.3.2.RELEASE</version>
    15. </dependency>
    16. <dependency>
    17. <groupId>org.springframework</groupId>
    18. <artifactId>spring-jdbc</artifactId>
    19. <version>4.3.2.RELEASE</version>
    20. </dependency>
    21. <dependency>
    22. <groupId>org.springframework</groupId>
    23. <artifactId>spring-aop</artifactId>
    24. <version>4.3.2.RELEASE</version>
    25. </dependency>
    26. <dependency>
    27. <groupId>org.springframework</groupId>
    28. <artifactId>spring-beans</artifactId>
    29. <version>4.3.2.RELEASE</version>
    30. </dependency>
    31. <dependency>
    32. <groupId>org.springframework</groupId>
    33. <artifactId>spring-expression</artifactId>
    34. <version>4.3.2.RELEASE</version>
    35. </dependency>
    36. <dependency>
    37. <groupId>org.springframework</groupId>
    38. <artifactId>spring-aspects</artifactId>
    39. <version>4.3.2.RELEASE</version>
    40. </dependency>
    41. <dependency>
    42. <groupId>org.springframework</groupId>
    43. <artifactId>spring-tx</artifactId>
    44. <version>4.3.2.RELEASE</version>
    45. </dependency>
    46. <dependency>
    47. <groupId>org.springframework</groupId>
    48. <artifactId>spring-web</artifactId>
    49. <version>4.3.2.RELEASE</version>
    50. </dependency>
    51. <!--springmvc核心依赖-->
    52. <dependency>
    53. <groupId>org.springframework</groupId>
    54. <artifactId>spring-webmvc</artifactId>
    55. <version>4.3.2.RELEASE</version>
    56. </dependency>
    57. <!--servlet-api-->
    58. <dependency>
    59. <groupId>javax.servlet</groupId>
    60. <artifactId>servlet-api</artifactId>
    61. <version>2.5</version>
    62. <scope>provided</scope>
    63. </dependency>

    2、编写springmvc配置文件

    ```java //只扫描控制器所在的包

  1. <a name="xELJx"></a>
  2. ## 3、配置springmvc的核心Servlet
  3. ```java
  4. <servlet>
  5. <servlet-name>springmvc</servlet-name>
  6. <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
  7. <!--指定springmvc配置文件位置-->
  8. <init-param>
  9. <param-name>contextConfigLocation</param-name>
  10. <param-value>classpath:springmvc.xml</param-value>
  11. </init-param>
  12. </servlet>
  13. <servlet-mapping>
  14. <servlet-name>springmvc</servlet-name>
  15. <url-pattern>/</url-pattern> <!-- /代表拦截所有请求,交给springmvc处理 -->
  16. </servlet-mapping>
  • 注意: 这里还要加载spring配置,通过在servlet写init­param标签,还是contextConfigLocation属性,value用来加载springmvc配置文件

    4、创建控制器

    1. @Controller
    2. @RequestMapping("/hello")
    3. public class HelloController {
    4. @RequestMapping("/hello")
    5. public String hello(){
    6. //1.收集数据
    7. //2.调用业务方法
    8. System.out.println("hello springmvc");
    9. //3.处理响应
    10. return "index";//解析结果:前缀+返回值+后缀
    11. }
    12. }
  • @Controller: 该注解用来类上标识这是一个控制器组件类并创建这个类实例

  • @RequestMapping:

    • 修饰范围: 用在方法或者类上
    • 注解作用: 用来指定类以及类中方法的请求路径
    • 注解详解:
      • 用在类上用来给类中所有方法加入一个统一请求路径在方法访问之前需要加入类上@requestMapping的路径
      • 用在方法上用来给当前方法加入指定的请求路径

    注意:一旦类上和方法上同时加入@requestMapping访问时必须:/项目名/类上@requestMapping的路径/访问方法上@requestMapping的路径

    5、部署项目、启动项目测试

    访问路径: http://localhost:8989/springmvc_day1/hello/hello

第三章 数据接收与传递

1、SpringMVC中跳转方式

1.1 跳转方式

  • 说明:跳转有两种,一种forward,一种是redirect。forward跳转,一次请求,地址栏不变,redirect跳转多次请求,地址栏改变。 ```xml

    1. Controller跳转到JSP

    1. forward跳转到页面: 默认就是forward跳转
    2. 语法: return "页面逻辑名"
    3. redirect跳转到页面: 使用springmvc提供redirect:关键字进行重定向页面跳转
    4. 语法: return "redirect:/index.jsp"
    5. 注意: 使用redirect跳转页面不会经过试图解析器(所以需要写路径的全名/index.jsp

2. Controller跳转到Controller

  1. forward跳转到Controller:使用springmvc提供的关键字forward:
  2. 语法: forward:/跳转类上@requestMapping的值/跳转方法上@RequestMapping的值
  3. redirect:跳转到Controller:使用springmvc提供关键字redirect:
  4. 语法: redirect:/跳转类上@requestMapping的值/跳转方法上@RequestMapping的值
  1. <a name="sEFFE"></a>
  2. ### 1.2 测试
  3. ```java
  4. @Controller
  5. @RequestMapping("forwardAndRedirect")
  6. public class ForwardAndRedirectController {
  7. /**
  8. * 测试forward跳转到页面
  9. * 默认: controller跳转到jsp页面就是forward跳转
  10. */
  11. @RequestMapping("test")
  12. public String test(){
  13. System.out.println("test ");
  14. return "index";
  15. }
  16. /**
  17. * 测试redirect跳转到页面
  18. * redirect跳转到页面: 使用springmvc提供关键字 redirect:
  19. * 使用语法: return "redirect:/index.jsp" return "redirect:视图全名"
  20. * 注意:redirect跳转不会经过视图解析器
  21. */
  22. @RequestMapping("test1")
  23. public String test1(){
  24. System.out.println("test1");
  25. return "redirect:/index.jsp";
  26. }
  27. /**
  28. * 测试forward跳转到相同controller类中不同方法
  29. * forward跳转到相同controller中不同方法: 使用springmvc提供关键字 forward:
  30. * 使用语法:
  31. * return "forward:/跳转Controller类上@requestMapping路径/跳转类中指定方法上@requestMapping路径"
  32. */
  33. @RequestMapping("test2")
  34. public String test2(){
  35. System.out.println("test2");
  36. //地址栏仍为test2,打印输出test2、test,页面展示test的跳转页面index.jsp
  37. return "forward:/forwardAndRedirect/test";
  38. }
  39. /**
  40. * 使用redirect跳转到相同controller类中不同方法
  41. * redirect跳转到相同controller类中不同方法: 使用springmvc提供关键字 redirect:
  42. * 使用语法:
  43. * return "redirect:/跳转Controller类上@requestMapping路径/跳转类中指定方法上@requestMapping路径"
  44. * @return
  45. */
  46. @RequestMapping("test3")
  47. public String test3(){
  48. System.out.println("test3");
  49. //地址栏为test,打印输出test3、test,跳转的页面为index.jsp
  50. return "redirect:/forwardAndRedirect/test";
  51. }
  52. /**
  53. * 测试跳转到不同controller类中相关方法
  54. * forward and redirect
  55. * forward:
  56. * redirect:
  57. */
  58. @RequestMapping("test4")
  59. public String test4(){
  60. System.out.println("test4");
  61. //HelloController类上RequestMapping/hello方法上的RequestMapping
  62. return "redirect:/hello/hello";
  63. }
  64. }

1.3 跳转方式总结

4.springmvc中跳转方式.png

2、SpringMVC中参数接收

接收参数语法说明:springmvc中使用控制器方法参数来收集客户端的请求参数,因此在接收请求参数时直接在需要控制器方法声明即可,springmvc可以自动根据指定类型完成类型的转换操作
image-20210806184304655.png

2.1 接收零散类型参数

如:八种基本类型 + String + 日期类型

1) 前台传递参数

  1. # GET 方式传递参数
  2. http://localhost:8080/springmvc_day1/param/test?name=zhangsan&age=19&sex=true&salary=11.11&bir=2012/12/12
  3. # POST 方式传递参数
  4. <h1>测试参数接收</h1>
  5. <form action="${pageContext.request.contextPath}/param/test" method="post">
  6. 用户名: <input type="text" name="name"/> <br>
  7. 年龄: <input type="text" name="age"/> <br>
  8. 性别: <input type="text" name="sex"> <br>
  9. 工资: <input type="text" name="salary"> <br>
  10. 生日: <input type="text" name="bir"> <br>
  11. <input type="submit" value="提交"/>
  12. </form>

2) 后台控制器接收

  1. @Controller
  2. @RequestMapping("/param")
  3. public class ParamController {
  4. @RequestMapping("/test")
  5. public String test(String name, Integer age, Boolean sex,Double salary,Date bir){
  6. System.out.println("姓名: "+name);
  7. System.out.println("年龄: "+age);
  8. System.out.println("性别: "+sex);
  9. System.out.println("工资: "+salary);
  10. System.out.println("生日: "+bir);
  11. return "index";
  12. }
  13. }

注意:springmvc在接收日期类型参数时日期格式必须为yyyy/MM/dd HH:mm:ss

2.2 接收对象类型参数

1) 前台传递参数

  1. # GET 方式请求参数传递
  2. http://localhost:8080/springmvc_day1/param/test1?name=zhangsan&age=19&sex=true&salary=11.11&bir=2012/12/12
  3. # POST 方式请求参数传递
  4. <h1>测试对象类型参数接收</h1>
  5. <form action="${pageContext.request.contextPath}/param/test1" method="post">
  6. 用户名: <input type="text" name="name"/> <br>
  7. 年龄: <input type="text" name="age"/> <br>
  8. 性别: <input type="text" name="sex"> <br>
  9. 工资: <input type="text" name="salary"> <br>
  10. 生日: <input type="text" name="bir"> <br>
  11. <input type="submit" value="提交"/>
  12. </form>

注意:在接收对象类型参数时和struts2接收不同,springmvc直接根据传递参数名与对象中属性名一致自动封装对象

2) 后台控制器接收

  1. //1.定义对象
  2. public class User {
  3. private String name;
  4. private Integer age;
  5. private Double salary;
  6. private Boolean sex;
  7. private Date bir;
  8. }
  9. //2.控制器中接收
  10. // 接收对象类型: 也是直接将要接收对象作为控制器方法参数声明
  11. // 注意:springmvc封装对象时直接根据传递参数key与对象中属性名一致自动封装对象
  12. @RequestMapping("/test1")
  13. public String test1(User user){
  14. System.out.println("接收的对象: "+user);
  15. //test1?name=zhangsan&age=19&sex=true&salary=11.11&bir=2012/12/12
  16. return "index";
  17. }

2.3 接收数组类型参数

1) 前台传递参数

  1. # GET 方式请求参数传递
  2. http://localhost:8080/springmvc_day1/param/test2?names=zhangsan&names=lisi&names=wangwu
  3. # POST 方式请求参数传递
  4. <h1>测试对象类型参数接收</h1>
  5. <form action="${pageContext.request.contextPath}/param/test2" method="post">
  6. 爱好: <br>
  7. 看书: <input type="checkbox" name="names"/>
  8. 看电视:<input type="checkbox" name="names"/>
  9. 吃饭: <input type="checkbox" name="names"/>
  10. 玩游戏: <input type="checkbox" name="names"/>
  11. <input type="submit" value="提交"/>
  12. </form>

2) 后台控制器接收

  1. // 接收数组: 将要接收数组类型直接声明为方法的形参即可
  2. // 注意: 保证请求参数多个参数key与声明数组变量名一致,springmvc会自动放入同一个数组中
  3. @RequestMapping("/test2")
  4. public String test2(String[] names){
  5. for (String name : names) {
  6. System.out.println(name);
  7. }
  8. return "index";
  9. }

注意:接收数组类型数据时前台传递多个key一致自动放入同一个数组中

2.4 接收集合类型参数(了解)

说明:springmvc不支持直接将接收集合声明为控制器方法参数进行接收,如果要接收集合类型参数必须使用对象封装要接收接收类型才可以

1) 前台传递参数

  1. # GET 方式请求参数传递
  2. http://localhost:8080/springmvc_day1/param/test3?lists=zhangsan&lists=lisi&lists=wangwu
  3. # POST 方式请求参数传递
  4. <h1>测试对象类型参数接收</h1>
  5. <form action="${pageContext.request.contextPath}/param/test3" method="post">
  6. 爱好: <br>
  7. 看书: <input type="checkbox" name="lists"/>
  8. 看电视:<input type="checkbox" name="lists"/>
  9. 吃饭: <input type="checkbox" name="lists"/>
  10. 玩游戏: <input type="checkbox" name="lists"/>
  11. <input type="submit" value="提交"/>
  12. </form>

2) 后台控制器接收

  1. // 1.封装接收集合类型对象---->在spring mvc中用来接收集合类型参数
  2. public class CollectionVO {
  3. private List<String> lists;
  4. public List<String> getLists() {
  5. return lists;
  6. }
  7. public void setLists(List<String> lists) {
  8. this.lists = lists;
  9. }
  10. private Map<String,String> maps;
  11. public Map<String, String> getMaps() {
  12. return maps;
  13. }
  14. public void setMaps(Map<String, String> maps) {
  15. this.maps = maps;
  16. }
  17. }
  18. //springmvc不能直接通过形参列表方式收集集合类型参数
  19. //如果要接收集合类型的参数必须将集合放入对象中接收才可以 推荐放入vo对象中接收集合类型
  20. // 2.控制器中接收集合类型参数
  21. @RequestMapping("/test3")
  22. public String test3(CollectionVO collectionVO){ //接收一个对象collectionVO
  23. collectionVO.getLists().forEach(name-> System.out.println(name)); //test3?lists=zhangsan&lists=lisi&lists=wangwu
  24. return "index";
  25. }
  26. //map集合
  27. //%27 = '
  28. //http://localhost:9999/springmvc_day1/param/test3?maps[%27aaa%27]=xiaochen&maps[%27bbb%27]=xiaohei&maps[%27ccc%27]=%E7%99%BE%E7%9F%A5%E6%95%99%E8%82%B2
  29. @RequestMapping("test3")
  30. public String test3(CollectionVO collectionVO){
  31. System.out.println("====================");
  32. collectionVO.getMaps().forEach((k,v)-> System.out.println("k= " + k+" v= "+v));
  33. return "index";
  34. }

2.5 接收参数中文乱码解决方案

注意:在使用springmvc过程中接收客户端的请求参数时有时会出现中文乱码,这事因此springmvc并没有对象请求参数进行编码控制,如果需要控制需要自行指定

1) 处理get请求

# 针对于GET方式中文乱码解决方案:tomcat的conf/server.xml文件中增加:URIEncoding=”UTF-8”

  1. <Connector connectionTimeout="20000" port="8080" protocol="HTTP/1.1" redirectPort="8443" URIEncoding="UTF-8"/>

2) 处理post请求

方式一:自定义编码filter
  1. //首先自定义CharacterEncodingFilter实现filter
  2. public class CharacterEncodingFilter implements Filter {
  3. private String encoding;
  4. @Override
  5. public void init(FilterConfig filterConfig) throws ServletException {
  6. this.encoding = filterConfig.getInitParameter("encoding");
  7. System.out.println(encoding);
  8. }
  9. @Override
  10. public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
  11. request.setCharacterEncoding(encoding);
  12. response.setCharacterEncoding(encoding);
  13. chain.doFilter(request,response);
  14. }
  15. @Override
  16. public void destroy() {
  17. }
  18. }
  19. <!--在web.xml中配置post请求方式中文乱码的Filter-->
  20. <filter>
  21. <filter-name>charset</filter-name>
  22. <filter-class>com.baizhi.filter.CharacterEncodingFilter</filter-class>
  23. <init-param>
  24. <param-name>encoding</param-name>
  25. <param-value>UTF-8</param-value>
  26. </init-param>
  27. </filter>
  28. <filter-mapping>
  29. <filter-name>charset</filter-name>
  30. <url-pattern>/*</url-pattern>
  31. </filter-mapping>

方式二:使用spring提供的Filter
  1. //使用spring提供的Filter,在web.xml中直接配置后使用
  2. <!--配置post请求方式中文乱码的Filter-->
  3. <filter>
  4. <filter-name>charset</filter-name>
  5. <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
  6. <init-param>
  7. <param-name>encoding</param-name>
  8. <param-value>UTF-8</param-value>
  9. </init-param>
  10. </filter>
  11. <filter-mapping>
  12. <filter-name>charset</filter-name>
  13. <url-pattern>/*</url-pattern>
  14. </filter-mapping>

image-20210806192023550.png

3、SpringMVC中数据传递机制

3.1 数据传递机制

# 1.数据怎么存
Servlet 作用域 Struts2 作用域 SpringMVC 作用域
# 2.数据怎么取
Servlet EL表达式 Struts2 EL表达式 SpringMVC EL表达式
# 3.数据怎么展示
Servlet JSTL标签 Struts2 JSTl标签 SpringMVC JSTL标签
image-20210806205024891.png

3.2 使用forward跳转传递数据

  1. 1、传递零散类型数据 <br /> 2、传递对象类型数据 <br /> 3、传递集合类型数据<br />1 使用servlet中原始的request作用域传递数据:request.setAttribute("key",value);
  1. //controller层
  2. @RequestMapping("test")
  3. public String test(HttpServletRequest request, HttpServletResponse response){
  4. //1.收集参数
  5. //2.调用业务方法 String name="小陈";
  6. String name = "小陈";
  7. User user = new User("21", "百知教育", 23, new Date());
  8. User user1 = new User("22", "xiaochen", 23, new Date());
  9. User user2 = new User("23", "xiaoming", 23, new Date());
  10. List<User> users = Arrays.asList(user1, user2);
  11. request.setAttribute("username",name);
  12. request.setAttribute("user",user);
  13. request.setAttribute("users",users);
  14. //3.视图响应处理,流程跳转
  15. return "attr";
  16. }
  1. <!-- attr.jsp -->
  2. <body>
  3. <h1>用来测试request作用域数据传递</h1>
  4. <h3>获取request作用域数据:${requestScope.username}</h3>
  5. <h3>获取request作用域数据:${username}</h3> <!-- ${requestScope.username}作用一样 -->
  6. <hr color="red">
  7. <h3>id:${requestScope.user.id}</h3> <!-- 获取对象的属性 -->
  8. <h3>name:${requestScope.user.name}</h3> <!-- 获取对象的属性 -->
  9. <h3>age:${requestScope.user.age}</h3> <!-- 获取对象的属性 -->
  10. <h3>bir: <fmt:formatDate value="${requestScope.user.bir}" pattern="yyyy-MM-dd"/></h3> <!-- 按指定时间格式输出 -->
  11. <hr color="red">
  12. <c:forEach items="${requestScope.users}" var="user"> <!-- 遍历集合元素,并设置为变量user -->
  13. id:${user.id} === ${user.name} === ${user.age} === <fmt:formatDate value="${user.bir}"/> <br>
  14. </c:forEach>
  15. </body>

2) 使用是springmvc中封装的Model和ModelMap对象(底层对request作用域封装)
model.addAttribute(key,value);
modelMap.addAttribute(key,value);

  1. //controller层
  2. @RequestMapping("test")
  3. public String test(Model model,
  4. HttpServletRequest request,
  5. HttpServletResponse response){
  6. //1.收集参数
  7. //2.调用业务方法 String name="小陈";
  8. String name = "小陈";
  9. User user = new User("21", "百知教育", 23, new Date());
  10. User user1 = new User("22", "xiaochen", 23, new Date());
  11. User user2 = new User("23", "xiaoming", 23, new Date());
  12. List<User> users = Arrays.asList(user1, user2);
  13. model.addAttribute("username",name);
  14. model.addAttribute("user",user);
  15. model.addAttribute("users",users);
  16. //3.视图响应处理,流程跳转
  17. return "attr";
  18. }
  19. //attr.jsp文件内容不变

3.3 使用Redirect跳转传递数据

1) 使用地址栏进行数据传递:url?name=zhangsan&age=21

  1. @RequestMapping("test1")
  2. public String test1(HttpServletRequest request) throws UnsupportedEncodingException {
  3. //1.收集数据
  4. //2.调用业务
  5. String name="小陈";
  6. //3.流程跳转
  7. return "redirect:/attr.jsp?name="+ URLEncoder.encode(name,"UTF-8");
  8. }
  1. <!-- attr.jsp -->
  2. <body>
  3. <h3>获取地址栏数据:${param.name}</h3>
  4. </body>

2) 使用session作用域:
session.setAttribute(key,value);
session.getAttribute(key);

  1. @RequestMapping("test1")
  2. public String test1(HttpServletRequest request) throws UnsupportedEncodingException {
  3. //1.收集数据
  4. //2.调用业务
  5. User user = new User("21", "百知教育", 23, new Date());
  6. request.getSession().setAttribute("user",user);
  7. //3.流程跳转
  8. return "redirect:/attr.jsp");
  9. }
  1. <!-- attr.jsp -->
  2. <body>
  3. <h3>id:${sessionScope.user.id}</h3>
  4. <h3>name:${sessionScope.user.name}</h3>
  5. <h3>age:${sessionScope.user.age}</h3>
  6. <h3>bir:${sessionScope.user.bir}</h3>
  7. </body>

4、SpringMVC处理静态资源拦截

# 1.处理静态资源拦截

# 问题:当web.xml中配置为”/“时,会拦截项目静态资源

image-20210806222745279.png

第四章 常用注解

1、RequestParam

1.1 使用说明

# 作用:把请求中指定名称的参数给控制器中的形参赋值。
# 属性:
value:请求(jsp)参数中的名称
required:请求参数中是否必须提供此参数。默认值:true。表示必须提供,如果不提供将报错。

1.2 使用示例

//jsp中的代码:
requestParam注解

//控制器中的代码:
@RequestMapping(“/testRequestParam”)
public String testRequestParam(@RequestParam(“name”) String username,@RequestParam(value=”age”,required=false)Integer age){
System.out.println(“执行了…”);
System.out.println(username+”,”+age);
return “success”;
}

//请求:
http://localhost:8080/anno/testRequestParam?name=test —-请求参数中没有age、由于配置了false,程序正常执行,不会报错

2、RequestBody

2.1 使用说明

# 作用:用于获取请求体内容。直接使用得到是 key=value&key=value…结构的数据。get 请求方式不适用。
# 属性:
required:是否必须有请求体。默认值是:true。当取值为tru 时,get请求方式会报错。如果取值为false,get请求得到是null。

2.2 使用示例

//jsp中的代码:


用户姓名:

用户年龄:


//控制器中的代码:
/*
获取到请求体的内容
@return
/
@RequestMapping(“/testRequestBody”)
public String testRequestBody(@RequestBody String body){
System.out.println(“执行了…”);
System.out.println(body); //输出:username=111&age=222
return “success”;
}

@RequestMapping(“/testRequestBody”)
public String testRequestBody(String username,String age){
System.out.println(“执行了…”);
System.out.println(username + age); //输出:111222
return “success”;
}

3、PathVaribale

3.1 使用说明

# 作用:
用于绑定url中的占位符。例如:请求url中/delete/{id},这个{id}就是url占位符。url支持占位符是spring3.0之后加入的。是springmvc支持rest风格URL的一个重要标志。
# 属性:
value:用于指定url中占位符名称。
required:是否必须提供占位符。

3.2 使用示例

//jsp中的代码:
testPathVariable

/*
PathVariable注解
@return
/
@RequestMapping(value=”/testPathVariable/{sid}”)
public String testPathVariable(@PathVariable(name=”sid”) String id){
System.out.println(“执行了…”);
System.out.println(id);
return “success”;
}

3.3 REST风格URL

# 什么是rest:
REST(英文:Representational State Transfer,简称 REST)描述了一个架构样式的网络系统,比如web应用程序。它首次出现在2000年Roy Fielding的博士论文中,他是HTTP规范的主要编写者之一。在目前主流的三种Web服务交互方案中,REST相比于SOAP(Simple Object Access protocol,简单对象访问协议)以及 XML-RPC 更加简单明了,无论是对 URL 的处理还是对 Payload 的编码,REST 都倾向于用更加简单轻量的方法设计和实现。值得注意的是 REST 并没有一个明确的标准,而更像是一种设计的风格。它本身并没有什么实用性,其核心价值在于如何设计出符合 REST 风格的网络接口。
# restful的优点
它结构清晰、符合标准、易于理解、扩展方便,所以正得到越来越多网站的采用。
# restful的特性:
资源(Resources):网络上的一个实体,或者说是网络上的一个具体信息。它可以是一段文本、一张图片、一首歌曲、一种服务,总之就是一个具体的存在。可以用一个 URI(统一资源定位符)指向它,每种资源对应一个特定的 URI 。要获取这个资源,访问它的 URI 就可以,因此 URI 即为每一个资源的独一无二的识别符。
# 表现层(Representation):
把资源具体呈现出来的形式,叫做它的表现层 (Representation)。比如,文本可以用 txt 格式表现,也可以用 HTML 格式、XML 格式、JSON 格式表现,甚至可以采用二进制格式。
# 状态转化(State Transfer):
每发出一个请求,就代表了客户端和服务器的一次交互过程。HTTP 协议,是一个无状态协议,即所有的状态都保存在服务器端。因此,如果客户端想要操作服务器,必须通过某种手段,让服务器端发生“状态转化”(State Transfer)。而这种转化是建立在表现层之上的,所以就是 “表现层状态转化”。具体说,就是 HTTP 协议里面,四个表示操作方式的动词:GET 、POST 、PUT、DELETE。它们分别对应四种基本操作:GET 用来获取资源,POST 用来新建资源,PUT 用来更新资源,DELETE 用来删除资源。
# restful 的示例:
/account/1 HTTP GET : 得到 id = 1 的 account
/account/1 HTTP DELETE: 删除 id = 1 的 account
/account/1 HTTP PUT: 更新 id = 1 的 account

3.4 基于HiddentHttpMethodFilter的示例(了解)

# 作用:
由于浏览器form表单只支持GET与POST请求,而DELETE、PUT等method并不支持,Spring3.0添加了一个过滤器,可以将浏览器请求改为指定的请求方式,发送给我们的控制器方法,使得支持 GET、POST、PUT 与 DELETE 请求。
# 使用方法:
第一步:在web.xml中配置该过滤器。
第二步:请求方式必须使用post请求。
第三步:按照要求提供_method请求参数,该参数的取值就是我们需要的请求方式。

4、RequestHeader

4.1 使用说明

# 作用:
用于获取请求消息头。
# 属性:
value:提供消息头名称
required:是否必须有此消息头
# 注:
在实际开发中一般不怎么用。

4.2 使用示例

RequestHeader

/*
获取请求头的值
@param header
@return
*/
@RequestMapping(value=”/testRequestHeader”)
public String testRequestHeader(@RequestHeader(value=”Accept”) String header, HttpServletRequest request,HttpServletResponse response) throws IOException {
System.out.println(“执行了…”);
System.out.println(header);
// return “success”;
// response.sendRedirect(request.getContextPath()+”/anno/testCookieValue”);
return “redirect:/param.jsp”;
}

5、CookieValue

5.1 使用说明

# 作用:
用于把指定cookie名称的值传入控制器方法参数。
# 属性:
value:指定cookie的名称。
required:是否必须有此cookie。

5.2 使用示例

CookieValue


/*
获取Cookie的值
@return
/
@RequestMapping(value=”/testCookieValue”)
public String testCookieValue(@CookieValue(value=”JSESSIONID”) String cookieValue){
System.out.println(“执行了…”);
System.out.println(cookieValue);
return “success”;
}

6、ModelAttribute

6.1 使用说明

# 作用:
该注解是 SpringMVC4.3 版本以后新加入的。它可以用于修饰方法和参数。
出现在方法上,表示当前方法会在控制器的方法执行之前,先执行。它可以修饰没有返回值的方法,也可以修饰有具体返回值的方法。
出现在参数上,获取指定的数据给参数赋值。
# 属性:
value:用于获取数据的 key。key 可以是 POJO 的属性名称,也可以是 map 结构的 key。
# 应用场景:
当表单提交数据不是完整的实体类数据时,保证没有提交数据的字段使用数据库对象原来的数据。
例如:
我们在编辑一个用户时,用户有一个创建信息字段,该字段的值是不允许被修改的。在提交表单数据是肯定没有此字段的内容,一旦更新会把该字段内容置为 null,此时就可以使用此注解解决问题。

6.2 使用示例

场景一:ModelAttribute修饰方法带返回值

public class User implements Serializable{

  1. private String uname;<br /> private Integer age;<br /> private Date date;<br /> get()、set()<br />}<br />/**<br /> * ModelAttribute注解<br /> * @return<br /> */<br />@RequestMapping(value="/testModelAttribute")<br />public String testModelAttribute(User user){<br /> System.out.println("testModelAttribute执行了...");<br /> System.out.println(user); //请求输入age为30、这儿也是输出30<br /> return "success";<br />}<br />/**<br /> * 该方法会先执行,通过输入的uname、查询数据库、获取user对象的所有属性<br /> */<br />@ModelAttribute<br />public User showUser(String uname){<br /> System.out.println("showUser执行了...");<br /> // 通过用户查询数据库(模拟)<br /> User user = new User();<br /> user.setUname(uname);<br /> user.setAge(20);<br /> user.setDate(new Date());<br /> return user;<br />}


用户姓名:

用户年龄:


场景二:ModelAttribute修饰方法不带返回值

public class User implements Serializable{

  1. private String uname;<br /> private Integer age;<br /> private Date date;<br /> get()、set()<br />}<br />/**<br /> * ModelAttribute注解<br /> * @return<br /> */<br />@RequestMapping(value="/testModelAttribute")<br />public String testModelAttribute(@ModelAttribute("abc") User user){<br /> System.out.println("testModelAttribute执行了...");<br /> System.out.println(user); <br /> return "success";<br />}<br />/**<br /> * 该方法会先执行,通过输入的uname、查询数据库、获取user对象的所有属性,并封装到map集合中<br /> */<br />@ModelAttribute<br />public void showUser(String uname, Map<String,User> map){<br /> System.out.println("showUser执行了...");<br /> // 通过用户查询数据库(模拟)<br /> User user = new User();<br /> user.setUname(uname);<br /> user.setAge(20);<br /> user.setDate(new Date());<br /> map.put("abc",user);<br />}


用户姓名:

用户年龄:


7、SessionAttribute

7.1 使用说明

# 作用:
用于多次执行控制器方法间的参数共享。
# 属性:
value:用于指定存入的属性名称
type:用于指定存入的数据类型。

7.2 使用示例

@Controller
@RequestMapping(“/anno”)
@SessionAttributes(value={“msg”}) //把msg=美美存入到session域对中
public class AnnoController {
/
SessionAttributes的注解
@return
*/
@RequestMapping(value=”/testSessionAttributes”)
public String testSessionAttributes(Model model){
System.out.println(“testSessionAttributes…”);
// 底层会存储到request域对象中
model.addAttribute(“msg”,”美美”);
return “success”;
}
/

获取值
@param modelMap
@return
/
@RequestMapping(value=”/getSessionAttributes”)
public String getSessionAttributes(ModelMap modelMap){
System.out.println(“getSessionAttributes…”);
String msg = (String) modelMap.get(“msg”);
System.out.println(msg);
return “success”;
}
/*
清除
@param status
@return
*/
@RequestMapping(value=”/delSessionAttributes”)
public String delSessionAttributes(SessionStatus status){
System.out.println(“getSessionAttributes…”);
status.setComplete();
return “success”;
}
}

testSessionAttributes
getSessionAttributes
delSessionAttributes


入门成功


${ msg }
${sessionScope}

第五章 响应数据和结果视图

1、返回值分类

1.1 字符串

controller方法返回字符串可以指定逻辑视图名,通过视图解析器解析为物理视图地址。指定逻辑视图名,经过视图解析器解析为jsp物理路径:/xx.jsp

  1. @RequestMapping("/testString")
  2. public String testString(Model model){
  3. System.out.println("testString方法执行了...");
  4. // 模拟从数据库中查询出User对象
  5. User user = new User();
  6. user.setUsername("美美");
  7. user.setPassword("123");
  8. user.setAge(30);
  9. // model对象
  10. model.addAttribute("user",user);
  11. return "success";
  12. }
  1. <!-- response.jsp文件 -->
  2. <body>
  3. <a href="user/testString" >testString</a>
  4. </body>
  5. <!-- success.jsp文件 获取由model封装的user对象 -->
  6. <body>
  7. <h3>执行成功</h3>
  8. ${user.username}
  9. ${user.password}
  10. </body>

1.2 void

  1. /**
  2. * void:默认请求转发至/testVoid.jsp,会报404
  3. * 请求转发一次请求,请求路径不用编写项目的名称
  4. * 重定向是两次请求,需要获取项目名称:request.getContextPath()
  5. */
  6. @RequestMapping("/testVoid")
  7. public void testVoid(HttpServletRequest request, HttpServletResponse response) throws Exception {
  8. System.out.println("testVoid方法执行了...");
  9. //方式一:编写请求转发的程序
  10. //request.getRequestDispatcher("/WEB-INF/pages/success.jsp").forward(request,response);
  11. //方式二:重定向
  12. //response.sendRedirect(request.getContextPath()+"/index.jsp");
  13. //设置中文乱码
  14. response.setCharacterEncoding("UTF-8");
  15. response.setContentType("text/html;charset=UTF-8");
  16. //方式三:直接会进行响应
  17. response.getWriter().print("你好");
  18. return;
  19. }
  1. <!-- response.jsp -->
  2. <body>
  3. <a href="user/testVoid" >testVoid</a>
  4. </body>

1.3 ModelAndView

  1. @RequestMapping("/testModelAndView")
  2. public ModelAndView testModelAndView(){
  3. //创建ModelAndView对象
  4. ModelAndView mv = new ModelAndView();
  5. System.out.println("testModelAndView方法执行了...");
  6. //模拟从数据库中查询出User对象
  7. User user = new User();
  8. user.setUsername("小凤");
  9. user.setPassword("456");
  10. user.setAge(30);
  11. //把user对象存储到mv对象中,也会把user对象存入到request对象
  12. mv.addObject("user",user);
  13. //指定跳转的页面:success.jsp
  14. mv.setViewName("success");
  15. return mv;
  16. }
  1. <!-- success.jsp 获取由ModelAndView封装的user对象 -->
  2. <body>
  3. <h3>执行成功</h3>
  4. ${user.username}
  5. ${user.password}
  6. ${user.age}
  7. </body>

2、@ResponseBody响应json数据

  1. @ResponseBody:为了进一步方便控制器与ajax集成,springmvc提供@responseBody该注解用在方法的返回值上,代表可以将方法的返回值转换为json格式字符串并响应到前台,**省去了通过第三方工具转换json的过程(???)**

2.1 引入相关依赖

  1. <dependency>
  2. <groupId>com.fasterxml.jackson.core</groupId>
  3. <artifactId>jackson-databind</artifactId>
  4. <version>2.9.0</version>
  5. </dependency>

2.2 开启mvc的注解驱动

在SpringMVC的核心配置文件中开启mvc的注解驱动,此时在HandlerAdaptor中会自动装配一个消息转换器:MappingJackson2HttpMessageConverter,可以将响应到浏览器的Java对象转换为Json格式的字符串

  1. <mvc:annotation-driven />

2.2 开发控制器

在处理器方法上使用@ResponseBody注解进行标识
将Java对象直接作为控制器方法的返回值返回,就会自动转换为Json格式的字符串

  1. @Controller
  2. @RequestMapping("json")
  3. public class JsonController {
  4. @RequestMapping("test1")
  5. @ResponseBody
  6. public Map<String,String> test(){
  7. HashMap<String,String> map = new HashMap<>();
  8. map.put("message","测试成功");
  9. return map;
  10. }
  11. @RequestMapping("/test2")
  12. public @ResponseBody User testResponseUser(){
  13. return new User(1001,"admin","123456",23,"男");
  14. //浏览器的页面中展示的结果:{"id":1001,"username":"admin","password":"123456","age":23,"sex":"男"}
  15. }
  16. }

2.3 访问测试

http://localhost:8989/springmvc_day2/json/test/
image.png

第六章 文件上传下载

1、文件上传

文件上传:指的就是将用户本地计算机中文件上传到服务器上的过程称之为文件上传

1.1 实现步骤

# 1.项目中引入相关依赖

  1. <dependency>
  2. <groupId>commons-fileupload</groupId>
  3. <artifactId>commons-fileupload</artifactId>
  4. <version>1.4</version>
  5. </dependency>

# 2.开发页面

  1. <!--upload.jsp-->
  2. <body>
  3. <h1>文件上传</h1>
  4. <form action="${pageContext.request.contextPath}/file/upload" method="post" enctype="multipart/form-data">
  5. <input type="file" name="img"/>
  6. <input type="submit" value="上传文件">
  7. </form>
  8. </body>

注意:
1、form表单提交方式必须为post
2、form表单的enctype属性必须为multipart/form-data
# 3.开发控制器

  1. @RequestMapping("upload")
  2. public String upload(MultipartFile img, HttpServletRequest request) throws IOException {
  3. //参数img与jsp中的file name相同
  4. //获取上传路径
  5. String realPath = request.getSession().getServletContext().getRealPath("/upload");
  6. //获取文件原始名称
  7. String originalFilename = aaa.getOriginalFilename();
  8. System.out.println("文件名: "+originalFilename);
  9. //上传文件到服务器
  10. aaa.transferTo(new File(realPath,originalFilename));
  11. return "index";
  12. }

# 4.配置文件上传解析器

  1. <!--springmvc.xml-->
  2. <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
  3. <!--控制文件上传大小单位字节 默认没有大小限制 这里是2M-->
  4. <property name="maxUploadSize" value="2097152"/>
  5. </bean>

注意:使用springmvc中multipartfile接收客户端上传的文件必须配置文件上传解析器且解析的id必须为multipartResolver
image-20210806225520216.png

1.2 细节处理

1、修改文件原始名称
2、自定义文件保存目录
3、文件上传大小限制

  1. @RequestMapping("upload")
  2. public String upload(MultipartFile img, HttpServletRequest request) throws IOException {
  3. System.out.println("文件名: "+img.getOriginalFilename());
  4. System.out.println("文件大小: "+img.getSize());
  5. System.out.println("文件类型: "+img.getContentType());
  6. //1.根据目录upload相对路径获取部署到服务之后绝对路径
  7. String realPath = request.getSession().getServletContext().getRealPath("/upload");
  8. //2.修改文件原始名称:若不修改文件名、上传相同文件名会覆盖上一个文件、当前只保留一个
  9. String extension = FilenameUtils.getExtension(img.getOriginalFilename()); //获取原文件名的后缀
  10. String newFileName = UUID.randomUUID().toString().replace("-","")+"."+extension;
  11. //3.生成当天日期目录
  12. LocalDate now = LocalDate.now(); //输出的时间格式为:XXXX-YY-MM new Date()输出的是年月日时分秒
  13. File dateDir = new File(realPath, now.toString()); //new File(父级目录, 子级目录)
  14. if(!dateDir.exists()) dateDir.mkdirs();
  15. //4.将文件上传到upload对应日期的目录中
  16. img.transferTo(new File(dateDir,newFileName)); //new File(目录, 文件名)
  17. return "index";
  18. }
  1. <!--springmvc.xml-->
  2. <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
  3. <!--注入文件上传下载大小限制 单位字节 2M=2097152字节 默认:没有限制-->
  4. <property name="maxUploadSize" value="20971520"/> <!--当前大小限制为20M-->
  5. </bean>

image-20210806233317427.png

2、文件下载

  1. 文件下载:将服务器上的文件下载到当前用户访问的计算机的过程称之为文件下载

2.1 实现思路

image-20210807090756419.png
# 1.项目中准备下载目录并存在下载的相关文件
image.png
# 2.开发下载控制器

  1. /**
  2. * 测试文件下载
  3. * @param fileName 要下载文件名
  4. * @return
  5. */
  6. @RequestMapping("download")
  7. public String download(String openStyle,
  8. String fileName,
  9. HttpServletRequest request,
  10. HttpServletResponse response) throws IOException {
  11. openStyle = openStyle==null?"inline":"attachment";
  12. //1.根据下载相对目录获取下载目录在服务器部署之后绝对目录
  13. String realPath = request.getSession().getServletContext().getRealPath("/down");
  14. //2.通过文件输入流读取文件
  15. FileInputStream is = new FileInputStream(new File(realPath, fileName));
  16. //3.获取响应输出流
  17. response.setContentType("text/plain;charset=UTF-8");
  18. //4.附件下载:attachment inline:在线打开
  19. //response.setHeader("content-disposition","attachment;fileName="+ URLEncoder.encode(fileName,"UTF-8"));
  20. response.setHeader("content-disposition",openStyle+";fileName="+ URLEncoder.encode(fileName,"UTF-8"));
  21. ServletOutputStream os = response.getOutputStream();
  22. //5.处理下载流复制 //操作io流用IOUtils 操作file 用 FileUtils
  23. IOUtils.copy(is,os);
  24. IOUtils.closeQuietly(is);
  25. IOUtils.closeQuietly(os);
  26. return null;
  27. //传统写法:处理下载流复制
  28. // int len;
  29. // byte[] b = new byte[1024];
  30. // while(true){
  31. // len = is.read(b);
  32. // if(len==-1)break;
  33. // os.write(b,0,len);
  34. // }
  35. //释放资源
  36. // is.close();
  37. // os.close();
  38. }

注意:下载时必须设置响应的头信息,指定文件以何种方式保存,另外下载文件的控制器不能存在返回值,代表响应只用来下载文件信息
# 3.开发页面

  1. <body>
  2. <h1>文件下载</h1>
  3. <a href="${pageContext.request.contextPath}/file/download?fileName=init.txt">init.txt</a>
  4. </body>

2.2 细节处理

1) 优化在线打开和附件下载

# 注意点:附件下载:attachment,在线打开:inline(只有文件能被浏览器识别才会在线打开,否则浏览器会附件下载,例如.exe、.war类型文件就只能下载)

  1. response.setHeader("content-disposition","inline;fileName="+ fileName);
  1. @RequestMapping("download")
  2. public void download(String openStyle,
  3. String fileName,
  4. HttpServletRequest request,
  5. HttpServletResponse response) throws IOException {
  6. //通过jsp传参的形式确定下载方式
  7. openStyle = openStyle==null?"inline":"attachment";
  8. ************************
  9. //4.附件下载attachment、在线打开inline
  10. response.setHeader("content-disposition",openStyle+";fileName="+ fileName);
  11. }
  1. <body>
  2. <h1>文件下载</h1>
  3. <ul> <!-- 在线打开不传openStyle,附件下载传参openStyle=attch -->
  4. <li>aa.txt <a href="${pageContext.request.contextPath}/file/download?fileName=aa.txt">在线打开</a> <a href="${pageContext.request.contextPath}/file/download?fileName=aa.txt&openStyle=attch">附件下载</a></li>
  5. <li>自我介绍.txt <a href="${pageContext.request.contextPath}/file/download?fileName=自我介绍.txt">在线打开</a> <a href="${pageContext.request.contextPath}/file/download?fileName=自我介绍.txt&openStyle=attch">附件下载</a></li>
  6. </ul>
  7. </body>

2) 使用IOUtils操作IO流

  1. //2.通过文件输入流读取文件
  2. FileInputStream is = new FileInputStream(new File(realPath, fileName));
  3. **************************************************
  4. ServletOutputStream os = response.getOutputStream();
  5. //5.处理下载流复制 //操作io流用IOUtils 操作file 用 FileUtils
  6. IOUtils.copy(is,os);
  7. IOUtils.closeQuietly(is); //优雅关闭 安静关流
  8. IOUtils.closeQuietly(os); //优雅关闭 安静关流

3) 处理中文文件名的问题

  1. //文件名称编码
  2. response.setHeader("content-disposition",openStyle+";fileName="+ URLEncoder.encode(fileName,"UTF-8"));

第七章 SpringMVC中拦截器

1、作用

image-20210807103909559.png
作用:类似于javaweb中的Filter,用来对请求进行拦截,可以将多个Controller中执行的共同代码放入拦截器中执行,减少Controller类中代码的冗余.

2、特点

  • 拦截器器只能拦截Controller的请求,不能拦截jsp。Filter可以拦截所有请求
  • 拦截器可中断用户的请求轨迹,不放行
  • 请求先经过拦截器,之后响应还会经过拦截器
  • 底层也是动态代理,AOP

    3、开发拦截器

    1. // 自定义拦截器,实现HandlerInterceptor接口
    2. public class MyInterceptor implements HandlerInterceptor {
    3. @Override
    4. //请求最先经过的方法 返回为true放行请求 返回为false中断请求
    5. //参数1: 当前请求对象 参数2:当前请求对应响应对象 参数3:当前请求的控制器对应的方法对象
    6. public boolean preHandle(HttpServletRequest request,
    7. HttpServletResponse response,
    8. Object handler) throws Exception {
    9. System.out.println(((HandlerMethod)handler).getMethod().getName()); //获取被拦截的方法名
    10. System.out.println("===========1=============");
    11. //强制用户登录
    12. /*Object user = request.getSession().getAttribute("user");
    13. if(user==null){
    14. //重定向到登录页面
    15. response.sendRedirect(request.getContextPath()+"/login.jsp");
    16. return false; //中断请求
    17. }*/
    18. return true;
    19. }
    20. @Override
    21. //控制器方法执行完成之后进入这个方法执行
    22. //参数1: 当前请求对象 参数2:当前请求对应响应对象 参数3:当前请求的控制器对应的方法对象 参数4: 当前请求控制器方法返回值 = 当前请求控制器方法返回的modelandview对象 modelandview 模型和试图
    23. public void postHandle(HttpServletRequest request,
    24. HttpServletResponse response,
    25. Object handler,
    26. ModelAndView modelAndView) throws Exception {
    27. System.out.println(modelAndView);
    28. System.out.println("===========3=============");
    29. }
    30. @Override
    31. //最后执行的方法
    32. //注意: 无论正确还是失败都会执行
    33. //参数1: 当前请求对象 参数2:当前请求对应响应对象 参数3:当前请求的控制器对应的方法对象 参数4: 请求过程中出现异常时异常对象
    34. public void afterCompletion(HttpServletRequest request,
    35. HttpServletResponse response,
    36. Object handler,
    37. Exception ex) throws Exception {
    38. if(ex!=null){
    39. System.out.println(ex.getMessage());
    40. }
    41. System.out.println("===========4=============");
    42. }
    43. }

    # 拦截器的执行顺序:
    # 1、请求经过拦截器会优先进入拦截器中preHandler方法执行preHandler方法中内容
    # 2、如果preHandler返回为true、代表放行请求,如果返回值为false、中断请求
    # 3、如果preHandler返回值为true,会执行当前请求对应的控制器中方法
    # 4、当控制器方法执行结束之后,会返回拦截器中执行拦截器中postHandler方法
    # 5、posthanlder执行完成之后响应请求,在响应请求完成后会执行afterCompletion方法
    image-20210807103239466.png

    4、配置拦截器

    ```java

  1. <!--再配置一个拦截器-->
  2. <mvc:interceptor>
  3. **********
  4. </mvc:interceptor>

  1. <a name="HdF9M"></a>
  2. # 第八章 SpringMVC全局异常处理
  3. <a name="i2KkT"></a>
  4. ### 1、作用
  5. 当控制器中某个方法在运行过程中突然发生运行时异常时,为了增加用户体验对于用户不能出现500错误代码,应该给用户良好展示错误界面,全局异常处理就能更好解决这个问题
  6. <a name="v49PU"></a>
  7. ### 2、全局异常处理开发
  8. ```java
  9. // 自定义全局异常处理类
  10. public class GlobalExceptionResolver implements HandlerExceptionResolver {
  11. /**
  12. * 用来处理发生异常时方法
  13. * @param request 当前请求对象
  14. * @param response 当前请求对应的响应对象
  15. * @param handler 当前请求的方法对象
  16. * @param ex 当前出现异常时的异常对象
  17. * @return 出现异常时展示视图和数据
  18. */
  19. @Override
  20. public ModelAndView resolveException(HttpServletRequest request,
  21. HttpServletResponse response,
  22. Object handler,
  23. Exception ex) {
  24. System.out.println("进入全局异常处理器获取的异常信息为: "+ex.getMessage());
  25. ModelAndView modelAndView = new ModelAndView();
  26. //基于不能业务异常跳转到不同页面
  27. if(ex instanceof UserNameNotFoundException){ //自定义异常类
  28. modelAndView.setViewName("redirect:/login.jsp");
  29. }else{
  30. modelAndView.setViewName("redirect:/error.jsp");
  31. //modelAndView.setViewName("500"); 此时会发请求,一般不采用 //相当于return "500" ===> /500.jsp
  32. }
  33. //modelandview中model默认放入request作用域,如果使用redirect跳转:model中数据会自动拼接到跳转url
  34. modelAndView.addObject("msg",ex.getMessage());
  35. return modelAndView;
  36. }
  37. }

3、配置全局异常处理

  1. <!--springmvc.xml配置全局异常处理类 -->
  2. <bean class="com.baizhi.globalexception.CustomerHanlderExceptionResolver" />

image-20210807113029227.png