spring集成Mybatis3【由“單獨搭建Mybatis”到“Mybatis與Spring的整合/集成”】

在J2EE領域,Hibernate與Mybatis是大家常用的持久層框架,它們各有特點,在持久層框架中處於領導地位。

本文主要介紹Mybatis(對於較小型的系統,特別是報表較多的系統,個人偏向Mybatis),對於它,個人比較喜歡的是:

  • 使用簡單、方便;
  • 支持的XML動態SQL的編寫,方便瀏覽、修改,同時降低SQL與應用程序之間的耦合。

不喜歡的是:

  • 出現錯誤時,調試不太方便

本文主要介紹Mybatis的搭建,是學習Mybatis過程後整理的札記,其中包括“單獨搭建Mybaits”和常用的“Mybatis與Spring的整合”。

 

一、數據庫的準備

因爲Mybatis是持久層框架,毫無疑問,是需要操作數據庫的。所以,在搭建之前,我們需要先創建一個簡單的表。

create table T_USER_TEST_1407
(
  USERNAME VARCHAR2(255),
  PASSWORD VARCHAR2(255)
)

 

插入一些數據,以作查詢的測試。

insert into T_USER_TEST_1407 (USERNAME, PASSWORD)
values ('nick', 'Optimistic,Confident,Love - 1');

 

二、單獨搭建Mybaits

1)環境準備、版本說明

此工程使用JDK1.6 + mybatis-3.2.4 + Oracle11g。

新建一個Web工程,由於只構建Mybatis,只引用Mybatis和Oracle JDBC驅動包

  • mybatis-3.2.4.jar
  • ojdbc6.jar

 

2)程序的搭建

首先,我們將數據源等配置信息放在一個xml,讓Mybatis可以根據這個信息去連接數據庫、管理事務。

目前我們可只關注environments節點,此節點是用於配置數據源、事務管理的 。

其他的節點,如typeAliases、mappers,是用於註冊一些信息的,後面會陸續提到。

複製代碼
 1 <?xml version="1.0" encoding="UTF-8" ?>
 2 <!DOCTYPE configuration
 3   PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
 4   "http://mybatis.org/dtd/mybatis-3-config.dtd">
 5   
 6 <configuration>
 7 
 8     <!-- Register Alias -->
 9     <typeAliases>
10         <typeAlias alias="user" type="com.nicchagil.mybatisonly.bean.User" />
11     </typeAliases>
12 
13     <!-- Data Source -->
14     <environments default="development">
15         <environment id="development">
16             <transactionManager type="JDBC" />
17             <dataSource type="POOLED">
18                 <property name="driver" value="oracle.jdbc.driver.OracleDriver" />
19                 <property name="url" value="jdbc:oracle:thin:@xxx.xxx.xxx.xxx:xxxx:xxxxxx" />
20                 <property name="username" value="xxxx" />
21                 <property name="password" value="xxxx" />
22             </dataSource>
23         </environment>
24     </environments>
25     
26     <!-- Register Mapper -->
27     <mappers>
28         <!-- SQL Mapper -->
29         <mapper resource="com/nicchagil/mybatisonly/mapper/sqlxml/UserMapper.xml" />
30     </mappers>
31     
32 </configuration>
複製代碼

 

既然有了配置的xml,下一步就需要讓Mybatis加載它了。

  1. 首先以輸入流的形式加載xml
  2. 以“SqlSessionFactoryBuilder -> SqlSessionFactory -> SqlSession”的流程最後構建出SqlSession。
    • SqlSession,顧名思義,是一次會話,是應用程序與數據庫交互的會話,所以,其生命週期應在一次數據庫連接之間,當然,此次數據庫連接可以包含一次或多次數據庫操作。
    • SqlSessionFactory,顧名思義,是SqlSession的工廠類,用於產出SqlSession。我們知道,SqlSession主要用於數據庫操作,而數據庫操作又是貫穿於應用程序整個生命週期當中的,那麼,"產出SqlSession"這個動作也應當貫穿於應用程序整個生命週期當中,所以,SqlSessionFactory的生命週期一般爲應用程序的整個生命週期,一般爲單例/static的形式存在。
    • SqlSessionFactoryBuilder,由代碼可見,其主要作用是從配置文件中獲取配置信息,然後構建SqlSessionFactory,所以其生命週期可以是臨時的,局部的。
  3. 通過SqlSession獲取UserMapper接口,再調用該接口的數據操縱方法。
