framework学习笔记day10---SpringMVC基础

SpringMVC概述

  • 三层结构

    • framework学习笔记day10---SpringMVC基础
  • 概述

    • SpringMVC 是一种基于 Java 的实现 MVC 模型的轻量级 Web 框架。
    • SpringMVC 已经成为目前最主流的MVC框架之一,并且随着Spring3.0 的发布,全面超越 Struts2,成为最优秀的 MVC 框架。它通过一套注解,让一个简单的 Java 类成为处理请求 的控制器,而无须实现任何接口。同时它还支持 RESTful 编程风格的请求。

SpringMVC入门案例

  • 开发步骤

    • ①引入相关依赖
    • ②编写web.xml
      • 配置DispatcherServlet,加载spring-mvc.xml 。类似于ModelBaseServlet
    • ③编写spring-mvc.xml
      • 扫描注解
      • 配置视图解析器。类似于ViewBaseServlet
    • ④编写UserController
    • ⑤代码测试
  • ①引入相关依赖

    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
        <junit.version>4.13.2</junit.version>
        <lombok.version>1.18.22</lombok.version>
        <spring.version>5.3.13</spring.version>
        <logback.version>1.2.7</logback.version>
        <slf4j.version>1.7.32</slf4j.version>
        <servlet.version>4.0.1</servlet.version>
    </properties>
    
    <dependencies>
    
    
        <!--web start-->
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <version>${servlet.version}</version>
        </dependency>
        <!--web end-->
    
    
    
        <!--logback start-->
        <dependency>
            <groupId>ch.qos.logback</groupId>
            <artifactId>logback-classic</artifactId>
            <version>${logback.version}</version>
        </dependency>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-api</artifactId>
            <version>${slf4j.version}</version>
        </dependency>
        <!--logback end-->
    
        <!--junit start-->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>${junit.version}</version>
            <scope>test</scope>
        </dependency>
        <!--junit end-->
    
        <!--lombok start-->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>${lombok.version}</version>
        </dependency>
        <!--lombok end-->
    
        <!--spring start-->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-test</artifactId>
            <version>${spring.version}</version>
        </dependency>
    
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-aspects</artifactId>
            <version>${spring.version}</version>
        </dependency>
    
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <!--spring end-->
    
    </dependencies>
    
  • ②编写web.xml

    <!DOCTYPE web-app PUBLIC
            "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
            "http://java.sun.com/dtd/web-app_2_3.dtd" >
    
    <web-app>
    
    
    
        <!--类似于ModelBaseServlet-->
        <servlet>
            <servlet-name>mvc</servlet-name>
            <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
            <!--加载spring-mvc.xml-->
            <init-param>
                <param-name>contextConfigLocation</param-name>
                <param-value>classpath:spring-mvc.xml</param-value>
            </init-param>
        </servlet>
    
        <servlet-mapping>
            <servlet-name>mvc</servlet-name>
            <url-pattern>/</url-pattern>
        </servlet-mapping>
    
    </web-app>
    
  • ③编写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.atguigu"></context:component-scan>
    
        <!--视图解析器,类似于ViewBaseServlet-->
        <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>
    </beans>
    
  • ④编写UserController

    @Controller
    public class UserController  {
    
        @RequestMapping("/selectUserList")
        public ModelAndView selectUserList(){
            List<User> userList = new ArrayList<>();
            userList.add(new User(1,"陈磊","alei"));
            userList.add(new User(2,"土澳","tuAo"));
            //存储数据,并跳转页面
            ModelAndView modelAndView = new ModelAndView();
            modelAndView.addObject("userList",userList);
            modelAndView.setViewName("demo01");
            return modelAndView;
        }
    
    }
    
  • ⑤代码测试

