初识 Sping MVC【上】

Spring MVC 入门

一、Spring MVC 概述

  • Spring MVC 是 Spring 提供的一个基于MVC设计模式的轻量级Web开发框架,本质上相当于Servlet。
  • 因为Spring MVC 本身就是Spring 框架的一部分,所以和Spring框架是无缝集成。是现在业界最主流的Web开发框架。

二、SpringMVC 执行流程

在这里插入图片描述1. 用户点击某个请求路径,发起一个 HTTP request 请求,该请求会被提交到 DispatcherServlet(前端控制器);
2. 由 DispatcherServlet 请求一个或多个 HandlerMapping(处理器映射器),并返回一个执行链(HandlerExecutionChain)。
3. DispatcherServlet 将执行链返回的 Handler 信息发送给 HandlerAdapter(处理器适配器);
4. HandlerAdapter 根据 Handler 信息找到并执行相应的 Handler(常称为 Controller);
5. Handler 执行完毕后会返回给 HandlerAdapter 一个 ModelAndView 对象(Spring MVC的底层对象,包括 Model 数据模型和 View 视图信息);
6. HandlerAdapter 接收到 ModelAndView 对象后,将其返回给 DispatcherServlet ;
7. DispatcherServlet 接收到 ModelAndView 对象后,会请求 ViewResolver(视图解析器)对视图进行解析;
8. ViewResolver 根据 View 信息匹配到相应的视图结果,并返回给 DispatcherServlet;
9. DispatcherServlet 接收到具体的 View 视图后,进行视图渲染,将 Model 中的模型数据填充到 View 视图中的 request 域,生成最终的 View(视图);
10. 视图负责将结果显示到浏览器(客户端)。

三、Spring MVC 入门

3.1入门案例:基于xml配置文件

3.1.1需求:

  • 基于XML配置文件的入门案例

3.1.2 搭建环境

  • 导入坐标
<packaging>war</packaging>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven.compiler.source>1.8</maven.compiler.source>
        <maven.compiler.target>1.8</maven.compiler.target>
        <!--声明不需要web.xml文件-->
        <failOnMissingWebXml>false</failOnMissingWebXml>
    </properties>

    <dependencies>

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>5.2.4.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-aspects</artifactId>
            <version>5.2.4.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-test</artifactId>
            <version>5.2.4.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>5.2.4.RELEASE</version>
        </dependency>
        <!-- 事务 -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-jdbc</artifactId>
            <version>5.2.4.RELEASE</version>
        </dependency>


        <!-- mysql驱动 -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.24</version>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
            <version>1.2.4</version>
        </dependency>
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.5.7</version>
        </dependency>
        <dependency>
            <groupId>tk.mybatis</groupId>
            <artifactId>mapper</artifactId>
            <version>3.5.2</version>
        </dependency>
        <dependency>
            <groupId>com.github.pagehelper</groupId>
            <artifactId>pagehelper</artifactId>
            <version>3.7.5</version>
        </dependency>

        <!--整合-->
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis-spring</artifactId>
            <version>2.0.5</version>
        </dependency>

        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
        </dependency>

        <!-- mvc json -->
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
            <version>2.10.2</version>
        </dependency>

        <!--swagger2-->
        <dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-swagger2</artifactId>
            <version>2.7.0</version>
        </dependency>
        <dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-swagger-ui</artifactId>
            <version>2.7.0</version>
        </dependency>


        <!--文件上传-->
        <dependency>
            <groupId>commons-fileupload</groupId>
            <artifactId>commons-fileupload</artifactId>
            <version>1.4</version>
        </dependency>

        <!--jsp相关-->
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <version>3.1.0</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>javax.servlet.jsp</groupId>
            <artifactId>javax.servlet.jsp-api</artifactId>
            <version>2.3.1</version>
            <scope>provided</scope>
        </dependency>

        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>jstl</artifactId>
            <version>1.2</version>
        </dependency>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-log4j12</artifactId>
            <version>1.7.10</version>
        </dependency>


    </dependencies>

3.1.3项目结构

在这里插入图片描述

3.1.4 实现

1.编写UserController:业务处理入口
package com.czxy.mvc.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

/**
 * @Author: 小新
 * @Date: 2021-12-06 17:55
 */