複製代碼
package com.nicchagil.mybatisonly;

import java.io.IOException;
import java.io.InputStream;

import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;

import com.nicchagil.mybatisonly.bean.User;
import com.nicchagil.mybatisonly.mapper.UserMapper;

public class Call {
    
    public static SqlSessionFactory sqlSessionFactory = null;

    public static void main(String[] args) throws IOException {
        
        // Query User
        /*
        kickStartMybatis();
        queryUser("nick");
        */
        
        // Inser User
        kickStartMybatis();
        insertUser("user004", "hello world.");
        
    }
    
    public static void kickStartMybatis() throws IOException {
        String resource = "com/nicchagil/mybatisonly/mybatis-config.xml";
        InputStream inputStream = Resources.getResourceAsStream(resource);
        sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
    }
    
    /**
     * Query User
     * @param username
     * @return
     */
    public static User queryUser(String username) {
        
        User user = null;
        SqlSession session = sqlSessionFactory.openSession();
        try {
            
            /* Un-recommended Method */
            /*
            user = (User)session.selectOne("com.nicchagil.mybatisonly.mapper.UserMapper.queryUser", username);
             */
            
            /* Recommended Method */
            UserMapper userMapper = session.getMapper(UserMapper.class);
            user = userMapper.queryUser(username);
            
            System.out.println("username - " + user.getUsername() + " , password - " + user.getPassword());
            
        } finally {
            session.close();
        }
        
        return user;
    }
    
    /**
     * Insert User
     * @param username
     * @param password
     */
    public static void insertUser(String username, String password) {
        
        SqlSession session = sqlSessionFactory.openSession();
        
        try {
            
            UserMapper userMapper = session.getMapper(UserMapper.class);
            
            User user = new User();
            user.setUsername(username);
            user.setPassword(password);
            
            userMapper.insertUser(user);
            
            // Flushes batch statements and commits database connection. 
            // Note that database connection will not be committed if no updates/deletes/inserts were called.
            session.commit();
            
            System.out.println("username - " + user.getUsername() + " , password - " + user.getPassword());
            
        } catch (Exception e) {
            session.rollback();
            e.printStackTrace();
            
            //TODO Print the exception logs
            //TODO Prompts fail to execute for user
            
        } finally {
            session.close();
        }
        
    }
    
    /**
     * Insert User
     * @param username
     * @param password
     */
    public static void insertUserBySQL(String username, String password) {
        
        SqlSession session = sqlSessionFactory.openSession();
        
        try {
            
            User user = new User();
            user.setUsername(username);
            user.setPassword(password);
            
            session.insert("com.nicchagil.mybatisonly.mapper.UserMapper.insertUser", user);
            
            // Flushes batch statements and commits database connection. 
            // Note that database connection will not be committed if no updates/deletes/inserts were called.
            session.commit();
            
        } catch (Exception e) {
            session.rollback();
            e.printStackTrace();
            
            //TODO Print the exception logs
            //TODO Prompts fail to execute for user
            
        } finally {
            session.close();
        }
        
    }

}
複製代碼

 

UserMapper是一個DAO的接口,是定義作哪些數據庫操作的。

複製代碼
1 package com.nicchagil.mybatisonly.mapper;
2 
3 import com.nicchagil.mybatisonly.bean.User;
4 
5 public interface UserMapper {
6     
7     public User queryUser(String username);
8 
9 }
複製代碼

 

UserMapper只是供調用的接口,那麼具體的實現邏輯在哪裏呢?

我們可見UserMaper.xml,它定義的SQL就是用於定義UserMapper接口的實現。我們需在mybatis-config.xml註冊UserMaper.xml,可見mybatis-config.xml的mappers節點

  • 我們可以看到id爲queryUser,與接口的方法名對應;
  • SQL我們很熟悉了,就是一個簡單的SQL,而#{username},就是接口方法的入參;
  • resultType爲"user",這個user是一個別名,具體對應com.nicchagil.mybatisonly.bean.User這個類,我們可以看到在mybatis-config.xml文件的typeAliases節點中已經註冊它們的映射關係。
