资讯专栏INFORMATION COLUMN

SpringMVC之源码分析--Controller(一)

CKJOKER / 2986人阅读

摘要:总结本章主要分析了接口抽象类以及对自定义的几个重要属性进行了测试,希望对大家有帮助,谢谢。

概述

Controller是Spring MVC为我们提供的基础的控制器接口,和HttpServlet一样,接收request和response参数处理用户请求,并返回ModelAndView,从概念上可以类比Struts的Action。

Controller主要实现的如下功能:

接收并处理用户请求

调用业务方法

返回ModelAndView

基于Controller开发请求处理Handler的特点:

需要实现Controller接口

请求参数需从请求request中获取

请求处理Handler与Spring深度耦合

就目前项目开发,几乎不会使用此方式进行开发,除非维护一些历史项目。目前是基于注解进行开发,从Spring2.5及之后开始支持。编写本章内容主要是基于知识点的全面性来考虑,大家可以了解了解。

本系列文章是基于Spring5.0.5RELEASE。

接口Controller

Spring提供的Controller接口,定义了一个方法,作用就是处理用户请求,源码如下:

package org.springframework.web.servlet.mvc;

public interface Controller {
    
    /**
     *接收request和response参数,处理用户请求
     *参数从request中获取
     *方法返回ModelAndView,Model为模型数据,View为视图
     */
    ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception;

}
Spring提供的实现类

Spring提供了如下实现:

AbstractController 控制浏览器缓存、支持的请求方法等等

ServletForwardingController 将Spring Handler接收的请求转发给一个Servlet去执行

ParameterizableViewController 参数化视图控制器,根据参数的逻辑视图名直接选择需要展示的视图

AbstractUrlViewController 根据请求URL路径直接转化为逻辑视图名的支持基类

UrlFilenameViewController 将请求URL路径转换为逻辑视图名并返回的实现类

ServletWrappingController Servlet包装控制器

以上是Spring MVC为我们提供Controller接口的默认实现,下面我们接着分析这些实现类。

AbstractController

该抽象类继承WebContentGenerator并实现Controller接口,其中WebContentGenerator类用于浏览器缓存控制、自定义Controller支持的请求方法类型(默认支持:GET/HEAD/POST)等。

WebContentGenerator类的主要属性如下:

/** 支持的请求方法类型,默认支持:GET、HEAD、POST */
@Nullable
private Set supportedMethods;

@Nullable
private String allowHeader;
/** 当前请求是否必须有session */
private boolean requireSession = false;

@Nullable
private CacheControl cacheControl;
/** 缓存过期时间,正数表示需要缓存,负数表示不做任何事情 */
private int cacheSeconds = -1; 

@Nullable
private String[] varyByRequestHeaders;

/** 是否使用HTTP1.0协议过期响应头:如果true则会在响应头添加“Expires:”;需要配合cacheSeconds使用 */
private boolean useExpiresHeader = false;

/** 是否使用HTTP1.1协议的缓存控制响应头,如果true则会在响应头添加;需要配合cacheSeconds使用 */
private boolean useCacheControlHeader = true;

/** 是否使用HTTP 1.1协议的缓存控制响应头,如果true则会在响应头添加;需要配合cacheSeconds使用 */
private boolean useCacheControlNoStore = true;

AbstractController类源码如下:

/** 表示该控制器是否在执行时同步session,从而保证该会话的用户串行访问该控制器 */
private boolean synchronizeOnSession = false;

/**
 *实现Controller接口的handleRequest方法
 */
@Override
@Nullable
public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response)
        throws Exception {

    if (HttpMethod.OPTIONS.matches(request.getMethod())) {
        response.setHeader("Allow", getAllowHeader());
        return null;
    }

    // 检查是否支持请求方法以及必须的session
    checkRequest(request);
    // 根据设置准备response
    prepareResponse(response);

    // 如果必要顺序执行handleRequestInternal方法
    if (this.synchronizeOnSession) {
        HttpSession session = request.getSession(false);
        if (session != null) {
            Object mutex = WebUtils.getSessionMutex(session);
            synchronized (mutex) {
                return handleRequestInternal(request, response);
            }
        }
    }
    
    return handleRequestInternal(request, response);
}

/**
 * 需要子类实现的模板方法
 */
@Nullable
protected abstract ModelAndView handleRequestInternal(HttpServletRequest request, HttpServletResponse response)
        throws Exception;
实战

本章实战是通过继承AbstractController类编写用户请求handler,测试如下几点:

继承AbstractController抽象类,实现handlerRequestInternal方法处理用户请求

通过前几篇及上面的分析,SimpleControllerHandlerAdapter类可以适配实现了Controller接口的类,AbstractController实现了Controller接口的handleRequest方法,并预留了handleRequestInternal模板方法供子类实现,用户处理用户请求,根据这个思路,我们要使用SimpleControllerHandlerAdapter适配Controller时,只需继承AbstractController类并实现handleRequestInternal方法即可,具体源码如下:

自定义Controller源码:

/**
 *继承AbstractController并实现handleRequestInternal方法
 */
public class HelloWorldController extends AbstractController {

    /**
     *通过response直接回写数据,也可通过ModelAndView指定逻辑视图并回写数据
     */
    @Override
    protected ModelAndView handleRequestInternal(HttpServletRequest request, HttpServletResponse response) throws Exception {
        Writer writer = response.getWriter();
        writer.write("hello AbstractController");
        writer.flush();
        return null;
    }

}

配置文件配置如下:









验证结果

代码编写完后,启动应用进行测试,AbstractController默认支持GET、HEAD、POST方法类型,我们使用Postman进行测试,GET请求结果如下:

HEAD、POST也能处理,但如果发起PUT请求则返回不支持方法类型,如下图:

指定请求方法类型

AbstractController默认支持GET、HEAD、POST三种请求类型,本例通过设置supportedMethods属性来设置支持的请求方法类型,代码如下:

配置文件配置如下:



    
    
        
            PUT
            POST
        
    

验证结果

只需在Controller Bean修改supportMethods属性接口,测试PUT请求,结果如下:

requireSession前置检查

当把requireSession属性设置为true时,访问Controller需检查有无session,如果没有将跑出HttpSessionRequiredException异常,代码如下:

配置文件配置如下:



    
    
        
            GET
            POST
        
    
    
    



新增的HelloWorld2Controller与HelloWorldController代码基础上增加获取session的代码,如下:

request.getSession(true);

测试验证

首先验证没有session情况下,结果如下:

说明在访问到自定义Controller前检查session没有,抛出HttpSessionRequiredException异常

我们增加了一个新的controller用于设置创建session,此时我们访问一次后,再访问需要验证的session的请求,结果如下:

通过结果可见,测试能正常访问了。

总结

本章主要分析了Controller接口、AbstractController抽象类以及对自定义Controller的几个重要属性进行了测试,希望对大家有帮助,谢谢。

最后创建了qq群方便大家交流,可扫描加入,同时也可加我qq:276420284,共同学习、共同进步,谢谢!

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/69567.html

相关文章

  • SpringMVC源码分析--Controller(二)

    摘要:概述上篇文章主要分析了提供的及抽象类,本章继续分析其具体的几个实现类。源码由继承关系继承抽象类,并实现模板方法,完成将接收的请求进行转发,源码如下实现父类模板方法获取部署文件中定义的,传入参数。 概述 上篇文章主要分析了Spring提供的Controller及抽象类AbstractController,本章继续分析其具体的几个实现类。 本系列文章是基于Spring5.0.5RELEAS...

    KevinYan 评论0 收藏0
  • SpringMVC源码分析--HandlerMapping(

    摘要:接口接口作用是将请求映射到处理程序,以及预处理和处理后的拦截器列表,映射是基于一些标准的,其中的细节因不同的实现而不相同。该参数是类型,作用是检查所有的映射解析器或使用或为的,默认为,即从上下文中检查所有的。 概述 在Spring MVC启动章节https://segmentfault.com/a/1190000014674239,介绍到了DispatcherServlet的onRef...

    ralap 评论0 收藏0
  • SpringMVC源码分析--ThemeResolver(三)

    摘要:类继承关系如下该类实现接口,实现解析设置主题功能继承类,以具备操作功能。新增并更换一张不同的图片。配置文件只要替换即可,代码如下配置默认的主题文件视图和控制器视图和控制器代码与上一章一致,参考上章代码。 概述 上节介绍了SessionThemeResolver解析器,本章分析下CookieThemeResolver,两个解析器实现的功能是一样的,只是使用的主题载体有区别而已,Sessi...

    OldPanda 评论0 收藏0
  • SpringMVC源码分析--LocaleResolver(

    摘要:概述为我们提供国际化支持,通过设置系统的环境,根据运行环境使用不同的语言显示。提供接口的作用是解析客户端使用的地区,目的是为了根据这些信息实现视图多语言即国际化。接口继承接口,增加时区支持。 概述 Spring MVC为我们提供国际化支持,通过设置系统的环境,根据运行环境使用不同的语言显示。Spring提供LocaleResolver接口的作用是解析客户端使用的地区(Locale),目...

    HtmlCssJs 评论0 收藏0
  • SpringMVC源码分析--HandlerAdapter(

    摘要:本系列文章是基于。说这么多就是想解释下什么是适配器。本节我们主要从整体以及概念上阐述了的,后续会逐个分析提供的四种适配器,希望本节对大家能有帮助,谢谢。最后创建了群方便大家交流,可扫描加入,同时也可加我,共同学习共同进步,谢谢 概述 本章开始,我们分析Spring MVC的另一个重要组件,即HandlerAdapter,从命名上我即可直观的理解为处理器适配器,那么处理器适配器是什么意思...

    dingda 评论0 收藏0

发表评论

0条评论

CKJOKER

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<