@Controller   //将当前类添加到spring容器中
@RequestMapping("/user")//给当前类中所有功能,设置一个路径访问前缀
public class UserController {
    //最终访问路径:/user/selectAll.action
    @RequestMapping("/selectAll")//当前功能方法,设置一个访问路径。
    public String selectAll(){
        return "/list.jsp";  //jsp页面在web下
    }
}
2.编写jsp页面
  • list.jsp:
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
列表页面
</body>
</html>
3. 编写核心配置文件,用于扫描controller
  • springmvc.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:p="http://www.springframework.org/schema/p"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xmlns:mvc="http://www.springframework.org/schema/mvc"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
                  http://www.springframework.org/schema/beans/spring-beans.xsd
                  http://www.springframework.org/schema/mvc
                  http://www.springframework.org/schema/mvc/spring-mvc.xsd
                  http://www.springframework.org/schema/aop
                  http://www.springframework.org/schema/aop/spring-aop.xsd
                  http://www.springframework.org/schema/context
                  http://www.springframework.org/schema/context/spring-context.xsd">
    <!-- 扫描注解包 -->
    <context:component-scan base-package="com.czxy.mvc.controller" />
</beans>
4.在web.xml中配置前端控制器:加载核心配置文件
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.4"
         xmlns="http://java.sun.com/xml/ns/j2ee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
	http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
    <!--设置前端控制器-->
    <servlet>
        <servlet-name>springmvc</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath:springmvc.xml</param-value>
        </init-param>
    </servlet>
    <servlet-mapping>
        <servlet-name>springmvc</servlet-name>
        <url-pattern>*.action</url-pattern>
    </servlet-mapping>
</web-app>
5.编写首页
  • index.jsp:
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
<a href="${pageContext.request.contextPath}/user/selectAll.action">入门案例</a>
</body>
</html>

3.2 入门案例:基于注解配置类

3.2.1 搭建环境

<packaging>war</packaging>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven.compiler.source>1.8</maven.compiler.source>
        <maven.compiler.target>1.8</maven.compiler.target>
        <!--声明不需要web.xml文件-->
        <failOnMissingWebXml>false</failOnMissingWebXml>
    </properties>

    <dependencies>

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>5.2.4.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-aspects</artifactId>
            <version>5.2.4.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-test</artifactId>
            <version>5.2.4.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>5.2.4.RELEASE</version>
        </dependency>
        <!-- 事务 -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-jdbc</artifactId>
            <version>5.2.4.RELEASE</version>
        </dependency>


        <!-- mysql驱动 -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.24</version>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
            <version>1.2.4</version>
        </dependency>
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.5.7</version>
        </dependency>
        <dependency>
            <groupId>tk.mybatis</groupId>
            <artifactId>mapper</artifactId>
            <version>3.5.2</version>
        </dependency>
        <dependency>
            <groupId>com.github.pagehelper</groupId>
            <artifactId>pagehelper</artifactId>
            <version>3.7.5</version>
        </dependency>

        <!--整合-->
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis-spring</artifactId>
            <version>2.0.5</version>
        </dependency>

        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
        </dependency>

        <!-- mvc json -->
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
            <version>2.10.2</version>
        </dependency>

        <!--swagger2-->
        <dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-swagger2</artifactId>
            <version>2.7.0</version>
        </dependency>
        <dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-swagger-ui</artifactId>
            <version>2.7.0</version>
        </dependency>


        <!--文件上传-->
        <dependency>
            <groupId>commons-fileupload</groupId>
            <artifactId>commons-fileupload</artifactId>
            <version>1.4</version>
        </dependency>

        <!--jsp相关-->
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <version>3.1.0</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>javax.servlet.jsp</groupId>
            <artifactId>javax.servlet.jsp-api</artifactId>
            <version>2.3.1</version>
            <scope>provided</scope>
        </dependency>

        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>jstl</artifactId>
            <version>1.2</version>
        </dependency>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-log4j12</artifactId>
            <version>1.7.10</version>
        </dependency>


    </dependencies>

3.2.2 项目结构

在这里插入图片描述

3.2.3 实现

1. 编写UserController :业务处理入口
package com.czxy.mvc.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

/**
 * @Author: 小新
 * @Date: 2021-12-07 16:48
 */
@Controller   //将当前类添加到Spring容器中
@RequestMapping("/user")    //给当前类中所有功能,设置一个路径访问前缀
public class UserController {

    /**
     * 最终访问路径  / user /selectAll.action
     * @return
     */
     @RequestMapping("/selectAll")//当前功能方法,设置一个访问路径
     public  String selectAll(){
         return "/pages/list.jsp";
     }
}
2.编写jsp展示页面
  • list.jsp:
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
 列表
</body>
</html>

