java web 分層之—5層架構

JSP 表現層---》Dispatch 分發請求--》Command 交互層---》service 業務邏輯層---》Dao 數據訪問層---》數據庫javascript

上圖爲demo程序的整體結構,其中framework包下是「框架」程序,二次開發人員無須改動。 html

表現層:index.jspjava

<%@ page language="java" contentType="text/html; charset=GBK" pageEncoding="GBK"%>  
<html>  
<head>  
<meta http-equiv="Content-Type" content="text/html; charset=GBK">  
<title>Insert title here</title>  
  
<script type="text/javascript">  
  
function doSubmit() {  
  
var username = document.getElementById("username").value;  
var password = document.getElementById("password").value;  
  
if (username == "" || password == "") {  
//alert("用戶名和密碼不能爲空!");  
document.getElementById("tips").innerHTML="<font color='red'>用戶名和密碼不能爲空!</span>";  
} else {  
document.loginForm.submit();  
}  
}  
</script>  
</head>  
<body>  
<span id="tips"></span>  
<form name="loginForm" action="user.cmd.UserCommand.do?method=login" method="post">  
用戶名:  
<input type="text" id="username" name="username" >  
  
密碼:  
<input type="password" id="password" name="password" >  
  
<input type="button" value="提交" onclick="doSubmit()">  
</form>  
</body>  
</html>  

  web.xml配置:web

<?xml version="1.0" encoding="UTF-8"?>  
<web-app xmlns="http://java.sun.com/xml/ns/javaee"  
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"  
version="2.5">   
   <servlet>  
   <servlet-name>dispatch</servlet-name>  
   <servlet-class>tool.Dispatch</servlet-class>  
   </servlet>  
     
   <servlet-mapping>  
   <servlet-name>dispatch</servlet-name>  
   <url-pattern>*.do</url-pattern>  
   </servlet-mapping>  
</web-app>  

  分發器:Dispatch.java,攔截全部.do結尾的請求,並將請求轉發給相應的cmd進行處理。sql

package framework.dispatch;  
  
import java.io.IOException;  
import java.lang.reflect.InvocationTargetException;  
import java.lang.reflect.Method;  
import javax.servlet.ServletException;  
import javax.servlet.http.HttpServlet;  
import javax.servlet.http.HttpServletRequest;  
import javax.servlet.http.HttpServletResponse;  
import framework.context.CommandContext;  
import framework.factory.InstanceFactory;  
  
public class Dispatch extends HttpServlet {  
  
    private static final long serialVersionUID = 1L;  
  
    @Override  
    protected void service(HttpServletRequest req, HttpServletResponse resp)throws ServletException, IOException {  
  
        //設置編碼  
        req.setCharacterEncoding("GBK");  
  
        //解析請求的url  
        StringBuffer url = req.getRequestURL();  
  
        //http://localhost:8080/test4/UserCommand.do  
        int a = url.lastIndexOf("/");  
        int b = url.lastIndexOf(".do");  
  
        //獲取請求的cmd的類名(含包路徑)  
        String cmdName = url.substring(a + 1, b);//substring(begin(含),end(不含)),即[)  
  
        try {  
  
            //獲取請求的cmd的實例  
            Object cmdObj = InstanceFactory.getInstance(cmdName);  
              
            //設置Command上下文信息,放於線程變量中。  
            CommandContext.init(req, resp, getServletContext(), getServletConfig());  
              
            //獲取請求的方法名  
            String methodName = req.getParameter("method");  
              
            //執行請求的方法,cmd層的方法  
            Method realMehood = cmdObj.getClass().getMethod(methodName);  
            String forwardPath = realMehood.invoke(cmdObj).toString();  
  
            //執行完畢,進行頁面跳轉  
            if(forwardPath != null){              
                req.getRequestDispatcher(forwardPath).forward(req, resp);  
            }  
        } catch (IllegalAccessException e) {  
            e.printStackTrace();  
        } catch (SecurityException e) {  
            e.printStackTrace();  
        } catch (NoSuchMethodException e) {  
            e.printStackTrace();  
        } catch (IllegalArgumentException e) {  
            e.printStackTrace();  
        } catch (InvocationTargetException e) {  
            e.printStackTrace();  
        }   
    }  
}  

  CommandContext,以線程變量的方式存儲當前線程的request、response、servletcontext、servletconfig對象。數據庫

