ContextLoaderListener可以不写嘛?

本文解析了Spring中ContextLoaderListener的工作原理及其如何启动Spring Web应用上下文容器,同时介绍了DispatcherServlet的初始化过程及获取Spring根容器的方法。

写了那么久的Spring,经常写这样的配置,这就是几行Spring、SpringMvc的基本配置, 但是最近也看到不写最前面的context-param以及listener的,好奇记录下.

<context-param>
		<param-name>contextConfigLocation</param-name>
		<param-value>classpath:spring.xml</param-value>
</context-param>

<listener>
		<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>

<servlet>
	<servlet-name>Springmvc</servlet-name>
	<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
	<load-on-startup>1</load-on-startup>
</servlet>

<servlet-mapping>
	<servlet-name>Springmvc</servlet-name>
	<url-pattern>/</url-pattern>
</servlet-mapping>

 

 

ContextLoaderListener监听器介绍

image

上图是ContextLoaderListener的结构图以及javadoc.    ContextLoaderListener肯定要实现ServletContextListener,这点不用多说,另外继承的类是ContextLoader.

JavaDoc告诉我们很多信息:Bootstrap listener启动类监听器用来启动/停止Spring Web上下文容器,代理给ContextLoader来完成启动启动工作。 listener应当在Log4jConfigListener之后注册。

           Spring3.1支持通过ContextLoaderListener构造器方式注入Web 上下文容器,servlet3.0也支持使用WebApplicationInitializer启动Spring容器来替代web.xml写法。

 

主要关注的是ContextLoaderListener,先主要关注容器启动这块吧!监听器的contextInitialized 方法:调用了ContextLoader的initWebApplicationContext,还是代理给了ContextLoader完成容器启动工作。

代码太占篇幅了,记录下加载过程即可:

   step1.检查ServletContext上下文是否有WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE这个属性,没有是正常的,有的话就说明Spring根容器重复定义了!

   step2. 尝试读取context-param中为contextClass的值作为根容器的class属性,如果没有指定context-param属性,就以ContextLoader类所在同一路径下的ContextLoader.properties文件中的 org.springframework.web.context.WebApplicationContext 作为key取出value , 默认为 org.springframework.web.context.support.XmlWebApplicationContext , 以这个作为Spring根容器类型,并且实例化XmlWebApplicationContext;

   step3. Spring根容器的ServletContext设置为当前ServletContext,并且读取web.xml中 其contextConfigLocation作为 Spring配置文件位置,最后调用 根容器的refresh 方法完成容器启动!

   step4. 根容器启动完之后,设置到 ServletContext的WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE 属性中 ,并且存到了ContextLoader中,可以通过静态方法ContextLoader.getCurrentWebApplicationContext就能获取到 Spring根容器。

 

 

DispatcherServlet的初始化

初始化的入口位于 org.springframework.web.servlet.HttpServletBean#init :

  SpringMvc容器类型默认为XmlWebApplicationContext,反射实例化该对象,并且通过ServletContext的 WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE属性得到Spring根容器,

作为SpringMVC容器的父容器。  另外,像如下形式的SpringMvc,没有指定spring配置文件的位置,那默认加载的配置文件位置为: /WEB-INF/Springmvc-servlet.xml 

<servlet>
       <servlet-name>Springmvc</servlet-name>
		<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
		<load-on-startup>1</load-on-startup>
	</servlet>

	<servlet-mapping>
		<servlet-name>Springmvc</servlet-name>
		<url-pattern>/</url-pattern>
</servlet-mapping>

 

也就是说没有ContextLoaderListener,对于SpringMvc容器的影响就是没了父容器,照样可以使用SpringMVC的特性

 

 

获取Spring根容器以及Web容器的方式

提供五种获取Spring根容器方案、三种获取Spring父容器方案:

@Controller
@RequestMapping("/context")
public class ContextController implements ApplicationContextAware {

    @Autowired
    private ApplicationContext ac;

    @RequestMapping("/demo1")
    @ResponseBody
    public String demo1(HttpServletRequest request){
        System.out.println("Spring根容器方式一:"+request.getServletContext().getAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE));
        System.out.println("Spring根容器方式二:"+ContextLoader.getCurrentWebApplicationContext());
        System.out.println("Spring根容器方式三:"+ WebApplicationContextUtils.getRequiredWebApplicationContext(request.getServletContext()));
        System.out.println("Spring根容器方式四:"+ WebApplicationContextUtils.getWebApplicationContext(request.getServletContext()));
        System.out.println("Spring根容器方式五:"+ac.getParent());
        System.out.println("SpringMvc容器获取方式一:"+ac);
        System.out.println("SpringMvc容器获取方式二:"+ac2);
                          //SpringMvc容器获取方式三 继承抽象类 WebApplicationObjectSupport,方式二方式三不能同时用
                          //调用getApplicationContext
        return "hello World";
    }

    private ApplicationContext ac2;
    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        ac2=applicationContext;
    }
}

