Spring MVC 入门就这一篇

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 的请求处理工作流如下图所示:

Spring MVC 入门就这一篇_第1张图片

以下是对应于到 DispatcherServlet 的传入 HTTP 请求的事件顺序:

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

上述的组件 HandlerMappingControllerViewResolverWebApplicationContext 的一部分,它是普通 ApplicationContext 的扩展,带有 Web 应用程序所需的一些额外功能。

Spring 整合 Spring MVC

引入依赖

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


    org.springframework
    spring-webmvc
    4.3.17.RELEASE

相关配置

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


    springServlet
    org.springframework.web.servlet.DispatcherServlet
    
        contextConfigLocation
        classpath*:/spring-mvc*.xml
    
    1


    springServlet
    /

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


    encodingFilter
    org.springframework.web.filter.CharacterEncodingFilter
    
        encoding
        UTF-8
    
    
        forceEncoding
        true
    


    encodingFilter
    /*

创建一个 spring-mvc 配置文件,用于配置 MVC




    Spring MVC Configuration

    
    
        
    

    
    

    
    
        
        
    

    
    

上述配置说明:

  • 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";
    }
}

@Controller

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

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

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

@RequestMapping

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

@RequestMapping 注解有六个属性:

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

@ResponseBody

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

如果需要返回自定义对象为 JSON 格式,需要添加以下依赖:



    com.fasterxml.jackson.core
    jackson-core
    2.9.5


    com.fasterxml.jackson.core
    jackson-databind
    2.9.5


    com.fasterxml.jackson.core
    jackson-annotations
    ${jackson.version}

Spring MVC 拦截器的使用

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

应用场景

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

实现拦截

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

  • preHandle():该方法在请求处理之前进行调用。该方法的返回值是布尔值 Boolean 类型的,当它返回为 false 时,表示请求结束,后续的 InterceptorController 都不会再执行;当返回值为 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:interceptor:定义一个拦截器
  • mvc:mapping:映射路径,需要拦截的请求路径
  • mvc:exclude-mapping:需要排除的请求路径,比如登录页本身是不需要拦截的,这里还包括了静态资源路径也是不需要拦截的
  • bean:配置指定的拦截器对象

你可能感兴趣的:(spring)