複製代碼
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
  PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
  "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.nicchagil.mybatisonly.mapper.UserMapper">

    <select id="queryUser" resultType="user">
        select * from t_user_test_1407 t where t.username = #{username}
    </select>
    
    <insert id="insertUser" parameterType="user">
        INSERT INTO t_user_test_1407 T (T.USERNAME, T.PASSWORD) VALUES (#{username}, #{password})
    </insert>

</mapper>
複製代碼

 

而com.nicchagil.mybatisonly.bean.User是實體類,用於裝載數據。

複製代碼
 1 package com.nicchagil.mybatisonly.bean;
 2 
 3 public class User {
 4 
 5     private String username;
 6     private String password;
 7 
 8     public String getUsername() {
 9         return username;
10     }
11 
12     public void setUsername(String username) {
13         this.username = username;
14     }
15 
16     public String getPassword() {
17         return password;
18     }
19 
20     public void setPassword(String password) {
21         this.password = password;
22     }
23 
24     @Override
25     public int hashCode() {
26         final int prime = 31;
27         int result = 1;
28         result = prime * result
29                 + ((password == null) ? 0 : password.hashCode());
30         result = prime * result
31                 + ((username == null) ? 0 : username.hashCode());
32         return result;
33     }
34 
35     @Override
36     public boolean equals(Object obj) {
37         if (this == obj)
38             return true;
39         if (obj == null)
40             return false;
41         if (getClass() != obj.getClass())
42             return false;
43         User other = (User) obj;
44         if (password == null) {
45             if (other.password != null)
46                 return false;
47         } else if (!password.equals(other.password))
48             return false;
49         if (username == null) {
50             if (other.username != null)
51                 return false;
52         } else if (!username.equals(other.username))
53             return false;
54         return true;
55     }
56 
57 }
複製代碼

 

最後,我們運行Call.java,將能成功查詢、插入數據庫。我們可通過打印的信息和查詢數據庫,以查看是否成功查詢、插入數據。

 

3)事務說明

對於數據庫有寫操作的應用程序,一般來說,事務是不可或缺的一部分。因爲未使用其他框架,這裏使用編程式事務,即使用SqlSession.commit()和SqlSession.rollback()方法,可見Call.java

  • 由於本程序對事務有異常回滾的要求,所以,需要獲取非自動提交的SqlSession
  • 如程序執行正常,則最後執行session.commit()以提交事務。
    • session.commit()有個需注意的地方,參考其如下注釋,即如果當前會話中不涉及updates/deletes/insert等寫數動作則不提交事務。所以,如果要觸發Mybatis提交事務,就需執行明確的觸發動作,如“執行session.insert(...)方法”或“執行對應的SQL Mapper配置中的insert、update、delete等標籤”等操作。(本人曾嘗試在SQL Mapper配置中用select標籤包含INSERT的SQL,使用SqlSession.commit()後,執行正常,但沒有提交事務,可見並未觸發,所以,需規範使用標籤)。如需強制提交,可用SqlSession.commit(boolean)。

      Flushes batch statements and commits database connection. Note that database connection will not be committed if no updates/deletes/inserts were called. To force the commit call SqlSession.commit(boolean)

  • 如程序執行異常,則回滾事務,session.rollback()

 

單獨搭建Mybaits完畢!

 

二、 Mybatis與Spring的整合

一個項目中,單獨使用Mybatis的情況並不多;更多的情況下,我們需要將Mybatis與其他框架進行整合,以便更好地使用。比如Mybatis + Spring,就是一個流行的整合組合。

 

1)環境準備、版本說明

本次用Mybatis3 + Spring3進行整合。注意,並不包含MVC框架的配置,因爲本文的目的是學習Mybatis,所以儘量不引用其他框架,以避免影響代碼的理解。

需引入的類庫詳情如下:

複製代碼
<dependencies>
  
    <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>3.2.10.RELEASE</version>
    </dependency>
    
    <dependency>
        <groupId>org.springframework.webflow</groupId>
        <artifactId>spring-webflow</artifactId>
        <version>2.4.0.RELEASE</version>
    </dependency>
    
    <dependency>
        <groupId>org.springframework.data</groupId>
        <artifactId>spring-data-oracle</artifactId>
        <version>1.0.0.RELEASE</version>
    </dependency>
    
    <dependency>
      <groupId>org.mybatis</groupId>
      <artifactId>mybatis</artifactId>
      <version>3.2.4</version>
    </dependency>
    
    <dependency>
      <groupId>org.mybatis</groupId>
      <artifactId>mybatis-spring</artifactId>
      <version>1.2.2</version>
    </dependency>

  </dependencies>