3.拷贝核心配置类MvcConfiguration:取代spring.xml
package com.czxy.mvc.config;

        import org.springframework.context.annotation.ComponentScan;
        import org.springframework.context.annotation.Configuration;
        import org.springframework.format.FormatterRegistry;
        import org.springframework.format.datetime.DateFormatter;
        import org.springframework.web.servlet.config.annotation.EnableWebMvc;
        import org.springframework.web.servlet.config.annotation.ViewResolverRegistry;
        import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

        import java.util.Date;


/**
 * @Author: 小新
 * @Date: 2021-12-07 16:48
 */
@Configuration
@ComponentScan(basePackages = {"com.czxy.mvc.controller","com.czxy.mvc.resolver"})
public class MvcConfiguration {

}

4.拷贝核心配置文件WebInitializer:取代web.xml
package com.czxy.mvc.config;

import org.springframework.web.WebApplicationInitializer;
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
import org.springframework.web.filter.CharacterEncodingFilter;
import org.springframework.web.servlet.DispatcherServlet;

import javax.servlet.FilterRegistration;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletRegistration;

/**
 * @Author: 小新
 * @Date: 2021-12-07 16:49
 */
public class WebInitializer  implements WebApplicationInitializer {
    @Override
    public void onStartup(ServletContext servletContext) throws ServletException {
        //1 配置spring工厂
        AnnotationConfigWebApplicationContext application = new AnnotationConfigWebApplicationContext();
        // 注册所有的配置类
        application.register(MvcConfiguration.class);

        //2 post中文乱码
        FilterRegistration.Dynamic encodingFilter = servletContext.addFilter("encoding", new CharacterEncodingFilter("UTF-8"));
        encodingFilter.addMappingForUrlPatterns(null, true, "/*");

        //3 核心控制器
        ServletRegistration.Dynamic mvcServlet = servletContext.addServlet("springmvc", new DispatcherServlet(application));
        mvcServlet.addMapping("*.action");
        mvcServlet.setLoadOnStartup(2);	//tomcat启动时,执行servlet的初始化方法
    }
}

5.编写首页
  • index.jsp:
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
<a href="${pageContext.request.contextPath}/user/selectAll.action">入门案例</a><br/>

四、Spring MVC 基础

4.1 窄化请求路径

  • @RequestMapping 放在类名上边 : 设置类请求路径。
  • @RequestMapping 放在方法名上边 : 设置方法请求路径。
  • 需求:使用/demo01/index.action 访问首页
  • 编写controller:
package com.czxy.mvc.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

/**
 * @Author: 小新
 * @Date: 2021-12-07 17:03
 */
@Controller
@RequestMapping("/demo01")
public class Demo01IndexController {
    @RequestMapping({"/index"})
    public String index(){
        return "/index.jsp";
    }
 }
  • 访问路径:
<a href="${pageContext.request.contextPath}/demo01/index.action">基础-窄化</a><br/>

4.2 多路径映射

  • @RequestMapping 允许配置多个访问路径
  • 编写 controller:
package com.czxy.mvc.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

/**
 * @Author: 小新
 * @Date: 2021-12-07 17:03
 */
@Controller
@RequestMapping("/demo01")
public class Demo01IndexController {
    /**
     * 多路径
     * @return
     */
     @RequestMapping({"/index","/index2"})
    public String index(){
        return "/index.jsp";
    }
  • 访问路径:
<a href="${pageContext.request.contextPath}/demo01/index2.action">基础-多路径</a><br/>

4.3 请求方法限定

  • @RequestMapping 默认支持各种请求方式的访问,可以通过 method属性限制不同的请求方式。
注解描述
@RequestMapping(method = RequestMethod.GET)只有get请求方式可访问
@RequestMapping(method = RequestMethod.POST)只有post请求方式可访问
@RequestMapping(method={RequestMethod.GET,RequestMethod.POST})get和post都可访问
  • 需求: 使用不同请求方式访问首页
    • GET请求抛出异常
    • POST允许访问
  • 编写 controller :
/**
     * get请求抛异常  RequestMethod.GET,
     * post允许访问  RequestMethod.POST
     * @return
     */
    @RequestMapping(value = "/post",method={RequestMethod.GET,RequestMethod.POST})
    public String get(){
        return "/index.jsp";
    }
  • 访问路径:
<a href="${pageContext.request.contextPath}/demo01/post.action">基础-get请求访问</a><br/>
<form action="${pageContext.request.contextPath}/demo01/post.action" method="post">
    <input type="submit" value="基础-post请求访问"/>
</form><br/>

4.4 参数绑定

4.4.1 简单数据类型

