Day68 Spring TX (事務)和配置細節以及單例設計模式

神一樣的我發表於2018-05-10

Spring其他配置細節

Spring其他配置細節:
    Spring配置檔案流程:
        載入Schema(配置全域性自動注入)
            bean
            aop
            context
        配置註解掃描
        配置代理模式
        配置屬性配置檔案掃描
        配置資料庫源
            使用${鍵名}獲取屬性檔案的值
        配置工廠
        配置mapper掃描
            使用sqlSessionFactoryBeanName配置工廠注入
        配置其他bean
        配置切面
    細節:
        Spring配置自動注入:
            在bean標籤中使用autowire屬性
                default:屬性的預設值,表示預設使用全域性配置方式
                byName:根據屬性名進行自動注入,只要有bean的id和屬性名相同,則自動進行賦值。
                byType:根據屬性型別進行注入。如果bean的型別和屬性的型別一致,則自動注入。
                constructor:根據構造器的形參的型別進行注入。其實還是byType
                    注意:引數必須是引用型別的屬性。
                no:不使用自動注入。必須手動配置property
            在頂層元標籤beans中使用 default-autowire="方式"設定全域性預設注入方式
            注意:
                使用了全域性自動注入(byName),配置工廠時可以不用手動注入資料來源物件
                配置mapper掃描時。可以不再手動注入工廠了。前提是沒有使用JDBC屬性配置檔案。

        Spring配置資料來源檔案
            配置資料來源檔案掃描
                <context:property-placeholder location="classpath:db.properties"/>
            使用${鍵名}配置dataScource的屬性值
            <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
                <property name="driverClassName" value="${jdbc.driver}"></property>
                <property name="url" value="${jdbc.url}"></property>
                <property name="username" value="${jdbc.username}"></property>
                <property name="password" value="${jdbc.password}"></property>
                </bean>
        注意:
            使用了此種配置方式,mapper掃描的工廠配置必須使用sqlSessionFactoryBeanName屬性進行配置。

Spring TX事務

SpringTX事務學習:
    Spring配置流程
        載入Scheme
            IOC
            AOP
            掃描相關
            配置全域性自動注入
        配置屬性檔案掃描
        配置註解掃描
        配置代理模式
        配置資料來源
            獲取屬性檔案中的資料庫引數
        配置工廠
        配置mapper掃描
            使用SqlSessionFactoryBeanName配置
        配置切面
        配置其他bean(註解)
        配置事務
-------------------------------------------------------------
    程式設計式事務:
        事務管理程式碼由程式設計師自己編寫。
        比如: commit()  callback()
    宣告式事務:
        事務管理程式碼不用程式設計師自己編寫。
        程式只需要宣告哪些程式碼需要進行事務管理即可。
    Spring宣告式事務的配置:
        1 匯入jar包
        2 在Spring配置檔案中配置哪些程式碼需要進行事務管理
    事務配置的屬性講解:
        name屬性:配置新增事務的方法,支援萬用字元
            <tx:method name="ins*"/>
        propagation 屬性(事務的傳播行為)
        isolation(事務的隔離界級別)
    事務的配置方式:
        <!-- 配置事務管理bean -->
                <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"></bean>
            <!--配置事務管理的內容  -->  
                <!--配置要管理的方法  -->
                <tx:advice id="advice" transaction-manager="transactionManager">
                    <tx:attributes>
                        <tx:method name="ins*"/>
                        <tx:method name="up*"/>
                        <tx:method name="del*"/>
                        <tx:method name="sel*"/>
                    </tx:attributes>
                </tx:advice>
                <!--配置方法所在的功能程式碼  -->
                <aop:config>
                    <aop:pointcut expression="execution(* com.bjsxt.serviceImpl.*.*(..))" id="point"/>
                    <aop:advisor advice-ref="advice" pointcut-ref="point"/>
                </aop:config>


Spring註解

