创建一个简单的UserDao层
public class UserDaoImpl implements UserDao {
@Override
public void save() {
System.out.println("userDaoImpl save.....");
}
}
然后写个简单的Service层
public class UserServiceImpl implements UserService {
private UserDao userDao;
public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}
@Override
public void save() {
userDao.save();
}
}
applicationContext.xml中注入对象并配置组件扫描
<!--配置组件扫描-->
<context:component-scan base-package="com.uncleChen"/>
<bean id="userDao" class="com.uncleChen.dao.impl.UserDaoImpl"></bean>
<bean id="userService" class="com.uncleChen.service.impl.UserServiceImpl">
<property name="userDao" ref="userDao"></property>
</bean>
在Servlet中直接获取ApplicationContext然后获取Service对象再调用save方法
@WebServlet(name = "userServlet", value = "/userServlet")
public class UserServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
ApplicationContext app=new ClassPathXmlApplicationContext("applicationContext.xml");
UserService userService = app.getBean("userService", UserService.class);
userService.save();
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doGet(request, response);
}
}
在开启服务器之后,用户每访问一次Servlet就会创建一个ApplicationContext对象,为了方便,可以使用监听器在项目启动时就创建好ApplicationContext对象,再将该对象放入上下文,每次用户访问Servlet都会调用放入上下文那个ApplicationContext对象
配置全局初始化参数将Spring配置文件与监听器解耦
<!-- web全局初始化参数-->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>applicationContext.xml</param-value>
</context-param>
再写一个简单的监听器
@WebListener
public class ContextLoaderListener implements ServletContextListener {
@Override
public void contextInitialized(ServletContextEvent sce) {
ServletContext servletContext = sce.getServletContext();
String contextConfigLocation = servletContext.getInitParameter("contextConfigLocation");
ApplicationContext app=
new ClassPathXmlApplicationContext(contextConfigLocation);
//在上下文公共域中添加applicationContext对象便于Servlet层访问
servletContext.setAttribute("app",app);
//测试监听器
System.out.println("spring容器创建完毕");
}
@Override
public void contextDestroyed(ServletContextEvent sce) {
//do something...
}
}
此时修改Servlet内容为:
public class UserServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
ServletContext servletContext = request.getServletContext();
//获取监听器提前放入ServletContext中的ApplicationContext对象
ApplicationContext app = (ApplicationContext) servletContext.getAttribute("app");
UserService userService = app.getBean("userService", UserService.class);
userService.save();
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doGet(request, response);
}
}
目前看来,只有一个Servlet的时候直接把ServletContext域中ApplicationContext的名称(在这里叫"app")写进Servlet没什么问题,但是多个Servlet都可以访问同一个ApplicationContext时就要每一个Servlet都写一次名称(这里还叫"app")很麻烦,耦合也很高,所以还可以创建一个工具类,专门提供ApplicationContext对象
创建工具类WebApplicationContextUtils
传入上下文ServletContext对象,返回监听器提前放入ServletContext中的ApplicationContext对象
public class WebApplicationContextUtils {
public static ApplicationContext getWebApplicationContext(ServletContext servletContext){
return (ApplicationContext) servletContext.getAttribute("app");
}
}
此时Servlet可以写成:
public class UserServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
ServletContext servletContext = request.getServletContext();
ApplicationContext app = WebApplicationContextUtils.getWebApplicationContext(servletContext);
UserService userService = app.getBean("userService", UserService.class);
userService.save();
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doGet(request, response);
}
}
运行结果:
监听器正常工作
访问资源后:
正常调用save方法
Spring提供的工具类直接使用
依赖注入
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>5.0.5.RELEASE</version>
</dependency>
先要把自己写的监听器注解去掉,再在web.xml中配置
<!-- 配置监听器-->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
然后直接使用即可
import com.uncleChen.service.UserService;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.support.WebApplicationContextUtils;
import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.annotation.*;
import java.io.IOException;
/**
* @author uncleChen
* @version 1.0
* @date 2022/2/17 1:10
*/
@WebServlet(name = "userServlet", value = "/userServlet")
public class UserServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
ServletContext servletContext = request.getServletContext();
WebApplicationContext app = WebApplicationContextUtils.getWebApplicationContext(servletContext);
UserService userService = app.getBean("userService", UserService.class);
userService.save();
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doGet(request, response);
}
}