  • 在控制器的方法中,只要有对应的参数名,spring mvc就可以自动完成参数封装
1.基本操作:
  • 需求:访问/demo02/findById.action?id=10,设置参数id
  • controller:
package com.czxy.mvc.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

/**
 * @Author: 小新
 * @Date: 2021-12-07 17:03
 */
@Controller
@RequestMapping("/demo02")
public class Demo02ParamController {

    /**
     * 限定:参数名和变量名必须保持一致。
     * @param id
     * @return
     */
    @RequestMapping({"/findById"})
    public String findById(String id){
        System.out.println("id: " + id);
        return "/index.jsp";
    }
}
  • 访问路径
<a href="${pageContext.request.contextPath}/demo02/findById.action?id=10">参数-简单数据</a> <br/>
2.自定义变量名:@RequestParam
  • 如果请求参数名和方法参数名不一致时,需要使用@RequestParam标记对应关系。
  • controller:
package com.czxy.mvc.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;

/**
 * @Author: 小新
 * @Date: 2021-12-07 17:03
 */
@Controller
@RequestMapping("/demo02")
public class Demo02ParamController {
    @RequestMapping({"/findById2"})
    public String findById2(@RequestParam("id") String name){
        System.out.println("name: " + name);
        return "/index.jsp";
    }
}
  • 访问路径:
<a href="${pageContext.request.contextPath}/demo02/findById2.action?id=10">参数-简单数据name-自定义</a> <br/>

4.4.2.绑定POJO类型

  • 当提交一组数据时,通常我们会提供一个JavaBean用于数据的封装。
  • User 类:
package com.czxy.mvc.domain;

import org.springframework.format.annotation.DateTimeFormat;

import java.util.Date;
import java.util.List;

/**
 * @Author: 小新
 * @Date: 2021-12-07 17:25
 */
public class User {
    private Integer id;
    private String username;
    private String password;
    private List<String> hobbies;
    private Date   birthday;
    @Override
    public String toString() {
        return "User{" +
                "id=" + id +
                ", username='" + username + '\'' +
                ", password='" + password + '\'' +
                ", hobbies=" + hobbies +
                ", birthday=" + birthday.toLocaleString()+
                '}';
    }

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public List<String> getHobbies() {
        return hobbies;
    }

    public void setHobbies(List<String> hobbies) {
        this.hobbies = hobbies;
    }

    public Date getBirthday() {
        return birthday;
    }

    public void setBirthday(Date birthday) {
        this.birthday = birthday;
    }
}
  • controller :
package com.czxy.mvc.controller;

import com.czxy.mvc.domain.User;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

/**
 * @Author: 小新
 * @Date: 2021-12-07 17:03
 */
@Controller
@RequestMapping("/demo02")
public class Demo02ParamController {
    /**
     *路径多参数
     *需求:请求多个参数`/demo02/add.action?id=10&username=jack&password=1234`
     * @param user
     * @return
     */
    @RequestMapping({"/add"})
    public String add(User user){
        System.out.println(user);
        return "/index.jsp";
    }
}
  • 访问路径:
<a href="${pageContext.request.contextPath}/demo02/add.action?id=10&username=jack&password=1234">参数-POJO-路径</a> <br/>
<!--表单参数-->
<form action="${pageContext.request.contextPath}/demo02/add.action" method="post">
    <input type="text" name="id" placeholder="id"/> <br/>
    <input type="text" name="username" placeholder="用户名"/> <br/>
    <input type="password" name="password" placeholder="密码"/> <br/>
    <input type="submit" value="参数-POJO-表单"/>
</form>

4.4.3复杂POJO

  • Order:
package com.czxy.mvc.domain;

/**
 * @Author: 小新
 * @Date: 2021-12-07 17:32
 */
public class Order {
    private Double price;
    private User user ;

    @Override
    public String toString() {
        return "Order{" +
                "price=" + price +
                ", user=" + user +
                '}';
    }

    public Double getPrice() {
        return price;
    }

    public void setPrice(Double price) {
        this.price = price;
    }

    public User getUser() {
        return user;
    }

