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
原文地址:https://www.cnblogs.com/afangfang/p/12736339.html