複製代碼

 

2)程序的搭建

首先,我們在Spring中配置關於Mybatis數據源的信息。

這裏以applicationContext-mybatis.xml來體現,配置瞭如下信息:

  • 註冊數據源,常見的有JDBC或JNDI,根據具體情況擇一。
  • 註冊sqlSessionFactory
    • sqlSessionFactory是用來生產sqlSession以操作數據庫的,所以,需指定sqlSessionFactory所引用的數據源
    • 指定相應的SQL Mapper文件在哪裏。我們自命名“_mapper後綴的xml文件”,主要用來定義SQL;“_resultmap後綴的xml文件”,則主要用來定義DB字段與應用程序實體屬性的映射。
    • 指定相應的應用程序實體在哪裏,並自動註冊不包含package名的別名
  • 在哪些package下掃描Mapper接口,即DAO接口
複製代碼
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/beans 
    http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
    http://www.springframework.org/schema/context
    http://www.springframework.org/schema/context/spring-context-3.0.xsd">

    <!-- JDBC Data Source -->
    <!-- 
    <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource" >
        <property name="driverClassName" value="oracle.jdbc.driver.OracleDriver" />
        <property name="url"
            value="jdbc:oracle:thin:@hostname:port:sid" />
        <property name="username" value="username" />
        <property name="password" value="password" />
    </bean>
    -->
    
    <!-- JNDI Data Source -->
    <bean id="dataSource" class="org.springframework.jndi.JndiObjectFactoryBean">
        <property name="jndiName">
            <value>JNDI_TEST_DB</value>
        </property>
    </bean>

    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
        <property name="dataSource" ref="dataSource" />
        <property name="mapperLocations">
            <list>
                <value>classpath:com/nicchagil/mybatis3spring3intg/mapper/sqlxml/*_mapper.xml</value>
                <value>classpath:com/nicchagil/mybatis3spring3intg/bean/resultmapxml/*_resultmap.xml</value>
            </list>
        </property>
        <property name="typeAliasesPackage" value="com.nicchagil.mybatis3spring3intg.bean" />
    </bean>

    <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
        <property name="basePackage" value="com.nicchagil.mybatis3spring3intg.mapper" />
        <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory" />
    </bean>

</beans>
複製代碼

 

 

除了Mybatis的信息,還有一些Spring的信息需要配置:

  • 根據註解自動掃描並註冊bean
  • Spring的聲明式事務管理(用以替代上一章節的“編程式事務”)
  • 由於本程序沒有集成MVC框架,在Servlet是通過Spring編程式地獲得Spring管理的bean,所以這裏註冊一個Spring的工具類。(使用了MVC框架並將框架交由Spring IOC容器管理的,可忽視此點配置)
複製代碼
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:tx="http://www.springframework.org/schema/tx"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/beans 
    http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
    http://www.springframework.org/schema/context
    http://www.springframework.org/schema/context/spring-context-3.0.xsd
    http://www.springframework.org/schema/tx  
    http://www.springframework.org/schema/tx/spring-tx-3.0.xsd">

    <context:component-scan base-package="com.nicchagil.mybatis3spring3intg" />
    
    <!-- Transaction Support -->
    <tx:annotation-driven transaction-manager="transactionManager" />
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource" />
    </bean>
    
    <bean id="SpringContextUtil" class="com.nicchagil.util.SpringContextUtil"/>

</beans>
複製代碼

 

 

衆所周知,以上是Spring的配置文件,那麼我們需要告訴應用程序“這些配置文件在哪裏”,所以我們需要在web.xml中告訴應用程序。另外,此web.xml註冊了一個Servlet,用於接收頁面的請求。

複製代碼
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.5">
  <display-name>mybatis3spring3Intg</display-name>
  <welcome-file-list>
    <welcome-file>index.html</welcome-file>
  </welcome-file-list>
  <listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
  </listener>
  <context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>classpath*:config/applicationContext*.xml</param-value>
  </context-param>
  <servlet>
    <description></description>
    <display-name>UserServlet</display-name>
    <servlet-name>UserServlet</servlet-name>
    <servlet-class>com.nicchagil.mybatis3spring3intg.servlet.UserServlet</servlet-class>
  </servlet>
  <servlet-mapping>
    <servlet-name>UserServlet</servlet-name>
    <url-pattern>/UserServlet</url-pattern>
  </servlet-mapping>
</web-app>
複製代碼

 

我們還需要定義Mapper的接口,即DAO接口。此處的Mapper的接口,我們已經在applicationContext-mybatis.xml中註冊爲指定路徑下自動掃描

複製代碼
package com.nicchagil.mybatis3spring3intg.mapper;

import com.nicchagil.mybatis3spring3intg.bean.User;

public interface UserMapper {
    
    public User find(String username);
    
    public void save(User user);

}
複製代碼

 

而Mapper的實現是如何的呢?

Mybatis會幫我們實現,我們只需要通過user_mapper.xml文件告訴Mybatis對應的SQL,此處的mapper文件,已經在applicationContext-mybatis.xml中註冊爲指定路徑下自動掃描

複製代碼
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
  PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
  "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.nicchagil.mybatis3spring3intg.mapper.UserMapper">

    <select id="find" resultType="user" resultMap="userResultMap">
        select * from t_user_test_1407 t where t.username = #{username}
    </select>
    
    <insert id="save" parameterType="user">
        INSERT INTO t_user_test_1407 T (T.USERNAME, T.PASSWORD) VALUES (#{username}, #{password})
    </insert>

</mapper>
複製代碼

 

可以看到,Mapper和SQL配置文件中都引用到了實體類,我們也需要定義。此處的實體類,已經在applicationContext-mybatis.xml中註冊爲指定路徑下自動掃描

複製代碼
package com.nicchagil.mybatis3spring3intg.bean;

public class User {

    private String username;
    private String password;
    private String childhoodName;

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public String getChildhoodName() {
        return childhoodName;
    }

    public void setChildhoodName(String childhoodName) {
        this.childhoodName = childhoodName;
    }

    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result
                + ((childhoodName == null) ? 0 : childhoodName.hashCode());
        result = prime * result
                + ((password == null) ? 0 : password.hashCode());
        result = prime * result
                + ((username == null) ? 0 : username.hashCode());
        return result;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        User other = (User) obj;
        if (childhoodName == null) {
            if (other.childhoodName != null)
                return false;
        } else if (!childhoodName.equals(other.childhoodName))
            return false;
        if (password == null) {
            if (other.password != null)
                return false;
        } else if (!password.equals(other.password))
            return false;
        if (username == null) {
            if (other.username != null)
                return false;
        } else if (!username.equals(other.username))
            return false;
        return true;
    }

}
複製代碼

 

實體的屬性與DB的字段之間的映射/匹配,我們需要定義一下。此處的resultmap.xml文件已經在applicationContext-mybatis.xml中註冊爲指定路徑下自動掃描

複製代碼
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">

<mapper namespace="com.nicchagil.mybatis3spring3intg.mapper.UserMapper">
    <resultMap type="user" id="userResultMap">
        <result property="username" column="USERNAME" />
        <result property="password" column="PASSWORD" />
        <result property="childhoodName" column="USERNAME" />
    </resultMap>
</mapper>
複製代碼

 

完成了DAO,那麼接着寫Service。

首先一個Service的接口。

複製代碼
package com.nicchagil.mybatis3spring3intg.service;

import com.nicchagil.mybatis3spring3intg.bean.User;

public interface UserService {
    
    public User query(String username);
    
    public void save(User user);
    
    public void testTransaction(User user1, User user2);

}
複製代碼

 

Service的實現類如下,這裏只簡單地測試查詢、保存、事務是否能正常處理。

 

複製代碼
package com.nicchagil.mybatis3spring3intg.service.impl;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.nicchagil.mybatis3spring3intg.bean.User;
import com.nicchagil.mybatis3spring3intg.mapper.UserMapper;
import com.nicchagil.mybatis3spring3intg.service.UserService;

@Service
public class UserServiceImpl implements UserService {
    
    @Autowired
    private UserMapper mapper;
    
    @Override
    public User query(String username) {
        return mapper.find(username);
    }
    
    @Override
    public void save(User user) {
        mapper.save(user);
    }

    @Override
    @Transactional
    public void testTransaction(User user1, User user2) {
        mapper.save(user1);
        
        // Code a NullPointerException to test transaction setting
        String str = null;
        str.charAt(0);
        
        mapper.save(user2);
    }
    
}
複製代碼

 

由於沒有整合MVC框架,此處由一個Servlet(此Servlet已於web.xml中註冊)獲取頁面請求並調用Service,

那麼如何在Servlet中獲得Spring IOC管理下Service的bean呢?這裏藉助SpringContextUtil(implements ApplicationContextAware),此SpringContextUtil於以上提及的applicationContext.xml中註冊

複製代碼
package com.nicchagil.mybatis3spring3intg.servlet;

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.nicchagil.mybatis3spring3intg.bean.User;
import com.nicchagil.mybatis3spring3intg.service.UserService;
import com.nicchagil.util.SpringContextUtil;

/**
 * Servlet implementation class UserServlet
 */