Spring註解:
    在配置檔案中宣告註解掃描
    @Component:相當於bean標籤配置。
    @Service:相當於@Component,一般寫在serviceImpl中(使用無參構造器建立物件)
    @Controller:相當於@Component寫在控制器上的。
    @Resource:按照屬性名或者屬性型別給物件進行注入(依賴注入) java  不需要寫屬性的get/set方法
    @Autowired:按照屬性型別給物件進行注入(依賴注入)      spring  不需要寫屬性的get/set方法
    @Value:給類的基本型別屬性註解賦值,需要屬性配置檔案,以及屬性檔案掃描
            @Value("${my.demo}")
            private String test;
    其他註解(註解配置AOP)

比較全面的Spring配置檔案

配置檔案applicationContext.xml格式:
    Spring配置流程
        載入Scheme
            IOC
            AOP
            掃描相關
            配置全域性自動注入
        配置屬性檔案掃描
        配置註解掃描
        配置代理模式
        配置資料來源
            獲取屬性檔案中的資料庫引數
        配置工廠
        配置mapper掃描
            使用SqlSessionFactoryBeanName配置
        配置切面
        配置其他bean(註解)
        配置事務

例子:

<?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:aop="http://www.springframework.org/schema/aop"
    xmlns:tx="http://www.springframework.org/schema/tx"
     xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="
        http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/tx
        http://www.springframework.org/schema/tx/spring-tx.xsd
        http://www.springframework.org/schema/aop
        http://www.springframework.org/schema/aop/spring-aop.xsd
         http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context.xsd
        "
            default-autowire="byName"
        >
        <!-- 設定註解掃描 -->
        <context:component-scan base-package="com.bjsxt.serviceImpl"></context:component-scan>
        <!--設定屬性檔案掃描  -->
        <context:property-placeholder location="classpath:db.properties"/>
        <!--設定代理模式  -->
        <aop:aspectj-autoproxy proxy-target-class="true"></aop:aspectj-autoproxy>
        <!--配置資料來源  -->
        <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
            <property name="driverClassName" value="${jdbc.driver}"></property>
            <property name="url" value="${jdbc.url}"></property>
            <property name="username" value="${jdbc.username}"></property>
            <property name="password" value="${jdbc.password}"></property>
        </bean>
        <!--配置工廠  -->
        <bean id="factory" class="org.mybatis.spring.SqlSessionFactoryBean"></bean>
        <!--配置mapper掃描  -->
        <bean id="mapper" class="org.mybatis.spring.mapper.MapperScannerConfigurer">
            <property name="basePackage" value="com.bjsxt.mapper"></property>
            <property name="sqlSessionFactroyBeanName" value="factory"></property>
        </bean>
        <!--配置切面  -->
                <!--配置切點bean  -->
                <!--配置通知bean  -->
                <!--織入形成切面  -->
        <!--配置事務  -->
            <!--配置事務bean  -->
            <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"></bean>
            <!--配置事務管理方法  -->
            <tx:advice id="advice" transaction-manager="transactionManager">
                <tx:attributes>
                    <tx:method name="ins*"/>
                    <tx:method name="up*"/>
                    <tx:method name="del*"/>
                    <tx:method name="sel*" read-only="true"/>                  ---只讀狀態加快查詢效率
                </tx:attributes>
            </tx:advice>
            <aop:config>
                <aop:pointcut expression="execution(* com.bjsxt.serviceImpl.*.*(..))" id="my"/>
                <aop:advisor advice-ref="advice" pointcut-ref="my"/>
            </aop:config>
        <!--配置其他bean  -->
</beans>

-------------------------------------------------------------------------------------------------------

db.properties:
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/mybatis
jdbc.username=root
jdbc.password=root


log4j.properties:

log4j.rootCategory=info



log4j.logger.com.bjsxt.mapper=debug, CONSOLE
log4j.logger.com.bjsxt.advice=debug, CONSOLE

log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender
log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout
log4j.appender.CONSOLE.layout.ConversionPattern=- %c-%d-%m%n


