使用spring 4.0 + maven 構建超簡單的web項目


一.需求

使用spring去管理web項目,是目前非常流行的一種思路,本文將介紹使用maven+spring 4.0.2 來構建一個簡單的web項目.

 

二.實現

1.新建一個maven項目,如下圖所示:

 

 

這里因為是構建web項目,所以,選擇的是webapp.

項目的架構圖:

 

 

2.在pom.xml中添加所依賴的jar包,如下所示:

<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/maven-v4_0_0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.amos</groupId>
    <artifactId>ssh_integrated</artifactId>
    <packaging>war</packaging>
    <version>0.0.1-SNAPSHOT</version>
    <name>ssh_integrated Maven Webapp</name>
    <url>http://maven.apache.org</url>
    <dependencies>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-web</artifactId>
            <version>4.0.2.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>3.8.1</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>4.0.2.RELEASE</version>
        </dependency>
    </dependencies>
    <build>
        <finalName>ssh_integrated_spring</finalName>
    </build>
</project>

 

3.新建一個接口com.amos.service.IHello.java,並實現接口.

package com.amos.service;

public interface IHello {
    
    public String sayHi();
    
}

com.amos.service.HelloImpl.java

package com.amos.service;

import java.util.Date;

public class HelloImpl implements IHello{
    private String msg;
    public void setMsg(String msg) {
        this.msg = msg;
    }
    
    public String sayHi() {
        
        return "當前時間:"+new Date()+" msg:"+msg;
    }
   
}

 

4.新建一個Servlet,並實現此Servlet

com.amos.web.HelloServlet

package com.amos.web;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.context.ApplicationContext;
import org.springframework.web.context.support.WebApplicationContextUtils;
import com.amos.service.IHello;
@WebServlet(name="HelloServlet",urlPatterns={"/hello"})
public class HelloServlet extends HttpServlet {
    private static final long serialVersionUID = 2801654413247618244L;
    private IHello hello;

    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        
        //方法1,使用傳統方式去加載beans.xml,每次請求時加載
        //ApplicationContext applicationContext = new ClassPathXmlApplicationContext("beans.xml");
        
        //方法2,使用監聽器的方式加載beans.xml,在一啟動的時候就加載監聽器,避免多次加載,提高效率
        //ApplicationContext applicationContext  = (ApplicationContext) this.getServletContext().getAttribute("SpringApplicationContext");
        
        //方法3,使用spring自帶的監聽器去加載beans.xml
        //ApplicationContext applicationContext  = (ApplicationContext) this.getServletContext().getAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE);
        //使用webapplicationcontextutils這個工具類可以很方便的獲取ApplicationContext,只需要傳入servletContext
        ApplicationContext applicationContext = WebApplicationContextUtils.getRequiredWebApplicationContext(this.getServletContext());
        
        hello = applicationContext.getBean(IHello.class);
        String sayHi = hello.sayHi();
        System.err.println("sayHi:" + sayHi);
        resp.setContentType("text/html;charset=utf-8");
        resp.getWriter().write("<h2>" + sayHi + "</h2>");
    }
}

注:這里要注意的是實現spring管理Bean的三種方式.

第一種:最傳統的方式,同時也是效率最低的一種,因為,每次發一個請求都要重新加載一次,而且對於不同的Servlet的要每個都去加載,會大大降低效率.

第二種:使用監聽器來實現加載beans.xml,每次項目啟動的時候加載一次就可以了.這樣大提高了效率.

com.amos.web.InitSpringFactoryListener.java

package com.amos.web;

import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class InitSpringFactoryListener implements ServletContextListener {
    public InitSpringFactoryListener() {
    }

    public void contextInitialized(ServletContextEvent arg0) {
        //這里將加載beans.xml加載到內存中,放到servletcontext中,名稱可以隨便取,這里取為SpringApplicationContext,
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("beans.xml");
        arg0.getServletContext().setAttribute("SpringApplicationContext", applicationContext);
    }
    public void contextDestroyed(ServletContextEvent arg0) {
    }
}

 

同時,web.xml中要定義一個listener屬性.

<!-- 自己去寫一個監聽器來實現加載beans.xml,進而啟動spring容器 -->
    <!--
    <listener>
        <listener-class>com.amos.web.InitSpringFactoryListener</listener-class> 
    </listener> -->

 

第三種:針對第二種方法,其實spring中已經封裝好了一種監聽器,人工去配置即可,原理和第二種方法一致.

 

只需要在web.xml中加入如下代碼即可.

<!-- 使用spring自帶的監聽器,其默認加載的是WEB-INF下的applicationContext.xml -->    
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>

但運行進會報如下錯誤:

