Spring Boot BaseController


placeholder image
admin 发布于:2022-05-09 21:49:24
阅读:loading

从Struts年代都有编写BaseAction,主要的目的是使用Struts提供的父类实现,如SUCCESS/ERROR等常量和国际化方法等,而在本站博客1.0版本中Spring MVC时仍是提供了BaseController,主要的目的是从父类提供常用的Web开发的变量,如HttpServletRequest、HttpServletResponse、HttpSession、Model等,同时提供一些公共的Controller方法,如输出一段<script/>脚本等用途,参考代码如下:

package cn.chendd.blog.base.controller;


/**
 * Base Controller
 *
 * @author chendd
 * @date 2019/9/18 17:05
 */
public abstract class BaseController {

    protected HttpServletRequest request;
    protected HttpServletResponse response;
    protected HttpSession session;
    protected Model model;

    @ModelAttribute
    public void initServletContext(Model model) {
        ServletRequestAttributes attributes = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes());
        this.request = attributes.getRequest();
        this.response = attributes.getResponse();
        this.session = request.getSession();
        this.model = model;
    }

    ///此处省略一些其它方法

}

细节说明

(1)示例代码省略一些import ...的包导入;

(2)示例代码提供了request、response、session、model;

(3)由于Spring @Controller组件默认为单例模式,而request、response等参数类型是yi些特殊的参数对象,每次请求均会生成新的对象,若不放心可进行验证;

(4)@ModelAttrribute注解是在Controller的方法执行之前先执行的方法;

(5)单独拿出来BaseController来细说,最主要的目的是曾经在初始化这些参数时的另外一种写法,但在Spring Boot环境定义统一的接口输出结果集时出现的一个非常隐晦的问题,参考如下代码:

    @ModelAttribute
    public void initServletContext(Model model , HttpServletRequest request , HttpServletResponse response) {
        this.request = request;
        this.response = response;
        this.session = request.getSession();
        this.model = model;
    }

注意了,当前这种通过参数对象注入的形式进行赋值的实现在一般的应用场景下是没有任何问题的,但是在使用@ControllerAdvice或@RestControllerAdvice生成全局的JSON格式的BaseResult(假设它是全局自定义JSON的输出类)对象时,当Controller的方法返回值类型定义为Object,且最终的返回值为null时,此时的输出结果就存在问题了,这个问题在博客2.0建站编码初期折腾了许久最终才在查阅了巨多资料和源码debug时发现的问题就在于使用参数注入的形式注入的response类型参数导致,所以如果你正好也定义了BaseController或者由此同样疑问的同时,不放采用ServletRequestAttributes的形式在方法内部进行参数类型的获取即可。


 点赞


 发表评论

当前回复:作者

 评论列表


留言区