SpringMVC的执行流程

  • 执行流程

    • framework学习笔记day10---SpringMVC基础

    • ①浏览器发起请求(/framework25/selectUserList),给前端控制器DispatcherServlet

    • ②前端控制器DispatcherServlet通过处理器映射器查询所有的处理器执行链

    • ③处理器映射器返回处理器执行链

    • ④前端控制器DispatcherServlet通过处理器适配找匹配的处理器

    • ⑤如果找到了匹配的处理器,处理器Handler就开始处理请求

    • ⑥处理器Handler返回响应(ModelAndView)给处理器适配器

    • ⑦处理器适配器将响应(ModelAndView)返回给前端控制器

    • ⑧前端控制器DispatcherServlet将响应(ModelAndView)交给视图解析器进行解析

    • ⑨视图解析器将渲染完毕的页面文件返回给前端控制器

    • ⑩前端控制器将渲染完毕的页面文件响应给浏览器展示

SpringMVC核心组件

  • 核心组件
    • DispatcherServlet : 前端控制器,负责调度其他组件
    • HandlerMapping : 处理器映射器,负责获取处理器执行链
    • HandlerAdapter:处理器适配器,负责给请求适配对应的处理器
    • Handler:处理器,处理请求
    • ViewResolver:视图解析器,处理视图(ModelAndView)

SpringMVC核心组件配置

  • 概述

    • SpringMVC默认已经对HandlerMapping、HandlerAdapter进行配置
  • 代码实现

    <!--处理器映射器-->
    <bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping"></bean>
    
    <!--处理器适配器-->
    <bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter"></bean>
    
    <!--处理器映射器、处理器适配器,同时也配置一些其他的辅助组件:类型转换器等等-->
    <mvc:annotation-driven></mvc:annotation-driven>
    

静态资源放行

  • 静态资源

    • 图片、css、js、html、文本等等
  • 方式一

    <!--放行静态资源-->
    <!--
        mapping: 访问路径
        location: 磁盘路径
    -->
    <mvc:resources mapping="/css/**" location="/css/"></mvc:resources>
    <mvc:resources mapping="/js/**" location="/js/"></mvc:resources>
    <mvc:resources mapping="/img/**" location="/img/"></mvc:resources>
    
  • 方式二

    <mvc:default-servlet-handler></mvc:default-servlet-handler>
    

@RequestMapping注解概述

  • 概述

    • Annotation for mapping web requests onto methods in request-handling classes with flexible method signatures.
    • 用于将请求映射到处理器方法上。
  • 常用属性

    • path : 设置访问路径
    • method : 设置请求方式
    • params : 设置必须要携带的请求参数
  • 作用

    • ①设置处理器的访问路径
    • ②窄化请求
    • ③限定请求方式
  • 代码实现

    @RequestMapping(path = "/request/testRequestMapping" , params = "username")
    public ModelAndView testRequestMapping(){
    
        ModelAndView modelAndView = new ModelAndView();
        modelAndView.setViewName("index");
        return modelAndView;
    }
    

@RequestMapping注解之访问路径

  • 分类

    • ①精确匹配
    • ②模糊匹配
  • ①精确匹配

  • ②模糊匹配

    /**
     * 模糊匹配
     * @return
     */
    @RequestMapping(path = "/myrequest/*")
    public ModelAndView testRequestMapping2(){
        ModelAndView modelAndView = new ModelAndView();
        modelAndView.setViewName("index");
        return modelAndView;
    }
    

@RequestMapping注解之窄化请求

  • 概述

    • 将@RequestMapping注解应用在类上。
  • 代码实现

    @Controller
    @RequestMapping("/request")
    public class RequestController {
    }
    

@RequestMapping注解之请求方式

  • 概述

    • 常用请求方式为:get、post、put、delete
  • 代码实现

    /**
     * 处理GET
     * @return
     */
    @RequestMapping(path = "/request/testRequestMapping3",method = RequestMethod.GET)
    public ModelAndView testRequestMapping3(){
    
        ModelAndView modelAndView = new ModelAndView();
        modelAndView.setViewName("index");
        return modelAndView;
    }
    
    
    /**
     * 处理POST
     * @return
     */
    @RequestMapping(path = "/request/testRequestMapping4",method = RequestMethod.POST)
    public ModelAndView testRequestMapping4(){
    
        ModelAndView modelAndView = new ModelAndView();
        modelAndView.setViewName("index");
        return modelAndView;
    }
    
    @GetMapping("/request/testRequestMapping3")
    public ModelAndView testRequestMapping3(){
    
        ModelAndView modelAndView = new ModelAndView();
        modelAndView.setViewName("index");
        return modelAndView;
    }
    
    
    
    @PostMapping("/request/testRequestMapping4")
    public ModelAndView testRequestMapping4(){
    
        ModelAndView modelAndView = new ModelAndView();
        modelAndView.setViewName("index");
        return modelAndView;
    }
    

请求参数绑定概述

  • 概述
    • 就是将页面上的请求参数绑定到java数据中。
  • 分类
    • 简单类型
    • javabean
    • 容器
    • javabean包装类

请求参数绑定之简单类型

  • 代码实现

    <form th:action="@{/request/testRequestParam1}" method="get">
    
        账户:<input type="text" name="userName" ><br>
        密码:<input type="text" name="userPwd" ><br>
        <button type="submit">提交</button>
    
    </form>
    
    @RequestMapping("/request/testRequestParam1")
    public ModelAndView testRequestParam1(String userName ,String userPwd){
        System.out.println("userName = " + userName);
        System.out.println("userPwd = " + userPwd);
        ModelAndView modelAndView = new ModelAndView();
        modelAndView.setViewName("index");
        return modelAndView;
    }
    

view-controller标签

  • 概述

    • 当一个处理器只是用来转发页面的话,就可以使用View-Controller来代替。
  • 代码实现

    <mvc:view-controller path="/demo02.html" view-name="demo02"></mvc:view-controller>
    <mvc:view-controller path="/demo03.html" view-name="demo03"></mvc:view-controller>
    

@RequestParam注解

  • 概述

    • 把请求中的指定名称的参数值传递给控制器中的形参赋值
  • 作用

    • ①设置请求参数名称
    • ②设置参数是否必需的参数
    • ③设置参数的默认值
  • 代码实现

    @RequestMapping("/request/testRequestParam2")
    public ModelAndView testRequestParam2(@RequestParam(value = "username" ,required = true ,defaultValue = "missing") String userName ){
        System.out.println("userName = " + userName);
        ModelAndView modelAndView = new ModelAndView();
        modelAndView.setViewName("index");
        return modelAndView;
    }
    

请求参数绑定之JavaBean

  • 代码实现

    <form th:action="@{/request/testRequestParam3}" method="get">
    
        账户:<input type="text" name="userName" ><br>
        密码:<input type="text" name="userPwd" ><br>
        <button type="submit">提交</button>
    
    </form>
    
    @RequestMapping("/request/testRequestParam3")
    public ModelAndView testRequestParam3(User user ){
        System.out.println("user = " + user);
        ModelAndView modelAndView = new ModelAndView();
        modelAndView.setViewName("index");
        return modelAndView;
    }
    
  • 注意事项

    • form表单中的name属性值和setXxx方法名有关。

请求参数绑定之JavaBean包装类

  • 概述

    • 如果一个JavaBean类(对象A)中包含另外一个JavaBean类(对象B)
  • 代码实现

    public class UserWrapper {
    
        private User user;
    
    }
    
    <form th:action="@{/request/testRequestParam4}" method="get">
    
        账户:<input type="text" name="user.userName" ><br>
        密码:<input type="text" name="user.userPwd" ><br>
        <button type="submit">提交</button>
    
    </form>
    
    @RequestMapping("/request/testRequestParam4")
    public ModelAndView testRequestParam4(UserWrapper userWrapper ){
        System.out.println("userWrapper = " + userWrapper);
        ModelAndView modelAndView = new ModelAndView();
        modelAndView.setViewName("index");
        return modelAndView;
    }
    

