最近在写个人博客,想在系统启动时自动把文章类别查询出来并保存,之前系统启动时是用redis对文章的浏览量和评论数进行保存。这次想用另一种方式。即将文章类别保存到应用的上下文。这里就要搞清楚三个概念ServletContext、ApplicationContext、ServletConfig、WebApplicationContext。这里主要参考了:https://blog.csdn.net/u010325193/article/details/84534861
1. ServletContext、ApplicationContext、ServletConfig、WebApplicationContext区别
我查了一下资料,三者定义如下:
-
ServletContext
这个是来自于servlet规范里的概念,它是servlet用来与容器间进行交互的接口的组合,也就是说,这个接口定义了一系列的方法,servlet通过这些方法可以很方便地与自己所在的容器进行一些交互,比如通过getMajorVersion与getMinorVersion来获取容器的版本信息等. 从它的定义中也可以看出,在一个应用中(一个JVM)只有一个ServletContext, 换句话说,容器中所有的servlet都共享同一个ServletContext. -
ServletConfig
它与ServletContext的区别在于,servletConfig是针对servlet而言的,每个servlet都有它独有的serveltConfig信息,相互之间不共享. -
ApplicationContext
这个类是Spring实现容器功能的核心接口,它也是Spring实现IoC功能中最重要的接口,从它的名字中可以看出,它维护了整个程序运行期间所需要的上下文信息, 注意这里的应用程序并不一定是web程序,也可能是其它类型的应用. 在Spring中允许存在多个applicationContext,这些context相互之间还形成了父与子,继承与被继承的关系,这也是通常我们所说的,在spring中存在两个context,一个是root context,一个是servlet applicationContext的意思. 这点后面会进一步阐述. -
WebApplicationContext
其实这个接口不过是applicationContext接口的一个子接口罢了,只不过说它的应用形式是web罢了. 它在ApplicationContext的基础上,添加了对ServletContext的引用,即getServletContext方法.
2. 两种方法在系统启动时将数据存储在ServletContext中
这里我用两种方法来实现,以加强对上述四个概念的理解
2.1 直接通过webApplicationContext获取ServletContext
@Component
@Order(Ordered.HIGHEST_PRECEDENCE)
public class ListenHandler {
//直接注入WebApplicationContext
@Autowired
private WebApplicationContext webApplicationContext;
//注入categoryService
@Autowired
private CategoryService categoryService;
@PostConstruct
public void init() throws Exception {
//获取所有文章类别数据
List<Category> categories = categoryService.queryAll();
//直接通过webApplicationContext获得servletContext
webApplicationContext.getServletContext().setAttribute("categories",categories);
//读取类别数据到servletContext
servletContext.setAttribute("categories",categories);
}
}
2.2 通过WebApplicationContext获取bean,通过bean获取数据再放到ServletContext中
@Component
@Order(Ordered.HIGHEST_PRECEDENCE)
public class ListenHandler {
//直接注入WebApplicationContext
@Autowired
private WebApplicationContext webApplicationContext;
@PostConstruct
public void init() throws Exception {
//获取所有文章类别数据,这里获取CategoryImpl,也就是categoryService的实现类
//注意"categoryImpl"类名首字母要小写
CategoryImpl categoryImpl =(CategoryImpl) applicationContext.getBean("categoryImpl");
List<Category> categories = categoryImpl.queryAll();
//直接通过webApplicationContext获得servletContext
webApplicationContext.getServletContext().setAttribute("categories",categories);
//读取类别数据到servletContext
servletContext.setAttribute("categories",categories);
}
}
3. controller层两种方法将将servletContext中的数据取出
3.1 通过ServletRequest获取servletContext
//查询所有的category
@GetMapping("/aqi/queryAllCategory")
public List<Category> queryAllCategory(ServletRequest servletRequest){
List<Category> categories = (List<Category>)servletRequest.getServletContext().getAttribute("categories");
return categories;
}
3.2 直接注入ServletContext
@Autowired
private ServletContext servletContext;
//查询所有的category
@GetMapping("/aqi/queryAllCategory")
public List<Category> queryAllCategory(ServletRequest servletRequest){
List<Category> categories = (List<Category>)servletContext.getAttribute("categories");
return categories;
}
4. 测试
这几种方式都可以,检验结果如下:
5.小结
ServletContext、ApplicationContext、ServletConfig、WebApplicationContext的概念还在一步步深入理解。感觉ServletContext就是Servlet上下文,web应用不死,ServletContext不死。ApplicationContext主要管理Spring内部的一些bean,WebApplicationContext实现了ApplicationContext,把ServletContext包了进来。