Spring集成web环境
1、前期准备工作
-
我先准备下web的环境(Servlet)
-
导入Servlet依赖
-
<dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> <version>3.1.0</version> </dependency>
-
创建web
@WebServlet("/UserServlet")
public class UserServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 加载我们的配置文件
ApplicationContext app = new AnnotationConfigApplicationContext(SpringConfigurataion.class);
// 获取service层对象
UserService userService = app.getBean(UserService.class);
// 调用他的save方法
userService.save();
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doGet(request, response);
}
}
- 运行效果
2、ApplicationContext应用上下文获取方式
2.1、原始方法的弊端
-
我们刚刚创建了web环境下的servlet充当controller层,但是原始环境下,我们想要使用我们在spring容器中创建的对象,依旧需要加载配置文件和getBean()获取到我们想要的对象类型
-
前端发送过来的请求不止一个,如果有多个请求发送过来,那么我们对于配置类的加载就需要多次加载,异常的麻烦
-
我们依旧加载了ApplicationContext app = new AnnotationConfigApplicationContext(SpringConfigurataion.class);
-
和使用getBean()获取我们的UserService的对象
-
@Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // 加载我们的配置文件 ApplicationContext app = new AnnotationConfigApplicationContext(SpringConfigurataion.class); // 获取service层对象 UserService userService = app.getBean(UserService.class); // 调用他的save方法 userService.save(); }
2.2、解决办法–图解
3、自定义Context-Linstener(解决2.2中问题的实践环节)
3.1、创建我们的监听器类–监听ServletContext
- 需要实现ServletContextListener类,重写他的两个方法
public class ContexLoadListener implements ServletContextListener {
@Override
public void contextInitialized(ServletContextEvent servletContextEvent) {
}
@Override
public void contextDestroyed(ServletContextEvent servletContextEvent) {
}
}
3.2、方法简述
- contextInitialized:ServletContex被创建的时候调用,我们可以在这个方法内部创建我们的Spring应用上下文的对象(相当于加载我们的配置类或者配置文件)
- contextDestroyed:ServletContex对象销毁的时候调用,不讲,暂时没用
3.3、方法实践
- 在ServletContext对象创建的时候加载我们的配置类
- 创建完毕之后获取到ServletContex对象,并将我们Spring应用上下文的对象存储到其中(app存到ServletContex中)
public class ContexLoadListener implements ServletContextListener {
@Override
public void contextInitialized(ServletContextEvent servletContextEvent) {
// 初始化我们程序的配置,加载配置文件
ApplicationContext app = new AnnotationConfigApplicationContext(SpringConfigurataion.class);
// 对象创建完毕,为了能让其它层拿到,将其存储在域中(最大域:ServletContex域)
// 获取这个对象
ServletContext context = servletContextEvent.getServletContext();
//将其存储进域中
context.setAttribute("app",app);
}
@Override
public void contextDestroyed(ServletContextEvent servletContextEvent) {
}
}
3.4、配置到Tomcat服务器当中
-
打开我们的web.xml中
-
创建监听器类的全限定名放入其中
-
<listener> <!-- 将我们配置的监听器类的全限定名放在这里 --> <listener-class>com.waves.Listener.ContexLoadListener</listener-class> </listener>
3.5、重新配置web层并重新设置我们的方法
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 获取我们的ServletContex对象
ServletContext servletContext = request.getServletContext();
// 获取我们的上下文对象
ApplicationContext app = (ApplicationContext) servletContext.getAttribute("app");
// 获取service层对象
UserService userService = app.getBean(UserService.class);
// 调用他的save方法
userService.save();
}
3.4、代码优化(ApplicationContext app = (ApplicationContext) servletContext.getAttribute(“app”))
-
这行代码是耦合死的,如何解决?
-
创建一个工具类,这个工具类返回一个ApplicationContext对象,这样我们在web层启动配置类的时候就不需要记住那个**“app”**的前缀了
-
创建一个WebServletContextUtil
-
public class WebServletContextUtil { // 设置一个静态方法,该方法返回一个ApplicationContext对象 public static Object getApplicationContext(ServletContext context) { return context.getAttribute("app"); } }
-
重新改造下我们的web层代码
-
@Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // 获取我们的ServletContex对象 ServletContext servletContext = request.getServletContext(); // 调用我们的工具类--获取上下文对象 ApplicationContext app = (ApplicationContext) WebServletContextUtil.getApplicationContext(servletContext); // 获取service层对象 UserService userService = app.getBean(UserService.class); // 调用他的save方法 userService.save(); }