请求参数中文乱码

  • 回顾

    • 在tomcat8.0,get请求没有中文参数乱码问题,post请求有中文参数乱码问题。
    • 之前,可以通过自定义CharacterEncodingFitler来解决该问题。
    • 在SpringMVC框架中有提供类似的过滤器用于解决中文参数乱码问题。
  • 代码实现

    <filter>
        <filter-name>encoding</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>
    </filter>
    <filter-mapping>
        <filter-name>encoding</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
    

请求参数绑定之容器

  • 代码实现

    <form th:action="@{/request/testRequestParam6}" method="post">
    
        javase : <input type="checkbox" name="hobbys" value="javase"><br>
        javame : <input type="checkbox" name="hobbys" value="javame"><br>
        javaee : <input type="checkbox" name="hobbys" value="javaee"><br>
    
        <button type="submit">提交</button>
    
    </form>
    
    @RequestMapping("/request/testRequestParam5")
    public ModelAndView testRequestParam5(String[] hobbys){
        System.out.println(Arrays.toString(hobbys));
        ModelAndView modelAndView = new ModelAndView();
        modelAndView.setViewName("index");
        return modelAndView;
    }
    
    @RequestMapping("/request/testRequestParam6")
    public ModelAndView testRequestParam6(@RequestParam("hobbys") List<String> hobbys){
        System.out.println(hobbys);
        ModelAndView modelAndView = new ModelAndView();
        modelAndView.setViewName("index");
        return modelAndView;
    }
    

请求参数绑定练习

  • 环境准备

    public class Student {
    
        private String stuName;
        private School school;
        private List<Subject> subjectList;
        private Subject[] subjectArray;
        private Map<String, Double> scores;
    }
    
    public class School {
        private String schoolName;
    }
    
    public class Subject { 
        private String subjectName;//学科名称
    
    }
    
  • 代码实现

    <form th:action="@{/request/testRequestParam7}" method="post">
    
        学生姓名:
            <input type="text" name="stuName"><br>
        学校名称:
            <input type="text" name="school.schoolName"><br>
        学科1名称[List类型]:
            <input type="text" name="subjectList[0].subjectName"><br>
        学科2名称[List类型]:
            <input type="text" name="subjectList[1].subjectName"><br>
        学科3名称[List类型]:
            <input type="text" name="subjectList[2].subjectName"><br>
        学科1名称[数组类型]:
            <input type="text" name="subjectArray[0].subjectName"><br>
        学科2名称[数组类型]:
            <input type="text" name="subjectArray[1].subjectName"><br>
        学科3名称[数组类型]:
            <input type="text" name="subjectArray[2].subjectName"><br>
        学科1分数:
            <input type="text" name="scores['javase']"><br>
        学科2分数:
            <input type="text" name="scores['javame']"><br>
        学科3分数:
            <input type="text" name="scores['javaee']"><br>
        <button type="submit">提交</button>
    
    </form>
    
    @RequestMapping("/request/testRequestParam7")
    public ModelAndView testRequestParam7(Student student){
        System.out.println(student);
        ModelAndView modelAndView = new ModelAndView();
        modelAndView.setViewName("index");
        return modelAndView;
    }
    

@RequestHeader注解

  • 概述

    • 通过这个注解获取请求消息头中的具体数据。
  • 代码实现

    @RequestMapping("/request/header")
    public ModelAndView getRequestHeader(@RequestHeader(value = "user-agent",defaultValue = "missing") String userAgent){
        System.out.println(userAgent);
        ModelAndView modelAndView = new ModelAndView();
        modelAndView.setViewName("index");
        return modelAndView;
    }
    

@CookieValue注解

  • 概述

    • 获取当前请求中的 Cookie 数据
  • 代码实现

    @RequestMapping("/request/cookie")
    public ModelAndView getCookie(@CookieValue(name = "JSESSIONID",defaultValue = "missing") String JSESSIONID){
        System.out.println(JSESSIONID);
        ModelAndView modelAndView = new ModelAndView();
        modelAndView.setViewName("index");
        return modelAndView;
    }
    

