SpringMVC

  • 回顾原生Servlet 获取请求参数
    • 通过 Servlet API 获取
      • 案例
    • 通过控制器方法的形参获取请求参数
      • 设置字符编码格式
        • CharacterEncodingFilter 部分源码
      • 案例
        • 无同名请求参数
        • 有同名请求参数
    • @RequestParam 注解获取请求参数
      • 案例
    • @RequestHeader 注解
      • 案例
    • @CookieValue
      • 案例
    • 通过 POJO 获取请求参数
      • 案例
  • 域对象共享数据
    • 使用 ServletAPI 向 request 域对象共享数据
    • 使用ModelAndView向request域对象共享数据
    • 使用 Model 向 request 域对象共享数据
    • 使用 Map 向 request 域对象共享数据
    • 使用 ModelMap 向 request 域对象共享数据
    • Model、ModelMap、Map的关系
    • 使用 ServletAPI 向 session 域共享数据
    • 使用ServletAPI向application域共享数据
  • 四大作用域说明
    • application 作用域
    • session 作用域
      • 了解
      • 删除 session 的三种方式
      • 注意
    • request 作用域
    • page 作用域
  • SpringMVC 的视图
    • ThymeleafView
      • 案例
      • 原理分析
    • 转发视图
      • 案例
      • 原理分析
    • 重定向视图
      • 案例
      • 原理分析
    • 转发与重定向(理解)
      • 转发
      • 重定向
    • SpringMVC 视图控制器(view-controller)
    • SpringMVC 视图解析器(InternalResourceViewResolver)

回顾原生Servlet 获取请求参数

通过 Servlet API 获取

  • 将 HttpServletRequest 作为控制器方法的形参,此时 HttpServletRequest 类型的参数表示封装了当前请求的请求报文的对象。

    一个 HTTP 请求报文由请求行(request line)、请求头部(header)、空行和请求数据 4 个部分组成

