• SpringMVC


    目录

    在这里插入图片描述

    本章资源

    1. Postman软件资源
    2. springmvc项目源码

    🍜Spring MVC 官方文档

    💞 SpringMVC文档

    资源已上传-离线文档 spring-framework-5.3.8\docs\reference\html
    在这里插入图片描述
    在这里插入图片描述

    💞 SpringMVC特点&概述

    1.SpringMVC从易用性, 效率上, 比曾经流行的Struts2更好
    2.SpringMVCWEB层框架 [解读: SpringMVC接管了Web层组件, 比如控制器, 视图, 视图解析, 返回给用户的数据格式, 同时支持MVC的开发模式/开发架构]
    3.SpringMVC通过注解, 让POJO成为控制器, 不需要继承类或者实现接口
    4.SpringMVC采用低耦合的组件设计方式, 具有更好地扩展性和灵活性
    5.支持REST格式的URL请求
    6.SpringMVC是基于Spring的, 也就是SpringMVC是在Spring基础上的. SpringMVC的核心包是 spring-web-5.3.8.jar, spring-webmvc-5.3.8.jar

    💞 Spring SpringMVC SpringBoot的关系

    1.Spring MVC只是Spring处理WEB层请求的一个模块/组件, Spring MVC的基石是Servlet[Java WEB]
    2.Spring Boot是为了简化开发者的使用, 推出的封神框架(约定优于配置, 简化了Spring的配置流程), SpringBoot包含很多组件/框架. Spring就是最核心的内容之一, 也包含Spring MVC
    3.它们大概的关系是: SpringBoot > Spring > Spring MVC

    🍜Spring MVC 快速入门

    🍜思路分析

    在这里插入图片描述

    🍜具体实现

    1.创建springmvc web工程, 导入jar新建javaweb项目, 参考👉
    在这里插入图片描述
    在这里插入图片描述

    2.创建src/applicationContext-mvc.xml容器文件
    在这里插入图片描述

    3.配置web.xml

    
    <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">
    
        
        <servlet>
            <servlet-name>springDispatcherServletservlet-name>
            <servlet-class>org.springframework.web.servlet.DispatcherServletservlet-class>
            
            <init-param>
                <param-name>contextConfigLocationparam-name>
                <param-value>classpath:applicationContext-mvc.xmlparam-value>
            init-param>
            
            <load-on-startup>1load-on-startup>
        servlet>
        
        <servlet-mapping>
            <servlet-name>springDispatcherServletservlet-name>
            
            <url-pattern>/url-pattern>
        servlet-mapping>
    web-app>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30

    说明: 这两个配置文件不一样
    在这里插入图片描述

    4.web目录新建login.jsp

    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <html>
    <head>
        <title>登录页面title>
    head>
    <body>
    <%--后面再填写?--%>
    <form action="?">
        username: <input type="text" name="username"/><br/>
        password: <input type="password" name="password"/><br/>
        <input type="submit" value="登录">
    form>
    body>
    html>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    5.在com.zzw.web包下新建UserServlet

    /*
    1.如果我们使用了SpringMVC, 在一个类上标识@Controller
    2.表示将该类视为一个控制器, 注入到容器
    3.比原生servlet开发要简化很多
    */
    @Controller
    public class UserServlet {
    
         //编写方法, 响应用户的请求
        /**
         * 解读
         * 1. login() 方法是用于响应用户的登录请求
         * 2. @RequestMapper(value="/login"), 类似于我们原生Servlet
         *    配置的url-pattern, 就是给方法配置一个url映射
         * 3. 即当用户在浏览器输入 http://localhost:8080/web工程路径/login 就能够访问到login()
         * 4. return "login ok"; 表示返回结果给视图解析器(InternalResourceViewResolver)
         *    , 视图解析器会根据配置, 来决定跳转到哪个页面
         *
         *     
         *
         *         
         *         
         *     
         *
         *     根据上面配置的 return "login_ok"; 就会转发到 /WEB-INF/pages/login_ok.jsp
         */
        @RequestMapping(value = "/login")
        public String login() {
            System.out.println("login ok...");
            return "login_ok";
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32

    6.在web路径/WEB-INF/pages目录下 新建login_ok.jsp`

    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <html>
    <head>
        <title>登陆成功title>
    head>
    <body>
    <h1>登陆成功~h1>
    body>
    html>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    7.配置applicationContext-mvc.xml

    说明: InternalResourceViewResolver的父类UrlBasedViewResovler, 有属性prefix, suffix
    在这里插入图片描述
    在这里插入图片描述

    
    <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.zzw.web"/>
    
        
        <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
            
            <property name="prefix" value="/WEB-INF/pages/"/>
            <property name="suffix" value=".jsp"/>
        bean>
    beans>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    8.配置Tomcat
    在这里插入图片描述
    在这里插入图片描述

    9.配置login.jsp页面访问路径 参考->web工程路径专题

    <body>
    <%--
    这里需要回顾 javaweb-web工程路径专题
    1. action="login" 表示url 是 http://localhost:8080/springmvc/login
       前提: 当前页面在web路径下, 相对路径为 http://localhost:8080/springmvc/login.jsp
    2. action="/login" 表示url 是 http://localhost:8080/login
    --%>
    <form action="login">
        username: <input type="text" name="username"/><br/>
        password: <input type="password" name="password"/><br/>
        <input type="submit" value="登录">
    form>
    body>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    🍜注意事项和细节

    1.学习如何搭建一个springmvc项目, 初步理解springmvc工作流程

    2.这里的UserServlet需要注解成@Controller, 我们称之为一个Handler处理器

    3.UserServlet指定url时, 是可以省略的

    4.关于SpringMVCDispatcherServlet的配置文件, 如果不在web.xml中指定applicationContext-mvc.xml, 默认在/WEB-INF/springDispatcherServlet-servlet.xml找这个配置文件 (推荐使用, 做修改, 并完成测试)

    查看DispatcherServlet父类FrameworkServlet的源码
    在这里插入图片描述

    1)修改web.xml, 注销init-param配置节点

    
    <servlet>
        <servlet-name>springDispatcherServletservlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServletservlet-class>
        
    
        
        
        
        
        
    
        
        <load-on-startup>1load-on-startup>
    servlet>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    这时运行会报错. 因为在WEB-INF目录下找不到springDispatcherServlet-servlet.xml文件

    2)剪切原applicationContext-mvc.xml/WEB-INF目录下, 文件名为: 你配置的DispatcherServlet名字-servlet.xml, 即/WEB-INF/springDispatcherServlet-servlet.xml
    在这里插入图片描述

    运行, 正常.

    🍜SpringMVC执行流程分析

    在这里插入图片描述

    🍜RequestMapping

    RequestMapping注解可以指定控制器/处理器的某个方法的请求的url

    🍜可以修饰类和方法

    1.说明: @RequestMapping注解可以修饰方法, 还可以修饰类. 当同时修饰类和方法时, 请求的url 就是组合 /类请求值/方法请求值

    案例
    1.com.zzw.web包下 新建UserHandler

    @RequestMapping(value = "/user")
    @Controller //UserHandler就是一个处理器/控制器, 会注入到容器
    public class UserHandler {
    
        /**
         * 1.method=RequestMethod.POST: 表示请求buy目标方法必须是 post
         * 2.RequestMethod 四个常用选项 POST, GET, PUT, DELETE[后面会详解]
         * 3.SpringMVC 控制器默认支持GET和POST两种方式
         *
         * buy()方法请求的url: http://ip:port/工程路径/user/buy
         * @return
         */
        @RequestMapping(value = "/buy", method = RequestMethod.POST)
        public String buy() {
            System.out.println("购买.");
            return "success";
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    2.web路径/WEB-INF/pages目录 新建success.jsp

    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <html>
    <head>
        <title>操作成功title>
    head>
    <body>
    <h1>恭喜, 操作成功~h1>
    body>
    html>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    3.web路径下 新建request.jsp, 测试

    <body>
    <%--解读
    1. action="user/buy" 对应 url http://localhost:8080/工程路径/user/buy
    --%>
    <form action="user/buy" method="post">
        购买人: <input type="text" name="username"/><br/>
        购买量: <input type="password" name="nums"/><br/>
        <input type="submit" value="购买">
    form>
    body>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    4.访问成功
    在这里插入图片描述

    🍜可以指定请求方式

    1.说明: @RequestMapping可以指定请求方式(post/get/put/delete..), 请求的方式要和指定的一样, 否则报错.

    2.SpringMVC控制器默认支持GETPOST两种方式, 也就是你不指定method, 可以接收GETPOST请求

    3.应用案例
    在这里插入图片描述
    在这里插入图片描述

    4.当你明确指定了method, 则需要按指定方式请求, 否则会报错.
    在这里插入图片描述

    🍜可以指定params和headers支持简单表达式

    1.param1:表示请求必须包含名为param1的请求参数. 比如 params = "bookId"
    2.!param1:表示请求不能包含名为param1的请求参数. 比如 params = "!bookId"
    3.param1 = value1:表示请求包含名为param1的请求参数, 且其值必须为value1. 比如 params = "bookId=100"
    4.param1 != value1:表示请求包含名为param1的请求参数, 但其值不能为value1. 比如 params = "bookId!=100"
    5.{"param1=value1", "param2"}:请求必须包含名为param1, param2的两个请求参数, 且param1参数的值必须为value1. 比如params = {"bookId=100", "price"}


    案例
    1.修改UserHandler.java增加方法search

    @RequestMapping(value = "/user")
    @Controller //UserHandler就是一个处理器/控制器, 会注入到容器
    public class UserHandler {
        /**
         * 解读
         * 1. params="bookId" 表示请求该目标方法时, 必须给一个bookId参数, 值没有限定
         * 2. search(String bookId) 表示请求目标方法时, 携带的bookId=100, 就会将请求携带的 bookId
         *    对应的值, 赋给 String bookId
         * @param bookId
         * @return
         */
        @RequestMapping(value = "/find", params = "bookId", method = RequestMethod.GET)
        public String search(String bookId) {
            System.out.println("查询书籍 bookId=" + bookId);
            return "success";
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    2.修改request.jsp

    <body>
    <h1>演示params的使用h1>
    <a href="user/find?bookId=100">查询书籍a>
    body>
    
    • 1
    • 2
    • 3
    • 4

    3.操作成功
    在这里插入图片描述
    如果bookId改为bookIdx, 报错
    在这里插入图片描述


    细节1:如果需要有bookId参数, 并且值为100. 否则报错.

    @RequestMapping(value = "/find", params = "bookId=100", method = RequestMethod.GET)
    
    • 1

    修改request.jsp

    <body>
    <h1>演示params的使用h1>
    <a href="user/find?bookId=200">查询书籍a>
    body>
    
    • 1
    • 2
    • 3
    • 4

    报错
    在这里插入图片描述

    细节2:需要有bookId参数, 并且值不为100. 否则报错.

    @RequestMapping(value = "/find", params = "bookId!=100", method = RequestMethod.GET)
    
    • 1

    修改request.jsp

    <body>
    <h1>演示params的使用h1>
    <a href="user/find?bookId=100">查询书籍a>
    body>
    
    • 1
    • 2
    • 3
    • 4

    报错
    在这里插入图片描述

    🍜支持Ant 风格资源地址

    1.?: 匹配文件名中的一个字符
    2.*: 匹配文件名中的任意字符
    3.**: 匹配多层路径

    4.举例
    /user/*/createUser:匹配/user/aaa/createUser, /user/bbb/createUserURL
    /user/**/createUser:匹配/user/createUser, /user/aaa/bbb/createUserURL
    /user/createUser??:匹配/user/createUseraa, /user/createUserbbURL

    案例
    1.修改UserHandler.java增加方法im

    @RequestMapping(value = "/user")
    @Controller //UserHandler就是一个处理器/控制器, 会注入到容器
    public class UserHandler {
    
        /**
         * 要求: 可以配置 /user/message/aa, /user/message/aa/bb/cc
         * @RequestMapping(value="/message/**") 表示可以匹配多层路径
         */
        @RequestMapping(value = "/message/**")
        public String im() {
            System.out.println("发送消息");
            return "success";
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    2.修改request.jsp

    <body>
    <hr><h1>演示Ant风格的请求资源方式h1>
    <a href="user/message/aa">发送消息1a>
    <a href="user/message/aa/bb/cc">发送消息2a>
    body>
    
    • 1
    • 2
    • 3
    • 4
    • 5

    3.测试成功…

    🍜配合@PathVariable 映射 URL 绑定的占位符

    1.@RequestMapping可以配合@PathVariable映射URL绑定的占位符
    2.这样就不需要在url地址上带参数名了, 更加的简洁明了.

    案例
    1.修改UserHandler.java增加方法register

    @RequestMapping(value = "/user")
    @Controller //UserHandler就是一个处理器/控制器, 会注入到容器
    public class UserHandler {
    
        /**
         * 前端页面: 占位符的演示
         * (value="/reg/{username}/{userId}"): 表示Kristina=>{username} 300=>{userId}
         *
         * @return
         */
        @RequestMapping(value = "/reg/{username}/{userId}")
        public String register(@PathVariable("username") String name,
                               @PathVariable("userId") int id) {
            System.out.println("接收到参数--" + "username=" + name + "--" + "userId=" + id);
            return "success";
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    2.修改request.jsp

    <body>
    <hr/><h1>占位符的演示h1>
    <a href="user/reg/Kristina/300">占位符的演示a>
    body>
    
    • 1
    • 2
    • 3
    • 4

    3.测试成功…

    🍜注意事项和使用细节

    1.映射的URL, 不能重复

    @RequestMapping(value = "/user")
    @Controller //UserHandler就是一个处理器/控制器, 会注入到容器
    public class UserHandler {
    
        @RequestMapping(value = "/hi")
        public String hi() {
            System.out.println("hi");
            return "success";
        }
    
        @RequestMapping(value = "/hi")
        public String hi2() {
            System.out.println("hi");
            return "success";
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    启动或重新发布时, 会报错. to { [/user/hi]}: There is already 'userHandler' bean method


    2.各种简写的方式

    @RequestMapping(value=“/buy”,method=RequestMethod.POST) 等价 @PostMapping(value=“/buy”)

    简写方式一览: @GetMapping @PostMapping @PutMapping @DeleteMapping
    在这里插入图片描述

    案例

    @RequestMapping(value = "/user")
    @Controller //UserHandler就是一个处理器/控制器, 会注入到容器
    public class UserHandler {
    
        /**
         * 5.@PostMapping(value="/buy") 等价 @Request(value="/buy", method=RequestMapping.POST)
         * @return
         */
        //@RequestMapping(value = "/buy", method = RequestMethod.POST)
        @PostMapping(value = "/buy")
        public String buy() {
            System.out.println("购买.");
            return "success";
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    测试request.jsp

    <body>
    <form action="user/buy" method="get">
        购买人: <input type="text" name="username"/><br/>
        购买量: <input type="password" name="nums"/><br/>
        <input type="submit" value="购买">
    form>
    body>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    报错
    在这里插入图片描述


    3.如果我们确定表单或者超链接会提交某个字段数据比如email, 要求提交的参数名和目标方法的参数名保持一致.

    案例
    1.修改UserHandler.java增加方法hello3

    @RequestMapping(value = "/user")
    @Controller //UserHandler就是一个处理器/控制器, 会注入到容器
    public class UserHandler {
        /**
         * hello3(String email) 表示如果我们的请求参数有 email=xx, 就会将传递的值, 赋给String email
         * , 要求名称保持一致, 如果不一致, 那么接收不到数据, 而是null
         * @param email
         * @return
         */
        @RequestMapping(value = "/hello3")
        public String hello3(String email) {
            System.out.println("email=" + email);
            return "success";
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    2.测试 浏览器地址栏 输入http://localhost:8080/springmvc/user/hello3?email=978964140@qq.com, 一定要注意提交参数名和后台方法的形参名保持一致, 否则后端接收不到参数

    在这里插入图片描述
    在这里插入图片描述

    3.如果输入一个错误的参数名, 那么后端接收不到数据
    在这里插入图片描述
    在这里插入图片描述

    在这里插入图片描述

    🍜作业布置

    1.熟悉SpringMVC的执行流程图
    2.熟悉@RequestMapping注解的使用方式
    3.编写一个表单, 以Post的方式提交Computer信息, 后端编写ComputerHandler, 可以接收到信息.


    代码实现

    1.修改request.jsp

    <body>
    <h1>电脑信息h1>
    <form action="?" method="post">
        品牌:<input type="text" name="brand"/><br/>
        价格:<input type="text" name="price"/><br/>
        数量:<input type="text" name="nums"/><br/>
        <input type="submit" value="提交">
    form>
    body>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    2.com.zzw.web包下 新建ComputerHandler

    @RequestMapping(value = "/computer")
    @Controller
    public class ComputerHandler {
    
        //这里一定要注意, info方法的形参名需要和请求的参数名保持一致
        @PostMapping(value = "/info", params = {"brand", "price", "nums"})
        public String info(String brand, String price, String nums) {
            System.out.println("电脑信息--brand=" +  brand
                    + "--price=" + price + "--nums" + nums);
            return "success";
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    3.配置页面访问路径

    <form action="computer/info" method="post">
    
    • 1

    4.测试成功…
    在这里插入图片描述

    🍜Postman

    在这里插入图片描述

    🍜Postman是什么

    1.Postman是一款功能超级强大的用于发送HTTP请求的 测试工具.
    2.做WEB页面开发和测试的人员常用工具.
    3.创建和发送任何的HTTP请求(GET/Post/Put/Delete)

    🍜Postman相关资源

    官方网站: https://www.postman.com/
    文档: https://learning.postman.com/docs/introduction/overview/
    下载地址: https://www.postman.com/downloads/.

    资料已上传…

    🍜Postman安装

    1.资料已上传, 下载后右键管理员身份打开即可安装(非常简单), Postman不会让你选择安装路径, 会直接安装, 一般安装在系统盘.
    2.安装成功, 在桌面上有快捷图标. 双击打开Postman.

    🍜Postman快速入门

    ●要求:使用Postmanhttp://www.baidu.com发出get请求, 得到返回的html格式数据

    调整字体大小: File–Settings
    在这里插入图片描述
    调整页面大小: ctrl++, ctrl+ -


    注册账号:(可选, 不注册不影响使用) 输入邮件, 用户名, 密码
    在这里插入图片描述


    1.创建Http Request, 如果你已经创建过, 会直接进入Workspace

    File–New
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

    2.发出请求
    在这里插入图片描述

    🍜Controller测试案例

    需求说明: 使用Postman, 完成UserHandler方法的请求


    1.完成请求
    在这里插入图片描述
    使用Postman测试Controller方法的步骤
    1.确定请求的地址 url: http://localhost:8080/springmvc/user/buy
    2.请求的方式 -Post
    3.确定请求的参数/数据 -无
    4.确定Header有没有特殊的指定 -无 http协议


    2.完成请求
    在这里插入图片描述

    在这里插入图片描述
    在这里插入图片描述

    使用Postman测试Controller方法的步骤
    1.确定请求的地址 url: http://localhost:8080/springmvc/user/find
    2.请求的方式 -Get
    3.确定请求的参数/数据 -bookId=100
    4.确定Header有没有特殊的指定 -无


    3.完成请求
    在这里插入图片描述

    在这里插入图片描述
    在这里插入图片描述

    使用Postman测试Controller方法的步骤
    1.确定请求的地址 url: http://localhost:8080/springmvc/user/message/aa/bb/cc
    2.请求的方式 -Get/Post
    3.确定请求的参数/数据 -无
    4.确定Header有没有特殊的指定 -无


    4.完成请求
    在这里插入图片描述

    在这里插入图片描述

    使用Postman测试Controller方法的步骤
    1.确定请求的地址 url: http://localhost:8080/springmvc/user/reg/zzw/23
    2.请求的方式 -Get/Post
    3.确定请求的参数/数据 -无
    4.确定Header有没有特殊的指定 -无


    5.完成请求
    在这里插入图片描述

    在这里插入图片描述

    使用Postman测试Controller方法的步骤
    1.确定请求的地址 url: http://localhost:8080/springmvc/user/hello3
    2.请求的方式 -Get
    3.确定请求的参数/数据 -email=xx@qq.com
    4.确定Header有没有特殊的指定 -无

    🍜其它说明

    1.创建 对应的Http Request, 放到已有的Collection

    在这里插入图片描述
    在这里插入图片描述

    2.在Headers选项页, 增加 Content-Type applicatoin/json
    在这里插入图片描述

    3.因为是Post请求, 在Body选项填写Json数据/Furn数据
    在这里插入图片描述

    🍜作业布置

    1.创建新的Collection, 命名为你的名字, 比如 zzwCollection
    在这里插入图片描述

    2.创建多个http request, 完成对UserHandler的各个方法的请求
    在这里插入图片描述

    测试1

    @RequestMapping(value = "/user")
    @Controller //UserHandler就是一个处理器/控制器, 会注入到容器
    public class UserHandler {
        @PostMapping(value = "/buy")
        public String buy() {
            System.out.println("购买.");
            return "success";
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    使用Postman测试Controller方法的步骤
    1.确定请求的地址 url: http://localhost:8080/springmvc/user/buy
    2.请求的方式 -Post
    3.确定请求的参数/数据 -无
    4.确定Header有没有特殊的指定 -无


    测试2

    @RequestMapping(value = "/user")
    @Controller //UserHandler就是一个处理器/控制器, 会注入到容器
    public class UserHandler {
        @RequestMapping(value = "/find", params = "bookId=100", method = RequestMethod.GET)
        public String search(String bookId) {
            System.out.println("查询书籍 bookId=" + bookId);
            return "success";
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    使用Postman测试Controller方法的步骤
    1.确定请求的地址 url: http://localhost:8080/springmvc/user/find
    2.请求的方式 -Get
    3.确定请求的参数/数据 -bookId=100
    4.确定Header有没有特殊的指定 -无


    测试3

    @RequestMapping(value = "/user")
    @Controller //UserHandler就是一个处理器/控制器, 会注入到容器
    public class UserHandler {
        @RequestMapping(value = "/message/**")
        public String im() {
            System.out.println("发送消息");
            return "success";
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    使用Postman测试Controller方法的步骤
    1.确定请求的地址 url: http://localhost:8080/springmvc/user/message/aa/bb/cc
    2.请求的方式 -Get/Post
    3.确定请求的参数/数据
    4.确定Header有没有特殊的指定 -无


    测试4

    @RequestMapping(value = "/user")
    @Controller //UserHandler就是一个处理器/控制器, 会注入到容器
    public class UserHandler {
        @RequestMapping(value = "/reg/{username}/{userId}")
        public String register(@PathVariable("username") String name,
                               @PathVariable("userId") int id) {
            System.out.println("接收到参数--" + "username=" + name + "--" + "userId=" + id);
            return "success";
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    使用Postman测试Controller方法的步骤
    1.确定请求的地址 url: http://localhost:8080/springmvc/user/reg/star/3000000
    2.请求的方式 -Get/Post
    3.确定请求的参数/数据 -无
    4.确定Header有没有特殊的指定 -无


    测试5

    @RequestMapping(value = "/user")
    @Controller //UserHandler就是一个处理器/控制器, 会注入到容器
    public class UserHandler {
        @GetMapping(value = "/hello3")
        public String hello3(String email) {
            System.out.println("email=" + email);
            return "success";
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    使用Postman测试Controller方法的步骤
    1.确定请求的地址 url: http://localhost:8080/springmvc/user/hello3
    2.请求的方式 -Get
    3.确定请求的参数/数据 -email=xx@qq.com
    4.确定Header有没有特殊的指定 -无

    🍜Rest

    🍜Rest基本介绍

    ●说明

    1.REST:Representational State Transfer. (资源)表现层状态转化. 是目前流行的请求方式. 它结构清晰, 很多网站使用.
    2.HTTP协议里面, 四个表示操作方式的动词: GET, POST, PUT, DELETE, 它们分别对应四种基本操作: GET用来获取资源, POST用来新建资源, PUT用来更新资源, DELETE用来删除资源
    3.实例. 传统的请求方法:
    getBook?id=1 GET
    delete?id=1 GET
    update POST
    add POST
    4.说明: 传统的url是通过参数来说明crud的类型, rest是通过get/post/put/delete来说明crud的类型

    REST的核心过滤器
    1.当前的浏览器只支持post/get请求, 因此为了得到put/delete的请求方式需要使用Spring提供的HiddenHttpMethodFilter过滤器进行转换.
    2.HiddenHttpMethodFilter:浏览器form表单只支持GETPOST请求, 而DELETE, PUTmethod并不支持, Spring添加了一个过滤器, 可以将这些请求转换为标准的http方法, 使得支持GET, POST, PUTDELETE请求.
    3.HiddenHttpMethodFilter只能对post请求方式进行转换.
    4.这个过滤器需要在web.xml中配置

    🍜Rest实例

    需求说明
    小明去书店买书, 完成购买书籍的增删改查

    1.修改web.xml, 配置HiddenHttpMethodFilter

    
    <filter>
        <filter-name>hiddenHttpMethodFilterfilter-name>
        <filter-class>org.springframework.web.filter.HiddenHttpMethodFilterfilter-class>
    filter>
    <filter-mapping>
        <filter-name>hiddenHttpMethodFilterfilter-name>
        <url-pattern>/*url-pattern>
    filter-mapping>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    2.修改springDispatcherServlet-serlvet.xml 添加配置

    
    
    <mvc:annotation-driven>mvc:annotation-driven>
    
    <mvc:default-servlet-handler/>
    
    • 1
    • 2
    • 3
    • 4
    • 5

    3.在web路径下创建rest.jsp, 注意引入jquery, 测试查询/添加/删除/修改

    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <html>
    <head>
        <title>rest测试title>
    head>
    <body>
    <h3>Rest风格的crud操作案例h3>
    <br/><hr>
    <h3>rest风格的url 查询书籍[get]h3>
    <a href="?">点击查询书籍a>
    <br/><hr>
    <h3>rest风格的url 添加书籍[post]h3>
    <form action="?" method="?">
        name:<input name="bookName" type="text"/><br/>
        <input type="submit" value="添加书籍">
    form>
    <br/><hr>
    <h3>rest风格的url 删除一本书h3>
    <a href="?" id="?">删除指定id的书a>
    <br/><hr>
    <h3>rest风格的url 修改书籍[put]h3>
    <form action="?">
        <input type="submit" value="修改书籍">
    form>
    body>
    html>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26

    4.在com.zzw.web.rest下, 创建BookHandler.java

    1.完成查询

     //BookHandler 处理rest风格的请求-增删改查
    @RequestMapping(value = "/user")
    @Controller
    public class BookHandler {
    
        //查询[GET]
        @GetMapping(value = "/book/{id}")
        public String getBook(@PathVariable("id") String id) {
            System.out.println("查询书籍 id=" + id);
            return "success";
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    5.前端修改请求地址

    <h3>rest风格的url 查询书籍[get]h3>
    <a href="user/book/200">点击查询书籍a>
    
    • 1
    • 2

    2.完成添加
    @PostMapping(value = "/book") @GetMapping(value = "/book/{id}")不重复

    //BookHandler 处理rest风格的请求-增删改查
    @RequestMapping(value = "/user")
    @Controller
    public class BookHandler {
    
        //查询[GET]
        @GetMapping(value = "/book/{id}")
        public String getBook(@PathVariable("id") String id) {
            System.out.println("查询书籍 id=" + id);
            return "success";
        }
    
        //添加[POST]
        @PostMapping(value = "/book")
        public String addBook(String bookName) {
            System.out.println("添加书籍 bookName=" + bookName);
            return "success";
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    前端修改请求地址

    <h3>rest风格的url 添加书籍[post]h3>
    <form action="user/book" method="post">
        name:<input name="bookName" type="text"/><br/>
        <input type="submit" value="添加书籍">
    form>
    
    • 1
    • 2
    • 3
    • 4
    • 5

    3.完成删除

    //BookHandler 处理rest风格的请求-增删改查
    @RequestMapping(value = "/user")
    @Controller
    public class BookHandler {
        //查询[GET]
        @GetMapping(value = "/book/{id}")
        public String getBook(@PathVariable("id") String id) {
            System.out.println("查询书籍 id=" + id);
            return "success";
        }
    
        //添加[POST]
        @PostMapping(value = "/book")
        public String addBook(String bookName) {
            System.out.println("添加书籍 bookName=" + bookName);
            return "success";
        }
    
        //删除[DELETE]
        @RequestMapping(value = "/book/{id}", method = RequestMethod.DELETE)
        public String deleteBook(@PathVariable("id") String id) {
            System.out.println("删除书籍 id=" + id);
            //return "success";//[如果这样写会报错 JSP 只允许 GET、POST 或 HEAD]
            //解读
            //1. redirect:/user/success重定向
            //2. 会被解析成 /工程路径/user/success
            return "redirect:/user/success";//提示: 重定向不能重定向到WEB-INF下的资源, 所以需要借助successGeneral方法
        }
    
        //如果请求时 /user/success, 就转发到 success.jsp
        //successGeneral 对应的url http://localhost:8080/springmvc/user/success
        @RequestMapping(value = "/success")
        public String successGeneral() {
            return "success";//由该方法 转发到success.jsp页面
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36

    知识点:
    1.web路径/script目录下存放jquery文件, jquery复习

    2.为什么前端做了一个操作后, 就可以被过滤器过滤处理, 定位到后端delete方法? 回答: HiddenHttpMethodFilter机制

    3.return “success”; 会报以下错误
    在这里插入图片描述


    前端修改

    <head>
        <title>rest测试title>
        <%--script标签建议放在head内--引入jquery--%>
        <script type="text/javascript" src="script/jquery-3.6.0.min.js">script>
        <script type="text/javascript">
            $(function () {//当页面加载完成后就执行
                // alert("ok...");
                //给删除超链接绑定一个点击事件
                $("#deleteBook").click(function () {
                    // alert("点击....");
                    //我们自己定义一个提交的行为
                    $("#hiddenForm").attr("action", this.href);
                    $("input:hidden").val("DELETE");
                    $("#hiddenForm").submit();
                    return false;//改变点击超链接的行为, 不再提交
                })
            });
        script>
    head>
    <body>
    <h3>rest风格的url 删除一本书h3>
    <%--解读
     1. 默认情况下, <a href="user/book/600">删除指定id的书a> 是get请求
     2. 怎么样将 get 请求转成 springmvc 可以识别的 delete 请求, 就要考虑HiddenHttpMethodFilter
        public static final String DEFAULT_METHOD_PARAM = "_method";
        -------------------------------------------------------------------------------------------------------------
        if ("POST".equals(request.getMethod()) && request.getAttribute(WebUtils.ERROR_EXCEPTION_ATTRIBUTE) == null) {
            String paramValue = request.getParameter(this.methodParam);
            if (StringUtils.hasLength(paramValue)) {
                String method = paramValue.toUpperCase(Locale.ENGLISH);
                if (ALLOWED_METHODS.contains(method)) {
                    requestToUse = new HttpMethodRequestWrapper(request, method);
                }
            }
        }
        -------------------------------------------------------------------------------------------------------------
        private static final List<String> ALLOWED_METHODS =
    			Collections.unmodifiableList(Arrays.asList(HttpMethod.PUT.name(),
    					HttpMethod.DELETE.name(), HttpMethod.PATCH.name()));
     3. 从上面代码可以看到 HiddenHttpMethodFilter 过滤器可以对以Post方式提交的delete, put, patch进行转换
        , 转换称springmvc可以识别的 RequestMethod.DELETE / RequestMethod.PUT...
     4. 我们需要将 get <a href="user/book/600">删除指定id的书a> 以 post方式提交给后端handler, 这样过滤器才会生效
     5. 我们可以通过jquery来处理--引入jquery
    --%>
    <a href="user/book/600" id="deleteBook">删除指定id的书a>
    <form action="" method="post" id="hiddenForm">
        <input type="hidden" name="_method"/>
    form>
    body>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49

    4.完成修改

    //BookHandler 处理rest风格的请求-增删改查
    @RequestMapping(value = "/user")
    @Controller
    public class BookHandler {
        //修改[PUT]
        @PutMapping(value = "/book/{id}")
        public String updateBook(@PathVariable("id") String id) {
            System.out.println("修改书籍 id=" + id);
            return "redirect:/user/success";
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    前端修改请求代码

    <h3>rest风格的url 修改书籍[put]h3>
    <form action="user/book/666" method="post">
        <input type="button" name="_method" value="PUT"/>
        <input type="submit" value="修改书籍"/>
    form>
    
    • 1
    • 2
    • 3
    • 4
    • 5

    🍜HiddenHttpMethodFilter机制

    打断点, 进行debug
    在这里插入图片描述
    在这里插入图片描述

    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

    🍜注意事项和细节

    1.HiddenHttpMethodFilter, 在将post转成delete / put请求时, 是按_method参数名 来读取的
    2.如果web项目是运行在Tomcat8及以上, 会发现被过滤成DELETEPUT请求, 到达控制器时能顺利执行, 但是返回时(forward)会报HTTP 405的错误提示: JSP 只允许 GET、POST 或 HEAD

    1. 解决方式1: 使用Tomcat7
    2. 解决方式2: 将请求转发(forward)改为请求重定向(redirect): 重定向到一个Handler, 由Handler转发到页面

    3.页面测试时, 如果出现点击修改书籍, 仍然走的是删除url, 是因为浏览器原因(缓存等原因).

    🍜课后作业

    需求说明
    小王去商超买衣服, 完成购买衣服的增删改查

    1.在web路径下创建restBuyClothes.jsp, 注意引入jquery, 测试查询/添加/删除/修改

    <head>
        <title>购买衣服title>
        <%--引入jquery--%>
        <script type="text/javascript" src="script/jquery-3.6.0.min.js">script>
    head>
    <body>
    <h3>rest风格的url 挑选衣服[get]h3>
    <a href="?">点击挑选衣服a>
    <br/><hr>
    <h3>rest风格的url 添加衣服[post]h3>
    <a href="?">点击添加衣服a>
    <form action="?" method="post">
        clothes: <input name="clothes" type="text"><br/>
        <input type="submit" value="添加衣服">
    form>
    <br/><hr>
    <h3>rest风格的url 删除一件衣服[delete]h3>
    <a href="?" id="deleteClothes">删除一件衣服a>
    <form action="" method="post" id="deleteForm">
        <input type="hidden" name="_method"/>
    form>
    <br/><hr>
    <h3>rest风格的url 修改衣服[get]h3>
    <form action="?" method="post">
        <input type="hidden" name="_method">
    form>
    body>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27

    2.在com.zzw.web.rest下, 创建ClothesHandler.java

    1.完成查询
    @PostMapping(value = "/clothes") @GetMapping(value = "/clothes/{brand}")不重复

    @RequestMapping(value = "/user")//处理Rest风格的请求 增删改查
    @Controller
    public class ClothesHandler {
    
        //挑选[GET]
        @GetMapping(value = "/clothes/{brand}")
        public String queryClothes(@PathVariable("brand") String brand) {
            System.out.println("挑选衣服 brand=" + brand);
            return "success";
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    .前端修改请求

    <h3>rest风格的url 挑选衣服[get]h3>
    <a href="user/clothes/阿迪达斯">点击挑选衣服a>
    
    • 1
    • 2

    2.完成添加

    @RequestMapping(value = "/user")
    @Controller
    public class ClothesHandler {//演示Rest风格的请求
    
        //挑选[GET]
        @GetMapping(value = "/clothes/{brand}")
        public String queryClothes(@PathVariable("brand") String brand) {
            System.out.println("挑选衣服 brand=" + brand);
            return "success";
        }
    
        //添加[POST]
        @PostMapping(value = "/clothes")
        public String addClothes(String brand) {
            System.out.println("添加衣服 brand=" + brand);
            return "success";
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    .前端修改请求

    <h3>rest风格的url 添加衣服[post]h3>
    <form action="user/clothes" method="post">
        clothes: <input name="brand" type="text"><br/>
        <input type="submit" value="添加衣服">
    form>
    
    • 1
    • 2
    • 3
    • 4
    • 5

    3.完成删除

    @RequestMapping(value = "/user")
    @Controller
    public class ClothesHandler {//演示Rest风格的请求
    
        //挑选[GET]
        @GetMapping(value = "/clothes/{brand}")
        public String queryClothes(@PathVariable("brand") String brand) {
            System.out.println("挑选衣服 brand=" + brand);
            return "success";
        }
    
        //添加[POST]
        @PostMapping(value = "/clothes")
        public String addClothes(String brand) {
            System.out.println("添加衣服 brand=" + brand);
    		//return "success";
            return "redirect:/user/success";
        }
    
        @RequestMapping(value = "/success2")
        public String successGeneral() {
            return "success";
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24

    .前端修改请求

    <head>
        <title>购买衣服title>
        <%--引入jquery--%>
        <script type="text/javascript" src="script/jquery-3.6.0.min.js">script>
        <script type="text/javascript">
            $(function () {
                // alert("123");
                $("#deleteClothes").click(function () {
                    // alert("ok..");
                    $("#deleteForm")[0].action = this.href;
                    $("input:hidden")[0].value = "DELETE";
                    $("#deleteForm").submit();
                    return false;
                })
            })
        script>
    head>
    <body>
    <h3>rest风格的url 删除一件衣服[delete]h3>
    <a href="user/clothes/361" id="deleteClothes">删除一件衣服a>
    <form action="" method="post" id="deleteForm">
        <input type="hidden" name="_method"/>
    form>
    body>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24

    4.完成修改

    @RequestMapping(value = "/user")
    @Controller
    public class ClothesHandler {//演示Rest风格的请求
    
        //挑选[GET]
        @GetMapping(value = "/clothes/{brand}")
        public String queryClothes(@PathVariable("brand") String brand) {
            System.out.println("挑选衣服 brand=" + brand);
            return "success";
        }
    
        //添加[POST]
        @PostMapping(value = "/clothes")
        public String addClothes(String brand) {
            System.out.println("添加衣服 brand=" + brand);
    		//return "success";
            return "redirect:/user/success";
        }
    
        @RequestMapping(value = "/success2")
        public String successGeneral() {
            return "success";
        }
    
        //修改[PUT]
        @PutMapping(value = "/clothes/{brand}")
        public String updateClothes(@PathVariable("brand") String brand) {
            System.out.println("修改衣服 brand=" + brand);
            return "redirect:/user/success2";
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31

    .前端修改请求

    <body>
    <h3>rest风格的url 修改衣服[get]h3>
    <form action="user/clothes/李宁" method="post">
        <input type="hidden" name="_method" value="PUT">
        <input type="submit" value="修改衣服"/>
    form>
    body>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    🍜SpringMVC映射请求数据

    🍜RequestParam - 获取参数值

    开发中, 如何获取到http://ip:port/url?参数名=参数值&参数名=参数值

    1.com.zzw.web.requestParam新建VoteHandler

    @RequestMapping("/vote")
    @Controller
    public class VoteHandler {
    
        /**
         * 解读
         * 1.获取到超链接传递的数据 请求 http://localhost:8080/springmvc/vote/vote01?name=xx
         * 2.@RequestParam 表示会接收提交的参数
         * 3,value="name" 表示提交的参数名是name
         * 4.required=false 表示该参数可以没有; 默认是true, 表示必须有这个参数
         * 5.当我们使用了 @RequestParam(value="name", required=false)后 请求的参数名和方法的形参名可以不一致
         */
        @RequestMapping(value = "/vote01")
        public String test01(@RequestParam(value = "name", required = false) String username) {
            System.out.println("得到username=" + username);
            return "success";
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    2.web路径下新建request_parameter.jsp

    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <html>
    <head>
        <title>测试 request parametertitle>
    head>
    <body>
    <h2>获取到超链接参数值h2>
    <hr>
    <a href="vote/vote01?name=zzw">获取超链接的参数a>
    body>
    html>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    3.Postman测试

    get方式提交
    在这里插入图片描述post方式提交
    在这里插入图片描述

    🍜获取http请求消息头

    ●说明
    1.在开发中, 如何获取到http请求的消息头信息
    2.使用较少

    案例
    1.修改VoteHandler.java, 增加方法 test02

    @RequestMapping("/vote")
    @Controller
    public class VoteHandler {
        /**
         * 需求: 获取http请求头信息, 获取到Accept-Encoding 和 Host
         * [涉及到知识点 http协议]
         * @param a1
         * @param a2
         * @return
         */
        @RequestMapping(value = "/vote02")
        public String test02(@RequestHeader("Accept-Encoding") String a1, @RequestHeader("Host") String a2) {
            System.out.println("Accept-Encoding=" + a1);
            System.out.println("Host=" + a2);
            //返回一个结果
            return "success";
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    修改request_parameter.jsp

    <h2>获取到消息头h2>
    <a href="vote/vote02">获取到Http消息头信息a>
    
    • 1
    • 2

    3.Postman测试
    在这里插入图片描述

    🍜获取JavaBean对象

    开发中, 如何获取到javabean对象, 就是以前的entity/pojo对象数据

    案例
    1.com.zzw.web.requestParam.entity包下新建Pet

    public class Pet {
        private Integer id;
        private String name;
    
    	//setter, getter, toString方法
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    同包下新建Master

    public class Master {
        private Integer id;
        private String name;
        private Pet pet;//对象的属性是另外一个对象[涉及到属性级联]
        
    	//setter, getter, toString方法
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    2.修改VoteHandler.java, 增加方法 test03

    public class VoteHandler {
        /**
         * 演示如何获取到提交数据->封装成java对象
         * 说明
         * 1.方法的形参用对应的类型来指定即可, SpringMVC会自动的进行封装
         * 2.如果要自动地完成封装, 要求提交的数据, 参数名和对象的字段名保持一致
         * 3.如果属性是对象, 这里仍然是通过 字段名.字段名 比如Master [pet]
         *   , 即提交的数据 参数名 是 pet.id pet.name, 这就是级联操作
         * 4.如果提交的数据 的参数名和对象的字段名不匹配, 则对象的属性值就是null
         * @return
         */
        @RequestMapping(value = "/vote03")
        public String test03(Master master) {
            System.out.println("master=" + master);
            //返回结果
            return "success";
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    3.修改request_parameter.jsp

    <%--解读
    1.这是一个表单, 表单的数据对应Master对象
    2.提交的数据参数名和对象的字段名一致即可
    --%>
    <h1>添加主人信息h1>
    <form action="vote/vote03" method="post">
        主人:<input type="text" name="id"/><br/>
        主人:<input type="text" name="name"/><br/>
        宠物名:<input type="text" name="pet.id"/><br/>
        宠物名:<input type="text" name="pet.name"/><br/>
        <input type="submit" value="添加主人和动物"/>
    form>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    3.Postman测试

    get方式提交
    在这里插入图片描述post方式提交
    在这里插入图片描述

    注意事项和细节

    1.支持级联数据获取
    2.表单的控件名称name需要和javabean对象名称呼应, 否则就是null

    🍜使用Servlet API

    ●说明
    1.开发中, 我们可以需要使用到原生的servlet api
    2.使用servlet api, 需要引入tomcat/lib下的servlet-api.jar

    案例
    1.修改VoteHandler.java, 增加方法 test04

    @RequestMapping("/vote")
    @Controller
    public class VoteHandler {
        /**
         * 使用servlet api, 来获取提交的数据
         * @param request
         * @param response
         * @return
         */
        @RequestMapping(value = "/vote04")
        public String test04(HttpServletRequest request,
                             HttpServletResponse response) {
            String username = request.getParameter("username");
            String password = request.getParameter("password");
            System.out.println("username=" + username);
            System.out.println("password=" + password);
            //返回结果
            return "success";
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    2.修改request_parameter.jsp

    <h1>演示 servlet api的使用h1>
    <form action="vote/vote04" method="post">
        用户名:<input type="text" name="username"/><br/>
        密 码:<input type="password" name="password"/><br/>
        <input type="submit" value="提交"/>
    form>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    3.Postman测试

    post方式提交
    在这里插入图片描述


    注意事项和细节
    1.除了HttpServletRequest, HttpServletResponse其它对象还可以以这样的方式获取
    2.HttpSession, java.security.Principal, InputStream, OutputStream, Reader, Writer
    3.其中一些对象也可以通过 HttpServletRequest / HttpServletResponse对象获取, 比如Session对象, 既可以通过参数传入, 也可以通过request.getSession()获取, 效果一样, 推荐使用参数形式传入, 更加简单明了

    @RequestMapping("/vote")
    @Controller
    public class VoteHandler {
        /**
         * 使用servlet api, 来获取提交的数据
         * @param request
         * @param response
         * @return
         */
        @RequestMapping(value = "/vote04")
        public String test04(HttpServletRequest request,
                             HttpServletResponse response,
                             HttpSession session2) {
            //获取到session
            //servlet的原生的方式
            HttpSession session = request.getSession();
            System.out.println("session=" + session);
            //注意: 通过参数传入的 session2 和 通过request.getSession()得到的 session对象是同一个
            System.out.println("session2=" + session2);
            //返回结果
            return "success";
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    🍜模型数据

    💞模型数据处理 - 数据放入request

    ●说明
    1.开发中, 控制器/处理器中获取的数据如何放入request域, 然后在前端(VUE/JSP/...)中显示

    方式1:
    通过HttpServletRequest放入request

    方式2:
    通过请求的方法参数Map 放入request

    方式3:
    通过返回 ModelAndView 对象实现request域数据

    🍜默认机制放入Request域

    1.web路径下新建model_data.jsp

    <head>
        <title>测试 模型数据title>
    head>
    <body>
    <h1>添加主人信息h1>
    <form action="?" method="?">
      主人号:<input type="text" name="?"/><br/>
      主人名:<input type="text" name="?"/><br/>
      宠物号:<input type="text" name="?"/><br/>
      宠物名:<input type="text" name="?"/><br/>
      <input type="submit" value="添加主人和动物"/>
    form>
    body>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    2.修改com.zzw.web.requestParam.VoteHandler.java, 增加方法 test05

    @RequestMapping("/vote")
    @Controller
    public class VoteHandler {
        /**
         * 1.演示将提交的数据->springmvc 封装到java对象->springmvc 会自动的将其放入到request域 [springmvc底层机制]
         * 2.这样我们就可以在跳转到的页面取出数据.
         * @return 参数名和对象的字段名保持一致
         */
        @RequestMapping(value = "/vote05")
        public String test05(Master master) {
    
            //解读
            //1.springmvc会自动地把获取的model模型, 放入到request域中, 名字就是master
            //  在request域中: ("master", master对象)
            //2.也可以手动将master放入到request...
    
            //返回一个结果
            return "vote_ok";
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    3.web路径/WEB-INF/pages目录 新建vote_ok.jsp el表达式

    <body>
    <h1>获取到的数据显示页面h1>
    <hr>
    取出 request域的数据-通过el表达式获取即可
    <br/>
    address: <br/>
    主人名字= ${requestScope.master.name}
    主人id= ${requestScope.master.id}
    宠物名字= ${requestScope.master.pet.name}
    body>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    4.完善model_data.jsp

    <h1>添加主人信息h1>
    <form action="vote/vote05" method="post">
        主人号:<input type="text" name="id"/><br/>
        主人名:<input type="text" name="name"/><br/>
        宠物号:<input type="text" name="pet.id"/><br/>
        宠物名:<input type="text" name="pet.name"/><br/>
        <input type="submit" value="添加主人和动物"/>
    form>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    5.测试…

    🍜通过HttpServletRequest放入request域

    1.修改VoteHandler.java, 增加代码

    @RequestMapping("/vote")
    @Controller
    public class VoteHandler {
            /**
         * 1.演示将提交的数据->springmvc 封装到java对象->springmvc 会自动的将其放入到request域 [springmvc底层机制]
         * 2.这样我们就可以在跳转到的页面取出数据.
         * @return 参数名和对象的字段名保持一致
         */
        @RequestMapping(value = "/vote05")
        public String test05(Master master, HttpServletRequest request) {
    
            //解读
            //1.springmvc会自动地把获取的model模型, 放入到request域中, 名字就是master
            //  在request域中: ("master", master对象)
    
            //2.也可以手动将master放入到request
            request.setAttribute("address", "济南");
            //3.如果我们希望修改master的属性值
            master.setName("coco");
            //4.分析一下springmvc默认存放对象到request域中, 属性名是如何确定的
            //  request域 ("master", master) 属性名是类名/类型名 首字母小写
    
            //返回一个结果
            return "vote_ok";
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26

    2.vote_ok.jsp

    <body>
    <h1>获取到的数据显示页面h1>
    <hr>
    取出 request域的数据-通过el表达式获取即可
    <br/>
    address: <br/>
    主人名字= ${requestScope.master.name}
    主人id= ${requestScope.master.id}
    宠物名字= ${requestScope.master.pet.name}
    body>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    测试
    在这里插入图片描述

    🍜通过方法参数Map 放入request域

    1.修改model_data.jsp, 增加代码

    <h1>添加主人信息[测试 Map ]h1>
    <form action="vote/vote06" method="post">
        主人号:<input type="text" name="id"/><br/>
        主人名:<input type="text" name="name"/><br/>
        宠物号:<input type="text" name="pet.id"/><br/>
        宠物名:<input type="text" name="pet.name"/><br/>
        <input type="submit" value="添加主人和动物"/>
    form>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    2.修改VoteHandler.java, 增加方法test06

    @RequestMapping("/vote")
    @Controller
    public class VoteHandler {
        /**
         * 演示通过Map 设置数据到request域
         * @return
         */
        @RequestMapping(value = "/vote06")
        public String test06(Master master, Map<String, Object> map) {
            //解读
            //1.需求是通过map对象, 添加属性到request中
            //2.原理分析: springmvc会遍历map, 然后将map的k-v存放到request域中
            map.put("address", "beijing...");
            map.put("master", null);
            //返回一个结果
            return "vote_ok";
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    3.Postman测试

    post方式提交
    在这里插入图片描述在这里插入图片描述

    🍜ModelAndView使用

    1.修改model_data.jsp, 增加代码

    <h1>添加主人信息[测试ModelAndView]h1>
    <form action="?" method="?">
        主人号:<input type="text" name="id"/><br/>
        主人名:<input type="text" name="name"/><br/>
        宠物号:<input type="text" name="pet.id"/><br/>
        宠物名:<input type="text" name="pet.name"/><br/>
        <input type="submit" value="添加主人和动物"/>
    form>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    2.修改VoteHandler.java, 增加方法test07

    @RequestMapping("/vote")
    @Controller
    public class VoteHandler {
        /**
         * 演示通过返回ModelAndView对象, 将数据放入request中
         * @return
         */
        @RequestMapping(value = "/vote07")
        public ModelAndView test07(Master master) {
    
            ModelAndView modelAndView = new ModelAndView();
            //放入属性到modelAndView对象
            modelAndView.addObject("address", "shanghai~");
            modelAndView.addObject("master", null);
            //可以把从数据库得到的数据->对象->放入到modelAndView[service-dao-db]
            //这里指定要跳转的视图名称
            modelAndView.setViewName("vote_ok");
            //返回结果
            return modelAndView;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    3.完善model_data.jsp

    <h1>添加主人信息[测试ModelAndView]h1>
    <form action="vote/vote07" method="post">
        主人号:<input type="text" name="id"/><br/>
        主人名:<input type="text" name="name"/><br/>
        宠物号:<input type="text" name="pet.id"/><br/>
        宠物名:<input type="text" name="pet.name"/><br/>
        <input type="submit" value="添加主人和动物"/>
    form>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    4.Postman测试

    post方式提交
    在这里插入图片描述
    在这里插入图片描述
    注意事项和细节
    1.从本质看, 请求响应的方法return xx时返回了一个字符串, 其实本质是返回了一个ModeAndView对象, 只是默认被封装起来的.
    2.ModelAndView即可以包含model数据, 也可以包含视图信息
    3.ModelAndView对象的addObject方法可以添加key-val数据.
    4.ModelAndView对象setView方法可以指定视图名称

    💞模型数据处理 - 数据放入session

    说明
    开发中, 控制器 / 处理器中获取的数据如何放入session域, 然后在前端(VUE/JSP/...)取出显示.

    案例
    1.修改model_data.jsp, 增加代码

    <h1>添加主人信息[测试session]h1>
    <form action="?" method="?">
        主人号:<input type="text" name="id"/><br/>
        主人名:<input type="text" name="name"/><br/>
        宠物号:<input type="text" name="pet.id"/><br/>
        宠物名:<input type="text" name="pet.name"/><br/>
        <input type="submit" value="添加主人和动物"/>
    form>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    2.修改VoteHandler.java, 增加方法test08

    @RequestMapping("/vote")
    @Controller
    public class VoteHandler {
        /**
         * 演示如何将数据设置到session域中
         * @return
         */
        @RequestMapping(value = "/vote08")
        public String test08(Master master, HttpSession httpSession) {
            //master对象是默认放在request域中
    
            //我们将master对象放入到session
            httpSession.setAttribute("master", master);
            httpSession.setAttribute("address", "beijing``");
            return "vote_ok";
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    3.vote_ok.jsp增加代码

    <head>
        <title>vote_oktitle>
    head>
    <body>
    取出 session域的数据<br/>
    address: ${sessionScope.address}<br/>
    主人名字= ${sessionScope.master.name}<br/>
    主人信息= ${sessionScope.master}<br/>
    body>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    4.完善model_data.jsp

    <h1>添加主人信息[测试session]h1>
    <form action="vote/vote08" method="post">
        主人号:<input type="text" name="id"/><br/>
        主人名:<input type="text" name="name"/><br/>
        宠物号:<input type="text" name="pet.id"/><br/>
        宠物名:<input type="text" name="pet.name"/><br/>
        <input type="submit" value="添加主人和动物"/>
    form>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    4.Postman测试

    post方式提交
    在这里插入图片描述

    💞模型数据 - @ModelAttribute

    ●基本说明
    开发中, 有时需要使用某个前置方法(比如prepareXxx(), 方法名由程序员定)给目标方法准备一个模型对象

    1.@ModelAttribute注解可以实现 这样的需求
    2.在某个方法上, 增加了@ModelAttribute注解后
    3.那么在调用该Handler的任何一个方法时, 都会先调用这个方法

    案例
    1.修改VoteHandler.java, 增加方法prepareModel

        /**
         * 解读
         * 1.当Handler的方法被标识 @ModelAttribute, 就视为一个前置方法
         * 2.当调用Handler的其它方法时, 都会先执行该前置方法
         * 3.类似我们前面学习Spring时, AOP的前置通知
         * 4.prepareModel 前置方法, 会切入到其它方法前执行. 底层是AOP机制
         */
        @ModelAttribute
        public void prepareModel() {
            System.out.println("prepareModel.........完成准备工作.........");
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    @ModelAttribute最佳实践
    修改用户信息(就是经典的使用这种机制的应用), 流程如下
    1.在修改前, 在前置方法中从数据库查出这个用户
    2.在修改方法(目标方法)中, 可以使用前置方法从数据库查询这个对象
    3.如果表单中对用户的某个属性修改了, 则以新的数据为准, 如果没有修改, 则以数据库的信息为准. 比如, 用户的某个属性不能修改, 就保持原来的值.

    🍜视图和视图解析器

    基本介绍
    1.在SpirngMVC中的目标方法最终返回都是一个视图(有各种视图)
    2.返回的视图都会由一个视图解析器来处理(视图解析器有很多种)

    🍜 自定义视图

    1.在默认情况下, 我们都是返回默认的视图, 然后返回的视图交由SpringMVCInternalResourceViewResolver视图解析器来处理的.

    
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        
        <property name="prefix" value="/WEB-INF/pages/"/>
        <property name="suffix" value=".jsp"/>
    bean>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    2.在实际开发中, 我们有时需要自定义视图, 这样可以满足更多更复杂的需求.


    实例-代码实现
    1.在web路径目录下 新建view.jsp

    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <html>
    <head>
        <title>自定义视图测试title>
    head>
    <body>
    <h2>自定义视图测试h2>
    <a href="?">点击到自定义视图a>br/><br/>
    body>
    html>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    2.com.zzw.web.viewresolver包下 新建GoodsHandler

    @RequestMapping("/goods")
    @Controller
    public class GoodsHandler {
    
        @RequestMapping("/buy")
        public String buy() {
            System.out.println("buy() 被调用...");
            return "?";//待会再填写自定义视图名称
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    3.com.zzw.web.viewresolver包下 新建MyView

    /**
     * 解读
     * 1.MyView 继承了AbstractView, 就可以作为一个视图使用
     * 2.@Component(value="myView"), 该视图会注入到容器中, 名字/id 是 zzwView
     */
    @Component(value = "zzwView")
    public class MyView extends AbstractView {
        @Override
        protected void renderMergedOutputModel(Map<String, Object> model, HttpServletRequest request, HttpServletResponse response) throws Exception {
            //完成视图渲染
            //并且可以确定我们要跳转的页面
            System.out.println("进入到自己的视图");
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    4.在web路径/WEB-INF/pages目录下 新建my_view.jsp

    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <html>
    <head>
        <title>my_view页面title>
    head>
    <body>
    <h2>进入到my_view页面h2>
    <p>是从自定义视图来的p>
    body>
    html>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    5.补充MyView的代码

    /**
     * 解读
     * 1.MyView 继承了AbstractView, 就可以作为一个视图使用
     * 2.@Component(value="myView"), 该视图会注入到容器中, 名字/id 是 zzwView
     */
    @Component(value = "zzwView")
    public class MyView extends AbstractView {
        @Override
        protected void renderMergedOutputModel(Map<String, Object> model,
                                               HttpServletRequest request,
                                               HttpServletResponse response) throws Exception {
            //完成视图渲染
            //并且可以确定我们要跳转的页面[请求转发] /WEB-INF/pages/my_view.jsp
            System.out.println("进入到自己的视图");
            //解读
            //1.下面就是进行请求转发到 /WEB-INF/pages/my_view.jsp
            //2./WEB-INF/pages/my_view.jsp 会被springmvc解析
            //  /springmvc/WEB-INF/pages/my_view.jsp
            request.getRequestDispatcher("/WEB-INF/pages/my_view.jsp")
                    .forward(request, response);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    6.配置springDispatcherServlet-servlet.xml, 增加自定义视图解析器

    
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        
        <property name="prefix" value="/WEB-INF/pages/"/>
        <property name="suffix" value=".jsp"/>
    bean>
    
    
    <bean class="org.springframework.web.servlet.view.BeanNameViewResolver">
        <property name="order" value="99"/>
    bean>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    7.view.jsp修改请求路径

    <h2>自定义视图测试h2>
    <a href="goods/buy">点击到自定义视图a>br/><br/>
    
    • 1
    • 2

    8.GoodsHandler.java完善代码

    @RequestMapping("/goods")
    @Controller
    public class GoodsHandler {
    
        @RequestMapping("/buy")
        public String buy() {
            System.out.println("buy() 被调用...");
            return "zzwView";//待会再填写自定义视图名称
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    9.Postman测试
    在这里插入图片描述

    🍜 自定义视图-步骤梳理

    1.创建一个Viewbean, 该bean需要继承自AbstractView, 并实现renderMergedOutputModel方法
    2.并把自定义View加入到IOC容器中
    3.自定义视图的视图处理器, 使用BeanNameViewResolver, 这个视图处理器也需要配置到ioc容器
    4.BeanNameViewResolver的调用优先级需要设置一下, 设置orderInteger.MAX_VALUE小的值, 以确保其在InternalResourceViewResolver之前被调用

    🍜 自定义视图解析器执行流程

    1.SpringMVC调用目标方法, 返回自定义ViewIOC容器中的id
    2.SpringMVC调用BeanNameViewResolver解析视图: 从IOC容器中获取 返回id值对应的bean, 即自定义View的对象
    3,SpringMVC调用自定义视图的renderMergedOutputModel方法渲染视图
    4.说明:如果在SpringMVC调用目标方法, 返回自定义View容器中的id, 不存在, 则仍然按照默认的视图处理器机制处理.


    debug源码
    在这里插入图片描述

    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    判断是否实现了View接口, 如果实现了, 返回View对象
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

    在MyView视图打个断点

    在这里插入图片描述
    进入到my_view.jsp
    在这里插入图片描述

    🍜 默认视图解析器执行流程

    1.配置默认视图解析器的优先级

    
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        
        <property name="prefix" value="/WEB-INF/pages/"/>
        <property name="suffix" value=".jsp"/>
        
        <property name="order" value="10"/>
    bean>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    2.debug源码

    在这里插入图片描述

    在这里插入图片描述
    进入到默认视图解析器
    在这里插入图片描述
    在这里插入图片描述
    由于没有zzwView.jsp页面, 页面会报错
    在这里插入图片描述

    🍜 多个视图解析器执行流程

    案例1: 假设自定义视图解析器的优先级大于默认视图解析器

    1.将默认视图解析器的优先级大小设置为默认

    
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        
        <property name="prefix" value="/WEB-INF/pages/"/>
        <property name="suffix" value=".jsp"/>
        
        
    bean>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    2.将自定义视图MyView.javabeanName改为zzwViewx

    /**
     * 解读
     * 1.MyView 继承了AbstractView, 就可以作为一个视图使用
     * 2.@Component(value="myView"), 该视图会注入到容器中, 名字/id 是 zzwView
     */
    @Component(value = "zzwViewx")
    public class MyView extends AbstractView {
        @Override
        protected void renderMergedOutputModel(Map<String, Object> model,
                                               HttpServletRequest request,
                                               HttpServletResponse response) throws Exception {
            //完成视图渲染
            //并且可以确定我们要跳转的页面[请求转发] /WEB-INF/pages/my_view.jsp
            System.out.println("进入到自己的视图");
            //解读
            //1.下面就是进行请求转发到 /WEB-INF/pages/my_view.jsp
            //2./WEB-INF/pages/my_view.jsp 会被springmvc解析
            //  /springmvc/WEB-INF/pages/my_view.jsp
            request.getRequestDispatcher("/WEB-INF/pages/my_view.jsp")
                    .forward(request, response);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    3.debug源码

    在这里插入图片描述
    在这里插入图片描述
    在容器中找不到id为zzwView的bean对象. 参数viewNamezzwView,
    在这里插入图片描述BeanName视图解析器返回了空, 开始循环第二个默认视图解析器
    在这里插入图片描述在这里插入图片描述对返回的view对象进行估算. 没有 /WEB-INF/pages/zzwView.jsp 这个文件, 会报404错误.
    在这里插入图片描述在这里插入图片描述

    案例2: 假设默认视图解析器的优先级大于自定义视图解析器

    1.将默认视图解析器的优先级大小设置为10, 此时自定义视图解析器的优先级是99.

    
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        
        <property name="prefix" value="/WEB-INF/pages/"/>
        <property name="suffix" value=".jsp"/>
        
        <property name="order" value="10"/>
    bean>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    2.将自定义视图MyView.java的beanName改为zzwView

    /**
     * 解读
     * 1.MyView 继承了AbstractView, 就可以作为一个视图使用
     * 2.@Component(value="myView"), 该视图会注入到容器中, 名字/id 是 zzwView
     */
    @Component(value = "zzwView")
    public class MyView extends AbstractView {
        @Override
        protected void renderMergedOutputModel(Map<String, Object> model,
                                               HttpServletRequest request,
                                               HttpServletResponse response) throws Exception {
            //完成视图渲染
            //并且可以确定我们要跳转的页面[请求转发] /WEB-INF/pages/my_view.jsp
            System.out.println("进入到自己的视图");
            //解读
            //1.下面就是进行请求转发到 /WEB-INF/pages/my_view.jsp
            //2./WEB-INF/pages/my_view.jsp 会被springmvc解析
            //  /springmvc/WEB-INF/pages/my_view.jsp
            request.getRequestDispatcher("/WEB-INF/pages/my_view.jsp")
                    .forward(request, response);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    3.debug源码
    在这里插入图片描述
    在这里插入图片描述在这里插入图片描述只要执行了默认视图解析器, 找不到页面, 会报404, 不会再执行下一个视图解析器.
    在这里插入图片描述

    🍜 指定请求转发或者重定向

    ● 目标方法中指定转发或者重定向

    1.默认返回的方法是请求转发, 然后用视图处理器进行处理, 比如在目标方法中这样写:
    在这里插入图片描述

    2.也可以在目标方法中直接指定重定向或请求转发的url地址

    3.如果指定重定向, 可以定向到web路径下的资源在这里插入图片描述

    但是有个例外: 不能重定向到/WEB-INF目录.
    原因: WEB-INF下的资源是服务器内部访问的, 浏览器不能访问
    在这里插入图片描述

    案例
    1.修改com.zzw.web.viewresolver.GoodsHandler.java, 增加方法order

    @RequestMapping("/goods")
    @Controller
    public class GoodsHandler {
    
        @RequestMapping("/order")
        public String order() {
            System.out.println("===========order()===========");
            //1.请求转发到 /WEB-INF/pages/my_view.jsp
            //2.下面的这个路径 /WEB-INF/pages/my_view.jsp
            //  会被解析成 /springmvc/WEB-INF/pages/my_view.jsp
            //return "forward:/WEB-INF/pages/my_view.jsp";
    
            //1.请求转发到 /aa/bb/ok.jsp
            //2.下面的这个路径 /aa/bb/ok.jsp
            //  会被解析成 /springmvc/aa/bb/ok.jsp
            //return "forward:/aa/bb/ok.jsp";
    
            /**
             * 直接指定要重定向的页面
             * 1. 对于重定向来说, 不能重定向到 /WEB-INF/ 目录下
             * 2. redirect 关键字, 表示进行重定向
             * 3. /login.jsp 会在服务器解析成 /springmvc/login.jsp
             */
            //return "redirect:/login.jsp";
    
            //重定向到 /WEB-INF/pages/my_view.jsp
            //下面的这个路径 /WEB-INF/pages/my_view.js 会在服务器解析成
            // /springmvc/WEB-INF/pages/my_view.jsp
            return "redirect:/WEB-INF/pages/my_view.jsp";
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31

    2.view.jsp增加代码

    <body>
    <h2>自定义视图测试h2>
    <a href="goods/buy">点击到自定义视图a><br/><br/>
    <a href="goods/order">测试在目标方法中指定请求转发或者重定向到页面a>
    body>
    
    • 1
    • 2
    • 3
    • 4
    • 5

    测试1

    //1.请求转发到 /WEB-INF/pages/my_view.jsp
    //2.下面的这个路径 /WEB-INF/pages/my_view.jsp 会被解析成 /springmvc/WEB-INF/pages/my_view.jsp
    return "forward:/WEB-INF/pages/my_view.jsp";
    
    • 1
    • 2
    • 3

    测试2

    //1.请求转发到 /aa/bb/ok.jsp
    //2.下面的这个路径 /aa/bb/ok.jsp 会被解析成 /springmvc/aa/bb/ok.jsp
    return "forward:/aa/bb/ok.jsp";
    
    • 1
    • 2
    • 3

    测试3

    /**
     * 直接指定要重定向的页面
     * 1. 对于重定向来说, 不能重定向到 /WEB-INF/ 目录下
     * 2. redirect 关键字, 表示进行重定向
     * 3. /login.jsp 会在服务器解析成 /springmvc/login.jsp
     */
    return "redirect:/login.jsp";
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    在这里插入图片描述
    在这里插入图片描述

    测试4

    //1.重定向到 /WEB-INF/pages/my_view.jsp
    //2.下面的这个路径 /WEB-INF/pages/my_view.js 会在服务器解析成 /springmvc/WEB-INF/pages/my_view.jsp
     return "redirect:/WEB-INF/pages/my_view.jsp";
    
    • 1
    • 2
    • 3

    在这里插入图片描述WEB-INF下的资源是服务器内部访问的, 浏览器不能访问
    在这里插入图片描述

    💞指定请求转发流程分析

    在这里插入图片描述

    debug源码

    在这里插入图片描述
    在这里插入图片描述

    调用默认的视图解析器
    在这里插入图片描述在这里插入图片描述

    已经作为一个bean对象存储在容器中
    在这里插入图片描述

    下一步, 开始渲染

    在这里插入图片描述

    下一步

    在这里插入图片描述

    进入

    在这里插入图片描述

    进入, renderMergedOutputModel()MyView.java中的相仿

    在这里插入图片描述

    下一步, 找到rd = request.getRequestDispatcher(dispatcherPath);

    在这里插入图片描述

    下一步

    在这里插入图片描述

    💞指定重定向流程分析

    在这里插入图片描述


    debug源码

    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

    SpringMVC有很多视图种类

    在这里插入图片描述

    下一步

    在这里插入图片描述在这里插入图片描述

    进入

    在这里插入图片描述

    进入, 调用RedirectView的视图渲染方法

    在这里插入图片描述

    💞作业布置

    1.熟悉前面的SpringMVC映射数据请求, 模型数据, 视图和视图解析的案例
    2.清晰Debug源码的流程
    3.完成一个简单的用户登录案例
    1)编写登陆页面web路径/homework/login.jsp
    2)com.zzw.web.homework.LoginHandler [doLogin方法], 如果用户输入用户名是zzw, 密码123, 就可以登陆成功; 否则登陆失败
    3)创建JavaBeancom.zzw.web.homework.entity.User.java
    4)表单提交数据到doLogin方法, 以User对象形式接收
    5)登陆成功到, 页面 web路径/WEB-INF/pages/homework/login_ok.jsp, 并显示登陆欢迎信息 [显示用户名, 模型数据会自动填充到request域中]
    6)登陆失败到, 页面 web路径/WEB-INF/pages/homework/login_err.jsp, 并给出重新登录的超链接 [考察web工程路径应用问题]


    代码实现

    1.在web路径/homework下 新建login.jsp

    <head>
        <title>登陆页面title>
    head>
    <body>
    <form action="<%=request.getContextPath()%>/doLogin">
        用户名: <input type="text" name="username"/><br/><br/>
        密 码: <input type="text" name="pwd"/><br/><br/>
        <input type="submit" value="登录"/>
    form>
    body>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    2.在com.zzw.web.homework下新建LoginHandler

    @Controller
    public class LoginHandler {
    
        @RequestMapping("/doLogin")
        public String doLogin(User user) {
            System.out.println("===========doLogin()===========");
            if ("zzw".equals(user.getUsername()) && "123".equals(user.getPwd())) {
    	        //使用的是默认视图解析器
                return "forward:/WEB-INF/pages/homework/login_ok.jsp";
            } else {
                return "forward:/WEB-INF/pages/homework/login_err.jsp";
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    3.填充login.jsp的请求路径 涉及-web工程路径问题

    <%--
        <%=request.getContextPath()%>/doLogin => /springmvc/doLogin
        /springmvc/doLogin 被浏览器解析成 http://localhost:8080/springmvc/doLogin
    --%>
    <form action="<%=request.getContextPath()%>/doLogin">
    
    • 1
    • 2
    • 3
    • 4
    • 5

    4.在com.zzw.web.homework.entity下新建User.java

    public class User {
        private String username;
        private String pwd;
    
    	//setter, getter方法
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    5.在web路径/WEB-INF/pages/homework下 新建login_ok.jsp
    登录成功到login_ok.jsp, 并显示登陆欢迎信息 模型数据默认放入request域.

    <head>
        <title>登陆成功title>
    head>
    <body>
    登陆成功, 欢迎 ${requestScope.user.username}
    body>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    6.在web路径/WEB-INF/pages/homework下 新建login_err.jsp
    登陆失败到login_err.jsp, 并给出重新登陆的超链接. 相对路径的知识点

    <head>
        <title>登陆失败</title>
    </head>
    <body>
    <a href="homework/login.jsp">重新登陆</a>
    </body>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    使用自定义视图解析器再次完成

    代码实现

    1.springDispatcherServlet-servlet.xml中注释掉默认视图解析器的优先级, 使用自定义视图

    
    
    • 1

    2.修改LoginHandler

    @Controller
    public class LoginHandler {
    
        @RequestMapping("/doLogin")
        public String doLogin(User user) {
            System.out.println("===========doLogin()===========");
            return "homeworkView";
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    3.新建com.zzw.web.homework.viewresolver.MyView

    /**
     * 解读
     * 1.MyView 继承了AbstractView, 就可以作为一个试图使用
     * 2.@Component("homeworkView") 表示该视图会注入到容器中, 名字/id 是 homeworkView
     */
    @Component("homeworkView")
    public class MyView extends AbstractView {
        @Override
        protected void renderMergedOutputModel(Map<String, Object> model, HttpServletRequest request, HttpServletResponse response) throws Exception {
            //完成视图渲染
            //并且可以确定我们要跳转的页面
            System.out.println("进入到了自己的视图");
    
            request.setCharacterEncoding("utf-8");
            String username = request.getParameter("username");
            String pwd = request.getParameter("pwd");
            if ("zzw".equals(username) && "123".equals(pwd)) {
                request.setAttribute("username", username);
                request.getRequestDispatcher("/WEB-INF/pages/homework/login_ok.jsp")
                        .forward(request, response);
            } else {
                request.getRequestDispatcher("/WEB-INF/pages/homework/login_err.jsp")
                        .forward(request, response);
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26

    4.修改login_ok.jsp

    登陆成功, 欢迎 ${requestScope.username}
    
    • 1

    在这里插入图片描述
    下一篇: 手动实现SpringMVC底层机制, 敬请期待…

  • 相关阅读:
    101道算法JavaScript描述【二叉树】5
    记录一次ffmpeg编译
    signature verification failed csb502报错
    Tyvj p1088 广东汕头聿怀初中
    Android 系统开发人员的权限说明文档
    ☆打卡算法☆LeetCode 28、实现 strStr() 算法解析
    2022腾讯云学生服务器价格申请认证及购买攻略
    Python程序性能测试小方法
    Linux离线安装Mysql-5.7
    Flask框架配置Celery-[2]:将前端上传的文件,通过异步任务保存,异步处理上传的文件
  • 原文地址:https://blog.csdn.net/qq_18817831/article/details/132344440