log4j.appender.LOGFILE=org.apache.log4j.FileAppender
log4j.appender.LOGFILE.File=D:\axis.log
log4j.appender.LOGFILE.Append=true
log4j.appender.LOGFILE.layout=org.apache.log4j.PatternLayout
log4j.appender.LOGFILE.layout.ConversionPattern=- %c-%d-%m%n
my.properties:
舉例:
my.sid=1
my.sname=zhangsan

web.xml:
<?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" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0">
     <!--配置Spring配置檔案路徑  -->
        <context-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath:applicationcontext.xml</param-value>
        </context-param>
     <!--配置監聽器  -->
        <listener>
            <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
        </listener>
</web-app>

Scope屬性以及單例設計模式

Scope:作用域
1.<bean>的屬性,
2.作用:控制物件有效範圍(單例,多例等)
3.<bean/>標籤對應的物件預設是單例的.
3.1 無論獲取多少次,都是同一個物件
4.scope可取值
4.1 singleton 預設值,單例
4.2 prototype 多例,每次獲取重新例項化
4.3 request 每次請求重新例項化
4.4 session 每個會話物件內,物件是單例的.
4.5 application 在application物件內是單例
4.6 global session spring推出的一個物件,依賴於spring-webmvc-portlet ,類似於session

單例設計模式:
1.作用: 在應用程式有保證最多隻能有一個例項.
2.好處:
2.1 提升執行效率.
2.2 實現資料共享. 案例:application物件
3.懶漢式
3.1 物件只有被呼叫時才去建立.
3.2 示例程式碼
public class SingleTon {
    //由於物件需要被靜態方法呼叫,把方法設定為static
    //由於物件是static,必須要設定訪問許可權修飾符為private ,如果是public可以直接呼叫物件,不執行訪問入口
    private static SingleTon singleton;
    /**
     * 方法名和類名相同
     * 無返回值.
     * 
     * 
     * 其他類不能例項化這個類物件
     * 
     * 對外提供訪問入口
     */
    private SingleTon(){}

    /**
     * 例項方法,例項方法必須通過物件呼叫
     * 
     * 設定方法為靜態方法
     * 
     * 
     * @return
     */
    public static SingleTon getInstance(){
        //新增邏輯如果例項化過,直接返回
        if(singleton==null){
            /*
             * 多執行緒訪問下,可能出現if同時成立的情況,新增鎖
             */
            synchronized (SingleTon.class) {
                //雙重驗證
                if(singleton==null){
                    singleton = new SingleTon();
                }
            }

        }
        return singleton;
    }
}
3.3 由於新增了鎖,所以導致效率低.
4.餓漢式
4.1 解決了懶漢式中多執行緒訪問可能出現同一個物件和效率低問題
public class SingleTon {
    //在類載入時進行例項化.
    private static SingleTon singleton=new SingleTon();
    private SingleTon(){}
    public static SingleTon getInstance(){
        return singleton;
    }
}

注意

標籤的使用:
  基本資料型別   name -  value
  引用資料型別   name -  ref

UserServlet如果建立的是UserServiceImpl  us=... 就必須修改代理模式為
修改代理模式原因:UserServlet建立的是實現類


使用註解配置屬性:註解不使用get/set方法,使用初始化賦值(構造器)。
使用註解配置以後,建立物件的時候,id為  類名首字母小寫。
一、自動注入
二、Spring中載入properties檔案


注意:
問題:
                如果配置了全域性自動注入default-autowire="byName",在使用
                屬性檔案給資料來源引數進行賦值時就會報錯,因為自動注入的級別是高於
                屬性檔案掃描的,也就屬性在沒有賦值之前就已經完成的自動注入.
            解決:
                在mapper掃描配置標籤中使用SqlSessionFactoryBeanName來進行配置factory注入.


小案例