org.springframework.beans.factory.BeanDefinitionStoreException: IOException parsing XML document from ServletContext resource [/WEB-INF/applicationContext.xml]; nested exception is java.io.FileNotFoundException: Could not open ServletContext resource [/WEB-INF/applicationContext.xml]
    at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.loadBeanDefinitions(XmlBeanDefinitionReader.java:343)
    at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.loadBeanDefinitions(XmlBeanDefinitionReader.java:303)
    at org.springframework.beans.factory.support.AbstractBeanDefinitionReader.loadBeanDefinitions(AbstractBeanDefinitionReader.java:180)
    at org.springframework.beans.factory.support.AbstractBeanDefinitionReader.loadBeanDefinitions(AbstractBeanDefinitionReader.java:216)
    at org.springframework.beans.factory.support.AbstractBeanDefinitionReader.loadBeanDefinitions(AbstractBeanDefinitionReader.java:187)
    at org.springframework.web.context.support.XmlWebApplicationContext.loadBeanDefinitions(XmlWebApplicationContext.java:125)
    at org.springframework.web.context.support.XmlWebApplicationContext.loadBeanDefinitions(XmlWebApplicationContext.java:94)
    at org.springframework.context.support.AbstractRefreshableApplicationContext.refreshBeanFactory(AbstractRefreshableApplicationContext.java:129)
    at org.springframework.context.support.AbstractApplicationContext.obtainFreshBeanFactory(AbstractApplicationContext.java:540)
    ........
    Caused by: java.io.FileNotFoundException: Could not open ServletContext resource [/WEB-INF/applicationContext.xml]
    at org.springframework.web.context.support.ServletContextResource.getInputStream(ServletContextResource.java:141)
    at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.loadBeanDefinitions(XmlBeanDefinitionReader.java:329)
    ... 22 more

說找不到applicationContext.xml文件,那么如何解決這個問題呢?

他說找不到,那就在WIB-INF目錄下建一個即可.

然后引入自定義的beans.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"
    xmlns:tx="http://www.springframework.org/schema/tx" xmlns:aop="http://www.springframework.org/schema/aop"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
               http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
               http://www.springframework.org/schema/context
               http://www.springframework.org/schema/context/spring-context-4.0.xsd
               http://www.springframework.org/schema/tx
               http://www.springframework.org/schema/tx/spring-tx-4.0.xsd
               http://www.springframework.org/schema/aop
               http://www.springframework.org/schema/aop/spring-aop-4.0.xsd
               ">
    <import resource="classpath:beans.xml"/>
</beans>         

這個時候問題解決.

這里HelloSerlvet中如何獲取對應的ApplicationContext呢?

//方法3,使用spring自帶的監聽器去加載beans.xml
        //ApplicationContext applicationContext  = (ApplicationContext) this.getServletContext().getAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE);
    

這個是需要查看源碼才能發現其屬性名稱,所以比較麻煩.這里還有一種較簡便的方法,如下所示:

//使用webapplicationcontextutils這個工具類可以很方便的獲取ApplicationContext,只需要傳入servletContext
        ApplicationContext applicationContext = WebApplicationContextUtils.getRequiredWebApplicationContext(this.getServletContext());
        

第三種方法,基本上配置完畢,但還會感覺很不爽,因為還要新建一個applicationContext.xml去專門import bean.xml,是相當討厭的.

其實還可以在web.xml中配置自定義的xml文件名稱,如下所示:

    <!-- 配置spring的加載文件路徑及文件名稱 -->
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:beans.xml</param-value>
    </context-param>

 

org.springframework.web.context.ContextLoaderListener中有這樣一段說明:

<p>Processes a {@link #CONFIG_LOCATION_PARAM "contextConfigLocation"}
* context-param and passes its value to the context instance, parsing it into
* potentially multiple file paths which can be separated by any number of
* commas and spaces, e.g. "WEB-INF/applicationContext1.xml,
* WEB-INF/applicationContext2.xml". Ant-style path patterns are supported as well,
* e.g. "WEB-INF/*Context.xml,WEB-INF/spring*.xml" or "WEB-INF/&#42;&#42;/*Context.xml".
* If not explicitly specified, the context implementation is supposed to use a
* default location (with XmlWebApplicationContext: "/WEB-INF/applicationContext.xml").
*

可以自定義spring默認加載的xml文件的名稱,可以以逗號和空格進行分隔,也可以使用Ant類型的去標記.xml如,WEB-INF/spring*.xml

否則默認的加載的就是applicationContext.xml.
可以在web.xml中進行配置其參數.

所以,最終的web.xml如下:

<!DOCTYPE web-app PUBLIC
 "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
 "http://java.sun.com/dtd/web-app_2_3.dtd" >
<web-app>
    <display-name>Archetype Created Web Application</display-name>
    <!-- 配置spring的加載文件路徑及文件名稱 -->
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:beans.xml</param-value>
    </context-param>

    <!-- 使用spring自帶的監聽器,其默認加載的是WEB-INF下的applicationContext.xml -->    
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>
    
    <!-- 自己去寫一個監聽器來實現加載beans.xml,進而啟動spring容器 -->
    <!--
    <listener>
        <listener-class>com.amos.web.InitSpringFactoryListener</listener-class> 
    </listener> -->
</web-app>

 

5.運行效果

6.本文源碼

 

https://github.com/amosli/ssh_integrated_spring

 

 


免責聲明!

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



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