Spring学习笔记-第七天:SpringWeb环境搭建:环境搭建/监听器获取上下文/优化;SpringMVC:概述/开发步骤和实现

一、Spring集成Web环境

1.基本三层环境的搭建

  1. 建立maven项目,配置好Dao层和Service的接口和实现

  2. 把Dao和Service层加入到Spring环境,可以使用xml配置或注解进行配置

  3. 配置数据源,可以xml文件中配置或注解配置,数据源可以用c3o0或druid等

  4. 配置web环境,web环境需要使用servlet组件,需要在pom.xml中设置坐标添加依赖,需要添加:

    1. 设置坐标
            <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <version>3.1.0</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>javax.servlet.jsp</groupId>
            <artifactId>javax.servlet.jsp-api</artifactId>
            <version>2.3.3</version>
            <scope>provided</scope>
        </dependency>
    
    1. 添加web层

      1. 添加web package
      2. 添加UserServlet,调用service,可以使用配置方式或getbean方式
      3. 在webapp中配置servlet和servlet映射
      
      <servlet>
      <servlet-name>UserServlet</servlet-name>
      <servlet-class>com.itheima.web.UserServlet</servlet-class>
      </servlet>
      <servlet-mapping>
      <servlet-name>UserServlet</servlet-name>
      <url-pattern>/userServlet</url-pattern>
      </servlet-mapping>
      
      

      4.配置Tomcat Server
      我之前idea没有引入过tomcat,所以需要配置环境:设置Configurations,添加Tomcat Server,设置之前下好的Tomcat路径,设置变量名,然后设置Deployment,设置成当前项目,配置完成
      5.测试
      之前我使用注解方式配置,试着写servlet,但出现了问题:输入localhost:8080/userServlet调用不了实现,出现405错误,之后写测试类发现功能正常,所以此时应该是注解依赖注入的过程中出现了问题,或不能在UserServlet类中注解@Autowired userService。
      具体情况和解决办法:

小总结

这集黑马六分钟的视频,从创建环境到最后成功运行花了将近两个小时,首先这次创建没有用它给的代码(其实是没找到资源。。)自己手动创建并部署了项目,并把原来他使用的set方法注入改成了注解方式,配置了Tomcat服务器并回顾了之前自己写的Java项目,发现以前写的确实太粗糙了,之后遇到了全注解配置后的servlet注入失败的问题,查阅了方法后基本都是一个思路:application方式获取bean对象。
在这个过程中遇到了不少bug,但也让我对Spring项目创建流程更熟悉了一点,收货颇丰。

2.用监听器优化ApplicationContext应用上下文获取方式

1.概述

使用ApplicationContext获取应用上下文存在弊端:若后期有很多个业务,有很多servlet组件,则每个业务中都需要应用上下文获取servlet,每次都得创建。
解决方法:创建和调用分开,用监听器,把

ApplicationContext app=new ClassPathXmlApplicationContext("applicationContext.xml");

设定成服务一启动就创建,创建好的对象放到最大的域当中(Application域/ServletContext域),则在web层任意serviet中都可以调用。
在Web项目中,可以使用ServletContextListener监听Web项目的启动,我们可以在Web应用启动时,就加载Spring的配置文件,创建应用上下文对象ApplicationContext,在将其存储到最大的域servletContext域中,就可以在任意位置中获得应用上下文ApplicationContext对象了

2.实现

  1. 创建一个新的package-listener,设置一个类-ContextLoaderListener,实现(implements)ServletContextListener
  2. ServletContextListener内部有两个方法:contextInitialized和contextDestroyed:上下文初始化的方法和上下文销毁的方法,继而在初始化方法中创建Application对象。
  3. 设定一个位置让web层拿到,将Spring的应用上下文对象存储到ServletContext域:通过给的servletContext调用getServlet方法,返回值设定setAttribute到ServletContext域
    public void contextInitialized(ServletContextEvent servletContextEvent) {
        ApplicationContext app=new ClassPathXmlApplicationContext("applicationContext.xml");
        //将Spring的应用上下文对象存储到ServletContext域
        ServletContext servletContext = servletContextEvent.getServletContext();
        servletContext.setAttribute("app",app);

    }
  1. 送到域中后,web层想调用域中的参数,获取ContextLoaderListener的类加载路径,然后在web.xml中配置监听器
    <listener>
        <listener-class>com.itheima.listener.ContextLoaderListener</listener-class>
    </listener>
  1. 在servlet中调用getServletContext()方法,获得servletContext。再调用getAttribute方法获得a参数;
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//        @Autowired
//        private UserService userService;
//        userService.save();
        ServletContext servletContext = this.getServletContext();
        ApplicationContext app = (ApplicationContext) servletContext.getAttribute("app");
        UserService userService=app.getBean(UserService.class);
        userService.save();
    }

3.进一步优化

