Spring與Web



在 Web 項目中使用 Spring 框架,首先要解決在 web 層(這里指 Servlet)中獲取到 Spring容器的問題。只要在 web 層獲取到了 Spring 容器,便可從容器中獲取到 Service 對象

一、Web項目中使用Spring

1. 新建一個Maven項目

此時選擇的就是maven-archetype-webapp

2. 使用之前的案例

還是使用Spring集成MyBatis那個案例的代碼,目錄如下

  1. service層、Dao層,domain全部代碼復制
  2. 配置文件applicationContext.xml、jdbc.properties,mybatis.xml,復制
  3. pom.xml、主要新增加入servlet,jsp依賴

這里還是直接把整個的pom.xml文件放在下面

<?xml version="1.0" encoding="UTF-8"?>

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>

  <groupId>com.md</groupId>
  <artifactId>10-spring-web</artifactId>
  <version>1.0-SNAPSHOT</version>
  <packaging>war</packaging>

  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <maven.compiler.source>1.8</maven.compiler.source>
    <maven.compiler.target>1.8</maven.compiler.target>
  </properties>

  <dependencies>

    <!-- 單元測試-->
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.11</version>
      <scope>test</scope>
    </dependency>

    <!--spring核心-->
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-context</artifactId>
      <version>5.2.5.RELEASE</version>
    </dependency>

    <!--spring事務用到的-->
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-tx</artifactId>
      <version>5.2.5.RELEASE</version>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-jdbc</artifactId>
      <version>5.2.5.RELEASE</version>
    </dependency>


    <!--mybatis的-->
    <dependency>
      <groupId>org.mybatis</groupId>
      <artifactId>mybatis</artifactId>
      <version>3.5.1</version>
    </dependency>

    <!--mybatis和spring集成的-->
    <dependency>
      <groupId>org.mybatis</groupId>
      <artifactId>mybatis-spring</artifactId>
      <version>1.3.1</version>
    </dependency>

    <!--mysql驅動-->
    <dependency>
      <groupId>mysql</groupId>
      <artifactId>mysql-connector-java</artifactId>
      <version>5.1.9</version>
    </dependency>


    <!--德魯伊,數據庫連接池-->
    <dependency>
      <groupId>com.alibaba</groupId>
      <artifactId>druid</artifactId>
      <version>1.1.12</version>
    </dependency>

    <!-- servlet依賴 -->
    <dependency>
      <groupId>javax.servlet</groupId>
      <artifactId>javax.servlet-api</artifactId>
      <version>3.1.0</version>
      <scope>provided</scope>
    </dependency>
    <!-- jsp依賴 -->
    <dependency>
      <groupId>javax.servlet.jsp</groupId>
      <artifactId>jsp-api</artifactId>
      <version>2.2.1-b03</version>
      <scope>provided</scope>
    </dependency>


    <!--為了使用監聽器對象,加入依賴-->
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-web</artifactId>
      <version>5.2.5.RELEASE</version>
    </dependency>


  </dependencies>

  <build>

    <!--目的是把src/main/java目錄中的xml文件包含到輸出結果中,也就是輸出到classes目錄中-->
    <resources>
      <resource>
        <directory>src/main/java</directory><!--所在的目錄-->
        <includes><!--包括目錄下的.properties,.xml 文件都會掃描到-->
          <include>**/*.properties</include>
          <include>**/*.xml</include>
        </includes>
        <filtering>false</filtering>
      </resource>
    </resources>



  </build>

</project>

3. 定義index頁面

<%--
  Created by IntelliJ IDEA.
  User: MD
  Date: 2020/8/11
  Time: 15:12
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
    <p>學生注冊</p>
    <form action="reg" method="post">
        <table>
            <tr>
                <td>id</td>
                <td><input type="text" name="id"></td>
            </tr>

            <tr>
                <td>姓名:</td>
                <td><input type="text" name="name"></td>
            </tr>
            <tr>
                <td>email:</td>
                <td><input type="text" name="email"></td>
            </tr>
            <tr>
                <td>年齡</td>
                <td><input type="text" name="age"></td>
            </tr>

            <tr>
                <td></td>
                <td><input type="submit" value="注冊"></td>
            </tr>
        </table>


    </form>
