Spring MVC最佳教学教程入门笔记

2022-02-16  本文已影响0人  我问你瓜保熟吗

一、Spring MVC入门

Spring MVC是Spring 提供的一个子模块,是一个实现了 Web MVC设计模式的轻量级Web框架。其提供了一个前端控制器 DispatcherServlet ,使开发人员无须额外开发控制器对象,可自动绑定用户输入,并能正确的转换数据类型,并内置了常见的校验器,可以校验用户输入 如果校验不能通过,那么就会重定向到输入表单。

MVC:Model+View+Controller(数据模型+视图+控制器)

三层架构:Presentation tier+Application tier + Data tier(展现层(mvc)+应用层(service)+数据访问层(dao))
MVC是三层架构的展现层,M是数据模型,是包含数据的对象,也就是Model类。V是指视图页面,包含JSP、FreeMarker、Themeleaf等。C是指控制器,也就是使用@Controller注解的类。

1、Maven依赖

                <!--spring+springmvc依赖,引入此包会自动引入Spring的四个核心包+spring-aop、spring-web、spring-webmvc-->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>5.3.14</version>
        </dependency>

                <!--servlet-api依赖-->
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <version>4.0.1</version>
            <scope>provided</scope>
        </dependency>

2、web.xml

此配置文件放在WEB-INF下。
web.xml中配置的DispatcherServlet, 该servelt会在服务启动的时候立即加载,并且在加载时需要一个springMVC配置文件,并根据该文件信息创建一个WebApplicationContext容器对象,也成为上下文环境。这个对象继承与ApplicationContext容器,他的初始化与BeanFactory、ApplicationContext有所区别,因为WebApplicationcontext需要ServletContext实例,也就是说他必须在拥有Web容器的前提下才能完成启动SpringWeb应用上下文的工作。有了WebApplicationcontext,就可以使用spring的IOC和AOP等其他功能了。

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
         version="4.0">

    <display-name>Archetype Created Web Application</display-name>

    <servlet>
        <!--配置前端过滤器-->
        <servlet-name>springmvc</servlet-name>
        <servlet-class>
            org.springframework.web.servlet.DispatcherServlet
        </servlet-class>
        <!--初始化时加载配置文件-->
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>/WEB-INF/springmvc-config.xml</param-value>
        </init-param>
        <!--表示容器在启动时立即加载Servlet-->
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>springmvc</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>
</web-app>

3、springmvc-config.xml

此配置文件放在WEB-INF下

<?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">

      <!--对url请求进行处理的bean-->
    <bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping"/>

    <!--对返回的数据进行处理的bean:分为json和页面两种返回类型,对应下面两个配置-->
    <!--返回json时用到这个类-->
    <bean class="org.springframework.web.servlet.view.BeanNameViewResolver"/>
    <bean id="jsonView" class="org.springframework.web.servlet.view.json.MappingJackson2JsonView"/>
  
    <!--定义视图解析器,返回jsp页面时用到这个类-->
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix" value="/WEB-INF/views/"/>
        <property name="suffix" value=".jsp"/>
    </bean>

    <!--配置拦截器-->
    <mvc:interceptors>
        <!--全局拦截器-->
        <bean class="com.example.ssm.interceptor.CustomInterceptor"/>
        <!--拦截全部url-->
        <mvc:interceptor>
            <mvc:mapping path="/**"/>
            <bean class="com.example.ssm.interceptor.CustomInterceptor"/>
        </mvc:interceptor>
        <!--拦截以/hello结尾的url-->
        <mvc:interceptor>
            <mvc:mapping path="/hello"/>
            <bean class="com.example.ssm.interceptor.CustomInterceptor"/>
        </mvc:interceptor>
    </mvc:interceptors>
</beans>

4、测试FirstController

package com.example.ssm.controller;

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class FirstController implements org.springframework.web.servlet.mvc.Controller {

    @RequestMapping("/hello")
    @Override
    public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception {

        ModelAndView mav = new ModelAndView();
        mav.addObject("msg", "这是我的第一个S平日那个MVC程序");
        mav.setViewName("first");
        return mav;
    }
}

// 或者

@Controller
public class FirstController {
    @RequestMapping("/hello")
    public String handleRequest(HttpServletRequest request, HttpServletResponse responsel, Model model) {
        System.out.println("进来了。。。。。。");

        model.addAttribute("msg", "这是我的第一个Spring MVC程序!");
        return "first";

    }
}

