您的位置:首页 > 编程语言 > Java开发

Spring MVC 入门就这一篇

antoniopeng 2020-04-23 21:34 42 查看 https://www.cnblogs.com/antoni

Spring MVC 概述

Spring MVC
也叫
Spring Web MVC
,属于展示层框架,是
Spring
框架的一部分。

MVC
模式作用在于分离应用程序的不同方面(业务逻辑、 UI 逻辑、输入逻辑),而
Spring MVC
框架分别对应为其提供了 模型(Model)视图(View)控制器(Controller) 三层架构和用于开发灵活和松散耦合的 Web 应用程序的组件,同时提供这些元素之间的松散耦合的实现。

  • 模型(Model):封装了应用程序数据,通常它们将由
    POJO
    类组成。
  • 视图(View):负责渲染模型数据,一般来说它生成客户端浏览器可以解释
    HTML
    输出。
  • 控制器(Controller):负责处理用户请求并构建适当的模型,并将其传递给视图进行渲染。

核心组件类 DispatcherServlet

Spring MVC
框架是围绕
DispatcherServlet
设计的,它处理所有的
HTTP
请求和响应。

Spring MVC
的请求处理工作流如下图所示:

以下是对应于到

DispatcherServlet
的传入
HTTP
请求的事件顺序:

  • 在接收到
    HTTP
    请求后,
    DispatcherServlet
    会查询
    HandlerMapping
    以调用相应的
    Controller
  • Controller
    接受请求并根据使用的 GET 或 POST 方法调用相应的服务方法。 服务方法将基于定义的业务逻辑设置模型数据,并将视图名称返回给
    DispatcherServlet
  • DispatcherServlet
    将从
    ViewResolver
    获取请求的定义视图。
  • 当视图完成,
    DispatcherServlet
    将模型数据传递到最终的视图,并在浏览器上呈现。

上述的组件

HandlerMapping
Controller
ViewResolver
WebApplicationContext
的一部分,它是普通
ApplicationContext
的扩展,带有
Web
应用程序所需的一些额外功能。

Spring 整合 Spring MVC

引入依赖

pom.xml
中添加主要依赖
org.springframework:spring-webmvc

<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>4.3.17.RELEASE</version>
</dependency>

相关配置

web.xml
中配置
DispatchServlet
处理所有的
HTTP
请求和响应:

<servlet>
<servlet-name>springServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath*:/spring-mvc*.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>sprin
56c
gServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>

web.xml
中还需配置字符集过滤器,用于解决中文编码问题:

<filter>
<filter-name>encodingFilter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
<init-param>
<param-name>forceEncoding</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>encodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>

创建一个

spring-mvc
配置文件,用于配置
MVC

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/s
ad8
chema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd">

<description>Spring MVC Configuration</description>

<!-- 使用 Annotation 自动注册 Bean,只扫描 @Controller -->
<context:component-scan base-package="com.lusifer.myshop" use-default-filters="false">
<context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
</context:component-scan>

<!-- 注解映射的支持 -->
<mvc:annotation-driven />

<!-- 定义视图文件解析 -->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/views/"/>
<property name="suffix" value=".jsp"/>
</bean>

<!-- 静态资源映射 -->
<mvc:resources mapping="/static/**" location="/static/" cache-period="31536000"/>
</beans>