当前监听器内部xml文件路径是写死的,可以进一步解耦,把它提取成配置文件,这里可以使用web.xml文件中的全局初始化参数

  • 首先在xml文件中配置
<!--    全局初始化参数-->
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>applicationContext.xml</param-value>
    </context-param>
  • 然后在监听器中通过getInitParameter()方法读取全局初始化参数
    public void contextInitialized(ServletContextEvent servletContextEvent) {

        ServletContext servletContext = servletContextEvent.getServletContext();
        //读取web.xml中的全局参数
        String contextConfigLocation = servletContext.getInitParameter("contextConfigLocation");
        ApplicationContext app=new ClassPathXmlApplicationContext(contextConfigLocation);
        //将Spring的应用上下文对象存储到ServletContext域
        servletContext.setAttribute("app",app);
        System.out.println("spring容器创建完毕...");
    }

进一步解耦:setAttribute中设定的app的名字也可以进行优化,把它具体的名字隐藏掉(项目传输过程中不直接传输字符串)可以创建一个工具类解决

  1. 创建工具类:WebApplicationContextUtils,返回名称
public class WebApplicationContextUtils {
    public static ApplicationContext getWebApplicationContext(ServletContext servletContext){
        return (ApplicationContext) servletContext.getAttribute("app");
    }
}

  1. 取名称的时候调用工具类中的函数,参数为前文中的servletContext
ServletContext servletContext = this.getServletContext();
       // ApplicationContext app = (ApplicationContext) servletContext.getAttribute("app");
        ApplicationContext app = WebApplicationContextUtils.getWebApplicationContext(servletContext);
        

Spring提供获取应用上下文的工具

前文中的监听类等其实不需要自己写,Spring提供了相应的封装:ContextLoaderListener——该监听器内部加载Spring配置文件,创建应用上下文对象,并存储在ServletContext域中,提供了一个客户端工具WebApplicationContextUtils供使用者获得应用上下文对象

我们要做的只有两件事:

  1. 在web.xml中配置ContextLoaderListener(导入Spring-web坐标)
    1. 导入坐标
    2. 配置监听器-不同的是,在告诉配置文件名称的时候,需要加classpath
  2. 使用WebApplicationContextUtils获取应用上下文对象ApplicationContext:使用方法和之前一样

在测试后,getbean出现空指针异常,发现是web.xml中监听器导错了...应该导入ContextLoaderListener,我打到ContextLoader就停了,。。

二、SpringMVC简介

1. SpringMVC概述

SpringMVC是一种基于Java的实现MVC设计模型的请求驱动类型的轻量级Web框架,属于SpringFrameWork的后续产品,已经融合在Spring Web Flow中
model view controller

2.SpringMVC开发的步骤

1.简略步骤

  1. 导入SpringMVC的jar包(坐标),得到前端控制器
  2. 配置DispathcerServlet
  3. 编写Controller,操作java bean和视图页面
  4. 将Controller使用注解配置到Spring容器中(@Controller-web层使用),配置业务方法的映射地址
  5. 配置组件扫描,用SpringMVC自带的,需要配置spring-mvc.xml文件
  6. 执行访问的测试

2.代码实现

  1. 导入spring-webmvc坐标
      <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>5.1.6.RELEASE</version>
        </dependency>
  1. 在web.xml中配置DispatchcerServlet
<!--    配置SpringMVC的前端控制器-->
    <servlet>
        <servlet-name>DispatcherServlet</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<!--        服务器加载时即运行-->
        <load-on-startup>1</load-on-startup>
        
    </servlet>
<!--    配置映射地址-->
    <servlet-mapping>
        <servlet-name>DispatcherServlet</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>
  1. 编写Controller和视图
  2. 配置Controller
@Controller
public class UserController {

    @RequestMapping("/quick")//请求映射,当访问到quick时,返回success.jsp
    public String save(){
        System.out.println("Controller save running...");
        return "success.jsp";
    }
}

  1. 配置context组件扫描,包扫描路径扫描controller
    <context:component-scan base-package="com.itheima.controller"/>

然后配置一个全局的初始化参数,告诉spring—mvc的配置文件地址
思路:springmvc是控制器用,所以在配置servlet时告诉配置文件位置

    <servlet>
        <servlet-name>DispatcherServlet</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启动失败,发现是dependance中没有加spring-core,注意这里要和spring-webmvc版本一致

3.小结

  1. url输入:localhost:8080/quick到Tomcat
    客户端发出请求
  2. Tomcat根据web.xml中的配置和缺省,找到servlet
    1. 接受额户端请求,解析请求资源地址
    2. 创建代表请求req对象
    3. 创建代表相应resp对象
    4. 调用目标资源
  3. Dispatcher根据映射地址找到对应的Controller
  4. Controller接受到请求后返回视图
  5. Tomcat获得resp中的内容,组装成http相应返回客户端
posted @ 2021-05-04 23:47  东风应笑我  阅读(129)  评论(0)    收藏  举报