需求:
這裡寫圖片描述
資料庫表:
根據實體類進行建立
js:1.9jQuery
匯入相關jar包:aopalliance.jar
asm-3.3.1.jar
aspectjweaver.jar
cglib-2.2.2.jar
commons-logging-1.1.1.jar
commons-logging-1.1.3.jar
javassist-3.17.1-GA.jar
log4j-1.2.17.jar
log4j-api-2.0-rc1.jar
log4j-core-2.0-rc1.jar
mybatis-3.2.7.jar
mybatis-spring-1.2.3.jar
mysql-connector-java-5.1.30.jar
slf4j-api-1.7.5.jar
slf4j-log4j12-1.7.5.jar
spring-aop-4.1.6.RELEASE.jar
spring-aspects-4.1.6.RELEASE.jar
spring-beans-4.1.6.RELEASE.jar
spring-context-4.1.6.RELEASE.jar
spring-core-4.1.6.RELEASE.jar
spring-expression-4.1.6.RELEASE.jar
spring-jdbc-4.1.6.RELEASE.jar
spring-tx-4.1.6.RELEASE.jar
spring-web-4.1.6.RELEASE.jar

src:
applicationContext.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:aop="http://www.springframework.org/schema/aop"
     xmlns:context="http://www.springframework.org/schema/context"
      xmlns:tx="http://www.springframework.org/schema/tx"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/aop
        http://www.springframework.org/schema/aop/spring-aop.xsd
        http://www.springframework.org/schema/tx
        http://www.springframework.org/schema/tx/spring-tx.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context.xsd
        "
        default-autowire="byName"
        >
        <!--配置註解掃描  -->
        <context:component-scan base-package="com.bjsxt.serviceImpl"></context:component-scan>
        <!--配置代理模式為cglib  -->
        <aop:aspectj-autoproxy proxy-target-class="true"></aop:aspectj-autoproxy>
        <!--資料來源配置檔案掃描  -->
        <context:property-placeholder location="classpath:db.properties"/>
        <!--配置資料來源  -->
        <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        <property name="driverClassName" value="${jdbc.driver}"></property>
        <property name="url" value="${jdbc.url}"></property>
        <property name="username" value="${jdbc.username}"></property>
        <property name="password" value="${jdbc.password}"></property>
        </bean>
        <!--配置工廠  -->
        <bean id="factory" class="org.mybatis.spring.SqlSessionFactoryBean"></bean>
        <!--配置mapper包掃描  -->
        <bean id="mapper" class="org.mybatis.spring.mapper.MapperScannerConfigurer">
        <property name="basePackage" value="com.bjsxt.mapper"></property>
        <property name="sqlSessionFactoryBeanName" value="factory"></property>
        </bean>
        <!--配置事務  -->
         <!--配置事務bean  -->
         <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"></bean>
         <!--配置事務管理辦法  -->
         <tx:advice id="advice" transaction-manager="transactionManager">
         <tx:attributes>
         <tx:method name="ins*"/>
         <tx:method name="up*"/>
         <tx:method name="del*"/>
         <tx:method name="sel*" read-only="true" />
         </tx:attributes>
         </tx:advice>
         <aop:config>
         <aop:pointcut expression="execution(* com.bjsxt.serviceImpl.*.*(..))" id="my"/>
         <aop:advisor advice-ref="advice" pointcut-ref="my"/>
         </aop:config>
         <!--配置切面  -->
            <!--配置切點bean  -->
            <!--配置通知bean  -->
            <!--織入形成切面  -->
         <!--配置其他bean  -->
        </beans>

db.properties:

jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/mybatis
jdbc.username=root
jdbc.password=root

com.bjsxt.mapper:
AccountMapper.java:

package com.bjsxt.mapper;

import org.apache.ibatis.annotations.Select;
import org.apache.ibatis.annotations.Update;

import com.bjsxt.pojo.Account;

public interface AccountMapper {
  //校驗賬戶和密碼
    @Select("select * from account where aid=#{0} and apwd=#{1}")
    Account getOutAccountInfo(int aid,String apwd);
  //校驗收款人
    @Select("select * from account where aid=#{0} and aname=#{1}")
    Account getInAccountInfo(int aid,String aname);
  //根據使用者賬戶查詢金額
    @Select("select * from account where aid=#{0}")
    Account getOutAccountMoney(int aid);
  //轉賬
    @Update("update account set amoney=amoney+#{1} where aid=#{0}")
    int transfer(int aid,double amoney);

}