package framework.context;  
  
import java.util.HashMap;  
import java.util.Map;  
  
import javax.servlet.ServletConfig;  
import javax.servlet.ServletContext;  
import javax.servlet.http.HttpServletRequest;  
import javax.servlet.http.HttpServletResponse;  
  
public class CommandContext {  
  
    private static ThreadLocal<Map<String,Object>> threadLocal = new ThreadLocal<Map<String,Object>>();  
      
    private static final String HTTP_SERVLET_REQUEST = "1";  
    private static final String HTTP_SERVLET_RESPONSE = "2";  
    private static final String SERVLET_CONTEXT = "3";  
    private static final String SERVLET_CONFIG = "4";  
      
    /* 
     * 初始化線程局部變量 
     */  
    public static void init(HttpServletRequest req,HttpServletResponse resp,ServletContext context,ServletConfig config){  
        threadLocal.remove();  
        Map<String,Object> localMap = new HashMap<String, Object>();  
        localMap.put(HTTP_SERVLET_REQUEST, req);  
        localMap.put(HTTP_SERVLET_RESPONSE, resp);  
        localMap.put(SERVLET_CONTEXT, context);  
        localMap.put(SERVLET_CONFIG, config);  
        threadLocal.set(localMap);  
    }  
    /* 
     * 獲取request對象 
     */  
    public static HttpServletRequest getRequest(){  
        return (HttpServletRequest)threadLocal.get().get(HTTP_SERVLET_REQUEST);  
    }  
    /* 
     * 獲取response對象 
     */  
    public static HttpServletResponse getResponse(){  
        return (HttpServletResponse)threadLocal.get().get(HTTP_SERVLET_RESPONSE);  
    }  
    /* 
     * 獲取servletContext對象 
     */  
    public static ServletContext getServletContext(){  
        return (ServletContext)threadLocal.get().get(SERVLET_CONTEXT);  
    }  
    /* 
     * 獲取servletConfig對象 
     */  
    public static ServletConfig getServletConfig(){  
        return (ServletConfig)threadLocal.get().get(SERVLET_CONFIG);  
    }  
}  

  command交互層:api

package user.cmd;  
  
import framework.context.CommandContext;  
import framework.factory.InstanceFactory;  
import user.service.UserService;  
  
public class UserCommand {  
      
    UserService userService = InstanceFactory.getInstance(UserService.class.getName());  
      
    /* 
     * 執行登陸驗證 
     */  
    public String login(){  
          
        String username = CommandContext.getRequest().getParameter("username");  
        String password = CommandContext.getRequest().getParameter("password");  
          
        //調用service層  
        boolean isOk = userService.checkLogin(username, password);  
        if(isOk){  
            return "ok.jsp";  
        }  
        return "fail.jsp";  
    }  
}  

  service層:UserService.javaoracle

package user.service;  
  
import framework.db.TransactionManager;  
import framework.factory.InstanceFactory;  
import user.dao.UserDao;  
  
  
public class UserService {  
      
    UserDao dao = InstanceFactory.getInstance(UserDao.class.getName());  
  
    /* 
     * 執行登陸驗證 
     */  
    public boolean checkLogin(String username, String password) {  
  
        if (password == null) {  
            return false;  
        }  
        String pass = null;  
          
        //拿到事務管理器  
        TransactionManager tm = TransactionManager.getTransManager();  
        try {  
            //開啓事務  
            tm.beginTransaction();  
              
            pass = dao.getPassword(username);  
              
            //提交事務  
            tm.commitTransaction();  
        } catch (RuntimeException e) {  
            e.printStackTrace();  
            tm.rollbackTransaction();//出現異常則回滾事務  
        }  
        if (password.equals(pass)) {  
            return true;  
        } else {  
            return false;  
        }  
    }  
}  

  Dao層:app

package user.dao;  
  
import java.sql.Connection;  
import java.sql.PreparedStatement;  
import java.sql.ResultSet;  
import java.sql.SQLException;  
  
import framework.db.DBUtil;  
  
//--建立表 T_USERS  
//CREATE TABLE T_USERS(  
//    USERNAME VARCHAR2(10) NOT NULL,  
//    PASSWORD VARCHAR2(60) NOT NULL  
//);  
//--設置主鍵  
//ALTER TABLE T_USERS ADD CONSTRAINT T_USERS_PK PRIMARY KEY(USERNAME);  
  
public class UserDao {  
      
    /* 
     * 根據用戶名,查詢密碼 
     */  
    public String getPassword(String username){  
          
        String pass = null;  
        Connection conn = null;  
        PreparedStatement ps = null;  
        ResultSet set = null;  
      
        try{  
            conn = DBUtil.getCon();  
            ps = conn.prepareStatement("select password from t_users where username=?");  
            ps.setString(1, username);  
            set = ps.executeQuery();  
              
            if (set.next()){  
                pass = set.getString("PASSWORD");  
            }     
        } catch (SQLException e) {  
            throw new RuntimeException("根據用戶名查詢密碼出錯",e);  
        }finally{  
            DBUtil.close(set, ps, conn);  
        }  
        return pass;  
    }  
}  

  實例工廠類:框架

package framework.factory;  
  
import java.util.HashMap;  
import java.util.Map;  
/* 
 * 實例工廠類,用於統一管理cmd、service、dao的實例。 
 */  
public class InstanceFactory {  
  
    //建立一個對象池  
    private static Map<String,Object> objPool = new HashMap<String, Object>();  
      
    /* 
     * 根據類的包路徑名稱,返回該類的一個實例。 
     */  
    public static <T> T getInstance(String clazz){  
          
        T obj = null;  
        if(objPool.containsKey(clazz)){//若是對象池中已存在,則直接從對象池中獲取。  
            obj = (T)objPool.get(clazz);  
        }else{  
            try {  
                //若是對象池中不存在,則動態建立一個該類的實例,並將新建立的實例放入對象池。  
                obj =  (T)Class.forName(clazz).newInstance();  
                objPool.put(clazz, obj);  
            } catch (InstantiationException e) {  
                e.printStackTrace();  
            } catch (IllegalAccessException e) {  
                e.printStackTrace();  
            } catch (ClassNotFoundException e) {  
                e.printStackTrace();  
            }  
        }  
        return obj;  
    }  
}  

  TransactionManager 事務管理器

package framework.db;  
  
import java.sql.Connection;  
import java.sql.SQLException;  
  
public class TransactionManager {  
  
    private Connection con;  
    private TransactionManager(Connection con){  
        this.con = con;  
    }  
      
    /* 
     * 開啓事務 
     */  
    public void beginTransaction(){  
        try {  
            con.setAutoCommit(false);  
        } catch (SQLException e) {  
            throw new RuntimeException("開啓事務失敗!",e);  
        }  
    }  
    /* 
     * 提交事務 
     */  
    public void commitTransaction(){  
        try {  
            con.commit();  
        } catch (SQLException e) {  
            throw new RuntimeException("提交事務失敗!",e);  
        }finally{         
            closeConnection();  
            DBUtil.threadLocalCon.remove();//將數據庫鏈接從線程局部變量中卸載。  
            }  
    }  
    /* 
     * 回滾事務 
     */  
    public void rollbackTransaction(){  
        try {  
            con.rollback();  
        } catch (SQLException e) {  
            throw new RuntimeException("回滾事務失敗!",e);  
        }finally{  
            closeConnection();  
            DBUtil.threadLocalCon.remove();//將數據庫鏈接從線程局部變量中卸載。  
        }  
    }  
    /* 
     * 獲取事務管理器 
     */  
    public static TransactionManager getTransManager(){  
        return new TransactionManager(DBUtil.getCon());  
    }  
    /* 
     * 關閉數據庫鏈接,僅限事務管理器內部使用,故private 
     */  
    private void closeConnection(){  
        if(con != null){  
            try {  
                con.close();  
            } catch (SQLException e) {  
                e.printStackTrace();  
            }  
        }  
    }  
}  

   DBUtil ,用於獲取數據庫鏈接和關閉鏈接

package framework.db;  
  
import java.io.FileNotFoundException;  
import java.io.IOException;  
import java.io.InputStream;  
import java.sql.Connection;  
import java.sql.DriverManager;  
import java.sql.ResultSet;  
import java.sql.SQLException;  
import java.sql.Statement;  
import java.util.Properties;  
  
public class DBUtil {  
  
    private static String url = null;  
    private static String driver = null;  
    private static String username = null;  
    private static String password = null;  
      
    static{  
        Properties p = new Properties();//加載數據源配置文件  
        InputStream inputStream = null;  
        try {  
            inputStream = Thread.currentThread().getContextClassLoader().getResourceAsStream("dataSource.properties");  
            p.load(inputStream);  
            url = p.getProperty("url");  
            driver = p.getProperty("driver");  
            username = p.getProperty("username");  
            password = p.getProperty("password");  
        } catch (FileNotFoundException e) {  
            e.printStackTrace();  
        } catch (IOException e) {  
            e.printStackTrace();  
        }finally{  
            try {  
                inputStream.close();  
            } catch (IOException e) {  
                e.printStackTrace();  
            }  
        }  
    }  
    //線程局部變量  
    protected static ThreadLocal<Connection>  threadLocalCon = new ThreadLocal<Connection>();  
      
    /* 
     * 獲取數據庫鏈接 
     */  
    public static Connection getCon() {  
  
        Connection con = threadLocalCon.get();  
        try {  
            if (con == null || con.isClosed()) {  
                Class.forName(driver);  
                con = DriverManager.getConnection(url, username, password);  
                threadLocalCon.set(con);  
            }  
        } catch (ClassNotFoundException e) {  
            e.printStackTrace();  
        } catch (SQLException e) {  
            e.printStackTrace();  
        }  
        return con;  
    }  
      
    /* 
     * 關閉結果集 ResultSet 
     */  
    public static void closeResultSet(ResultSet rs){  
        if(rs != null){  
            try {  
                rs.close();  
            } catch (SQLException e) {  
                e.printStackTrace();  
            }  
        }  
    }  
    /* 
     * 關閉 句柄 
     */  
    public static void closeStatement(Statement st){  
        if(st != null){  
            try {  
                st.close();  
            } catch (SQLException e) {  
                e.printStackTrace();  
            }  
        }  
    }  
    /* 
     * 在事務中調用dao層方法時,會首先設置事務自動提交爲false,該場景下,關閉鏈接由事務管理器負責。 
     * 若是dao層方法沒有在事務中執行,則此時事務自動提交爲true,該場景下,由本方法負責關閉鏈接。 
     */  
    public static void closeConnectionIfAutoCommit(Connection con){  
        if(con != null){  
        try {  
            if(con.getAutoCommit()){          
                con.close();  
            }  
        } catch (SQLException e) {  
            e.printStackTrace();  
        }  
    }  
    }  
    /* 
     * 依次關閉ResultSet、Statement、Connection 
     */  
    public static void close(ResultSet rs,Statement st,Connection con){  
        closeResultSet(rs);  
        closeStatement(st);  
        closeConnectionIfAutoCommit(con);  
    }  
}  

  dataSource.properties配置文件

#Oracle DataSource  
url=jdbc:oracle:thin:@localhost:1521:loushang  
driver=oracle.jdbc.driver.OracleDriver  
username=apitest  
password=apitest  
相關文章
相關標籤/搜索