public class UserServlet extends HttpServlet {
    private static final long serialVersionUID = 1L;
       
    /**
     * @see HttpServlet#HttpServlet()
     */
    public UserServlet() {
        super();
        // TODO Auto-generated constructor stub
    }

    /**
     * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
     */
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        this.doPost(request, response);
    }

    /**
     * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
     */
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        
        String action = request.getParameter("action");
        
        UserService service = (UserService)SpringContextUtil.getBean("userServiceImpl");
        
        if ("find".equals(action)) {
            User user = service.query(request.getParameter("username"));
            System.out.println(user.getUsername() + " - " + user.getPassword() + " - " + user.getChildhoodName());
            
        }
        
        if ("save".equals(action)) {
            User user = new User();
            user.setUsername(request.getParameter("username"));
            user.setPassword(request.getParameter("password"));
            
            service.save(user);
            System.out.println(user.getUsername() + " - " + user.getPassword());
            
        }
        
        if ("testTransaction".equals(action)) {
            User user1 = new User();
            user1.setUsername(request.getParameter("username"));
            user1.setPassword(request.getParameter("password"));
            
            User user2 = new User();
            user2.setUsername(request.getParameter("username") + " - Double");
            user2.setPassword(request.getParameter("password") + " - Double");
            
            service.testTransaction(user1, user2);
            System.out.println(user1.getUsername() + " - " + user1.getPassword());
            System.out.println(user2.getUsername() + " - " + user2.getPassword());
            
        }
        
    }

}
複製代碼

 

