zoukankan      html  css  js  c++  java
  • 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  
    

      

  • 相关阅读:
    Linux:DHCP服务配置
    调整 全局jvm 大小 tomcat 调整jvm大小
    Arts打卡第8周
    mysql 对返回的值是null进行判断和重新赋值
    从xml中返回的对象,和new 返回的对象时不同的。
    检查时异常和运行是异常 + 事务回滚 +隔离级别
    怎么在for循环中新建出不同的list
    mysql中查询某个字段重复的数据
    Arts打卡第7周
    将Excel文件导入到Navicat Premium中日期变为0000-00-00
  • 原文地址:https://www.cnblogs.com/qukaicheng/p/7655437.html
Copyright © 2011-2022 走看看