转载于:https://www.cnblogs.com/lvbinbin2yujie/p/10616889.html

以下是一个简单的 JavaWeb 新闻管理项目的整体代码实现示例,该示例采用 SSM(Spring + Spring MVC + MyBatis)框架,数据库使用 MySQL。 ### 1. 项目结构 ``` news-management-system ├── src │ ├── main │ │ ├── java │ │ │ └── com │ │ │ └── example │ │ │ ├── controller │ │ │ │ ├── NewsController.java │ │ │ │ ├── UserController.java │ │ │ ├── dao │ │ │ │ ├── NewsDao.java │ │ │ │ ├── UserDao.java │ │ │ ├── entity │ │ │ │ ├── News.java │ │ │ │ ├── User.java │ │ │ ├── service │ │ │ │ ├── NewsService.java │ │ │ │ ├── NewsServiceImpl.java │ │ │ │ ├── UserService.java │ │ │ │ ├── UserServiceImpl.java │ │ │ └── util │ │ │ └── MyBatisUtil.java │ │ ├── resources │ │ │ ├── mapper │ │ │ │ ├── NewsMapper.xml │ │ │ │ ├── UserMapper.xml │ │ │ ├── mybatis-config.xml │ │ │ ├── spring-mvc.xml │ │ │ └── spring.xml │ │ └── webapp │ │ ├── WEB-INF │ │ │ ├── web.xml │ │ │ └── views │ │ │ ├── news │ │ │ │ ├── newsList.jsp │ │ │ │ ├── newsAdd.jsp │ │ │ ├── user │ │ │ │ ├── login.jsp │ │ │ │ ├── register.jsp ``` ### 2. 实体类 #### News.java ```java package com.example.entity; import java.util.Date; public class News { private int newsId; private String title; private String content; private Date publishTime; private int author; private int category; // 构造函数、Getter 和 Setter 方法 public News() {} public News(int newsId, String title, String content, Date publishTime, int author, int category) { this.newsId = newsId; this.title = title; this.content = content; this.publishTime = publishTime; this.author = author; this.category = category; } // Getter 和 Setter 方法 public int getNewsId() { return newsId; } public void setNewsId(int newsId) { this.newsId = newsId; } public String getTitle() { return title; } public void setTitle(String title) { this.title = title; } public String getContent() { return content; } public void setContent(String content) { this.content = content; } public Date getPublishTime() { return publishTime; } public void setPublishTime(Date publishTime) { this.publishTime = publishTime; } public int getAuthor() { return author; } public void setAuthor(int author) { this.author = author; } public int getCategory() { return category; } public void setCategory(int category) { this.category = category; } } ``` #### User.java ```java package com.example.entity; public class User { private int userId; private String username; private String password; private String role; // 构造函数、Getter 和 Setter 方法 public User() {} public User(int userId, String username, String password, String role) { this.userId = userId; this.username = username; this.password = password; this.role = role; } // Getter 和 Setter 方法 public int getUserId() { return userId; } public void setUserId(int userId) { this.userId = userId; } public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } public String getRole() { return role; } public void setRole(String role) { this.role = role; } } ``` ### 3. DAO 接口 #### NewsDao.java ```java package com.example.dao; import com.example.entity.News; import java.util.List; public interface NewsDao { List<News> getAllNews(); void addNews(News news); } ``` #### UserDao.java ```java package com.example.dao; import com.example.entity.User; public interface UserDao { User getUserByUsername(String username); void addUser(User user); } ``` ### 4. MyBatis Mapper XML 文件 #### NewsMapper.xml ```xml <?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.example.dao.NewsDao"> <select id="getAllNews" resultType="com.example.entity.News"> SELECT * FROM news </select> <insert id="addNews" parameterType="com.example.entity.News"> INSERT INTO news (title, content, publish_time, author, category) VALUES (#{title}, #{content}, #{publishTime}, #{author}, #{category}) </insert> </mapper> ``` #### UserMapper.xml ```xml <?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.example.dao.UserDao"> <select id="getUserByUsername" parameterType="String" resultType="com.example.entity.User"> SELECT * FROM users WHERE username = #{username} </select> <insert id="addUser" parameterType="com.example.entity.User"> INSERT INTO users (username, password, role) VALUES (#{username}, #{password}, #{role}) </insert> </mapper> ``` ### 5. Service 接口和实现类 #### NewsService.java ```java package com.example.service; import com.example.entity.News; import java.util.List; public interface NewsService { List<News> getAllNews(); void addNews(News news); } ``` #### NewsServiceImpl.java ```java package com.example.service.impl; import com.example.dao.NewsDao; import com.example.entity.News; import com.example.service.NewsService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import java.util.List; @Service public class NewsServiceImpl implements NewsService { @Autowired private NewsDao newsDao; @Override public List<News> getAllNews() { return newsDao.getAllNews(); } @Override public void addNews(News news) { newsDao.addNews(news); } } ``` #### UserService.java ```java package com.example.service; import com.example.entity.User; public interface UserService { User getUserByUsername(String username); void addUser(User user); } ``` #### UserServiceImpl.java ```java package com.example.service.impl; import com.example.dao.UserDao; import com.example.entity.User; import com.example.service.UserService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; @Service public class UserServiceImpl implements UserService { @Autowired private UserDao userDao; @Override public User getUserByUsername(String username) { return userDao.getUserByUsername(username); } @Override public void addUser(User user) { userDao.addUser(user); } } ``` ### 6. Controller 类 #### NewsController.java ```java package com.example.controller; import com.example.entity.News; import com.example.service.NewsService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PostMapping; import java.util.List; @Controller @RequestMapping("/news") public class NewsController { @Autowired private NewsService newsService; @GetMapping("/list") public String newsList(Model model) { List<News> newsList = newsService.getAllNews(); model.addAttribute("newsList", newsList); return "news/newsList"; } @GetMapping("/add") public String newsAddForm() { return "news/newsAdd"; } @PostMapping("/add") public String newsAdd(News news) { newsService.addNews(news); return "redirect:/news/list"; } } ``` #### UserController.java ```java package com.example.controller; import com.example.entity.User; import com.example.service.UserService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PostMapping; @Controller @RequestMapping("/user") public class UserController { @Autowired private UserService userService; @GetMapping("/login") public String loginForm() { return "user/login"; } @GetMapping("/register") public String registerForm() { return "user/register"; } @PostMapping("/register") public String register(User user) { userService.addUser(user); return "redirect:/user/login"; } } ``` ### 7. 配置文件 #### mybatis-config.xml ```xml <?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd"> <configuration> <environments default="development"> <environment id="development"> <transactionManager type="JDBC"/> <dataSource type="POOLED"> <property name="driver" value="com.mysql.cj.jdbc.Driver"/> <property name="url" value="jdbc:mysql://localhost:3306/news_management?useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC"/> <property name="username" value="root"/> <property name="password" value="password"/> </dataSource> </environment> </environments> <mappers> <mapper resource="mapper/NewsMapper.xml"/> <mapper resource="mapper/UserMapper.xml"/> </mappers> </configuration> ``` #### spring.xml ```xml <?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:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx" xsi:schemaLocation="http://www.springframework.org/schema/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/aop http://www.springframework.org/schema/aop/spring-aop.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd"> <context:component-scan base-package="com.example"/> <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"> <property name="configLocation" value="classpath:mybatis-config.xml"/> </bean> <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer"> <property name="basePackage" value="com.example.dao"/> </bean> </beans> ``` #### spring-mvc.xml ```xml <?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/schema/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"> <context:component-scan base-package="com.example.controller"/> <mvc:annotation-driven/> <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <property name="prefix" value="/WEB-INF/views/"/> <property name="suffix" value=".jsp"/> </bean> </beans> ``` #### web.xml ```xml <?xml version="1.0" encoding="UTF-8"?> <web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd" version="4.0"> <context-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:spring.xml</param-value> </context-param> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> <servlet> <servlet-name>spring-mvc</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>spring-mvc</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping> </web-app> ``` ### 8. JSP 页面示例 #### newsList.jsp ```jsp <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %> <!DOCTYPE html> <html> <head> <title>新闻列表</title> </head> <body> <h1>新闻列表</h1> <table border="1"> <tr> <th>新闻ID</th> <th>标题</th> <th>发布时间</th> </tr> <c:forEach items="${newsList}" var="news"> <tr> <td>${news.newsId}</td> <td>${news.title}</td> <td>${news.publishTime}</td> </tr> </c:forEach> </table> <a href="${pageContext.request.contextPath}/news/add">添加新闻</a> </body> </html> ``` #### newsAdd.jsp ```jsp <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!DOCTYPE html> <html> <head> <title>添加新闻</title> </head> <body> <h1>添加新闻</h1> <form action="${pageContext.request.contextPath}/news/add" method="post"> <label for="title">标题:</label> <input type="text" id="title" name="title" required><br> <label for="content">内容:</label> <textarea id="content" name="content" required></textarea><br> <label for="author">作者ID:</label> <input type="text" id="author" name="author" required><br> <label for="category">分类ID:
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值