handleRequest是Controller接口的实现方法, FirstController 类会调用该方法来处理请求,并返回一个包含视图名或包含视图名和模型的 ModelAndView 对象。

5、验证

image.png

二、核心类和注解

1、DispatcherServlet

DispatcherServlet 的全名是 org. springframework. web.servlet.DispatcherServlet ,它在程序中充当着前端控制器的角色在使用时,只需将其配置在项目的 web.xml 文件中。

<?xml version="1.0" encoding="UTF-8" ?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xmlns="http://java.sun.com/xml/ns/javaee"
         xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
         id="WeApp_ID" version="3.0">

    <servlet>
        <!--配置前端过滤器-->
        <servlet-name>springmvc</servlet-name>
        <servlet-class>
            org.springframework.web.servlet.DispatcherServlet
        </servlet-class>
        <!--初始化时加载SpringMVC的配置文件-->
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath:springmvc-config.xml</param-value>
        </init-param>
        <!--表示容器在启动时立即加载Servlet-->
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>springmvc</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>

</web-app>

<Ioad-on-startup> 元素和<init-param>元素都是可选的,如果<Ioad-ons-tartup>元素的值为1,则在应用程序启动时会立即加载该 Servlet;如果<Ioad-on-startup>素不存在,则应用程序会在第一个Servlet请求时加载该Servlet。如果<init-param>元素存在并且通过其子元素配置了 Sprihg MVC 配置文件的路径,则应用程序在启动时会加载配置路径下的配置文件;如果没有通过<init-param>元素配置,则应用程序会默认到 WEB-INF 目录下寻找如下方式命名的配置文件。**servletName**-servlet.xml其中,servletName 指的是部署在 web.xml中的DispatcherServlet 的名称,在上面 web.xml中的配置代码中即为 springmvc ,而-servlet. xml是配置文件名的固定写法,所以应用程序会在WEB-INF 下寻找 springmvc-servlet. xml 。

2、SpringMVC注解

(1)@RequestMapping

RequestMapping 注解类型用于映射一个请求或一个方法,@RequestMapping("/firstController")

注意,路径区分大小写

(2)合注解

三、请求处理方法的参数类型和返回类型

1、参数类型

HttpServletRequest
HttpServletResponse
HttpSession
@PathVariable
@RequestParam
@RequestHeader
@RequestBody
@Model/ModelMap
......等等
String 类型的返回值不能携带数据,需要Model 参数类型,通过该参数类型的addAttribute()方法,添加所需数据即可添加需要在视图中显示的属性。需要注意的是,org.springframework.ui.Model 类型不是一个 Servlet API 型,而是一个包含了 Map 对象的 Spring MVC 类型,如果方法中添加了 Model参数,则每次调用请求处理方法时,Spring MVC 都会创建 Model 对象,并将其作为参数传递给方法。

2、返回类型

(1)ModevlAndView

@Controller
public class FirstController {
    public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) {

        ModelAndView mav = new ModelAndView();
        mav.addObject("这是我的第一个Spring MVC程序!");
        mav.setViewName("/WEB-INF/first.jsp");
        return mav;
    }
}

(2)String

由于 ModelAndView 类型未能实现数据与视图之间的解耦,所以在企业开发时,方法的返回类型通常都会使用 String,配合Model携带参数,返回到页面。

@Controller
public class FirstController {
    public String handleRequest(HttpServletRequest request, Model model) {

        model.addAttribute("msg", "这是我的第一个Spring MVC程序!");
        return "first";
    }
}

String处理返回视图页面外,还可以进行重定向与请求转发

public String handleRequest(HttpServletRequest request, Model model) {

        // 重定向请求路径
    return "redirect:index";
}

public String handleRequest(HttpServletRequest request, Model model) {

        // 请求转发
    return "forward:index";
}

(3)其它

void
Model/ModelMap
View
Map
......等等

四、数据绑定

在执行程序时,Spring MVC会根据客户端请求参数的不同,将请求消息中的信息以一定的方式转换并绑定到控制器类的方法参数中,这种将请求消息数据与后台方法参数建立连接的过程,就是 Spring MVC 中的数据绑定。

1、绑定SpringMVC默认数据类型

当前端请求的参数比较简单是,可以在后台的Controller形参中直接使用Spring MVC 提供的默认参数类型。

2、绑定Java基本数据类型

简单数据类型的绑定,就算指Java中几种基本数据类型的绑定。如,int、String、Double等。
当前端请求中的参数名和后台控制器类中的形参名不一致,则后台无法接收到前台传来的参数,这时需要使用Spring MVC提供的@RequestParam注解进行数据绑定。