案例

  • 创建 test_param.html 页面用来测试获取请求参数的效果

    <!DOCTYPE html>
    <html lang="en" xmlns:th="http://www.thymeleaf.org">
    <head><meta charset="UTF-8"><title>测试请求参数</title>
    </head>
    <body><h1>测试请求参数</h1><a th:href="@{/testServletAPI(name='tom', age=18)}">测试使用ServletAPI获取请求参数</a><br/>
    </body>
    </html>
    
  • 创建 Controller,并编写对应控制器方法

    package com.laoyang.mvc.controller;import org.springframework.stereotype.Controller;
    import org.springframework.web.bind.annotation.RequestMapping;
    import javax.servlet.http.HttpServletRequest;/*** @ClassName ParamController* @Description: 测试获取请求参数的功能* @Author Laoyang* @Date 2022/1/7 11:13*/
    @Controller
    public class ParamController {/*** 跳转至 test_param 页面*/@RequestMapping("/param")public String doTestParam() {return "test_param";}/*** 通过 ServletAPI 获取请求参数* 形参位置的 request 表示当前请求(通过它可以获取到当前请求中的数据)* > 实际开发中 request 用的比较少,一般都是用注解获取*/@RequestMapping("/testServletAPI")public String testServletAPI(HttpServletRequest request){String name = request.getParameter("name");String age = request.getParameter("age");System.out.println(name + "--->" + age);    // tom--->18return "success";}
    }
  • 启动Tomcat测试效果

    • 浏览器效果

    • 控制台效果

通过控制器方法的形参获取请求参数

  • 在控制器方法的形参位置,设置和请求参数同名的形参,当浏览器发送请求,匹配到请求映射时,在 DispatcherServlet 中就会将请求参数赋值给相应的形参

设置字符编码格式

  • 为什么要设置?

    如果我们不设置字符编码的话,那么表单提交中文数据之后,就会导致乱码,所以这里先设置对应的字符编码,这样就不用担心后面的测试会出现乱码的问题了。

在 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_4_0.xsd"version="4.0"><!-- 设置字符编码格式 --><filter><filter-name>encoding-filter</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>forceEncoding</param-name><param-value>true</param-value></init-param></filter><filter-mapping><filter-name>encoding-filter</filter-name><url-pattern>/*</url-pattern></filter-mapping>
</web-app>

Ps:虽然我这里只写了设置字符编码的代码,但是之前的配置也是要加上的(比如注册前端控制器那些配置),我这里为了简洁,就不全部展示出来了。

CharacterEncodingFilter 部分源码

public class CharacterEncodingFilter extends OncePerRequestFilter {// 字符编码格式@Nullableprivate String encoding;// 是否强制使用手动设置的编码格式private boolean forceRequestEncoding = false;private boolean forceResponseEncoding = false;public void setForceEncoding(boolean forceEncoding) {this.forceRequestEncoding = forceEncoding;this.forceResponseEncoding = forceEncoding;}@Overrideprotected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)throws ServletException, IOException {String encoding = getEncoding();if (encoding != null) {// 如果 forceRequestEncoding 不为false 或者还没有设置 request 的字符编码,那么就设置request的字符编码if (isForceRequestEncoding() || request.getCharacterEncoding() == null) {request.setCharacterEncoding(encoding);}// 如果 forceResponseEncoding 不为false,就设置 response 的字符编码if (isForceResponseEncoding()) {response.setCharacterEncoding(encoding);}}// 如果 encoding 没有配置,则使用默认的编码格式filterChain.doFilter(request, response);}
}

案例

无同名请求参数

  • 在 test_param.html 页面编写超链接

    <!DOCTYPE html>
    <html lang="en" xmlns:th="http://www.thymeleaf.org">
    <head><meta charset="UTF-8"><title>测试请求参数</title>
    </head>
    <body><h1>测试请求参数</h1><!-- 通过控制器方法的形参获取请求参数 --><a th:href="@{/parameter(name='tom', age=18)}">通过控制器方法的形参获取请求参数</a><br/>
    </body>
    </html>
    
  • 编写对应控制器方法

    package com.laoyang.mvc.controller;import org.springframework.stereotype.Controller;
    import org.springframework.web.bind.annotation.RequestMapping;
    import javax.servlet.http.HttpServletRequest;
    import java.util.Arrays;
    import java.util.List;@Controller
    public class ParamController {/*** 通过控制器方法的形参获取请求参数(无重名属性写法)* 如果没有重名的请求参数传过来,那么只需要将传过来的请求参数名和控制器方法中的参数名保持一致即可*/@RequestMapping("/parameter")public String doParameter(String name, Integer age) {System.out.println(name + "--->" + age);    // tom--->18return "success";}
    }
    
  • 启动Tomcat查看效果

    控制台打印:admin--->12345--->篮球,足球

有同名请求参数

  • 在 test_param.html 页面编写表单

    <!DOCTYPE html>
    <html lang="en" xmlns:th="http://www.thymeleaf.org">
    <head><meta charset="UTF-8"><title>测试请求参数</title>
    </head>
    <body><h1>测试请求参数</h1><form method="get" th:action="@{/parameter2}">用户名:<input name="username" type="text"><br/>密码:<input name="password" type="text"><br/>爱好:<input name="hobby" type="checkbox" value="篮球">篮球<input name="hobby" type="checkbox" value="足球">足球<input name="hobby" type="checkbox" value="羽毛球">羽毛球<br/><input type="submit" value="提交测试"></form>
    </body>
    </html>
    
  • 编写对应控制器方法

    package com.laoyang.mvc.controller;import org.springframework.stereotype.Controller;
    import org.springframework.web.bind.annotation.RequestMapping;
    import javax.servlet.http.HttpServletRequest;
    import java.util.Arrays;
    import java.util.List;@Controller
    public class ParamController {/*** 通过控制器方法的形参获取请求参数(无重名属性写法)* 如果有多个重名的请求参数传过来(比如表单中的复选框),则可以使用下面的几种方式接收:* 1、可以使用请求参数名与控制参数名相同的方式进行接收(String hobby),多个值之间默认会使用逗号分隔(a,b,c)* 2、可以使用一个数组进行接收(String[] hobby)* > 大家可根据自己的需求进行使用*/@RequestMapping("/parameter2")public String doParameter2(String username, String password, String[] hobby) {// System.out.println(username + "--->" + password + "--->" + hobby);System.out.println(username + "--->" + password);System.out.println(Arrays.toString(hobby));return "success";}
    }
    
  • 启动Tomcat查看效果

    效果和无同名参数是一样的,都可以获取到对应的请求参数

@RequestParam 注解获取请求参数

  • @RequestParam 是将请求参数和控制器方法的形参创建映射关系

  • @RequestParam 注解一共有三个属性

    • value:指定为形参赋值的请求参数的参数名

    • required:设置是否必须传输此请求参数,默认值为 true

      若设置为true时,则当前请求必须传输value所指定的请求参数,若没有传输该请求参数,且没有设置 defaultValue 属性,则页面报错 400:Required String parameter 'xxx' is not present;若设置为 false,则当前请求不是必须传输 value 所指定的请求参数,若没有传输,则注解所标识的形参的值为 null

    • defaultValue:不管 required 属性值为 true 或 false,当 value 所指定的请求参数没有传输或传输的值为 “”(空字符串)时,则使用默认值为形参赋值

案例

  • 在 test_param.html 页面编写表单

    <!DOCTYPE html>
    <html lang="en" xmlns:th="http://www.thymeleaf.org">
    <head><meta charset="UTF-8"><title>测试请求参数</title>
    </head>
    <body><h1>测试请求参数</h1><!-- 使用注解方式获取请求参数 --><form method="get" th:action="@{/parameter3}"><!-- 用户名设置为 user_name,这样后端的 username 形参就接收不到了这个时候就需要使用 @RequestParam 注解进行获取 -->用户名:<input name="user_name" type="text"><br/>密码:<input name="password" type="text"><br/>爱好:<input name="hobby" type="checkbox" value="篮球">篮球<input name="hobby" type="checkbox" value="足球">足球<input name="hobby" type="checkbox" value="羽毛球">羽毛球<br/><input type="submit" value="提交测试"></form>
    </body>
    </html>
    
  • 编写对应控制器方法

    package com.laoyang.mvc.controller;import org.springframework.stereotype.Controller;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RequestParam;
    import javax.servlet.http.HttpServletRequest;
    import java.util.Arrays;
    import java.util.List;@Controller
    public class ParamController {@RequestMapping("/parameter3")public String doParameter3(String username,String password,String[] hobby) {//        System.out.println(username + "--->" + password + "--->" + hobby);System.out.println(username + "--->" + password);System.out.println(Arrays.toString(hobby));return "success";}
    }
    

    为了能够让大家看到更好的效果,我这里先不加 @RequestParam 注解

  • 启动Tomcat查看效果

    浏览器中的效果基本没什么问题,但是控制台中打印的效果就是:null--->12345--->篮球,足球

    虽然浏览器发送请求的时候带了 user_name,但是控制器方法中并没有可以接收这个值的参数,所以最后得到的值就是 null

  • 使用 @RequestParam 注解获取请求参数

    package com.laoyang.mvc.controller;import org.springframework.stereotype.Controller;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RequestParam;
    import javax.servlet.http.HttpServletRequest;
    import java.util.Arrays;
    import java.util.List;@Controller
    public class ParamController {/*** 使用 @RequestParam 注解获取请求参数* 参数说明:* name:请求参数名称* value:请求参数名称(这个参数用的比 name 要多,但是效果是一样的)* required:默认为true,表示是否必须传输 value或name 对应的请求参数* (比如这里对应的请求参数为 user_name,如果我们在请求映射的时候发现请求参数中并没有 user_name 这个值,那么就会报 400)* defaultValue:默认值,如果没有传输 value或name 对应的请求参数,则会使用我们设置的默认值*                      如果传输了对应的请求参数,则使用传输过来的值*                      该属性会将 required 值设置为 false*/@RequestMapping("/parameter3")public String doParameter3(@RequestParam(value = "user_name", defaultValue = "haha") String username,String password,String[] hobby) {//        System.out.println(username + "--->" + password + "--->" + hobby);System.out.println(username + "--->" + password);System.out.println(Arrays.toString(hobby));return "success";}
    }
    

    大家可以结合注释中的属性说明,进行设置,然后测试对应的效果,我这里就不一 一展示了

  • 再次测试

    控制台打印admin--->123456--->篮球,足球(具体打印的数据就是这些,只是格式不同罢了,大家不要太较真),因为我们还设置了默认值,所以如果在表单提交的时候 user_name 为空,那么最后打印的就是 haha--->123456--->篮球,足球,有兴趣的话可以测试一下

@RequestHeader 注解

  • @RequestHeader 是将请求头信息和控制器方法的形参创建映射关系
  • @RequestHeader 注解一共有三个属性:value、required、defaultValue,用法同 @RequestParam

案例

  • 在 test_param.html 页面编写超链接

    <!DOCTYPE html>
    <html lang="en" xmlns:th="http://www.thymeleaf.org">
    <head><meta charset="UTF-8"><title>测试请求参数</title>
    </head>
    <body><h1>测试请求参数</h1><!-- 使用 @RequestHeader 注解获取请求头信息 --><a th:href="@{/header}">测试@RequestHeader注解获取请求头信息</a><br/>
    </body>
    </html>
    
  • 编写对应控制器方法

    package com.laoyang.mvc.controller;import org.springframework.stereotype.Controller;
    import org.springframework.web.bind.annotation.RequestHeader;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RequestParam;
    import javax.servlet.http.HttpServletRequest;
    import java.util.*;@Controller
    public class ParamController {/*** 使用 @RequestHeader 注解获取请求头信息* 可以使用 Map 获取到所有的请求头信息,也可以只获取请求头信息中某一个参数* > @RequestHeader 注解的属性和 @RequestParam 注解的一样,所以这里就不多说了*/@RequestMapping("/header")public String doHeader(@RequestHeader("Host") String host, @RequestHeader Map<String, String> headers) {for (Map.Entry<String, String> map : headers.entrySet()) {System.out.println(map.getKey() + ":" + map.getValue());}System.out.println("host:" + host);return "success";}
    }
    
  • 启动Tomcat查看效果

    • 浏览器就是页面跳转成功的效果
    • 主要还是看控制台打印,大家也可以直接把 Map 设置为返回值,然后把获取的请求头存进 Map 中然后进行返回,这样就可以看到在页面中看到获取到的请求头数据了(也可以直接使用 F12 进行查看)

@CookieValue

  • @CookieValue 是将 cookie 数据和控制器方法的形参创建映射关系
  • @CookieValue 注解一共有三个属性:value、required、defaultValue,用法同 @RequestParam

案例

  • 在 test_param.html 页面编写超链接

    <!DOCTYPE html>
    <html lang="en" xmlns:th="http://www.thymeleaf.org">
    <head><meta charset="UTF-8"><title>测试请求参数</title>
    </head>
    <body><h1>测试请求参数</h1><!-- 使用 @CookieValue 注解获取 Cookie 信息 --><a th:href="@{/cookie}">测试@CookieValue注解获取请求头信息</a><br/>
    </body>
    </html>
    
  • 编写对应控制器方法

    package com.laoyang.mvc.controller;import org.springframework.stereotype.Controller;
    import org.springframework.web.bind.annotation.CookieValue;
    import org.springframework.web.bind.annotation.RequestHeader;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RequestParam;
    import javax.servlet.http.Cookie;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpSession;
    import java.util.*;@Controller
    public class ParamController {/*** 使用 @CookieValue 注解获取 Cookie 信息* > 注意:每个人的 cookie 可能不太一样,具体可在浏览器 F12 中进行查看*/@RequestMapping("/cookie")public String doCookie(@CookieValue("JSESSIONID") String jsessionid) {System.out.println("---->" + jsessionid);return "success";}
    }
    
  • 启动Tomcat查看效果

    • 主要看控制台的打印效果,所以这里就不截图了,大家可自行查看

通过 POJO 获取请求参数

可以在控制器方法的形参位置设置一个实体类类型的形参,此时若浏览器传输的请求参数的参数名和实体类中的属性名一致,那么请求参数就会为此属性赋值。

案例

  • 编写对应实体类

    package com.laoyang.mvc.pojo;public class User {private String username;private String password;private String sex;private Integer age;private String email;public User() {}public User(String username, String password, String sex, Integer age, String email) {this.username = username;this.password = password;this.sex = sex;this.age = age;this.email = email;}public String getUsername() {return username;}public void setUsername(String username) {this.username = username;}public String getPassword() {return password;}public void setPassword(String password) {this.password = password;}public String getSex() {return sex;}public void setSex(String sex) {this.sex = sex;}public Integer getAge() {return age;}public void setAge(Integer age) {this.age = age;}public String getEmail() {return email;}public void setEmail(String email) {this.email = email;}@Overridepublic String toString() {return "User{" +"username='" + username + '\'' +", password='" + password + '\'' +", sex='" + sex + '\'' +", age=" + age +", email='" + email + '\'' +'}';}
    }
    
  • 在 test_param.html 页面编写表单

    <!DOCTYPE html>
    <html lang="en" xmlns:th="http://www.thymeleaf.org">
    <head><meta charset="UTF-8"><title>测试请求参数</title>
    </head>
    <body><h1>测试请求参数</h1><!-- 通过 POJO 获取请求参数 --><form th:action="@{/doUser}" method="post">用户名:<input type="text" name="username"><br/>密码:<input type="password" name="password"><br/>性别:<input type="radio" name="sex" value="男">男<input type="radio" name="sex" value="女">女<br/>年龄:<input type="text" name="age"><br/>邮箱:<input type="text" name="email"><br/><input type="submit" value="测试pojo获取参数"></form>
    </body>
    </html>
    
  • 编写对应控制器方法

    package com.laoyang.mvc.controller;import com.laoyang.mvc.pojo.User;
    import org.springframework.stereotype.Controller;
    import org.springframework.web.bind.annotation.CookieValue;
    import org.springframework.web.bind.annotation.RequestHeader;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RequestParam;
    import javax.servlet.http.Cookie;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpSession;
    import java.util.*;@Controller
    public class ParamController {/*** 通过 POJO 获取请求参数* 在需要传输多个请求参数的时候最好就是用这种方式* 如果全部写在控制器方法的形参中会显得非常冗余,而且也比较麻烦*/@RequestMapping("/doUser")public String doPojo(User user) {System.out.println(user);return "success";}
    }
    
  • 启动Tomcat查看效果

    此时在浏览器输入完对于的表单数据后,控制器方法中就可以正常拿到对应的参数值,并进行打印(记得一定要配置好编码格式!)

域对象共享数据

  • 为了整洁,创建一个新的工程来进行演示,和之前一样的东西:web.xmlspring-mvc.xmlpom.xml

  • HelloController:

    package com.laoyang.mvc.controller;import org.springframework.stereotype.Controller;
    import org.springframework.web.bind.annotation.RequestMapping;@Controller
    public class TestController {/*** 跳转至首页*/@RequestMapping("/")public String doIndex() {return "index";}
    }
    
  • index.html:

    <!DOCTYPE html>
    <html lang="en" xmlns:th="http://www.thymeleaf.org">
    <head><meta charset="UTF-8"><title>首页</title>
    </head>
    <body><h1>首页</h1>
    </body>
    </html>
    

使用 ServletAPI 向 request 域对象共享数据

  • 在 index.html 中编写超链接

    <!DOCTYPE html>
    <html lang="en" xmlns:th="http://www.thymeleaf.org">
    <head><meta charset="UTF-8"><title>首页</title>
    </head>
    <body><h1>首页</h1><!-- 使用 ServletAPI 向 request 域对象共享数据 -->
    <a th:href="@{/doServletAPI}">使用ServletAPI向request域对象共享数据</a><br/></body>
    </html>
    
  • 编写对应控制器方法

    package com.laoyang.mvc.controller;import org.springframework.stereotype.Controller;
    import org.springframework.web.bind.annotation.RequestMapping;
    import javax.servlet.http.HttpServletRequest;@Controller
    public class ScopeController {/*** 使用ServletAPI向request域对象共享数据*/@RequestMapping("/doServletAPI")public String doRequest(HttpServletRequest request) {request.setAttribute("name", "我是张三!");return "success";}
    }
    
  • 创建 success.html 页面,并获取域对象

    <!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="${name}"></p></body>
    </html>
    
  • 启动Tomcat查看效果

使用ModelAndView向request域对象共享数据

  • 在 index.html 中编写超链接

    <!DOCTYPE html>
    <html lang="en" xmlns:th="http://www.thymeleaf.org">
    <head><meta charset="UTF-8"><title>首页</title>
    </head>
    <body><h1>首页</h1>
    <!-- 使用 ModelAndView 向 request 域对象共享数据 -->
    <a th:href="@{/doModelAndView}">使用ModelAndView向request域对象共享数据</a><br/>
    </body>
    </html>
    
  • 编写对应控制器方法

    package com.laoyang.mvc.controller;import org.springframework.stereotype.Controller;
    import org.springframework.ui.Model;
    import org.springframework.ui.ModelMap;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.servlet.ModelAndView;
    import javax.servlet.http.HttpServletRequest;
    import java.util.Map;@Controller
    public class ScopeController {/*** 使用 ModelAndView 向 request 域对象共享数据*/@RequestMapping("/doModelAndView")public ModelAndView doModelAndView() {ModelAndView modelAndView = new ModelAndView();// 处理模型数据,即向请求域 request 共享数据modelAndView.addObject("modelAndView", "Hello, ModelAndView");// 设置视图名称(也就是页面名称)modelAndView.setViewName("success");return modelAndView;}
    }
    
  • 在 success.html 页面获取域对象

    <!DOCTYPE html>
    <html lang="en" xmlns:th="http://www/thymeleaf.org">
    <head><meta charset="UTF-8"><title>测试多种获取域对象的方式</title>
    </head>
    <body><h1>测试多种获取域对象的方式</h1>
    <!-- 使用 ModelAndView 方式共享的数据 -->
    <p th:text="${modelAndView}"></p></body>
    </html>
    
  • 启动Tomcat查看效果

使用 Model 向 request 域对象共享数据

  • 在 index.html 中编写超链接

    <!DOCTYPE html>
    <html lang="en" xmlns:th="http://www.thymeleaf.org">
    <head><meta charset="UTF-8"><title>首页</title>
    </head>
    <body><h1>首页</h1><!-- 使用 Model 向 request 域对象共享数据 -->
    <a th:href="@{/doModel}">使用Model向request域对象共享数据</a><br/></body>
    </html>
    
  • 编写对应控制器方法

    package com.laoyang.mvc.controller;import org.springframework.stereotype.Controller;
    import org.springframework.ui.Model;
    import org.springframework.ui.ModelMap;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.servlet.ModelAndView;
    import javax.servlet.http.HttpServletRequest;
    import java.util.Map;@Controller
    public class ScopeController {/*** 使用 Model 向 request 域对象共享数据*/@RequestMapping("/doModel")public String doModel(Model model) {model.addAttribute("model", "代码人,代码魂!");return "success";}
    }
    
  • 在 success.html 页面获取域对象

    <!DOCTYPE html>
    <html lang="en" xmlns:th="http://www/thymeleaf.org">
    <head><meta charset="UTF-8"><title>测试多种获取域对象的方式</title>
    </head>
    <body><h1>测试多种获取域对象的方式</h1><!-- 使用 Model 方式共享的数据 -->
    <p th:text="${model}"></p></body>
    </html>
    
  • 启动Tomcat查看效果

使用 Map 向 request 域对象共享数据

  • 在 index.html 中编写超链接

    <!DOCTYPE html>
    <html lang="en" xmlns:th="http://www.thymeleaf.org">
    <head><meta charset="UTF-8"><title>首页</title>
    </head>
    <body><h1>首页</h1><!-- 使用 Map 向 request 域对象共享数据 -->
    <a th:href="@{/doMap}">使用Map向request域对象共享数据</a><br/></body>
    </html>
    
  • 编写对应控制器方法

    package com.laoyang.mvc.controller;import org.springframework.stereotype.Controller;
    import org.springframework.ui.Model;
    import org.springframework.ui.ModelMap;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.servlet.ModelAndView;
    import javax.servlet.http.HttpServletRequest;
    import java.util.Map;@Controller
    public class ScopeController {/*** 使用 Map 向 request 域对象共享数据*/@RequestMapping("/doMap")public String doMap(Map<String, Object> map) {// map 中添加的每一个数据就是一个共享数据map.put("map", "代码小白!");return "success";}
    }
    
  • 在 success.html 页面获取域对象

    <!DOCTYPE html>
    <html lang="en" xmlns:th="http://www/thymeleaf.org">
    <head><meta charset="UTF-8"><title>测试多种获取域对象的方式</title>
    </head>
    <body><h1>测试多种获取域对象的方式</h1><!-- 使用 ModelMap 方式共享的数据 -->
    <p th:text="${modelMap}"></p>
    </body>
    </html>
    
  • 启动Tomcat查看效果

使用 ModelMap 向 request 域对象共享数据

  • 在 index.html 中编写超链接

    <!DOCTYPE html>
    <html lang="en" xmlns:th="http://www.thymeleaf.org">
    <head><meta charset="UTF-8"><title>首页</title>
    </head>
    <body><h1>首页</h1><!-- 使用 ModelMap 向 request 域对象共享数据 -->
    <a th:href="@{/doModelMap}">使用ModelMap向request域对象共享数据</a><br/></body>
    </html>
    
  • 编写对应控制器方法

    package com.laoyang.mvc.controller;import org.springframework.stereotype.Controller;
    import org.springframework.ui.Model;
    import org.springframework.ui.ModelMap;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.servlet.ModelAndView;
    import javax.servlet.http.HttpServletRequest;
    import java.util.Map;@Controller
    public class ScopeController {/*** 使用 ModelMap 向 request 域对象共享数据*/@RequestMapping("/doModelMap")public String doModelMap(ModelMap modelMap) {modelMap.addAttribute("modelMap", "2022必没bug!!!");return "success";}
    }
    
  • 在 success.html 页面获取域对象

    <!DOCTYPE html>
    <html lang="en" xmlns:th="http://www/thymeleaf.org">
    <head><meta charset="UTF-8"><title>测试多种获取域对象的方式</title>
    </head>
    <body><h1>测试多种获取域对象的方式</h1>
    <!-- 使用 ModelMap 方式共享的数据 -->
    <p th:text="${modelMap}"></p>
    </body>
    </html>
    
  • 启动Tomcat查看效果

Model、ModelMap、Map的关系

一共有五种共享方式:

  • 第一种:使用 ServletAPI(不建议使用)
  • 第二种:使用 ModelAndView
  • 第三种:使用 Model
  • 第四种:使用 Map
  • 第五种:使用 ModelMap

Model、Map、ModelMap 的关系:

BindingAwareModelMap 以及父级的部分源码:
public class BindingAwareModelMap extends ExtendedModelMap {}
public class ExtendedModelMap extends ModelMap implements Model {}
public class ModelMap extends LinkedHashMap<String, Object> {}这三个方式都是通过 BindingAwareModelMap 类进行实例化的:
因为 BindingAwareModelMap 继承了 ExtendedModelMap,而 ExtendedModelMap 继承了 ModelMap,所以BindingAwareModelMap 可以对 ModelMap 进行实例化
因为 BindingAwareModelMap 继承了 ExtendedModelMap,而 ExtendedModelMap 实现了 Model,所以BindingAwareModelMap 可以对 Model 进行实例化
因为 BindingAwareModelMap 继承了 ExtendedModelMap,而 ExtendedModelMap 继承了 ModelMap,而 ModelMap 又继承了 LinkedHashMap,所以可以对 Map 进行实例化

使用 ServletAPI 向 session 域共享数据

  • 在 index.html 中编写超链接

    <!DOCTYPE html>
    <html lang="en" xmlns:th="http://www.thymeleaf.org">
    <head><meta charset="UTF-8"><title>首页</title>
    </head>
    <body><h1>首页</h1>
    <!-- 使用 ServletAPI 向 session 域共享数据 -->
    <a th:href="@{/doSession}">使用ServletAPI向session域共享数据</a><br/></body>
    </html>
    
  • 编写对应控制器方法

    package com.laoyang.mvc.controller;import org.springframework.stereotype.Controller;
    import org.springframework.ui.Model;
    import org.springframework.ui.ModelMap;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.servlet.ModelAndView;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpSession;
    import java.util.Map;@Controller
    public class ScopeController {/*** 使用ServletAPI向 Session 域共享数据*/@RequestMapping("/doSession")public String doSession(HttpSession session) {session.setAttribute("servletApi", "这是session数据~");return "success";}
    }
    
  • 在 success.html 页面获取 session 域对象

    <!DOCTYPE html>
    <html lang="en" xmlns:th="http://www/thymeleaf.org">
    <head><meta charset="UTF-8"><title>测试多种获取域对象的方式</title>
    </head>
    <body><h1>测试多种获取域对象的方式</h1>
    <!-- 使用 ServletAPI 向 Session域共享的数据 -->
    <p th:text="${session.servletApi}"></p></body>
    </html>
    

    注意:在页面获取 session 数据的时候需要使用 “session.属性” 才可以获取到对应的值

  • 启动Tomcat查看效果

使用ServletAPI向application域共享数据

  • 在 index.html 中编写超链接

    <!DOCTYPE html>
    <html lang="en" xmlns:th="http://www.thymeleaf.org">
    <head><meta charset="UTF-8"><title>首页</title>
    </head>
    <body><h1>首页</h1>
    <!-- 使用 ServletAPI 向 application 域共享数据 -->
    <a th:href="@{/doApplication}">使用ServletAPI向application域共享数据</a><br/></body>
    </html>
    
  • 编写对应控制器方法

    package com.laoyang.mvc.controller;import org.springframework.stereotype.Controller;
    import org.springframework.ui.Model;
    import org.springframework.ui.ModelMap;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.servlet.ModelAndView;
    import javax.servlet.ServletContext;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpSession;
    import java.util.Map;@Controller
    public class ScopeController {/*** 使用ServletAPI向 application 域共享数据*/@RequestMapping("/doApplication")public String doApplication(HttpSession session) {ServletContext application = session.getServletContext();application.setAttribute("applicationScope", "这是application的数据哦!");return "success";}
    }
    
  • 在 success.html 页面获取 application 域对象

    <!DOCTYPE html>
    <html lang="en" xmlns:th="http://www/thymeleaf.org">
    <head><meta charset="UTF-8"><title>测试多种获取域对象的方式</title>
    </head>
    <body><h1>测试多种获取域对象的方式</h1>
    <!-- 使用 ServletAPI 向 application域共享的数据 -->
    <p th:text="${application.applicationScope}"></p>
    </body>
    </html>
    

    调用的方式和 session 的差不多,也是需要使用“”对应的域对象.对应的属性” 才能获取到对应的值

  • 启动Tomcat查看效果

四大作用域说明

application 作用域

  • 如果把变量放到 application 里,就说明它的作用域是 application。

  • 有效范围:application 的有效范围是整个应用;整个应用是指从应用启动,到应用结束。我们没有说 “从服务器启动,到服务器关闭”,是因为一个服务器可能部署多个应用,当然你关闭了服务器,就会把上面所有的应用都关闭了。

    application 作用域里的变量,它们的存活时间是最长的,如果不手动删除,它们就可以一直使用

  • Object getAttribute(String name) //从application中获取信息;

  • void setAttribute(String name,Object value) //向application作用域中设置信息。

session 作用域

  • 如果把变量放到 session 里,就说明它的作用域是session(session 存放在服务器端的内存中)。
  • 有效范围:它的有效范围是当前会话;所谓当前会话,就是指从用户打开浏览器开始,到用户关闭浏览器这中间的过程。
  • Object HttpSession.getAttribute(String name) //从session中获取信息。
  • void HttpSession.setAttribute(String name,Object value)//向session中保存信息。
  • HttpSessionHttpServletRequest.getSessio() //获取当前请求所在的session的对象。

了解

  • session 从浏览器发出第一个 HTTP 请求即可认为会话开始。但结束就不好判断了,因为浏览器关闭时并不会通知服务器,所以只能通过如下这种方法判断:

    如果一定的时间内客户端没有反应,则认为会话结束。

  • Tomcat 的默认值为 120 分钟,但这个值也可以通过 HttpSession的setMaxInactiveInterval() 方法来设置:

    void setMaxInactiveInterval(int interval)

  • 如果想主动让会话结束,例如用户单击 “注销” 按钮的时候,可以使用 HttpSession 的 invalidate() 方法,用于强制结束当前 session

删除 session 的三种方式

  • Session 超时:超时指的是连续一定时间服务器没有收到该 Session 所对应客户端的请求,并且这个时间超过了服务器设置的 Session 超时的最大时间。
  • 程序调用 HttpSession.invalidate()
  • 服务器关闭或服务停止

注意

  1. 访问 *.html 的静态资源因为不会被编译为 Servlet,也就不涉及 session 的问题了。
  2. 当 JSP 页面没有显式禁止 session 的时候,在打开浏览器第一次请求该 jsp 的时候,服务器会自动为其创建一个 session,并赋予它一个 sessionID,发送给客户端的浏览器。
  3. 由于 session 会消耗内存资源,因此,如果不打算使用 session,应该在所有的 JSP 中关闭它。
  4. session 不会应该浏览器的关闭而删除,只能通过上面说的三种方式删除。

request 作用域

  • request 里的变量可以跨越 forward 前后的两页,但是只要刷新页面,它们就重新计算了。

  • 请求转发servlet. getRequestDispatcher("new.jsp").forward(req,resp);

注意

  1. 转发是服务器行为,而重定向是客户端行为。
  2. 无论在服务器上如何转发,浏览器地址栏中显示的仍然是最初那个 Servlet 的地址。

page 作用域

  • page 对象的作用范围仅限于用户请求的当前页面
  • request 和 page 的生命周期都是短暂的,它们之间的区别:一个 request 可以包含多个 page 页(include,forward 及 filter)。

更多可看这位大佬写的博客:https://m.php.cn/article/418934.html

SpringMVC 的视图

  • SpringMVC 中的视图是 View 接口,视图的作用:渲染数据,将模型 Model 中的数据展示给用户 SpringMVC 视图的种类很多,默认有转发视图和重定向视图
  • 当工程引入 jstl 的依赖,转发视图会自动转换为 JstlView
  • 若使用的视图技术为 Thymeleaf,在 SpringMVC 的配置文件中配置了 Thymeleaf 的视图解析器,由此视图解析器解析之后所得到的是 ThymeleafView

ThymeleafView

当控制器方法中所设置的视图名称没有任何前缀时,此时的视图名称会被 SpringMVC 配置文件中所配置的视图解析器解析,视图名称拼接视图前缀和视图后缀所得到的最终路径,会通过转发的方式实现跳转。

案例

  • 创建 view.html 页面,并编写超链接

    <!DOCTYPE html>
    <html lang="en" xmlns:th="http://www.thymeleaf.org">
    <head><meta charset="UTF-8"><title>视图测试</title>
    </head>
    <body>
    <h1>SpringMVC视图</h1>
    <a th:href="@{/doThymeleafView}">测试ThymeleafView</a><br/>
    </body>
    </html>
    
  • 编写对应控制器方法

    package com.laoyang.mvc.controller;import org.springframework.stereotype.Controller;
    import org.springframework.web.bind.annotation.RequestMapping;@Controller
    public class ViewController {/*** 跳转至视图测试页面*/@RequestMapping("/doView")public String doView() {return "view";}/*** 默认(无前缀)* ThymeleafView 视图对象*/@RequestMapping("/doThymeleafView")public String doThymeleafView() {return "success";}
    }
    
  • 启动Tomcat查看效果

    • 正常效果就是可以正常访问到 view 页面和 success 页面,这里就不截图了(localhost:8080/springmvc/doView)
    • 实现原理可看下面的原理分析

原理分析

部分源码:

public class DispatcherServlet extends FrameworkServlet {protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {ModelAndView mv = null;mv = ha.handle(processedRequest, response, mappedHandler.getHandler());// 处理ModelAndView封装的模型数据和视图信息processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);}// 处理ModelAndView封装的模型数据和视图信息private void processDispatchResult(HttpServletRequest request, HttpServletResponse response,@Nullable HandlerExecutionChain mappedHandler, @Nullable ModelAndView mv,@Nullable Exception exception) throws Exception {if (mv != null && !mv.wasCleared()) {// 如果视图不为空,则将该视图进行渲染render(mv, request, response);if (errorView) {WebUtils.clearErrorRequestAttributes(request);}}}// 渲染视图protected void render(ModelAndView mv, HttpServletRequest request, HttpServletResponse response) throws Exception {// 本地化(就是本地的环境,由两个部分组成,一个是语言码,一个是国家码,比如 zh_CH 就表示“中文_中国”)Locale locale =(this.localeResolver != null ? this.localeResolver.resolveLocale(request) : request.getLocale());response.setLocale(locale);View view;// 获取视图名称String viewName = mv.getViewName();if (viewName != null) {/* 根据视图名称和ModelAndView中封装的模型数据获取到视图对象因为我们没有在控制器方法返回的时候设置前缀,所以这里创建的是一个ThymeleafView(视图对象)> 可简单理解为:当控制器方法中所设置的视图名称没有任何前缀时,得到的就是ThymeleafView视图对象*/view = resolveViewName(viewName, mv.getModelInternal(), locale, request);if (view == null) {throw new ServletException("Could not resolve view with name '" + mv.getViewName() +"' in servlet with name '" + getServletName() + "'");}}}
}

注意:以上只是部分源码解析,如果想要看到更加详细的,可以自行去源码中探索!

转发视图

  • SpringMVC 中默认的转发视图是 InternalResourceView

  • SpringMVC 中创建转发视图的情况

    当控制器方法中所设置的视图名称以 “forward:” 为前缀时,就会创建 InternalResourceView 视图,此时的视图名称不会被 SpringMVC 配置文件中所配置的视图解析器解析,而是会将前缀 “forward:” 去掉,剩余部分作为最终路径通过转发的方式实现跳转。

    例如"forward:/",“forward:/employee”

案例

  • 在 view.html 中编写超链接

    <!DOCTYPE html>
    <html lang="en" xmlns:th="http://www.thymeleaf.org">
    <head><meta charset="UTF-8"><title>视图测试</title>
    </head>
    <body>
    <h1>SpringMVC视图</h1>
    <a th:href="@{/doForward}">测试InternalResourceView</a><br/></body>
    </html>
    
  • 编写对应控制器方法

    package com.laoyang.mvc.controller;import org.springframework.stereotype.Controller;
    import org.springframework.web.bind.annotation.RequestMapping;@Controller
    public class ViewController {/*** 跳转至视图测试页面*/@RequestMapping("/doView")public String doView() {return "view";}/*** 默认(无前缀)* ThymeleafView 视图对象*/@RequestMapping("/doThymeleafView")public String doThymeleafView() {return "success";}/*** 转发视图(前缀为:“forward:”)* InternalResourceView 视图对象*/@RequestMapping("/doForward")public String doInternalResourceView() {/*1、使用 forward 为前缀时不能直接访问具体的页面(会报404),因为页面必须通过服务器进行访问>错误写法:return "forward:success";2、如果想要通过 forward 访问到具体页面,可以转发到一个跳转到某个页面的控制器方法(控制器方法设置的请求路径)中比如:forward:/doThymeleafView3、这里最终页面显示的地址是 /doForward,而不是 /doThymeleafView*/return "forward:/doThymeleafView";}
    }
    
  • 启动Tomcat查看效果

    • 正常效果就是可以正常访问到 view 页面和 success 页面,这里就不截图了

原理分析

  • 关键的一些源码还是刚才的那些,所以这里就不做记录了

重定向视图

  • SpringMVC 中默认的重定向视图是 RedirectView

  • 当控制器方法中所设置的视图名称以 “redirect:” 为前缀时,创建 RedirectView视图,此时的视图名称不会被 SpringMVC 配置文件中所配置的视图解析器解析,而是会将前缀 “redirect:” 去掉,剩余部分作为最终路径通过重定向的方式实现跳转。

    例如"redirect:/",“redirect:/employee”

案例

  • 在 view.html 中编写超链接

    <!DOCTYPE html>
    <html lang="en" xmlns:th="http://www.thymeleaf.org">
    <head><meta charset="UTF-8"><title>视图测试</title>
    </head>
    <body>
    <h1>SpringMVC视图</h1>
    <a th:href="@{/doRedirect}">测试RedirectView</a><br/></body>
    </html>
    
  • 编写对应控制器方法

    package com.laoyang.mvc.controller;import org.springframework.stereotype.Controller;
    import org.springframework.web.bind.annotation.RequestMapping;@Controller
    public class ViewController {/*** 跳转至视图测试页面*/@RequestMapping("/doView")public String doView() {return "view";}/*** 默认(无前缀)* ThymeleafView 视图对象*/@RequestMapping("/doThymeleafView")public String doThymeleafView() {return "success";}/*** 重定向视图(前缀为:“redirect:”)* RedirectView 视图对象*/@RequestMapping("/doRedirect")public String doRedirectView() {/*1、使用 redirect 为前缀时不能直接访问具体的页面(会报404)>错误写法:return "redirect:success";2、如果想要通过 redirect 访问到具体页面,可以转发到一个跳转到某个页面的控制器方法(控制器方法设置的请求路径)中比如:redirect:/doThymeleafView3、这里最终页面显示的地址是 /doThymeleafView,而不是 /doRedirect*/return "redirect:/doThymeleafView";}
    }
  • 启动Tomcat查看效果

    • 正常效果就是可以正常访问到 view 页面和 success 页面,这里就不截图了

原理分析

  • 关键的一些源码还是刚才的哪些,所以这里就不做记录了

转发与重定向(理解)

转发与重定向的作用:在 Servlet 中实现页面的跳转

转发

  • 概念:由服务器进行的页面跳转就被称为 “转发”

  • 特点

    • 地址栏不发生变化,显示的是上一个页面的地址
    • 请求次数:只有一次请求(就是浏览器向服务器发送的那一次请求)
    • 请求域数据不会丢失
    • 根目录:http://localhost:8080/项目地址/,包含了项目的访问地址
  • 原生 Servlet 实现转发使用 request.getRequestDispatcher("/地址").forward(request, response);

  • SpringMVC 使用转发在返回的地址前使用 redirect: 当做前缀(底层会进行解析,最后得到一个 InternalResourceView 视图对象)

重定向

  • 概念:由服务器进行的页面跳转就被称为 “重定向”
  • 特点
    • 地址栏显示的是新的地址
    • 请求次数:两次
    • 请求域中的数据会丢失,因为是两次次请求
    • 根目录:http://localhost:8080/,没有项目的访问地址

SpringMVC 视图控制器(view-controller)

当控制器方法中,仅仅用来实现页面跳转,即只需要设置视图名称时,可以将处理器方法使用 view-controller标签进行表示。

注意

1、如果不单单是跳转页面,而是进行了一定的操作,那么就不要使用 view-controller,因为 view-controller 无法实现对应操作!
2、在配置文件中配置view-controller之后,会导致 controller 控制器中的所有请求映射失效

  • 注释掉 index 的请求映射

    package com.laoyang.mvc.controller;import org.springframework.stereotype.Controller;
    import org.springframework.web.bind.annotation.RequestMapping;@Controller
    public class TestController {/*** 跳转至首页*/
    //    @RequestMapping("/")
    //    public String doIndex() {//        return "index";
    //    }}
    
  • 在 spring-mvc.xml 配置文件中使用 view-controller 标签进行处理

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:context="http://www.springframework.org/schema/context"xmlns:mvc="http://www.springframework.org/schema/mvc"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/mvc https://www.springframework.org/schema/mvc/spring-mvc.xsd"><!-- 扫描组件 --><context:component-scan base-package="com.laoyang.mvc" /><!-- 配置 Thymeleaf 视图解析器 --><bean id="viewResolver" class="org.thymeleaf.spring5.view.ThymeleafViewResolver"><!-- 优先级 --><property name="order" value="1"/><!-- 字符编码 --><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="prefix" value="/WEB-INF/templates/"/><!-- 视图后缀 --><property name="suffix" value=".html"/><!-- 模板模型 --><property name="templateMode" value="HTML5"/><!-- 页面编码格式 --><property name="characterEncoding" value="UTF-8"/></bean></property></bean></property></bean><!--path:设置处理的请求地址,该路径是和 @RequestMapping 注解中的地址是一样的简单理解:就是把 controller 中用来跳转页面的控制器方法写在了配置文件中view-controller:设置请求地址所对应的视图名称注意:1、如果不单单是跳转页面,而是进行了一定的操作,那么就不要写在配置文件中,因为配置文件无法实现对应操作!2、在配置文件中配置view-controller之后,会导致 controller 控制器中的所有请求映射失效--><!-- 访问方式:http://localhost:8080/springmvc/ --><mvc:view-controller path="/" view-name="index"/><!-- 访问方式:http://localhost:8080/springmvc/doView --><mvc:view-controller path="/doView" view-name="view"/>
    </beans>
    

    为了更好的看懂,我这里还配置了一个跳转到 view.html 页面的 view-controller,记得要把对应控制器中的控制器方法注释掉! 不注释掉的话可能会出现一些不必要的问题。

  • 启动Tomcat测试效果

    • 访问方式:localhost:8080/springmvc/

    • 访问方式:localhost:8080/springmvc/doView

    • 可以看到,我们在配置文件中配置的路径是可以正常访问到对应的页面的,但是此时会有一个小问题,就是点击页面的超链接之后会报 404,这是因为 view-controller 标签会导致所有控制器中的请求映射失效。

  • 解决请求映射失效问题(annotation-driven)

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:context="http://www.springframework.org/schema/context"xmlns:mvc="http://www.springframework.org/schema/mvc"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/mvc https://www.springframework.org/schema/mvc/spring-mvc.xsd"><!-- 扫描组件 --><context:component-scan base-package="com.laoyang.mvc" /><!-- 配置 Thymeleaf 视图解析器 --><bean id="viewResolver" class="org.thymeleaf.spring5.view.ThymeleafViewResolver"><!-- 优先级 --><property name="order" value="1"/><!-- 字符编码 --><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="prefix" value="/WEB-INF/templates/"/><!-- 视图后缀 --><property name="suffix" value=".html"/><!-- 模板模型 --><property name="templateMode" value="HTML5"/><!-- 页面编码格式 --><property name="characterEncoding" value="UTF-8"/></bean></property></bean></property></bean><!--path:设置处理的请求地址,该路径是和 @RequestMapping 注解中的地址是一样的view-controller:设置请求地址所对应的视图名称--><!-- 访问方式:http://localhost:8080/springmvc/ --><mvc:view-controller path="/" view-name="index"/><!-- 访问方式:http://localhost:8080/springmvc/doView --><mvc:view-controller path="/doView" view-name="view"/><!-- 解决请求映射失效问题:开启 mvc 的注解驱动 --><mvc:annotation-driven />
    </beans>
    
  • 再次测试

    此时点击超链接就可以正常进行映射了

SpringMVC 视图解析器(InternalResourceViewResolver)

我们上面使用的视图解析器都是解析 html 页面的(ThymeleafViewResolver),但如果视图使用的是 JSP 页面,那么就需要使用 InternalResourceViewResolver 视图解析器

  • 创建一个新的项目,然后把 web.xml、pom 依赖复制到这个新项目中

  • 在 resource 目录下创建并编写 spring-mvc.xml 配置文件

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:context="http://www.springframework.org/schema/context"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd"><!-- 扫描组件 --><context:component-scan base-package="com.laoyang.mvc" /><!-- 视图解析器 --><bean id="resolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver"><property name="prefix" value="/WEB-INF/templates/" /><property name="suffix" value=".jsp" /></bean>
    </beans>
    
  • 在 webapp 目录下创建 index.jsp

    • 说明

      Tomcat 的 web.xml 文件中配置了默认欢迎页(index.html,index.htm,index.jsp);但是在 Tomcat 中,每一个 webapp 目录下的子目录都被认为是一个 JSP 站点,所以只能访问到 index.jsp 欢迎页

      如果在 webapp 目录下同时创建了 index.html 和 index.jsp,那么访问的时候就会报 404,如果只有 index.html,那么启动后也是会报404,因为访问不到默认页

    <%--Created by IntelliJ IDEA.User: LaoyangDate: 2022/1/10Time: 17:15To change this template use File | Settings | File Templates.
    --%>
    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <html>
    <head><title>首页</title>
    </head>
    <body><h1>Hello Tom!</h1><!--pageContext.request.contextPath:page域对象中的数据,通过这个域对象可以拿到上下文路径> 因为 jsp 不会自动给我们加上上下文路径然后在进行访问,所以这里我们需要手动添加,并且必须添加为动态的上下文路径> 如果是配置固定的上下文路径,那么以后一旦修改,维护起来就很麻烦--><a href="${pageContext.request.contextPath}/doSuccess">访问 success.jsp 页面</a>
    </body>
    </html>
    
  • 在 WEB-INF/templates 目录下创建 success.jsp

    <%--Created by IntelliJ IDEA.User: LaoyangDate: 2022/1/10Time: 17:22To change this template use File | Settings | File Templates.
    --%>
    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <html>
    <head><title>主页面</title>
    </head>
    <body><h1>主页面效果</h1>
    </body>
    </html>
    
  • 编写对应的控制器方法,实现页面跳转

    package com.laoyang.mvc.controller;import org.springframework.stereotype.Controller;
    import org.springframework.web.bind.annotation.RequestMapping;/*** @ClassName JspController* @Description: JSP 跳转* @Author Laoyang* @Date 2022/1/10 17:12*/
    @Controller
    public class JspController {@RequestMapping("/doSuccess")public String doSuccess() {// 这里返回的 jsp 页面会被 spring-mvc.xml 配置文件中的视图解析器进行解析return "success";}
    }
    

SpringMVC视图及如何在域对象中共享数据相关推荐

  1. Javaweb8==未实现前后端分离的列表展示、新增、删除、修改功能。 servlet(逻辑处理,封装数据进域对象,转发到jsp)+jsp(el表达式获取域对象中的数据+JSTL替换if for)。

    最终环境配置: IDEA2021+JDK8+mysql connector java5+Mysql5+mybatis3.5:从数据库取出数据. +(servlet+jsp+el表达式jstl):ser ...

  2. [原创]java WEB学习笔记48:其他的Servlet 监听器:域对象中属性的变更的事件监听器 (3 个),感知 Session 绑定的事件监听器(2个)...

    本博客为原创:综合 尚硅谷(http://www.atguigu.com)的系统教程(深表感谢)和 网络上的现有资源(博客,文档,图书等),资源的出处我会标明 本博客的目的:①总结自己的学习过程,相当 ...

  3. R语言window函数提取时序数据数据子集(subset):使用xts包将dataframe数据转化为时间序列数据(time series)、使用window函数从时间序列对象中提取数据子集

    R语言window函数提取时序数据数据子集(subset):使用xts包将dataframe数据转化为时间序列数据(time series).使用window函数从时间序列对象中提取数据子集 目录

  4. es6 取数组的第一个和最后一个_ES6:解构——JavaScript 从数组和对象中提取数据的优雅方法...

    转载请注明出处,保留原文链接以及作者信息 ES6 有很多新特性,它很大程度上提升了 JavaScript 的编程体验,并且也告诉外界,JavaScript 依旧强势. 其中一个新特性是其对数组和对象的 ...

  5. JS(解构) 之数组和对象中提取数据总结

    解构含义 解构功能含义:从复杂数据类型中(数组或对象)中提取数据的过程. JS(解构) 之数组 从数组中提取首个元素 方式一:基于数组下标提取元素 const names = ['zzg', 'zcx ...

  6. JS-JSON-获取JSON对象中的数据展示到表格里

    JS-JSON-获取JSON对象中的数据展示到表格里 1.要求 点击按钮,将学生信息展示到表格里,并显示总记录条数. 2.实现思路 创建JSON对象 先创建一个JSON对象data,有总人数total ...

  7. es6数组里面获取某个值对_ES6:解构——JavaScript 从数组和对象中提取数据的文雅要领...

    转载请说明出处,保存原文链接以及作者信息 ES6 有许多新特征,它很大程度上提升了 JavaScript 的编程体验,而且也通知外界,JavaScript 照旧强势. 个中一个新特征是其对数组和对象的 ...

  8. DRF 中Request对象中获得数据

    DRF 中response对象中获得数据 1.Request 1).data request.data 返回解析之后的请求体数据.类似于Django中标准的request.POST和 request. ...

  9. 如何在不同Activity或Fragment中共享数据(普通数据或ViewModel)

    文章目录 如何在不同Activity或Fragment中共享数据(普通数据或ViewModel) 共享普通数据 LifecycleStore,ShareDataStore,RefCountStore ...

最新文章

  1. ModuleNotFoundError: No module named ‘pandas.rpy‘
  2. Python中的itertools.product
  3. 【Python数据预处理】 归一化(按列减均值,除方差),标准化(按列缩放到指定范围),正则化(范数)
  4. mysql提高缓存_合理配置MySQL缓存 提高缓存命中率
  5. 编程生涯 21 载,那些我踩过的坑
  6. Bootloader及u-boot简介/u-boot系统启动流程
  7. 你应该知道的 HBase 基础,都在这儿了
  8. 逻辑性最强的React Native环境搭建与调试
  9. VS2010中使用sprintf出现warning C4997: 'sprintf': This function or variable may be unsafe.
  10. 六个重要的.NET概念:栈、堆、值类型、引用类型、装箱和拆箱
  11. 哪种linux好,哪种LINUX好用
  12. asp.net在前台web页面中使用Javascript调用RTX腾讯通的聊天窗口
  13. cass简码大全_南方CASS简码.doc
  14. vue中使用友盟统计,统计到每个路由
  15. 一阶线性微分方程 解法
  16. A-priori算法的简单实现
  17. Caused by: org.activiti.engine.ActivitiException: resource ‘org/activiti/db/create/activiti.dm.creat
  18. L298N电机驱动的使用
  19. GFS(分布式文件系统)
  20. EC20-GPS功能初次使用

热门文章

  1. chr 13 java 替换_Java ROT13编码转换算法实现
  2. ubuntu14关闭来宾账户
  3. Iqoo手机删除内置应用
  4. iOS 系统权限配置
  5. 来来来,一起去看临泉王冲林岗的红枫叶
  6. prince2 成功的项目管理_学员心得 | 宋文彬:学习PRINCE2的心路历程
  7. 【巡店软件系统开发】1、软件架构及基础功能的设定
  8. OpenGL实现在三维空间拖拽物体
  9. VS Reporting Service--新建报表
  10. 面向对象(高级)章节练习题