0
点赞
收藏
分享

微信扫一扫

SpringMVC视图及如何在域对象中共享数据

犹大之窗 2022-01-21 阅读 47

SpringMVC

回顾原生Servlet 获取请求参数

通过 Servlet API 获取

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

案例

  • 创建 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--->18
            return "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>

CharacterEncodingFilter 部分源码

public class CharacterEncodingFilter extends OncePerRequestFilter {
   // 字符编码格式
   @Nullable
   private String encoding;
   // 是否强制使用手动设置的编码格式
   private boolean forceRequestEncoding = false;
   private boolean forceResponseEncoding = false;
   
   public void setForceEncoding(boolean forceEncoding) {
      this.forceRequestEncoding = forceEncoding;
      this.forceResponseEncoding = forceEncoding;
   }
  
    @Override
    protected 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--->18
            return "success";
        }
    }
    
  • 启动Tomcat查看效果

    在这里插入图片描述

有同名请求参数

  • 在 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";
        }
    }
    
  • 启动Tomcat查看效果

    在这里插入图片描述

  • 使用 @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";
        }
    }
    
  • 再次测试

    在这里插入图片描述

@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;
        }
    
        @Override
        public 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>
    
  • 启动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>
    
  • 启动Tomcat查看效果

    在这里插入图片描述

四大作用域说明

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)。

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:” 去掉,剩余部分作为最终路径通过转发的方式实现跳转。

案例

  • 在 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:/doThymeleafView
    
             3、这里最终页面显示的地址是 /doForward,而不是 /doThymeleafView
             */
            return "forward:/doThymeleafView";
        }
    }
    
  • 启动Tomcat查看效果

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

原理分析

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

在这里插入图片描述

重定向视图

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

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

案例

  • 在 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:/doThymeleafView
    
             3、这里最终页面显示的地址是 /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标签进行表示。

  • 注释掉 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>
    
  • 启动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 欢迎页

    <%--
      Created by IntelliJ IDEA.
      User: Laoyang
      Date: 2022/1/10
      Time: 17:15
      To 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: Laoyang
      Date: 2022/1/10
      Time: 17:22
      To 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";
        }
    }
    
举报

相关推荐

0 条评论