处理器返回ModelAndView

  • 概述
    • ModelAndView封装了数据和逻辑视图名称

处理器返回字符串

  • 概述

    • 一般情况下,就是逻辑视图名称
  • 代码实现

    @RequestMapping("/response/testResponseStr")
    public String testResponseStr(Model model) {
        List<User> userList = new ArrayList<>();
        userList.add(new User(1, "陈磊", "alei"));
        userList.add(new User(2, "土澳", "tuAo"));
        model.addAttribute("userList", userList);//存储数据
        return "demo01";//跳转逻辑视图
    }
    

处理器返回值操作转发和重定向

  • 概述

    • 默认情况下,处理器只能在视图解析器设置的目录范围内进行页面的跳转;
    • 如果想要跳到目录范围以外的资源,那么就需要用到前缀符号!!!
  • 代码实现

    /**
     * 转发到目录范围以外的资源
     *
     * @return
     */
    @RequestMapping("/response/forward")
    public String response2Forward() {
        return "forward:/mydemo01.html";
    }
    
    
    /**
     * 重定向到目录范围以外的资源
     *
     * @return
     */
    @RequestMapping("/response/redirect")
    public String response2Redirect() {
        return "redirect:/mydemo01.html";
    }
    
    
    /**
     * 重定向到具体的处理器
     * @return
     */
    @RequestMapping("/response/jump2Method")
    public String jump2Method(){
        return "redirect:/response/testResponseStr";
    }
    
  • 注意事项

    • 使用"redirect:"操作重定向时,MVC框架已经内置了项目的访问路径。

原生ServletAPI对象

  • 原生Servlet对象
    • HttpServletRequest
    • HttpServletResponse
    • HttpSession
    • ServletContext

获取request和response对象

  • 代码实现

    @RequestMapping("/servlet/getRequestResponse")
    public String getRequestResponse(HttpServletRequest request , HttpServletResponse response){
        System.out.println("request = " + request);
        System.out.println("response = " + response);
        return "index";
    }
    

获取session对象

  • 代码实现

    @RequestMapping("/servlet/getSession")
    public String getSession(HttpServletRequest request){
        System.out.println("session = " + request.getSession());
        return "index";
    }
    
    @RequestMapping("/servlet/getSession2")
    public String getSession2(HttpSession session){
        System.out.println("session = " + session);
        return "index";
    }
    

获取ServletContext对象

  • 代码实现

    @RequestMapping("/servlet/getServletContext")
    public String getServletContext(HttpServletRequest request){
        System.out.println("servletContext = " + request.getServletContext());
        return "index";
    }
    
    
    @Autowired
    private ServletContext servletContext;
    
    @RequestMapping("/servlet/getServletContext2")
    public String getServletContext2(){
        System.out.println("servletContext = " + servletContext);
        return "index";
    }
    

象(掌握)

  • 代码实现

    @RequestMapping("/servlet/getSession")
    public String getSession(HttpServletRequest request){
        System.out.println("session = " + request.getSession());
        return "index";
    }
    
    @RequestMapping("/servlet/getSession2")
    public String getSession2(HttpSession session){
        System.out.println("session = " + session);
        return "index";
    }
    

获取ServletContext对象

  • 代码实现

    @RequestMapping("/servlet/getServletContext")
    public String getServletContext(HttpServletRequest request){
        System.out.println("servletContext = " + request.getServletContext());
        return "index";
    }
    
    
    @Autowired
    private ServletContext servletContext;
    
    @RequestMapping("/servlet/getServletContext2")
    public String getServletContext2(){
        System.out.println("servletContext = " + servletContext);
        return "index";
    }
    
上一篇:SpringBoot源码剖析-自动配置SpringMVC


下一篇:springMVC