com.bjsxt.pojo:
Account.java:

package com.bjsxt.pojo;

public class Account {
 private int aid;
 private String aname;
 private String apwd;
 private double amoney;
public Account() {
    super();
    // TODO Auto-generated constructor stub
}
public Account(int aid, String aname, String apwd, double amoney) {
    super();
    this.aid = aid;
    this.aname = aname;
    this.apwd = apwd;
    this.amoney = amoney;
}
public int getAid() {
    return aid;
}
public void setAid(int aid) {
    this.aid = aid;
}
public String getAname() {
    return aname;
}
public void setAname(String aname) {
    this.aname = aname;
}
public String getApwd() {
    return apwd;
}
public void setApwd(String apwd) {
    this.apwd = apwd;
}
public double getAmoney() {
    return amoney;
}
public void setAmoney(double amoney) {
    this.amoney = amoney;
}
@Override
public String toString() {
    return "Account [aid=" + aid + ", aname=" + aname + ", apwd=" + apwd + ", amoney=" + amoney + "]";
}
@Override
public int hashCode() {
    final int prime = 31;
    int result = 1;
    result = prime * result + aid;
    long temp;
    temp = Double.doubleToLongBits(amoney);
    result = prime * result + (int) (temp ^ (temp >>> 32));
    result = prime * result + ((aname == null) ? 0 : aname.hashCode());
    result = prime * result + ((apwd == null) ? 0 : apwd.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;
    Account other = (Account) obj;
    if (aid != other.aid)
        return false;
    if (Double.doubleToLongBits(amoney) != Double.doubleToLongBits(other.amoney))
        return false;
    if (aname == null) {
        if (other.aname != null)
            return false;
    } else if (!aname.equals(other.aname))
        return false;
    if (apwd == null) {
        if (other.apwd != null)
            return false;
    } else if (!apwd.equals(other.apwd))
        return false;
    return true;
}

}

com.bjsxt.service:
AccountService.java:

package com.bjsxt.service;

import org.apache.ibatis.annotations.Select;

import com.bjsxt.pojo.Account;

public interface AccountService {
      //校驗賬戶和密碼
        Account getOutAccountInfoService(int aid,String apwd);
      //校驗收款人
        Account getInAccountInfoService(int aid,String aname);
      //校驗金額
        Account getOutAccountMoney(int aid);
        //轉賬
        int transfer(int aid,int aid2,double amoney);
}

com.bjsxt.serviceImpl:
AccountServiceImpl.java:

package com.bjsxt.serviceImpl;

import javax.annotation.Resource;

import org.springframework.stereotype.Service;

import com.bjsxt.mapper.AccountMapper;
import com.bjsxt.pojo.Account;
import com.bjsxt.service.AccountService;
@Service
public class AccountServiceImpl implements AccountService{

