Spring与WEB环境集成

📅 2026/8/2 4:15:19 👁️ 阅读次数 📝 编程学习
Spring与WEB环境集成

1.生命周期对比(记住核心区别)

依赖范围 编译时 测试时 运行时 是否打进 jar/war 包 compile(默认) ✅ ✅ ✅ 是 test ❌ ✅ ❌ 否(仅测试时用,如 JUnit) runtime ❌ ✅ ✅ 是(如 JDBC 驱动) provided ✅ ✅ ❌ (容器提供) 否 #Idea 里面下载 SmartTomcat 插件。安装插件。 配置 VM OPtion: -Dfile.encoding=GBK 防止tomcat启动后,输出的中文乱码。 #windows8080端口被占用,杀进程; C:\Users\admin>netstat -ano |findstr :8080 TCP 0.0.0.0:8080 0.0.0.0:0 LISTENING 22180 TCP [::]:8080 [::]:0 LISTENING 22180 C:\Users\admin>taskkill /PID 22180 /F 成功: 已终止 PID 为 22180 的进程。

2.环境搭建

package com.ycl.dao; public interface UserDao { public void save(); } package com.ycl.dao.impl; import com.ycl.dao.UserDao; public class UserDaoImpl implements UserDao { public void save(){ System.out.println("save running..."); } } package com.ycl.service; public interface UserService { public void save(); } package com.ycl.service.impl; import com.ycl.dao.UserDao; import com.ycl.service.UserService; public class UserServiceImpl implements UserService { private UserDao userDao; public void setUserDao(UserDao userDao) { this.userDao = userDao; } @Override public void save() { userDao.save(); } } applicationContext.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" 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"> <!--加载外部配置文件properties--> <context:property-placeholder location="classpath:jdbc.properties"/> <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"> <property name="driverClass" value="${jdbc.driver}"></property> <property name="jdbcUrl" value="${jdbc.url}"></property> <property name="user" value="${jdbc.username}"></property> <property name="password" value="${jdbc.password}"></property> </bean> <!--配置组件扫描 扫面这个包及其子包 --> <context:component-scan base-package="com.ycl"></context:component-scan> <!--配置dao--> <bean id="userDao" class="com.ycl.dao.impl.UserDaoImpl"></bean> <!--配置service--> <bean id="userService" class="com.ycl.service.impl.UserServiceImpl"> <property name="userDao" ref="userDao"/> </bean> </beans> web.xml <?xml version="1.0" encoding="UTF-8"?> <web-app xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_1.xsd" version="3.1"> <servlet> <servlet-name>UserServlet</servlet-name> <servlet-class>com.ycl.web.UserServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>UserServlet</servlet-name> <url-pattern>/userServlet</url-pattern> </servlet-mapping> </web-app> package com.ycl.web; import com.ycl.service.UserService; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; public class UserServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { super.doGet(req, resp); ApplicationContext app = new ClassPathXmlApplicationContext("applicationContext.xml"); UserService userService = app.getBean(UserService.class);//只有一个时,可以使用.class; userService.save(); } } #由于这个代码要执行很多次,为了方便把 spring 的配置直接放入配置文件中。 ApplicationContext app = new ClassPathXmlApplicationContext("applicationContext.xml"); UserService userService = app.getBean(UserService.class);//只有一个时,可以使用.class; ApplicationContext应用上下文获取方式。 应用上下文对象是通过 new ClassPathXmlApplicationContext(spring配置文件)方式获取的,但是每次从 容器中获得 Bean 时都要编写 new ClassPathXmlApplicationContext(spring配置文件),这样的弊端是 配置文件加载多次,应用上下文创建创建多次。 我们希望应用上下文被创建一次就可以了。 上下文创建过程放入监听器的初始化方法中。 将创建好的对象放大最大域中。 在Web项目中,可以使用 ServletContextListener 监听WEB应用的启动,我们可以在web应用启动时,就 加载 Spring的配置文件,创建应用上下文对象 ApplicationContext,在将其存储到最大的域 servletContext域 中,这样就可以在任意位置从域中获得应用上下文 ApplicationContext 对象了。 #这个监听器封装 spring 上下文的创建,加载 web.xml 文件中配置的applicationContext.xml文件名称。 #同时给spring上下文起一个名称 "app" package com.ycl.listener; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import javax.servlet.ServletContext; import javax.servlet.ServletContextEvent; import javax.servlet.ServletContextListener; public class ContextLoaderListener implements ServletContextListener { @Override public void contextInitialized(ServletContextEvent sce) { ServletContext servletContext = sce.getServletContext(); //读取web.xml中的全局参数.获得xml文件。无论xml文件名称是否是 applicationContext.xml 都可以。 String contextConfigLocation = servletContext.getInitParameter("contextConfigLocation"); ApplicationContext app = new ClassPathXmlApplicationContext(contextConfigLocation); //将Spring的应用上下文对象存储到 ServletContext 域中。 servletContext.setAttribute("app",app); System.out.println("spring 容器创建完毕..."); } @Override public void contextDestroyed(ServletContextEvent sce) { } } #通过这个"app" 属性名称获得 spring servlet 上下文; package com.ycl.listener; import org.springframework.context.ApplicationContext; import javax.servlet.ServletContext; public class WebApplicationContextUtils { public static ApplicationContext getWebApplicationContext(ServletContext servletContext){ return (ApplicationContext) servletContext.getAttribute("app"); } } #用户WEB端,获取容器时不需要单独创建 ApplicationContext 上下文; #也不需要通过 "app" 属性名获得 ApplicationContext 上下文; 而是通过上面我们封装的方法获得上下文。 # WebApplicationContextUtils 类,ContextLoaderListener类 成为公共类,封装了spring容器的创建 #同时 "app" 不需要多处显示设置。 package com.ycl.web; import com.ycl.listener.WebApplicationContextUtils; import com.ycl.service.UserService; import org.springframework.context.ApplicationContext; import javax.servlet.ServletContext; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; public class UserServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { super.doGet(req, resp); //ApplicationContext app = new ClassPathXmlApplicationContext("applicationContext.xml"); //ServletContext servletContext = req.getServletContext(); 或者如下; ServletContext servletContext = this.getServletContext(); //ApplicationContext app = (ApplicationContext) servletContext.getAttribute("app"); ApplicationContext app = WebApplicationContextUtils.getWebApplicationContext(servletContext); UserService userService = app.getBean(UserService.class);//只有一个时,可以使用.class; userService.save(); } } web.xml <?xml version="1.0" encoding="UTF-8"?> <web-app xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_1.xsd" version="3.1"> <!--全局初始化参数,如果xml文件的名称叫别的,直接改这里就好,不用动代码--> <contxt-param> <param-name>contextConfigLocation</param-name> <param-value>applicationContext.xml</param-value> </contxt-param> <!--配置监听器--> <listener> <listener-class>com.ycl.listener.ContextLoaderListener</listener-class> </listener> <servlet> <servlet-name>UserServlet</servlet-name> <servlet-class>com.ycl.web.UserServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>UserServlet</servlet-name> <url-pattern>/userServlet</url-pattern> </servlet-mapping> </web-app> 1.将监听器ContextLoaderListener类放到 web.xml 中; 2.在监听器ContextLoaderListener类中创建Spring上下文环境。并在监听器中设置一个上下文名称。 3.WebApplicationContextUtils 通过上下文名称获取Spring创建的上下文。 4.UserServlet 用户类直接获取 ServletContext上下文。 这样将 applicationContext.xml 的配置文件名称提取到了 web.xml; 同时 "app" 容器上下文名称提取到 WebApplicationContextUtils 类中。所有其他的WEB类,实现上面均 不涉及上下文的创建和通过上下文名称获取上下文。 "app" 这个上下文名称和 ApplicationContext.xml 文件名称和具体的WEB实现类解除耦合。 package com.ycl.web; import com.ycl.listener.WebApplicationContextUtils; import com.ycl.service.UserService; import org.springframework.context.ApplicationContext; import javax.servlet.ServletContext; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; public class UserServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { super.doGet(req, resp); //ApplicationContext app = new ClassPathXmlApplicationContext("applicationContext.xml"); //ServletContext servletContext = req.getServletContext(); 或者如下; ServletContext servletContext = this.getServletContext(); //ApplicationContext app = (ApplicationContext) servletContext.getAttribute("app"); ApplicationContext app = WebApplicationContextUtils.getWebApplicationContext(servletContext); UserService userService = app.getBean(UserService.class);//只有一个时,可以使用.class; userService.save(); } }

上面手写的监听器: ContextLoaderListener 类,其实 Spring已经帮我们实现了。
Spring提供获取应用上下文的工具。
上面的分析不用手动实现,Spring 提供了一个监听器 ContextLoaderListener 就是对上述功能的封装,
该监听器加载 Spring配置文件,创建应用上下文对象,并存储到 ServletContext 域中,提供了一个
客户端工具 WebApplicationContextUtils 供使用者获得应用上下文对象。

所以我们需要做的只有两件事情:
(1)在 web.xml 中配置 ContextLoaderListener 监听器(导入 Spring-web坐标)
(2)使用 WebApplicationContextUtils 获得应用上下文对象 ApplicationContext;

http访问时报:405; HTTP状态 405 - 方法不允许 类型 状态报告 消息 此URL不支持Http方法GET 描述 请求行中接收的方法由源服务器知道,但目标资源不支持 #解决方法,注释如下方法; //super.doGet(req, resp); web.xml <?xml version="1.0" encoding="UTF-8"?> <web-app xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_1.xsd" version="3.1"> <!--全局初始化参数,如果xml文件的名称叫别的,直接改这里就好,不用动代码--> <context-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:applicationContext.xml</param-value> </context-param> <!--配置监听器--> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> <servlet> <servlet-name>UserServlet</servlet-name> <servlet-class>com.ycl.web.UserServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>UserServlet</servlet-name> <url-pattern>/userServlet</url-pattern> </servlet-mapping> </web-app> #获取上下文; package com.ycl.web; import com.ycl.service.UserService; import org.springframework.web.context.WebApplicationContext; import org.springframework.web.context.support.WebApplicationContextUtils; import javax.servlet.ServletContext; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; public class UserServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { super.doGet(req, resp); ServletContext servletContext = this.getServletContext(); WebApplicationContext app = WebApplicationContextUtils.getWebApplicationContext(servletContext); UserService userService = app.getBean(UserService.class);//只有一个时,可以使用.class; userService.save(); } } 总结: Spring 集成 web 环境步骤; (1)配置 ContextLoaderListener 监听器 (2)使用 WebApplicationContextUtils 获得应用上下文;