</body>
</html>

4. 定義RegisterServlet

在com.md下新建一個包controller,在下面創建RegisterServlet,繼承HttpServlet

package com.md.controller;

import com.md.domain.Student;
import com.md.service.StudentService;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.support.WebApplicationContextUtils;

import javax.servlet.ServletContext;
import javax.servlet.ServletContextListener;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * @author MD
 * @create 2020-08-11 15:22
 */
public class RegisterServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        request.setCharacterEncoding("UTF-8");

        String strId = request.getParameter("id");
        String strName = request.getParameter("name");
        String strEmail = request.getParameter("email");
        String strAge = request.getParameter("age");

        // 創建spring的容器對象
        String config = "spring.xml";
        ApplicationContext c = new ClassPathXmlApplicationContext(config);

        // 獲取service
        StudentService studentService = (StudentService) c.getBean("studentService");
        studentService.addStudent(new Student(Integer.parseInt(strId),
                                strName,strEmail,Integer.parseInt(strAge)));


        // 跳的另一個頁面
        request.getRequestDispatcher("/result.jsp").forward(request,response);

    }
}

5. 定義result頁面

<%--
  Created by IntelliJ IDEA.
  User: MD
  Date: 2020/8/11
  Time: 15:30
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>

注冊成功

</body>
</html>

6. web.xml 注冊 Servlet

<?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">

    <!--
	version="4.0"
	如果新建的這個版本低,不是4.0的,可以找之前寫的項目,把上面的信息粘貼過來就行
	-->

    <servlet>
        <servlet-name>RegisterServlet</servlet-name>
        <servlet-class>com.md.controller.RegisterServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>RegisterServlet</servlet-name>
        <url-pattern>/reg</url-pattern>
    </servlet-mapping>
    
</web-app>

此時和java web類似,配置Tomcat,啟動,然后運行

7. 運行結果分析

當表單提交,跳轉到 result.jsp 后,多刷新幾次頁面,查看后台輸出,發現每刷新一次頁面,就 new 出一個新的 Spring 容器。即,每提交一次請求,就會創建一個新的 Spring 容器

對於一個應用來說,只需要一個 Spring 容器即可。所以,將 Spring 容器的創建語句放在 Servlet 的 doGet()或 doPost()方法中是有問題的,需要改進

二、 使用 Spring 的器監聽器 ContextLoaderListener

對於 Web 應用來說,ServletContext 對象是唯一的,一個 Web 應用,只有一個ServletContext 對象,該對象是在 Web 應用裝載時初始化的。

若將 Spring 容器的創建時機,放在 ServletContext 初始化時,就可以保證 Spring 容器的創建只會執行一次,也就保證了Spring 容器在整個應用中的唯一性

當 Spring 容器創建好后,在整個應用的生命周期過程中,Spring 容器應該是隨時可以被訪問的。即,Spring 容器應具有全局性。而放入 ServletContext 對象的屬性,就具有應用的全局性。所以,將創建好的 Spring 容器,以屬性的形式放入到 ServletContext 的空間中,就保證了 Spring 容器的全局性

上述的這些工作,已經被封裝在了如下的 Spring 的 Jar 包的相關 API 中:spring-web-5.2.5.RELEASE

1. maven依賴pom.xml

<dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-web</artifactId>
      <version>5.2.5.RELEASE</version>
    </dependency>

2. 注冊監聽器 ContextLoaderListener

若 要 在 ServletContext 初 始 化 時 創 建 Spring 容 器 , 就 需 要 使 用 監 聽 器 接 口ServletContextListener 對 ServletContext 進行監聽。在 web.xml 中注冊該監聽器

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

3. 指定 Spring 配置文件的位置

<context-param>

ContextLoaderListener 在對 Spring 容器進行創建時,需要加載 Spring 配置文件。其默認的 Spring 配置文件位置與名稱為:WEB-INF/applicationContext.xml。