    //宣告mapper介面屬性
    @Resource
    private AccountMapper accountMapper;
     //校驗賬號和密碼
    @Override
    public Account getOutAccountInfoService(int aid, String apwd) {
        return accountMapper.getOutAccountInfo(aid, apwd);
    }
    //校驗賬號和姓名
    @Override
    public Account getInAccountInfoService(int aid, String aname) {
        return accountMapper.getInAccountInfo(aid, aname);
    }
    //校驗金額
    @Override
    public Account getOutAccountMoney(int aid) {
        return accountMapper.getOutAccountMoney(aid);
    }
    //轉賬
    @Override
    public int transfer(int aid,int aid2, double amoney) {
        int i=accountMapper.transfer(aid, -amoney);
        i+=accountMapper.transfer(aid2, amoney);
        return i;
    }

}

com.bjsxt.servlet:
AccountServlet.java:

package com.bjsxt.servlet;

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.bjsxt.pojo.Account;
import com.bjsxt.serviceImpl.AccountServiceImpl;

/**
 * Servlet implementation class AccountServlet
 */
@WebServlet("/account")
public class AccountServlet extends HttpServlet {
    //宣告業務層物件
    private AccountServiceImpl asi;
    @Override
    public void init() throws ServletException {
            //獲取spring容器物件
          ApplicationContext ac=WebApplicationContextUtils.getWebApplicationContext(getServletContext());
           //獲取業務層物件
          asi=(AccountServiceImpl) ac.getBean("accountServiceImpl");
    }
    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //設定請求編碼格式
        req.setCharacterEncoding("utf-8");
        //設定響應編碼格式
        resp.setCharacterEncoding("utf-8");
        resp.setContentType("text/html;charset=utf-8");
        //獲取請求資料
        String oper=req.getParameter("oper");
       if("trans1".equals(oper)){
           trans1(req,resp);
       }else if("trans2".equals(oper)){
           trans2(req,resp);
       }else if("trans3".equals(oper)){
           trans3(req,resp);
       }
       else if("trans".equals(oper)){
           trans(req,resp);
       }else {
           System.out.println("AccountServlet.service(沒有找到對應的操作符)");
       }
    }
    //開始轉賬
    private void trans(HttpServletRequest req, HttpServletResponse resp) throws IOException {
        //獲取請求資料
        int aid=req.getParameter("aid")!=""?Integer.parseInt(req.getParameter("aid")):0;
        double amoney=req.getParameter("amoney")!=""?Double.parseDouble(req.getParameter("amoney")):0.0;
        int aid2=req.getParameter("aid2")!=""?Integer.parseInt(req.getParameter("aid2")):0;
        //處理資料
        int i=asi.transfer(aid, aid2, amoney);
        if(i==2){
            resp.sendRedirect("success.jsp");
        }else{
            resp.sendRedirect("fail.jsp");
        }

    }
    //校驗賬戶使用者名稱 收款人賬戶
    private void trans3(HttpServletRequest req, HttpServletResponse resp) throws IOException {
        //獲取請求資料
        int aid2=req.getParameter("aid2")!=""?Integer.parseInt(req.getParameter("aid2")):0;
        String aname=req.getParameter("aname");
        //處理請求資料
        Account a=asi.getInAccountInfoService(aid2, aname);
        //獲取轉賬人
        Account a2=(Account) req.getSession().getAttribute("account");
        if(a!=null&&a2.getAid()!=a.getAid()){
            resp.getWriter().write("true");
        }else{
            resp.getWriter().write("false");
        }

    }
    //校驗金額
    private void trans2(HttpServletRequest req, HttpServletResponse resp) throws IOException {

        //獲取請求資料
        double amoney=req.getParameter("amoney")!=""?Double.parseDouble(req.getParameter("amoney")):0.0;
        //處理請求資料
        Account a=(Account) req.getSession().getAttribute("account");
        int aid=a!=null?a.getAid():0;
        Account a2=asi.getOutAccountMoney(aid);
        double money=a2!=null?a2.getAmoney():0.0;
        if(amoney<=money){
            resp.getWriter().write("true");
        }else{
            resp.getWriter().write("false");
        }   
    }
    //校驗賬戶密碼
    private void trans1(HttpServletRequest req, HttpServletResponse resp) throws IOException {
        //獲取請求資料
        int aid=req.getParameter("aid")!=""?Integer.parseInt(req.getParameter("aid")):0;
        String apwd=req.getParameter("apwd");
        //處理請求資料
        Account account= asi.getOutAccountInfoService(aid, apwd);
        //響應處理結果
        if(account!=null){
            req.getSession().setAttribute("account", account);
            resp.getWriter().write("true");
        }else{
            resp.getWriter().write("false");
        }

    }

}

WebContent:
js:1.9
web.xml:

<?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" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0">
  <context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>classpath:applicationContext.xml</param-value>
  </context-param>
  <listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
  </listener>
</web-app>

trans.jsp:

<%@ page language="java" contentType="text/html; charset=utf-8"
    pageEncoding="utf-8"%>