    public void setUser(User user) {
        this.user = user;
    }
}
  • controller:
package com.czxy.mvc.controller;

import com.czxy.mvc.domain.Order;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

/**
 * @Author: 小新
 * @Date: 2021-12-07 17:03
 */
@Controller
@RequestMapping("/demo02")
public class Demo02ParamController {
    /**
     * 复杂POJO(包装(POJO))
     * @param order
     * @return
     */
    @RequestMapping({"/addOrder"})
    public String addOrder(Order order){
        System.out.println(order);
        return "/index.jsp";
    }
}
  • 访问路径:
<!--提交订单以及用户数据-->
<form action="${pageContext.request.contextPath}/demo02/addOrder.action" method="post">
    <input type="text" name="price" placeholder="价格" /> <br/>
    <input type="text" name="user.id" placeholder="用户id" /> <br/>
    <input type="text" name="user.username" placeholder="用户名" /> <br/>
    <input type="password" name="user.password" placeholder="密码"/> <br/>
    <input type="submit" value="复杂-POJO-表单"/> <br/>
</form>

4.4.4 绑定数组/集合

  • controller:
package com.czxy.mvc.controller;

import com.czxy.mvc.domain.Order;
import com.czxy.mvc.domain.User;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;

/**
 * @Author: 小新
 * @Date: 2021-12-07 17:03
 */
@Controller
@RequestMapping("/demo02")
public class Demo02ParamController {
    /**
     * 绑定数组/集合
     * @param user
     * @return
     */
    @RequestMapping({"/add"})
    public String add(User user){
        System.out.println(user);
        return "/index.jsp";
    }
}
  • 访问路径:
<!--绑定数组/集合-->
<form action="${pageContext.request.contextPath}/demo02/add.action" method="post">
    <input type="text" name="id" placeholder="id"/> <br/>
    <input type="text" name="username" placeholder="用户名"/> <br/>
    <input type="password" name="password" placeholder="密码"/> <br/>
    <input type="checkbox" name="hobbies" value="抽烟" />抽烟
    <input type="checkbox" name="hobbies" value="喝酒" />喝酒
    <input type="checkbox" name="hobbies" value="烫头" />烫头 <br/>
    <input type="text" name="birthday" value="2021-12-09"/><br/>
    <input type="submit" value="参数-POJO-表单-绑定数组(集合)"/>
</form>
自定义参数绑定: 日期
  • Spring MVC 默认支持的日期格式 yyyy/MM/dd
方式一:全局配置
  • MvcConfiguration 配置类:
package com.czxy.mvc.config;

        import org.springframework.context.annotation.ComponentScan;
        import org.springframework.context.annotation.Configuration;
        import org.springframework.format.FormatterRegistry;
        import org.springframework.format.datetime.DateFormatter;
        import org.springframework.web.servlet.config.annotation.EnableWebMvc;
        import org.springframework.web.servlet.config.annotation.ViewResolverRegistry;
        import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

        import java.util.Date;


/**
 * @Author: 小新
 * @Date: 2021-12-07 16:48
 */
@Configuration
@ComponentScan(basePackages = {"com.czxy.mvc.controller"})
@EnableWebMvc
public class MvcConfiguration implements WebMvcConfigurer {
    /**
     * 设置日期转换
     * @param registry
     */
    public void addFormatters(FormatterRegistry registry) {
        DateFormatter dateFormatter = new DateFormatter();
        dateFormatter.setPattern("yyyy-MM-dd");
        registry.addFormatterForFieldType(Date.class,dateFormatter);
    }
}
方式二:单独设置
  • User 类
//方式2:单独设置
    @DateTimeFormat(pattern = "yyyy-MM-dd")
    private Date   birthday;

4.5 视图解析器

4.5.1 什么是视图解析器

  • Spring MVC 中的视图解析器的主要作用就是将 逻辑视图 转换成用户可以看到的 物理视图
  • 返回jsp的具体位置 如:return "/pages/list.jsp";我们称为物理视图
  • 在开发中,我们发现 物理视图 都有相同的前缀和后缀。所以将相同的前缀和后缀抽取到视图解析器中。

4.5.2 配置MvcConfiguration

package com.czxy.mvc.config;

        import org.springframework.context.annotation.ComponentScan;
        import org.springframework.context.annotation.Configuration;
        import org.springframework.format.FormatterRegistry;
        import org.springframework.format.datetime.DateFormatter;
        import org.springframework.web.servlet.config.annotation.EnableWebMvc;
        import org.springframework.web.servlet.config.annotation.ViewResolverRegistry;
        import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

        import java.util.Date;


/**
 * @Author: 小新
 * @Date: 2021-12-07 16:48
 */
@Configuration
@ComponentScan(basePackages = {"com.czxy.mvc.controller","com.czxy.mvc.resolver"})
@EnableWebMvc
public class MvcConfiguration implements WebMvcConfigurer {


    /**
     * 设置日期转换
     * @param registry
     */
    public void addFormatters(FormatterRegistry registry) {
        DateFormatter dateFormatter = new DateFormatter();
        dateFormatter.setPattern("yyyy-MM-dd");
        registry.addFormatterForFieldType(Date.class,dateFormatter);
    }

    /**
     * 配置视图解析器
     * @param registry
     */
    public void configureViewResolvers(ViewResolverRegistry registry) {
        //前缀 : pages   后缀 : .jsp
        registry.jsp("/pages/",".jsp");

    }
}

4.5.3使用controller

package com.czxy.mvc.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

/**
 * @Author: 小新
 * @Date: 2021-12-07 16:48
 */
@Controller   //将当前类添加到Spring容器中
@RequestMapping("/user")    //给当前类中所有功能,设置一个路径访问前缀
public class UserController {
    /**
     * 返回逻辑视图名
     * @return
     *
    @RequestMapping("/selectAll2")//当前功能方法,设置一个访问路径
    public  String selectAll2(){
        return "list";
    }
  • 访问路径:
<a href="${pageContext.request.contextPath}/user/selectAll2.action">视图解析器</a><br/>

4.5.4 绕过视图解析器

  • 声明式 请求转发重定向 , 都可以绕过视图解析器。
  • controller:
package com.czxy.mvc.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

/**
 * @Author: 小新
 * @Date: 2021-12-07 16:48
 */
@Controller   //将当前类添加到Spring容器中
@RequestMapping("/user")    //给当前类中所有功能,设置一个路径访问前缀
public class UserController {
    /**
     * 绕过视图解析器
     * redirect  &  forward  都可以绕过视图解析器
     * @return
     */
    @RequestMapping("/selectAll2")//当前功能方法,设置一个访问路径
    public  String selectAll2(){
        return "forward:/pages/list.jsp";
    }
}
  • 访问路径:
<a href="${pageContext.request.contextPath}/user/selectAll2.action">绕过视图解析器</a><br/>

4.6 方法返回值

4.6.1 默认返回值:ModelAndView

  • 编写controller:
package com.czxy.mvc.controller;

import com.czxy.mvc.domain.Person;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.HashMap;

/**
 * @Author: 小新
 * @Date: 2021-12-07 18:15
 */
@Controller
@RequestMapping("/demo03")
public class Demo03BookeController {

    /**
     * 默认返回值 ModelAndView
     * @return
     */
    @RequestMapping("/list")
    public ModelAndView list(){
        //1、创建对象
        ModelAndView modelAndView = new ModelAndView();
        //2、设置视图
        modelAndView.setViewName("book");
        //3、设置模型数据
         modelAndView.addObject("username","jack");
        return modelAndView;
    }
}
  • 编写视图页面 book.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
${username}
</body>
</html>
  • 访问路径:
<a href="${pageContext.request.contextPath}/demo03/list.action">返回值-ModelAndView</a><br/>

4.6.2 返回字符串

1)请求转发(默认)
  • 编写controller
package com.czxy.mvc.controller;

import com.czxy.mvc.domain.Person;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.HashMap;

/**
 * @Author: 小新
 * @Date: 2021-12-07 18:15
 */
@Controller
@RequestMapping("/demo03")
public class Demo03BookeController {
    /**
     * 默认  请求转发
     * @param model
     * @return
     */
    @RequestMapping("/list2")
    public String list2(Model model){
        //设置数据
        model.addAttribute("username","jack2");
        return "book";
    }
}
  • 访问路径:
<a href="${pageContext.request.contextPath}/demo03/list2.action">返回值-请求转发(默认)</a><br/>
2)重定向
  • 编写 controller
package com.czxy.mvc.controller;

import com.czxy.mvc.domain.Person;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.HashMap;

/**
 * @Author: 小新
 * @Date: 2021-12-07 18:15
 */
@Controller
@RequestMapping("/demo03")
public class Demo03BookeController {
    /**
     * 重定向
     * @return
     */
    @RequestMapping("/list4")
    public String list4(Model model){
        model.addAttribute("username","jack3");
        return "redirect:/pages/book.jsp";
    }
}
  • 访问路径:
<a href="${pageContext.request.contextPath}/demo03/list4.action">返回值-重定向</a><br/>

4.6.3 返回值 void

1) 返回void
  • 需求:controller 返回 void
  • 编写 controller:
    package com.czxy.mvc.controller;

   import com.czxy.mvc.domain.Person;
   import org.springframework.stereotype.Controller;
   import org.springframework.ui.Model;
   import org.springframework.web.bind.annotation.RequestMapping;
   import org.springframework.web.bind.annotation.ResponseBody;
   import org.springframework.web.servlet.ModelAndView;

   import javax.servlet.ServletException;
   import javax.servlet.http.HttpServletRequest;
   import javax.servlet.http.HttpServletResponse;
   import java.io.IOException;
   import java.util.HashMap;

   /**
    * @Author: 小新
    * @Date: 2021-12-07 18:15
    */
   @Controller
   @RequestMapping("/demo03")
   public class Demo03BookeController {
    * 返回值void
    * 根据访问路径显示对应的视图路径,该视图不存在,所以提示404*/
   @RequestMapping("/void1")
   public void void1(){
       System.out.println("void1 执行了!");
   }
}
  • 访问路径:
<a href="${pageContext.request.contextPath}/demo03/void1.action">返回值-void1</a><br/>
2)请求调度器
  • 需求:使用servlet 请求调度器完成请求转发/请求包含操作。
  • 编写 controller :
     package com.czxy.mvc.controller;

    import com.czxy.mvc.domain.Person;
    import org.springframework.stereotype.Controller;
    import org.springframework.ui.Model;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.ResponseBody;
    import org.springframework.web.servlet.ModelAndView;

    import javax.servlet.ServletException;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import java.io.IOException;
    import java.util.HashMap;

    /**
     * @Author: 小新
     * @Date: 2021-12-07 18:15
     */
    @Controller
    @RequestMapping("/demo03")
    public class Demo03BookeController {
    
    //方式一: 获得request对象
    //@Resource
    //private HttpServletRequest request;

    /**
     * 请求调度器
     * 使用servlet 请求调度器完成`请求转发`/`请求包含`操作。
     * @param response
     * @param request
     * @throws ServletException
     * @throws IOException
     */
    @RequestMapping("/void2")
    public void void2(/*方式二:*/HttpServletResponse response , HttpServletRequest request) throws Exception {
        //设置数据
        request.setAttribute("username","void2");
        //请求转发
        request.getRequestDispatcher("/pages/book.jsp").forward(request,response);

        //请求包含
        //request.getRequestDispatcher("/pages/book.jsp").include(request,response);
    }
}
  • 访问路径:
<a href="${pageContext.request.contextPath}/demo03/void2.action">请求调度器-void2</a><br/>
3)response 响应数据
  • 编写 controller
     package com.czxy.mvc.controller;

    import com.czxy.mvc.domain.Person;
    import org.springframework.stereotype.Controller;
    import org.springframework.ui.Model;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.ResponseBody;
    import org.springframework.web.servlet.ModelAndView;

    import javax.servlet.ServletException;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import java.io.IOException;
    import java.util.HashMap;

    /**
     * @Author: 小新
     * @Date: 2021-12-07 18:15
     */
    @Controller
    @RequestMapping("/demo03")
    public class Demo03BookeController {
/**
     * response 响应数据
     * @param request
     * @param response
     * @throws IOException
     */
    @RequestMapping("/void3")
    public void void3(HttpServletRequest request , HttpServletResponse response) throws IOException {
        response.setContentType("text/html;charset=UTF-8");//解决乱码问题
        response.getWriter().print("<font color='pink' size='28px'>void3</font>");
    }
}
  • 访问路径:
<a href="${pageContext.request.contextPath}/demo03/void3.action">response 响应数据-void3</a><br/>
4)响应JSON
  • 编写 controller:
     package com.czxy.mvc.controller;

    import com.czxy.mvc.domain.Person;
    import org.springframework.stereotype.Controller;
    import org.springframework.ui.Model;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.ResponseBody;
    import org.springframework.web.servlet.ModelAndView;

    import javax.servlet.ServletException;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import java.io.IOException;
    import java.util.HashMap;

    /**
     * @Author: 小新
     * @Date: 2021-12-07 18:15
     */
    @Controller
    @RequestMapping("/demo03")
    public class Demo03BookeController {
       /**
     * 响应JSON
     */
    @RequestMapping("/void4")
    @ResponseBody
    public void void4(){
        System.out.println("void4");
    }
}
  • 访问路径:
<a href="${pageContext.request.contextPath}/demo03/void4.action">响应JSON 响应数据-void4</a><br/>

4.7 异常处理器

4.7.1 什么是异常处理器

  • 对控制器抛出的异常进行拦截,并做出友好处理的程序。

  • 在spring mvc使用过程中,如果程序出现异常,默认情况将抛向浏览器。
    在这里插入图片描述

  • spring mvc 需要使用异常处理器对异常进行处理。

4.7.2 异常处理器执行流程

在这里插入图片描述

4.7.3 基本功能

1)需求
  • 访问 /demo04/item.action?id=1
  • id =1 系统异常
  • id =2 自定义异常
  • id =3 正常
2) 实现
  • 运行时异常:RuntimeException 【推荐】,并重新构造方法。
  • 编译时异常:Exception
  • 步骤一:编写自定义异常
package com.czxy.mvc.exception;

/**
 * @Author: 小新
 * @Date: 2021-12-09 16:38
 */
public class CustomException extends RuntimeException {
    public CustomException() {
        super();
    }

    public CustomException(String message) {
        super(message);
    }

    public CustomException(String message, Throwable cause) {
        super(message, cause);
    }

    public CustomException(Throwable cause) {
        super(cause);
    }

    protected CustomException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
        super(message, cause, enableSuppression, writableStackTrace);
    }
}
  • 步骤二:编写Controller,一个参数,控制逻辑代码(正常、系统异常、自定义异常)
package com.czxy.mvc.controller;

import com.czxy.mvc.exception.CustomException;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

/**
 * @Author: 小新
 * @Date: 2021-12-09 16:39
 */
@Controller
@RequestMapping("/demo04")
public class Demo4ItemController {

    /**
     * 异常处理器
     *  id =1 系统异常
     *  id =2 自定义异常
     *  id =3 正常
     * 一个参数,控制逻辑代码(正常、系统异常、自定义异常)
     * @param id
     * @return
     */
    @RequestMapping("/item")
    public String item(Integer id){
        if (id == 1){
            //系统异常
            int i = 1 / 0 ;
        }else if (id == 2){
            //自定义异常
            CustomException exception = new CustomException("自定义异常");
            throw exception;
        }
        //正常  id == 3
        return "forward:/index.jsp";
    }
}
  • 访问路径:
<a href="${pageContext.request.contextPath}/demo04/item.action?id=1">异常处理 id =1 系统异常</a> <br/>
<a href="${pageContext.request.contextPath}/demo04/item.action?id=2">异常处理 id =2 自定义异常 </a> <br/>
<a href="${pageContext.request.contextPath}/demo04/item.action?id=3">异常处理正常</a> <br/>

4.7.4 异常处理器:

1)方式一:实现接口
  • 编写 HandlerExceptionResolver接口的实现类
  • 并根据参数Exception e对捕获的异常进行处理:自定义异常、系统异常。
	package com.czxy.mvc.resolver;

import com.czxy.mvc.exception.CustomException;
import org.springframework.web.servlet.HandlerExceptionResolver;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * @Author: 小新
 * @Date: 2021-12-10 11:04
 */
//@Component
public class CustomExceptionResolver implements HandlerExceptionResolver {
    @Override
    public ModelAndView resolveException(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) {
        //1、统一异常
        ModelAndView modelAndView = new ModelAndView();
        if (e instanceof CustomException){
            //自定义异常
            CustomException customException = (CustomException) e;
            modelAndView.addObject("error",customException.getMessage());
        }else{
            //系统异常
            modelAndView.addObject("sorry! 系统失联了~");
        }

        modelAndView.setViewName("forward:/error.jsp");
        return modelAndView;
    }
}
2)方式二:通知类
  • 编写 GlobalExceptionResolver 类,用于处理所有异常
package com.czxy.mvc.resolver;

import com.czxy.mvc.exception.CustomException;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;

/**
 * @Author: 小新
 * @Date: 2021-12-10 11:13
 */
@ControllerAdvice
public class GlobalExceptionResolver {

    /**
     * 自定义异常处理器
     * @param ce
     * @param model
     * @return
     */
    @ExceptionHandler(CustomException.class)
    public String custom(CustomException ce , Model model){
        model.addAttribute("error",ce.getMessage());
        return "forward:/error.jsp";
    }

    /**
     * 其他异常处理器
     * @param e
     * @param model
     * @return
     */
    @ExceptionHandler(Exception.class)
    public String other(Exception e , Model model){
        model.addAttribute("系统繁忙,请稍后再试哦~");
        return "forward:/error.jsp";
    }
}
3) 错误信息展示
  • error.jsp:
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>错误页面</title>
</head>
<body>
${error}
</body>
</html>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值