複製代碼
package com.nicchagil.util;

import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;

public class SpringContextUtil implements ApplicationContextAware {
    
    private static ApplicationContext applicationContext = null;

    @Override
    public void setApplicationContext(ApplicationContext ac)
            throws BeansException {
        applicationContext = ac;

    }

    public static ApplicationContext getApplicationContext() {
        return applicationContext;
    }
    
    public static Object getBean(String beanName) {
        return applicationContext.getBean(beanName);
    }
    
    public static boolean containsBean(String beanName) {
        return applicationContext.containsBean(beanName);
    }

}
複製代碼

 

 

幾乎大功告成。

這裏寫了些觸發測試的頁面,執行結果可通過“查看控制檯”或“查詢數據庫”獲得。哈哈!~~

導航頁

複製代碼
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Insert title here</title>
</head>
<body>

<a href="find.html">find</a>
<br/>
<a href="save.html">save</a>
<br/>
<a href="testTransaction.html">testTransaction</a>

</body>
</html>
複製代碼

 

輸入username查詢記錄的觸發頁面

複製代碼
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Insert title here</title>
</head>
<body>

    <form action="UserServlet">
        <input type="hidden" name="action" value="find">
        <input type="text" name="username">
        <input type="submit">
    </form>

</body>
</html>
複製代碼

 

保存頁面

複製代碼
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Insert title here</title>
</head>
<body>
<body>

    <form action="UserServlet">
        <input type="hidden" name="action" value="save">
        <input type="text" name="username"> 
        <input type="password" name="password"> 
        <input type="submit">
    </form>

</body>

</body>
</html>
複製代碼

 

測試事務的觸發頁面

複製代碼
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Insert title here</title>
</head>
<body>
<body>

    <form action="UserServlet">
        <input type="hidden" name="action" value="testTransaction">
        <input type="text" name="username"> 
        <input type="password" name="password"> 
        <input type="submit">
    </form>

</body>

</body>
</html>
複製代碼
轉載自:http://www.cnblogs.com/nick-huang/p/3838326.html
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章