3、绑定POJO类型

POJO类型的数据绑定就是将所有关联的请求参数封装在一个POJO中,然后在方法中直接使用POJO作为形参来完成数据绑定。前端参数名必须要和POJO属性名一样,否则后台接收的参数值为null。POJO类型里面的属性值,可以为其它相关POJO类。

4、自定义数据绑定

有些特殊类型的参数无法在后台进行直接转换,如日期数据需要自定义转换器(Converter)活格式化(Formatter)来进行数据绑定。
Spring提供了一个Converter用于将一种类型的对象转换为另一种类型的对象,如将前台输入的日期2021/04/08字符串与后台的Date绑定,此时就可以自定义一个Converter。

  1. Converter
import org.springframework.core.convert.converter.Converter;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;

public class DateConvert implements Converter<String, Date> {
    /*定义时间格式*/
    private String datePattern = "yyyy-MM-dd HH:mm:ss";

    @Override
    public Date convert(String source) {
        SimpleDateFormat sdf = new SimpleDateFormat(datePattern);
        try {
            return sdf.parse(source);
        } catch (ParseException e) {
            throw new IllegalArgumentException(
                    "无效的数据格式,请使用这种数据格式:" + datePattern);
        }
    }
}

springmvc-config.xml

    <mvc:annotation-driven conversion-service="conversionService"/>

    <bean id="conversionService" class="org.springframework.context.support.ConversionServiceFactoryBean">
        <property name="converters">
            <set>
                <bean class="com.example.ssm.convert.DateConvert"/>
            </set>
        </property>
    </bean>
  1. Formatter
package com.example.ssm.convert;

import org.springframework.format.Formatter;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;


public class DateFormatter implements Formatter<Date> {
    //定义时间格式
    private String datePattern = "yyyy-MM-dd HH:mm:ss";
    // 生命SimpleDateFormat对象
    private SimpleDateFormat simpleDateFormat;


    @Override
    public Date parse(String source, Locale locale) throws ParseException {
        simpleDateFormat = new SimpleDateFormat(datePattern);
        return simpleDateFormat.parse(source);
    }

    @Override
    public String print(Date date, Locale locale) {
        return new SimpleDateFormat().format(date);
    }
}

springmvc-config.xml

    <bean id="conversionService" class="org.springframework.format.support.FormattingConversionServiceFactoryBean">
        <property name="formatters">
            <set>
                <bean class="com.example.ssm.convert.DateFormatter"/>
            </set>
        </property>
    </bean>

5、绑定数组

例如前台传来多个类型相同的参数,如用户id,用来批量删除用户,就可以用绑定数组的方式。

    public String deleteUsers(Integer[] ids) {
        if (ids != null) {
            for (Integer id : ids) {
                System.out.println("已删除id为" + id + "的用户!");
            }
        } else {
            System.out.println("ids=null");
        }
        return "success";
    }

6、绑定集合

如果前台批量传来的数据,包含不同类型例如用户信息,需要用绑定集合。定义一个包含用户信息类的集合,然后在接受方法中将参数类型定义为该包装类的集合。后台方法中不支持直接使用集合形参进行数据绑定,所以需要使用包装POJO作为形参,然后在包装POJO中包装一个集合属性。

public class UserVO {
    private List<User> users;

    public List<User> getUsers() {
        return users;
    }

    public void setUsers(List<User> users) {
        this.users = users;
    }
}
    public String editUsers(UserVO userList) {
        /*将所有用户数据封装到集合中*/
        List<User> users = userList.getUsers();
        /*循环输出所有用户信息*/
        for (User user : users) {
            if (user.getId() != null) {
                System.out.println("修改成功");
            }
        }

        return "success";
    }

五、JSON数据交互和RESTful支持

1、JSON数据交互

JSON ( JavaScript Object Notation , JS 对象标记)是一种轻量级的数据交换格式 它是基于JavaScript 的一个子集,采用完全独立于编程语言的文本格式来存储和表示数据。

  1. Spring MVC中JSON 数据交互需默认要使用Jackson读取JSON数据,或将java对象转为json。引入以下maven依赖会自动导入以下3个必须的Jackson包。
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
            <version>2.13.1</version>
        </dependency>
  1. JSON格式转换注解

@RequestBody用于将请求体中的数据绑定到万法的形参中 该注解用在方法的形参上
@ResponseBody用于直接返回陀turn 对象 该注解用在方法上

  1. Spring MVC配置
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:mvc="http://www.springframework.org/schema/mvc"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:tx="http://www.springframework.org/schema/tx"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans-4.3.xsd
       http://www.springframework.org/schema/mvc
       http://www.springframework.org/schema/mvc/spring-mvc-4.3.xsd
       http://www.springframework.org/schema/context
       http://www.springframework.org/schema/context/spring-context-4.3.xsd">

    <!--定义组件扫描器,指定需要扫描的包-->
    <context:component-scan base-package="com.example.ssm.controller"/>
    <!--配置注解驱动-->
    <mvc:annotation-driven/>
    <!--配置静态资掘的访问映射,此配置中的文件,将不被前端控制器拦截-->
    <mvc:resources location="classpath:/js" mapping="/js/**"/>
    <!--配置视图解析器-->
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix" value="/WEB-INF/jsp/"/>
        <property name="suffix" value=".jsp"/>
    </bean>
</beans>
  1. 测试代码
    @RequestMapping("/testJson")
    @ResponseBody
    public User testJson(@RequestBody User user) {
        System.out.println(user);
        return user;
    }

2、RESTFul支持

RESTful 也称之为 REST ( Representational State Transfer ),可以将它理解为一种软件架构风格或设计风格,而不是一个标准简单来说,RESTful 风格就是把请求参数变成请求路径的一种风格。RESTful 风格在 HTIP 请求中,使用 put delete post get 方式分别对应添加、删除、修改和查询的操作。

    @RequestMapping("/user/{id}")
    @ResponseBody
    public User selectUser(@PathVariable("id") String id){
        User user = new User();
        user.setUsername("king");
        return user;
    }

@PathVariable("id")注解则用于接收并绑定请求参数,它可以将请求 URL 中的变量映射到方法的形参上,如果请求路径为 "/user/{id}" ,即请求参数中的 id 和方法形参名称 id 一样,则@PathVariable 后面的("id") 可以省略。

六、拦截器

Spring MVC 中的拦截器( Interceptor )类似于 Servlet 中的过滤器( Filter) ,它主要用于拦截用户请求并做相应的处理 例如通过拦截器可以进行权限验证、记录请求信息的日志、判断用户是否登录等,是AOP思想的具体应用。

1、定义拦截器类

通常拦截器类可以通过两种方式来定义:一种是通过实现 Handlerlnterceptor接口,或继承 Handlerlnterceptor 接口的实现类(如 HandlerlnterceptorAdapter )来定义;另一种是通过实现 WebRequestlnterceptor接口,或继承 WebRequestlnterceptor 接口的实现类来定义。

public class CustomInterceptor implements HandlerInterceptor {

    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.println("preHandle....");
        return true;
    }

    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        System.out.println("postHandle....");
    }

    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        System.out.println("afterCompletion....");
    }
}

2、配置拦截器

<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:mvc="http://www.springframework.org/schema/mvc"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:tx="http://www.springframework.org/schema/tx"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans-4.3.xsd
       http://www.springframework.org/schema/mvc
       http://www.springframework.org/schema/mvc/spring-mvc-4.3.xsd
       http://www.springframework.org/schema/context
       http://www.springframework.org/schema/context/spring-context-4.3.xsd">

    <!--配置组件扫描器,指定需要扫描的包-->
    <context:component-scan base-package="com.example.ssm.controller"/>
    <mvc:resources location="classpath:/js" mapping="/js/**"/>
    <!--配置视图解析器-->
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix" value="/WEB-INF/jsp/"/>
        <property name="suffix" value=".jsp"/>
    </bean>
  
    <!--配置拦截器-->
    <mvc:interceptors>
        <!--<mvc:interceptors>直接配置bean将拦截所有请求-->
        <bean class="com.example.interceptor.CustomInterceptor"/>
        <!--拦截全部url-->
        <mvc:interceptor>
            <mvc:mapping path="/**"/>
            <bean class="com.example.interceptor.CustomInterceptor1"/>
        </mvc:interceptor>
        <!--拦截以/hello结尾的url-->
        <mvc:interceptor>
            <mvc:mapping path="/hello"/>
            <bean class="com.example.interceptor.CustomInterceptor2"/>
        </mvc:interceptor>
    </mvc:interceptors>
</beans>

当有多个拦截器同时工作时,它们的 preHandle()方法会按照配置文件中拦截器的配置顺序执行,而它们的 postHandle()方法和 afterCompletion()方法则会按照配置顺序的反序执行

3、案例:拦截器实现用户登录

。。。。待补充

上一篇下一篇

猜你喜欢

热点阅读