上述配置说明:

  • context:component-scan
    :当前配置文件为 MVC 相关,故只需要扫描包含
    @Controller
    的注解即可,由于
    spring-context.xml
    配置文件中也配置了包扫描,所以还需要排除
    @Controller
    的注解扫描。
  • InternalResourceViewResolver
    :视图文件解析器的一种,用于配置视图资源的路径和需要解释的视图资源文件类型,这里有两个需要配置的属性
    prefix
    (前缀)以及
    suffix
    (后缀)。
    prefix
    :配置视图资源路径,如:
    /WEB-INF/views/
  • suffix
    :配置视图资源类型,如:
    .jsp
  • mvc:resources
    :静态资源映射,主要用于配置静态资源文件存放路径,如:JS、CSS、IMG 等。
  • 第一个 Controller 控制器

    创建

    IndexController

    @Controller
    public class IndexController {
    
    @Autowired
    private HelloSpringService helloSpringService;
    
    @RequestMapping(value = {"", "/index"}, method = RequestMethod.GET)
    public String index() {
    return "index";
    }
    
    @RequestMapping(value = "login", method = RequestMethod.POST)
    public String login(@RequestParam(required = true) String email, @RequestParam(required = true) String password) {
    return "redirect:/main";
    }
    }
    ad8 [/code]

    @Controller

    Spring MVC
    中,控制器
    Controller
    负责处理由
    DispatcherServlet
    分发的请求,它把用户请求的数据经过业务处理层处理之后封装成一个
    Model
    ,然后再把该
    Model
    返回给对应的
    View
    进行展示。

    Spring MVC
    中提供了一个非常简便的定义
    Controller
    的方法,你无需继承特定的类或实现特定的接口,只需使用
    @Controller
    标记一个类是控制器,然后使用
    @RequestMapping
    @RequestParam
    等一些注解用以定义
    URL
    请求和
    Controller
    方法之间的映射,这样的
    Controller
    就能被外界访问到。此外
    Controller
    不会直接依赖于
    HttpServletRequest
    HttpServletResponse
    HttpServlet
    对象,它们可以通过
    Controller
    的方法参数灵活的获取到。

    @Controller
    只是定义了一个控制器类,而使用
    @RequestMapping
    注解的方法才是真正处理请求的处理器。

    @RequestMapping

    @RequestMapping
    是一个用来处理请求地址映射的注解,可用于类或方法上。用于类上,表示类中的所有响应请求的方法都是以该地址作为父路径。

    @RequestMapping
    注解有六个属性:

    • value
      :指定请求的实际地址。
    • method
      :指定请求的类型,如 GET、POST、PUT、DELETE 等。
    • consumes
      :指定处理请求的提交内容类型(Content-Type),如
      application/json
      text/html
    • produces
      : 指定返回的内容类型。
    • params
      :指定请求的参数值。
    • headers
      :指定请求中的
      header
      值。

    @ResponseBody

    该注解用于将

    Controller
    的方法返回的对象,通过适当的
    HttpMessageConverter
    转换为指定格式后,直接写入
    HTTP
    响应正文中。

    如果需要返回自定义对象为

    JSON
    格式,需要添加以下依赖:

    <!-- Json Begin -->
    <dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-core</artifactId>
    <version>2.9.5</version>
    </dependency>
    <dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifact
    27b3
    Id>jackson-databind</artifactId>
    <version>2.9.5</version>
    </dependency>
    <dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-annotations</artifactId>
    <version>${jackson.version}</version>
    </dependency>
    <!-- Json End -->

    Spring MVC 拦截器的使用

    Spring  MVC
    的处理器拦截器,类似于
    Servlet
    开发中的过滤器
    Filter
    ,用于对处理器进行预处理和后处理。

    应用场景

    • 日志记录:记录请求信息的日志,以便进行信息监控、信息统计、计算 PV 等。
    • 权限检查:如登录检测,进入处理器检测检测是否登录,如果没有直接返回到登录页面。
    • 性能监控:有时候系统在某段时间莫名其妙的慢,可以通过拦截器在进入处理器之前记录开始时间,在处理完后记录结束时间,从而得到该请求的处理时间。
    • 通用行为:读取 Cookie 得到用户信息并将用户对象放入请求,从而方便后续流程使用。

    实现拦截

    Spring MVC
    拦截器需要实现
    HandlerInterceptor
    接口,该接口定义了 3 个方法,分别为
    preHandle()
    postHandle()
    afterCompletion()
    ,需要通过重写这 3 个方法来对用户的请求进行拦截处理的。

    • preHandle()
      :该方法在请求处理之前进行调用。该方法的返回值是布尔值
      Boolean
      类型的,当它返回为
      false
      时,表示请求结束,后续的
      Interceptor
      Controller
      都不会再执行;当返回值为
      true
      时,就会继续调用下一个拦截器的
      preHandle
      方法,如果已经是最后一个拦截器的时候,就会是调用当前请求的
      Controller
      中的方法。
    • postHandle()
      :只能在当前所属拦截器的
      preHandle()
      的返回值为
      true
      的时候,才能被调用。
      postHandle()
      在当前请求进行处理之后,也就是在
      Controller
      中的方法调用之后执行,但是它会在
      DispatcherServlet
      进行视图返回渲染之前被调用,所以在这个方法中对
      Controller
      处理之后的
      ModelAndView
      对象进行操作。
    • afterCompletion()
      :也是需要当前对应的当前的
      preHandle()
      的返回值为
      true
      时才会执行。因此,该方法将在整个请求结束之后,也就是在
      DispatcherServlet
      渲染了对应的视图之后执行,这个方法的主要作用是用于进行资源清理的工作。

    创建拦截器

    这里以登录拦截器作为演示示例。当未登录时是无法直接访问需要登录权限的操作的,为了做到这个效果,我们使用登录拦截器来判断用户是否登录,如果用户已登录则放行让用户继续操作,否则就将其跳转到登录页。

    创建

    LoginInterceptor
    拦截器类

    public class LoginInterceptor implements HandlerInterceptor {
    
    public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o) throws Exception {
    
    User user = (User) httpServletRequest.getSession().getAttribute("user");
    
    // 判断用户是否登录
    if (user == null) {
    // 用户未登录,重定向到登录页
    httpServletResponse.sendRedirect("/login");
    return false;
    }
    
    // 放行
    return true;
    }
    
    public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception {
    // 如果请求来自登录页
    if (modelAndView.getViewName().endsWith("login")) {
    // 则直接重定向到首页不再显示登录页
    httpServletResponse.sendRedirect("/main");
    }
    }
    
    public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception {
    
    }
    }

    配置拦截器

    拦截器定义后还需要在

    spring-mvc.xml
    文件中配置拦截器,代码如下:

    <!-- 拦截器配置,拦截顺序:先执行后定义的,排在第一位的最后执行。-->
    <mvc:interceptors>
    <mvc:interceptor>
    <mvc:mapping path="/**"/>
    <mvc:exclude-mapping path="/static/**"/>
    <mvc:exclude-mapping path="/login"/>
    <bean class="com.antoniopeng.springmvc.web.interceptor.LoginInterceptor"/>
    </mvc:interceptor>
    </mvc:interceptors>

    相关配置说明:

    标签: