java web 分层之—5层架构

JSP 表现层---》Dispatch 分发请求--》Command 交互层---》service 业务逻辑层---》Dao 数据访问层---》数据库

上图为demo程序的总体结构,其中framework包下是“框架”程序,二次开发人员无须改动。 

表现层:index.jsp

<%@ 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配置:

<?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进行处理。

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交互层:

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.java

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层:

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  

  

原文地址:https://www.cnblogs.com/qukaicheng/p/7655437.html