<!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=utf-8">
<title>Insert title here</title>
<script type="text/javascript" src="js/j.js"></script>
<script type="text/javascript">
$(function(){
    $("#account").blur(function(){
        if($(this).val()==""||$(this).val()==null){
            $(this).next().html("請輸入賬號").css("color","red");

        }else{
            $(this).next().html("√").css("color","green");
        }

    })
    $("#account2").blur(function(){
        if($(this).val()==""||$(this).val()==null){
            $(this).next().html("請輸入賬號").css("color","red");

        }else{
            $(this).next().html("√").css("color","green");
        }

    })
    //校驗賬號密碼
    $("#pwd").blur(function(){
        var account=$("#account").val();
        var pwd=$(this).val();
        $.get("account",{oper:"trans1",aid:account,apwd:pwd},function(data){
            if("true"==data){
                $("#s1").html("√").css("color","green");
            }else{
                $("#s1").html("×").css("color","red");
            }
        })
    })
    //校驗金額
    $("#money").blur(function(){
        var money=$(this).val();
        $.get("account",{oper:"trans2",amoney:money},function(data){
            if("true"==data){
                $("#s2").html("√").css("color","green");
            }else{
                $("#s2").html("×").css("color","red");
            }
        })
    })
    //校驗收款人賬號
    $("#name").blur(function(){
        var account2=$("#account2").val();
        var name=$(this).val();
        $.get("account",{oper:"trans3",aid2:account2,aname:name},function(data){
            if("true"==data){
                $("#name").next().html("√").css("color","green");
            }else{
                $("#name").next().html("×").css("color","red");
            }   

        })

    })
    //校驗submit
    $("form").submit(function(){
        $("input[type=text]").trigger("blur");
        $("input[type=password]").trigger("blur");
        if($("span").css("color")=="rgb(255, 0, 0)"){
            return false;
        }else{
            return true;
        }
    })

})
</script>
</head>
<body>
<h3>轉賬頁面</h3>
<hr />
   <div>
   <form action="account"  method="get"  >
   <input type="hidden"  name="oper" value="trans"/>
    轉賬賬戶:<input type="text"  name="aid" value=""  id="account"/><span id="saccount"></span><br />
   密碼:<input type="password" name="apwd" value="" id="pwd" /><span id="s1"></span><br />
   金額: <input type="text"  name="amoney" value="" id="money"/><span id="s2"></span><br />
  收款賬號: <input type="text" name="aid2" value="" id="account2"/><span></span><br />
  收款人姓名  <input type="text" name="aname" value="" id="name"/><span></span><br />
  <input type="submit"  value="開始轉賬"   id="btn"/>
  </form>
     </div>
</body>
</html>

success.jsp:

<%@ page language="java" contentType="text/html; charset=utf-8"
    pageEncoding="utf-8"%>
<!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=utf-8">
<title>Insert title here</title>
<script type="text/javascript" src="js/j.js"></script>
<script type="text/javascript">

</script>
</head>
<body>
<span>轉賬成功</span>
</body>
</html>

fail.jsp:

<%@ page language="java" contentType="text/html; charset=utf-8"
    pageEncoding="utf-8"%>
<!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=utf-8">
<title>Insert title here</title>
</head>
<body>
  轉賬失敗,請檢查填寫的資訊是否正確
</body>
</html>

原始碼地址:
連結:https://pan.baidu.com/s/1P31bbwVcsvn9KT_gKnl2NQ 密碼:ee3d

容易出錯的地方

1、獲取前臺請求資料的時候注意:
如果請求資料為空,會報格式轉換異常,可以用三木運算子判斷進行對其賦值
//獲取請求資料
int aid=req.getParameter("aid")!=""?Integer.parseInt(req.getParameter("aid")):0;
2、如果轉賬頁面沒有輸入賬號,那麼在查詢金額的時候獲取session裡的賬戶ID會報空指標,可以這樣解決:
int aid=a!=null?a.getAid():0;
3、在form表單的submit校驗的時候,$("form"),雙引號裡面不應該加#。
4、不要忘了web.xml

小結

Spring其他配置細節
Spring TX事務
Spring註解
比較全面的Spring配置檔案
Scope屬性以及單例設計模式
注意
小案例

相關文章