• MVC案例之通过配置切换底层存储源(面向接口)


    1.深入理解面向接口编程:

                    在类中调用接口的方法,而不必关心具体的实现。这将有利于代码的解耦。使程序有更好的可移植性

                    和可扩展性

    动态修改 Customer 的存储方式:通过修改类路径下的 switch.properties 文件的方式来实现

    switch.properties

    ①. CustomerServlet 中不能在通过 private CustomerDAO customerDAO =

                                                                    new CustomerDAOXMLImpl(); 的方式来写死实现类

    ②. 需要通过一个类的一个方法来获取具体的实现类的对象

    2.实现步骤

    当前 WEB 应用才启动的时候,InitServlet 被创建,并由 Servlet 容器调用其 init() 方法:

    读取类路径下的 switch.properties 文件

    获取 switch.properties 的 type 属性值

    赋给了 CustomerDAOFactory 的 type 属性值

    InitServlet

    package com.aff.mvcapp.servlet;
    import java.io.IOException;
    import java.io.InputStream;
    import java.util.Properties;
    import javax.servlet.ServletException;
    import javax.servlet.annotation.WebServlet;
    import javax.servlet.http.HttpServlet;
    import com.aff.mvcapp.dao.factory.CustomerDAOFactory;
    
    @WebServlet("/initServlet")
    public class InitServlet extends HttpServlet {
        private static final long serialVersionUID = 1L;
    
        @Override
        public void init() throws ServletException {
            CustomerDAOFactory.getInstance().setType("jdbc");
            InputStream is = getServletContext().getResourceAsStream("/WEB-INF/classes/switch.properties");
        Properties properties = new Properties();
    try {
            properties.load(is);
            String type = properties.getProperty("type");
            CustomerDAOFactory.getInstance().setType(type);
        } catch (IOException e) {
            e.printStackTrace();
        }
        }
    }

    web.xml

    <?xml version="1.0" encoding="UTF-8"?>
    <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" version="3.1">
      <servlet>
        <servlet-name>CustomerServlet</servlet-name>
        <servlet-class>com.aff.mvcapp.servlet.CustomerServlet</servlet-class>
      </servlet>
      <servlet-mapping>
        <servlet-name>CustomerServlet</servlet-name>
        <url-pattern>*.do</url-pattern>
      </servlet-mapping>
      
      <servlet>
      <servlet-name>InitServlet</servlet-name>
      <servlet-class>com.aff.mvcapp.servlet.InitServlet</servlet-class>
      <load-on-startup>1</load-on-startup>
      </servlet>
    </web-app>

       创建 CustomerServlet 时,为 customerDAO 属性赋值是通过 CustomerDAOFactory 的

       getCustomerDAO() 方法完成的 。

       此时的 type 已经在 InitServlet 中被赋值了。

    CustomerServlet 
    package com.aff.mvcapp.servlet;
    import java.io.IOException;
    import java.lang.reflect.Method;
    import java.util.List;
    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 com.aff.mvcapp.dao.CriteriaCustomer;
    import com.aff.mvcapp.dao.CustomerDAO;
    import com.aff.mvcapp.dao.factory.CustomerDAOFactory;
    import com.aff.mvcapp.domian.Customer;
    
    @WebServlet("/customerServlet")
    public class CustomerServlet extends HttpServlet {
        private CustomerDAO customerDAO = CustomerDAOFactory.getInstance().getCustomerDAO();
        //private CustomerDAO customerDAO = new CustomerDAOImpl();
    
        private static final long serialVersionUID = 1L;
        
        protected void doGet(HttpServletRequest request, HttpServletResponse response)
                throws ServletException, IOException {
            doPost(request, response);
        }
    
        protected void doPost(HttpServletRequest request, HttpServletResponse response)
                throws ServletException, IOException {
            // 1. 获取ServletPath: /edit.do 或 addCustomer.do
            String servletPath = request.getServletPath();
            // 2.去除 / 和 .do 得到类似于 edit 或 addCustomer 这样的字符串
            String methodName = servletPath.substring(1);
            methodName = methodName.substring(0, methodName.length() - 3);
    
            try {
                // 3.利用反射获取 methodName 对应的方法
                Method method = getClass().getDeclaredMethod(methodName, HttpServletRequest.class,
                        HttpServletResponse.class);
                // 4.利用反射调用对应的方法
                method.invoke(this, request, response);
            } catch (Exception e) {
                // e.printStackTrace();
                // 可以有一些响应
                response.sendRedirect("error.jsp");
            }
        }
    
        private void addCustomer(HttpServletRequest request, HttpServletResponse response)
                throws ServletException, IOException {
            // 1.获取表单参数:name address phone
            String name = request.getParameter("name");
            String address = request.getParameter("address");
            String phone = request.getParameter("phone");
    
            // 2.检验 name 是否被占用
            // 2.1调用CustomerDAO的getCountWithName(String name) 获取 name 在数据库中是否存在
            long count = customerDAO.getCountWithName(name);
            // 2.2若返回值大于0,则响应 newcustomer.jsp 页面, 通过转发的方式响应newcustomer.jsp
            if (count > 0) {
                // 2.2.1要求页面显示一个错误消息: 用户名 name已经被占用,请重新选择,
                // 在request中放入一个属性message :用户名 name 已经被占用,请重新选择!
                // 在页面通过request.getAttribute("message")的方式显示
                request.setAttribute("message", "用户名 " + name + "已经被占用,请重新选择");
    
                // 2.2.2 newcustomer.jsp 的表单可以回显
                // 通过value="<%=request.getParameter("name") == null ? "" :
                // request.getParameter("name") %>"进行回显
    
                // 2.2.3结束方法:return
                request.getRequestDispatcher("/newcustomer.jsp").forward(request, response);
                return;
            }
            // 3.若验证通过,把表单参数封装为一个Customer 对象 customer
            Customer customer = new Customer(name, address, phone);
    
            // 4.调用CustomerDAO的 save(Customer customer) 执行保存操作
            customerDAO.save(customer);
    
            // 5.重定向的 success.jsp 页面:使用重定向可以避免表单的重复提交问题
            response.sendRedirect("success.jsp");
    
        }
    
        private void edit(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            String forwardPath = "/error.jsp";// 初始值
            // 1.获取请求参数 id
            String idStr = request.getParameter("id");
            // 2.调用CustomerDAO 的 customerDAO.get(id) 获取 id 对应的Customer 对象customer
            try {
                Customer customer = customerDAO.get(Integer.parseInt(idStr));
                if (customer != null) {// 当customer为null是转到 error.jsp
                    forwardPath = "/updatecustomer.jsp";
                    // 3.将customer放入request 中
                    request.setAttribute("customer", customer);
                }
            } catch (Exception e) {
            }
            // 4.响应updatecustomer.jsp 页面: 转发
            request.getRequestDispatcher(forwardPath).forward(request, response);
    
        }
    
        private void update(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            // 1.获取表单参数:id,name,addres, phone, oldName
            String id = request.getParameter("id");
            String name = request.getParameter("name");
            String address = request.getParameter("address");
            String phone = request.getParameter("phone");
            String oldName = request.getParameter("oldName");
    
            // 2.检查name是否被占用
            // 2.比较name和oldName 是否相同,若相同说明 name可用
            // 2.1若不相同, 则调用CustomerDAO 的 getCountWithName(String name) 获取 name在数据库中是否存在
            if (!oldName.equalsIgnoreCase(name)) {
                long count = customerDAO.getCountWithName(name);
                if (count > 0) {
                    // 2.2若返回值大于0,则响应 updatecustomer.jsp 页面,
                    // 通过转发的方式响应updatecustomer.jsp
                    // 2.2.1要求页面显示一个错误消息: 用户名 name已经被占用,请重新选择,
                    // 在request中放入一个属性message :用户名 name 已经被占用,请重新选择!
                    // 在页面通过request.getAttribute("message")的方式显示
                    request.setAttribute("message", "用户名" + name + "已经被占用,请重新选择!");
    
                    // 2.2.2 updatecustomer.jsp 的表单可以回显
                    // address, phone 显示提交表单的新的值,而 name 显示oldName, 而不是新提交的 name
    
                    // 2.2.3结束方法:return
                    request.getRequestDispatcher("/updatecustomer.jsp").forward(request, response);
                    return;
                }
            }
            
            //3.若验证通过,则把表单参数封装为一个Customer 对象 customer
            Customer customer  = new Customer(name, address, phone);
            customer.setId(Integer.parseInt(id));//表单过来的 安全的
            
            //4.调用CustomerDAO 的 update(Customer customer) 执行更新操作
            customerDAO.update(customer);
            //5.重定向到    query.do
            response.sendRedirect("query.do");
            
    
        }
    
        private void query(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    
            String name = request.getParameter("name");
            String address = request.getParameter("address");
            String phone = request.getParameter("phone");
    
            CriteriaCustomer cc = new CriteriaCustomer(name, address, phone);
    
            // 1.调用 CustomerDAO 的 getForListWithCriteriaCustomer() 得到 Customer 的集合
            List<Customer> customers = customerDAO.getForListWithCriteriaCustomer(cc);
    
            // 2.把 Customer 的集合放入 request 中
            request.setAttribute("customers", customers);
    
            // 3.转发页面到 index.jsp 中( 不能使用重定向)
            request.getRequestDispatcher("/index.jsp").forward(request, response);
    
        }
    
        private void delete(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            String idstr = request.getParameter("id");
            int id = 0;
            // try-catch的作用 , 防止恶意的输入, idStr 不能转为int类型,若出异常 id直接为0
            try {
                id = Integer.parseInt(idstr);
                customerDAO.delete(id);
            } catch (Exception e) {
            }
            response.sendRedirect("query.do");
        }
    }

    CustomerDAOFactory  的 getCustomerDAO() 方法为 customerDAO 属性赋值

    CustomerDAOFactory 
    package com.aff.mvcapp.dao.factory;
    import java.util.HashMap;
    import java.util.Map;
    import com.aff.mvcapp.dao.CustomerDAO;
    import com.aff.mvcapp.dao.impl.CustomerDAOImpl;
    import com.aff.mvcapp.dao.impl.CustomerDAOXMLImpl;
    
    public class CustomerDAOFactory {
    
        private Map<String, CustomerDAO> daos = new HashMap<>();
    private static CustomerDAOFactory instance = new CustomerDAOFactory();
        public static CustomerDAOFactory getInstance() {
            return instance;
        }
        public String type = null;
        public void setType(String type) {
            this.type = type;
        }
        private CustomerDAOFactory() {
            daos.put("jdbc", new CustomerDAOImpl());
            daos.put("xml", new CustomerDAOXMLImpl());
        }
    
        public CustomerDAO getCustomerDAO() {
            return daos.get(type);
        }
    
    }
    All that work will definitely pay off
  • 相关阅读:
    JDK内置工具使用
    awk 数组
    c++面试题
    C++内存分配
    awk 数字比较
    awk脚本 排序
    awk 读取 shell 变量的方法
    NVelocity系列:Getting Start With NVelocity
    Castle.ActiveRecord分页示例
    NVelocity系列:NVelocity配置详解
  • 原文地址:https://www.cnblogs.com/afangfang/p/12736339.html
Copyright © 2020-2023  润新知