但一般會將該配置文件放置於項目的 classpath 下,即 src 下,所以需要在 web.xml 中對 Spring 配置文件的位置及名稱進行指定

此時為了和默認的不同,把applicationContext.xml重命名為spring.xml文件

<context-param>
        <!--  contextConfigLocation:表示配置文件的路徑 -->
        <param-name>contextConfigLocation</param-name>
        <!--自定義配置文件的路徑-->
        <param-value>classpath:spring.xml</param-value>
    </context-param>

此時web.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">


    <!--如果新建的這個版本低,可以找之前寫的項目,把上面的信息粘貼過來就行-->


    <servlet>
        <servlet-name>RegisterServlet</servlet-name>
        <servlet-class>com.md.controller.RegisterServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>RegisterServlet</servlet-name>
        <url-pattern>/reg</url-pattern>
    </servlet-mapping>
    
    
    <!-- 注冊監聽器
        監聽器被創建后或讀取這個/WEB-INF/applicationContext.xml這個文件
        為什么要讀取文件:
            因為監聽器中要創建ApplicationContext對象,需要加載配置文件
            /WEB-INF/applicationContext.xml就是監聽器默認讀取的spring配置文件路徑

        可以修改默認的文件位置

        配置監聽器:目的是創建容器對象,創建了容器對象,就能把spring.xml配置文件中的所有對象創建好
        用戶發起請求就可以直接使用對象了

        重點:下面的這段代碼和如何獲取對象
    -->


    <context-param>
        <!--  contextConfigLocation:表示配置文件的路徑 -->
        <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>
</web-app>

此時的目錄結構

4. 獲取Spring容器對象

1. 直接從 ServletContext 中獲取

        WebApplicationContext c = null;
        // 獲取ServletContext中的容器對象,創建好的容器對象
        String key = WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE;
        Object attr = getServletContext().getAttribute(key);
        if (attr != null){
            c = (WebApplicationContext) attr;
        }

2. 通過 WebApplicationContextUtils 獲取

// 使用框架中的方法獲取容器對象
        WebApplicationContext c = null;
        ServletContext sc = getServletContext();
        c = WebApplicationContextUtils.getRequiredWebApplicationContext(sc);

        System.out.println("容器對象的信息--------"+c);

以上兩種方式,無論使用哪種獲取容器對象,刷新 result頁面后,可看到代碼中使用的 Spring 容器均為同一個對象

此時RegisterServlet的全部代碼

package com.md.controller;

import com.md.domain.Student;
import com.md.service.StudentService;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.support.WebApplicationContextUtils;

import javax.servlet.ServletContext;
import javax.servlet.ServletContextListener;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * @author MD
 * @create 2020-08-11 15:22
 */
public class RegisterServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        request.setCharacterEncoding("UTF-8");

        String strId = request.getParameter("id");
        String strName = request.getParameter("name");
        String strEmail = request.getParameter("email");
        String strAge = request.getParameter("age");

        // 創建spring的容器對象
        //String config = "spring.xml";
        //ApplicationContext c = new ClassPathXmlApplicationContext(config);


        // 配置完成之后可以直接這么使用


//        WebApplicationContext c = null;
//        // 獲取ServletContext中的容器對象,創建好的容器對象
//        String key = WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE;
//        Object attr = getServletContext().getAttribute(key);
//        if (attr != null){
//            c = (WebApplicationContext) attr;
//        }


        // 使用框架中的方法獲取容器對象,推薦
        WebApplicationContext c = null;
        ServletContext sc = getServletContext();
        c = WebApplicationContextUtils.getRequiredWebApplicationContext(sc);
        
        // 直接縮短為一行
 //WebApplicationContext c = WebApplicationContextUtils.getRequiredWebApplicationContext(getServletContext());
        System.out.println("容器對象的信息--------"+c);




        // 獲取service
        StudentService studentService = (StudentService) c.getBean("studentService");
        studentService.addStudent(new Student(Integer.parseInt(strId),
                                strName,strEmail,Integer.parseInt(strAge)));


        // 跳的另一個頁面
        request.getRequestDispatcher("/result.jsp").forward(request,response);

    }
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM