MVC是Model-View-Controller的简称,即模型-视图-控制器。
MVC是一种设计模式,它把应用程序分成三个核心模块:模型、视图、控制器,它们各自处理自己的任务。模型是应用程序的主体部分,模型表示业务数据和业务逻辑。一个模型能为多个视图提供数据。由于应用于模型的代码只需写一次就可以被多个视图重用,所以提高了代码的可重用性。视图是用户看到并与之交互的界面,作用如下:视图向用户显示相关的数据,接受用户的输入,不进行任何实际的业务处理。控制器接受用户的输入并调用模型和视图去完成用户的需求。控制器接收请求并决定调用哪个模型组件去处理请求,然后决定调用哪个视图来显示模型处理返回的数据。
把逻辑部分、访问数据库的部分放在Servlet,显示部分放在JSP页面。
发请求到服务器,服务器调用Servlet,Servlet做一个控制器,根据请求的情况取去调用Java类,Java类完成业务逻辑和访问数据库的操作,根据POJO的返回结果转向JSP,JSP进行显示,显示的时候可以使用一些标准标签库。
POJO里包含处理逻辑、业务逻辑,并去访问数据库。
Servlet根据不同的返回结果转向不同的JSP页面,转向的方式包括重定向和转发。
model:
controller:Servlet
view:JSP
一、查询和删除
1.1 查询
需求
点击超链接后在页面显示所有学生考试信息
数据库
字段
flowId
type
idCard
examCard
studentName
location
grade
数据表截图
Bean
public classStudent {privateInteger flowId;private inttype;privateString idCard;privateString examCard;privateString studentName;privateString location;private intgrade;publicInteger getFlowId() {returnflowId;
}public voidsetFlowId(Integer flowId) {this.flowId =flowId;
}public intgetType() {returntype;
}public void setType(inttype) {this.type =type;
}publicString getIdCard() {returnidCard;
}public voidsetIdCard(String idCard) {this.idCard =idCard;
}publicString getExamCard() {returnexamCard;
}public voidsetExamCard(String examCard) {this.examCard =examCard;
}publicString getStudentName() {returnstudentName;
}public voidsetStudentName(String studentName) {this.studentName =studentName;
}publicString getLocation() {returnlocation;
}public voidsetLocation(String location) {this.location =location;
}public intgetGrade() {returngrade;
}public void setGrade(intgrade) {this.grade =grade;
}public Student(Integer flowId, int type, String idCard, String examCard, String studentName, String location, intgrade) {this.flowId =flowId;this.type =type;this.idCard =idCard;this.examCard =examCard;this.studentName =studentName;this.location =location;this.grade =grade;
}//反射需要一个无参的构造器
publicStudent(){
}
}
流程
页面
超链接的页面 c.jsp
Titlec.jsp截图
转发的页面 students.jsp
User: JieZhao
Date:2019/8/13Time:13:38To changethis template use File | Settings |File Templates.--%>
Titlestus = (List)request.getAttribute("students");%>
FlowId | Type | IdCard | ExamCard | StudentName | Location | Grade |
---|
for(Student student: stus){%>
代码
Dao
public classStudentDao {public ListgetAll(){
List students = new ArrayList<>();
Connection connection= null;
PreparedStatement preparedStatement= null;
ResultSet resultSet= null;try{
String driverClass= "com.mysql.jdbc.Driver";
String url= "jdbc:mysql:///aidata";
String user= "root";
String passward= "root";
Class.forName(driverClass);
connection=DriverManager.getConnection(url, user, passward);
String sql= "SELECT flow_id, type, id_card, exam_card, sutdent_name, Location, Grade FROM examstudent";
preparedStatement=connection.prepareStatement(sql);
resultSet=preparedStatement.executeQuery();while(resultSet.next()){int flowId = resultSet.getInt(1);int type = resultSet.getInt(2);
String idCard= resultSet.getString(3);
String examCard= resultSet.getString(4);
String studentName= resultSet.getString(5);
String location= resultSet.getString(6);int grade = resultSet.getInt(7);
Student student= newStudent(flowId, type, idCard, examCard, studentName, location, grade);
students.add(student);
}
}catch(Exception e){
e.printStackTrace();
}finally{try{if(resultSet != null){
resultSet.close();
}
}catch(SQLException e){
e.printStackTrace();
}try{if(preparedStatement != null){
preparedStatement.close();
}
}catch(SQLException e){
e.printStackTrace();
}try{if(connection != null){
connection.close();
}
}catch(SQLException e){
e.printStackTrace();
}
}returnstudents;
}
}
Servlet
public class ListAllStudentsServlet extendsHttpServlet {protected void doGet(HttpServletRequest request, HttpServletResponse response) throwsIOException, ServletException {
StudentDao studentDao= newStudentDao();
List students =studentDao.getAll();
request.setAttribute("students", students); //结果添加到students属性里,存到request里
request.getRequestDispatcher("/students.jsp").forward(request, response);//将request转发到students.jsp页面
}
}
配置web.xml
listAllStudent
com.aidata.mvc.ListAllStudentsServlet
listAllStudent
/listAllStudent
1.2 删除
students.jsp里添加删除按钮
Dao里添加删除方法
public voiddeleteByFlowId(Integer flowId){
List students = new ArrayList<>();
Connection connection= null;
PreparedStatement preparedStatement= null;try{
String driverClass= "com.mysql.jdbc.Driver";
String url= "jdbc:mysql:///aidata";
String user= "root";
String password= "root";
Class.forName(driverClass);
connection=DriverManager.getConnection(url, user, password);
String sql= "DELETE FROM examstudent WHERE flow_id = ?";
preparedStatement=connection.prepareStatement(sql);
preparedStatement.setInt(1, flowId);
preparedStatement.executeUpdate();
}catch(Exception e){
e.printStackTrace();
}finally{try{if(preparedStatement != null){
preparedStatement.close();
}
}catch(SQLException e){
e.printStackTrace();
}try{if(connection != null){
connection.close();
}
}catch(SQLException e){
e.printStackTrace();
}
}
}
Servlet添加删除的Servlet
public class DeleteStudentServlet extendsHttpServlet {protected voiddoGet(HttpServletRequest request, HttpServletResponse response)throwsIOException, ServletException {
String flowId= request.getParameter("flowId");
StudentDao studentDao= newStudentDao();
studentDao.deleteByFlowId(Integer.parseInt(flowId));
List students =studentDao.getAll();
request.setAttribute("students", students);
request.getRequestDispatcher("/listAllStudent").forward(request, response); // 重定向到servlet
}
}
配置web.xml
deleteStudent
com.aidata.mvc.DeleteStudentServlet
deleteStudent
/deleteStudent
二、案例
2.1 架构分析
下面开始做一个小案例:利用MVC模式对数据进行增删改查
没有业务层,直接由Servlet调用DAO,所以也没有事务操作,可以在DAO中直接获取Connection对象
采取MVC设计模式
使用到的技术:
MVC设计模式:JSP、Servlet
数据库使用MySQL
连接数据库使用C3P0数据库连接池
JDBC工具采用DBUtils
页面的提示操作采用jQuery
技术难点:
多个请求如何使用一个Servlet
模糊查询
在创建或修改的情况下,验证用户名已经被使用,并给出提示信息
2.2 DAO层
DAO 模式
DAO (DataAccessobjects 数据存取对象)是指位于业务逻辑和持久化数据之间实现对持久化数据的访问。通俗来讲,就是将数据库操作都封装起来。
对外提供相应的接口
在面向对象设计过程中,有一些"套路”用于解决特定问题称为模式。
DAO 模式提供了访问关系型数据库系统所需操作的接口,将数据访问和业务逻辑分离对上层提供面向对象的数据访问接口。
从以上 DAO 模式使用可以看出,DAO 模式的优势就在于它实现了两次隔离。
1、隔离了数据访问代码和业务逻辑代码。业务逻辑代码直接调用DAO方法即可,完全感觉不到数据库表的存在。分工明确,数据访问层代码变化不影响业务逻辑代码,这符合单一职能原则,降低了藕合性,提高了可复用性。
2、隔离了不同数据库实现。采用面向接口编程,如果底层数据库变化,如由 MySQL 变成 Oracle 只要增加 DAO 接口的新实现类即可,原有 MySQ 实现不用修改。这符合 "开-闭" 原则。该原则降低了代码的藕合性,提高了代码扩展性和系统的可移植性。
一个典型的DAO 模式主要由以下几部分组成。
1、DAO接口: 把对数据库的所有操作定义成抽象方法,可以提供多种实现。
2、DAO 实现类: 针对不同数据库给出DAO接口定义方法的具体实现。
3、实体类:用于存放与传输对象数据。
4、数据库连接和关闭工具类: 避免了数据库连接和关闭代码的重复使用,方便修改。
数据库
建立数据表
Create tablecustomers(
idint primary keyauto_increment,
namevarchar(30) not null unique,
addressvarchar(30),
phonevarchar(30)
);
# 为 name 字段添加唯一约束alter table customers add constraint name_uk unique(name);
数据表截图
C3P0数据源
使用eclipse
添加c3p0的jar包和mysql驱动的jar包到根目录的lib目录中
添加commons-dbutils-1.3.jar到根目录的lib目录中
添加c3p0的配置文件到src目录
c3p0-config.xml
root
root
com.mysql.jdbc.Driver
jdbc:mysql:///aidata
5
5
5
10
20
5
实体类
Customer.java
packagecom.aidata.mvcapp.domain;public classCustomer {privateInteger id;privateString name;privateString address;privateString phone;publicInteger getId() {returnid;
}public voidsetId(Integer id) {this.id =id;
}publicString getName() {returnname;
}public voidsetName(String name) {this.name =name;
}publicString getAddress() {returnaddress;
}public voidsetAddress(String address) {this.address =address;
}publicString getPhone() {returnphone;
}public voidsetPhone(String phone) {this.phone =phone;
}
@OverridepublicString toString() {return "Customer [id=" + id + ", name=" + name + ", address=" + address + ", phone=" + phone + "]";
}
}
数据库连接和关闭工具类
JdbcUtils.java
packagecom.aidata.mvcapp.db;importjava.sql.Connection;importjava.sql.SQLException;importjavax.sql.DataSource;importcom.mchange.v2.c3p0.ComboPooledDataSource;/*** @ClassName JdbcUtils
* @Description JDBC操作的工具类
*@authorJZ
* @Date
*@version1.0.0*/
public classJdbcUtils {/*** @Description 释放连接
*@paramconnection*/
public static voidreleaseConnection(Connection connection) {try{if (connection != null) {
connection.close();
}
}catch(Exception e) {//TODO: handle exception
}
}private static DataSource dataSource = null;//数据源只能创建一次,所以用static
static{
dataSource= new ComboPooledDataSource("mvcapp");
}/*** @Description 返回数据源的一个Connection对象
*@return*@throwsSQLException*/
public static Connection getConnection() throwsSQLException {returndataSource.getConnection();
}
}
DAO接口
CustomerDAO.java
该接口定义了和业务相关的功能,操作customer
packagecom.aidata.mvcapp.dao;importjava.util.List;importcom.aidata.mvcapp.domain.Customer;public interfaceCustomerDAO {public ListgetAll();public voidsave(Customer customer);publicCustomer get(Integer id);public voiddelete(Integer id);/***
* @Description 返回和name相等的记录数
*@paramname
*@return
*/
public longgetCountWithName(String name);
}
DAO 实现类
DAO.java
该类不和业务相关,即和customer不相关,而是关注增删改查的功能
增删改都是update,查
packagecom.aidata.mvcapp.dao;importjava.lang.reflect.ParameterizedType;importjava.lang.reflect.Type;importjava.sql.Connection;importjava.util.List;importorg.apache.commons.dbutils.QueryRunner;importorg.apache.commons.dbutils.handlers.BeanHandler;importorg.apache.commons.dbutils.handlers.BeanListHandler;importorg.apache.commons.dbutils.handlers.ScalarHandler;importcom.aidata.mvcapp.db.JdbcUtils;/*** @ClassName DAO
* @Description 封装了CRUD的方法,以供子类继承使用 当前DAO没有事务,直接在方法中获取数据库连接 整个DAO采取DBUtils解决方案
*@authorJZ
* @Date
*@version1.0.0
*@param
* 所处理的实体类的类型*/
public class DAO{private QueryRunner queryRunner = newQueryRunner();private Classclazz;publicDAO() {
Type superClass=getClass().getGenericSuperclass();if (superClass instanceofParameterizedType) {
ParameterizedType parameterizedType=(ParameterizedType) superClass;
Type[] typeArgs=parameterizedType.getActualTypeArguments();if (typeArgs != null && typeArgs.length > 0) {
clazz= (Class) typeArgs[0];
}
}
}/*** @Description 返回某一个字段的值,例如某一天记录的customerName或 返回数据表中由多少条记录等
*@paramsql
*@paramargs
*@return
*/
public E getForValue(String sql, Object... args) {
Connection connection= null;try{
connection=JdbcUtils.getConnection();return (E) queryRunner.query(connection, sql, newScalarHandler(), args);
}catch(Exception e) {
e.printStackTrace();
}finally{
JdbcUtils.releaseConnection(connection);
}return null;
}/*** @Description 返回 T 所对应的List
*@paramsql
*@paramargs
*@return
*/
public ListgetForList(String sql, Object... args) {
Connection connection= null;try{
connection=JdbcUtils.getConnection();return queryRunner.query(connection, sql, new BeanListHandler<>(clazz), args);
}catch(Exception e) {
e.printStackTrace();
}finally{
JdbcUtils.releaseConnection(connection);
}return null;
}/*** @Description 返回对应T的一个实例类对象
*@paramsql
*@paramargs
*@return
*/
publicT get(String sql, Object... args) {
Connection connection= null;try{
connection=JdbcUtils.getConnection();return queryRunner.query(connection, sql, new BeanHandler<>(clazz), args);
}catch(Exception e) {
e.printStackTrace();
}finally{
JdbcUtils.releaseConnection(connection);
}return null;
}/*** @Description 封装了INSERT、DELETE、UPDATE操作
*@paramsql
* SQL语句
*@paramargs
* 填充SQL语句的占位符*/
public voidupdate(String sql, Object... args) {
Connection connection= null;try{
connection=JdbcUtils.getConnection();
queryRunner.update(connection, sql, args);
}catch(Exception e) {
e.printStackTrace();
}finally{
JdbcUtils.releaseConnection(connection);
}
}
}
CustomerDAOJdbcImpl.java
将业务和功能结合起来,实现了业务操作
packagecom.aidata.mvcapp.dao.impl;importjava.util.List;importcom.aidata.mvcapp.dao.CustomerDAO;importcom.aidata.mvcapp.dao.DAO;importcom.aidata.mvcapp.domain.Customer;public class CustomerDAOJdbcImpl extends DAO implementsCustomerDAO {
@Overridepublic ListgetAll() {
String sql= "SELECT id, name, address, phone From customers";returngetForList(sql);
}
@Overridepublic voidsave(Customer customer) {
String sql= "INSERT INTO customers(name, address, phone) VALUES(?,?,?)";
update(sql, customer.getName(), customer.getAddress(), customer.getPhone());
}
@OverridepublicCustomer get(Integer id) {
String sql= "SELECT id, name, address, phone FROM customers WHERE id = ?";returnget(sql, id);
}
@Overridepublic voiddelete(Integer id) {
String sql= "DELETE FROM customers WHERE id = ?";
update(sql, id);
}
@Overridepublic longgetCountWithName(String name) {
String sql= "SELECT count(id) FROM customers WHERE name = ?";returngetForValue(sql, name);
}
}
2.3 多个请求对应一个Servlet
第一种方式:url添加参数
jsp
定义Servlet
packagecom.aidata.mvcapp.servlet;importjava.io.IOException;importjavax.servlet.ServletException;importjavax.servlet.http.HttpServlet;importjavax.servlet.http.HttpServletRequest;importjavax.servlet.http.HttpServletResponse;public class CustomerServlet extendsHttpServlet {private static final long serialVersionUID = 1L;publicCustomerServlet() {
}protected voiddoGet(HttpServletRequest request, HttpServletResponse response)throwsServletException, IOException {
doPost(request, response);
}protected voiddoPost(HttpServletRequest request, HttpServletResponse response)throwsServletException, IOException {
String method= request.getParameter("method");switch(method) {case "add":
add(request, response);break;case "query":
query(request, response);break;case "delete":
delete(request, response);break;
}
}private void add(HttpServletRequest request, HttpServletResponse response) throwsServletException, IOException {
System.out.println("add");
}private void query(HttpServletRequest request, HttpServletResponse response) throwsServletException, IOException {
System.out.println("query");
}private void delete(HttpServletRequest request, HttpServletResponse response) throwsServletException, IOException {
System.out.println("delete");
}
}
web.xml
customerServlet
com.aidata.mvcapp.servlet.CustomerServlet
customerServlet
/customerServlet
缺点:当添加一个请求时,需要在 Servlet 中修改两处代码:switch、添加方法;url 中使用 method=xxx 暴漏了要调用的方法,不私密,有安全隐患。
第二种方式:反射
jsp
web.xml
customerServlet
com.aidata.mvcapp.servlet.CustomerServlet
customerServlet
*.do
Servlet
packagecom.aidata.mvcapp.servlet;importjava.io.IOException;importjava.lang.reflect.InvocationTargetException;importjava.lang.reflect.Method;importjavax.servlet.ServletException;importjavax.servlet.http.HttpServlet;importjavax.servlet.http.HttpServletRequest;importjavax.servlet.http.HttpServletResponse;public class CustomerServlet extendsHttpServlet {private static final long serialVersionUID = 1L;publicCustomerServlet() {
}protected voiddoGet(HttpServletRequest request, HttpServletResponse response)throwsServletException, IOException {
doPost(request, response);
}protected voiddoPost(HttpServletRequest request, HttpServletResponse response)throwsServletException, IOException {
String servletPath=request.getServletPath();
String methodName= servletPath.substring(1);
methodName= methodName.substring(0, methodName.length() - 3);
System.out.println(methodName);
Method method;try{
method= getClass().getDeclaredMethod(methodName, HttpServletRequest.class, HttpServletResponse.class);
method.invoke(this, request, response);
}catch (NoSuchMethodException |SecurityException e) {//TODO Auto-generated catch block
e.printStackTrace();
}catch(IllegalAccessException e) {//TODO Auto-generated catch block
e.printStackTrace();
}catch(IllegalArgumentException e) {//TODO Auto-generated catch block
e.printStackTrace();
}catch(InvocationTargetException e) {//TODO Auto-generated catch block
e.printStackTrace();
}
}private voidaddCustomer(HttpServletRequest request, HttpServletResponse response)throwsServletException, IOException {
System.out.println("add");
}private void query(HttpServletRequest request, HttpServletResponse response) throwsServletException, IOException {
System.out.println("query");
}private voiddeleteCustomer(HttpServletRequest request, HttpServletResponse response)throwsServletException, IOException {
System.out.println("delete");
}private void edit(HttpServletRequest request, HttpServletResponse response) throwsServletException, IOException {
System.out.println("edit");
}
}
流程:
2.4 模糊查询
非模糊查询
JSP
Insert title hereCustomerName: | |
Address: | |
Phone: | |
Add New Customer |
customers = (List)request.getAttribute("customers");if(customers != null && customers.size() > 0){%>
ID | CustomerName | Address | Phone | UPDATE\DELETE |
---|
for(Customer customer: customers){%>
Servlet
packagecom.aidata.mvcapp.servlet;importjava.io.IOException;importjava.lang.reflect.InvocationTargetException;importjava.lang.reflect.Method;importjava.util.List;importjavax.servlet.ServletException;importjavax.servlet.http.HttpServlet;importjavax.servlet.http.HttpServletRequest;importjavax.servlet.http.HttpServletResponse;importcom.aidata.mvcapp.dao.CustomerDAO;importcom.aidata.mvcapp.dao.impl.CustomerDAOJdbcImpl;importcom.aidata.mvcapp.domain.Customer;public class CustomerServlet extendsHttpServlet {private static final long serialVersionUID = 1L;private CustomerDAO customerDAO = newCustomerDAOJdbcImpl();publicCustomerServlet() {
}protected voiddoGet(HttpServletRequest request, HttpServletResponse response)throwsServletException, IOException {
doPost(request, response);
}protected voiddoPost(HttpServletRequest request, HttpServletResponse response)throwsServletException, IOException {
String servletPath=request.getServletPath();
String methodName= servletPath.substring(1);
methodName= methodName.substring(0, methodName.length() - 3);
System.out.println(methodName);
Method method;try{
method= getClass().getDeclaredMethod(methodName, HttpServletRequest.class, HttpServletResponse.class);
method.invoke(this, request, response);
}catch (NoSuchMethodException |SecurityException e) {//TODO Auto-generated catch block
e.printStackTrace();
}catch(IllegalAccessException e) {//TODO Auto-generated catch block
e.printStackTrace();
}catch(IllegalArgumentException e) {//TODO Auto-generated catch block
e.printStackTrace();
}catch(InvocationTargetException e) {//TODO Auto-generated catch block
e.printStackTrace();
}
}private voidaddCustomer(HttpServletRequest request, HttpServletResponse response)throwsServletException, IOException {
System.out.println("add");
}private void query(HttpServletRequest request, HttpServletResponse response) throwsServletException, IOException {//1.调用CustomerDAO的getAll()方法,得到Customer的集合
List customers =customerDAO.getAll();//2.把customer集合放入request中
request.setAttribute("customers", customers);//3.转发页面到index.jsp,不能用重定向
request.getRequestDispatcher("/index.jsp").forward(request, response);
}private voiddeleteCustomer(HttpServletRequest request, HttpServletResponse response)throwsServletException, IOException {
System.out.println("delete");
}private void edit(HttpServletRequest request, HttpServletResponse response) throwsServletException, IOException {
System.out.println("edit");
}
}
模糊查询
接口添加方法,定义用于查询的类
需要在 CustomerDAO 接口中定义一个 getForListWithCriteriaCustomer(CriteriaCustomer cc)。 其中 CriteriaCustomer 用于封装查询条件:name, address, phone。因为查询条件很多时候和 domain 类并不相同,所以要做成一个单独的类
packagecom.aidata.mvcapp.dao;importjava.util.List;importcom.aidata.mvcapp.domain.Customer;public interfaceCustomerDAO {public ListgetForListWithCriteriaCustomer(CriteriaCustomer cc);public ListgetAll();public voidsave(Customer customer);publicCustomer get(Integer id);public voiddelete(Integer id);/*** @Description 返回和name相等的记录数
*@paramname
*@return
*/
public longgetCountWithName(String name);
}
CriteriaCustomer
packagecom.aidata.mvcapp.dao;public classCriteriaCustomer {privateString name;privateString address;privateString phone;publicCriteriaCustomer(String name, String address, String phone) {super();this.name =name;this.address =address;this.phone =phone;
}publicString getName() {returnname;
}public voidsetName(String name) {this.name =name;
}publicString getAddress() {returnaddress;
}public voidsetAddress(String address) {this.address =address;
}publicString getPhone() {returnphone;
}public voidsetPhone(String phone) {this.phone =phone;
}
}
拼 SQL
SQL: "SELECT id, name, address, phone FROM customers WHERE " +
"name LIKE ? AND address LIKE ? ANDphone LIKE ?";
packagecom.aidata.mvcapp.dao.impl;importjava.util.List;importcom.aidata.mvcapp.dao.CriteriaCustomer;importcom.aidata.mvcapp.dao.CustomerDAO;importcom.aidata.mvcapp.dao.DAO;importcom.aidata.mvcapp.domain.Customer;public class CustomerDAOJdbcImpl extends DAO implementsCustomerDAO {
@Overridepublic ListgetAll() {
String sql= "SELECT id, name, address, phone From customers";returngetForList(sql);
}
@Overridepublic voidsave(Customer customer) {
String sql= "INSERT INTO customers(name, address, phone) VALUES(?,?,?)";
update(sql, customer.getName(), customer.getAddress(), customer.getPhone());
}
@OverridepublicCustomer get(Integer id) {
String sql= "SELECT id, name, address, phone FROM customers WHERE id = ?";returnget(sql, id);
}
@Overridepublic voiddelete(Integer id) {
String sql= "DELETE FROM customers WHERE id = ?";
update(sql, id);
}
@Overridepublic longgetCountWithName(String name) {
String sql= "SELECT count(id) FROM customers WHERE name = ?";returngetForValue(sql, name);
}
@Overridepublic ListgetForListWithCriteriaCustomer(CriteriaCustomer cc) {
String sql= "SELECT id, name, address, phone FROM customers WHERE "
+ "name LIKE ? AND address LIKE ? AND phone LIKE ?";returngetForList(sql, cc.getName(), cc.getAddress(), cc.getPhone());
}
}
为了正确的填充占位符时,重写了 CriteriaCustomer 的 getter:
packagecom.aidata.mvcapp.dao;public classCriteriaCustomer {privateString name;privateString address;privateString phone;publicCriteriaCustomer(String name, String address, String phone) {super();this.name =name;this.address =address;this.phone =phone;
}publicString getName() {if (name == null) {
name= "%%";
}else{
name= "%" + name + "%";
}returnname;
}public voidsetName(String name) {this.name =name;
}publicString getAddress() {if (address == null) {
address= "%%";
}else{
address= "%" + address + "%";
}returnaddress;
}public voidsetAddress(String address) {this.address =address;
}publicString getPhone() {if (phone == null) {
phone= "%%";
}else{
phone= "%" + phone + "%";
}returnphone;
}public voidsetPhone(String phone) {this.phone =phone;
}
}
修改 Servlet
获取请求参数,把请求参数封装为CriteriaCustomer 对象,再调用 getForListWithCriteriaCustomer(CriteriaCustomer cc) 方法
packagecom.aidata.mvcapp.servlet;importjava.io.IOException;importjava.lang.reflect.InvocationTargetException;importjava.lang.reflect.Method;importjava.util.List;importjavax.servlet.ServletException;importjavax.servlet.http.HttpServlet;importjavax.servlet.http.HttpServletRequest;importjavax.servlet.http.HttpServletResponse;importcom.aidata.mvcapp.dao.CriteriaCustomer;importcom.aidata.mvcapp.dao.CustomerDAO;importcom.aidata.mvcapp.dao.impl.CustomerDAOJdbcImpl;importcom.aidata.mvcapp.domain.Customer;public class CustomerServlet extendsHttpServlet {private static final long serialVersionUID = 1L;private CustomerDAO customerDAO = newCustomerDAOJdbcImpl();publicCustomerServlet() {
}protected voiddoGet(HttpServletRequest request, HttpServletResponse response)throwsServletException, IOException {
doPost(request, response);
}protected voiddoPost(HttpServletRequest request, HttpServletResponse response)throwsServletException, IOException {
String servletPath=request.getServletPath();
String methodName= servletPath.substring(1);
methodName= methodName.substring(0, methodName.length() - 3);
System.out.println(methodName);
Method method;try{
method= getClass().getDeclaredMethod(methodName, HttpServletRequest.class, HttpServletResponse.class);
method.invoke(this, request, response);
}catch (NoSuchMethodException |SecurityException e) {//TODO Auto-generated catch block
e.printStackTrace();
}catch(IllegalAccessException e) {//TODO Auto-generated catch block
e.printStackTrace();
}catch(IllegalArgumentException e) {//TODO Auto-generated catch block
e.printStackTrace();
}catch(InvocationTargetException e) {//TODO Auto-generated catch block
e.printStackTrace();
}
}private voidaddCustomer(HttpServletRequest request, HttpServletResponse response)throwsServletException, IOException {
System.out.println("add");
}private void query(HttpServletRequest request, HttpServletResponse response) throwsServletException, IOException {
String name= request.getParameter("name");
String phone= request.getParameter("phone");
String address= request.getParameter("address");
CriteriaCustomer cc= newCriteriaCustomer(name, address, phone);//1.调用CustomerDAO的getAll()方法,得到Customer的集合
List customers =customerDAO.getForListWithCriteriaCustomer(cc);//2.把customer集合放入request中
request.setAttribute("customers", customers);//3.转发页面到index.jsp,不能用重定向
request.getRequestDispatcher("/index.jsp").forward(request, response);
}private voiddeleteCustomer(HttpServletRequest request, HttpServletResponse response)throwsServletException, IOException {
System.out.println("delete");
}private void edit(HttpServletRequest request, HttpServletResponse response) throwsServletException, IOException {
System.out.println("edit");
}
}
2.5 删除操作
Servlet
超链接:delete.do?id=
Servlet 的 delete 方法
获取 id
调用 DAO 执行删除
重定向到 query.do(若目标页面不需要读取当前请求的 request 属性,就可以使用重定向),将显示删除后的 Customer 的 List
packagecom.aidata.mvcapp.servlet;importjava.io.IOException;importjava.lang.reflect.InvocationTargetException;importjava.lang.reflect.Method;importjava.util.List;importjavax.servlet.ServletException;importjavax.servlet.http.HttpServlet;importjavax.servlet.http.HttpServletRequest;importjavax.servlet.http.HttpServletResponse;importcom.aidata.mvcapp.dao.CriteriaCustomer;importcom.aidata.mvcapp.dao.CustomerDAO;importcom.aidata.mvcapp.dao.impl.CustomerDAOJdbcImpl;importcom.aidata.mvcapp.domain.Customer;public class CustomerServlet extendsHttpServlet {private static final long serialVersionUID = 1L;private CustomerDAO customerDAO = newCustomerDAOJdbcImpl();publicCustomerServlet() {
}protected voiddoGet(HttpServletRequest request, HttpServletResponse response)throwsServletException, IOException {
doPost(request, response);
}protected voiddoPost(HttpServletRequest request, HttpServletResponse response)throwsServletException, IOException {
String servletPath=request.getServletPath();
String methodName= servletPath.substring(1);
methodName= methodName.substring(0, methodName.length() - 3);
System.out.println(methodName);
Method method;try{
method= getClass().getDeclaredMethod(methodName, HttpServletRequest.class, HttpServletResponse.class);
method.invoke(this, request, response);
}catch (NoSuchMethodException |SecurityException e) {//TODO Auto-generated catch block
e.printStackTrace();
}catch(IllegalAccessException e) {//TODO Auto-generated catch block
e.printStackTrace();
}catch(IllegalArgumentException e) {//TODO Auto-generated catch block
e.printStackTrace();
}catch(InvocationTargetException e) {//TODO Auto-generated catch block
e.printStackTrace();
}
}private voidaddCustomer(HttpServletRequest request, HttpServletResponse response)throwsServletException, IOException {
System.out.println("add");
}private void query(HttpServletRequest request, HttpServletResponse response) throwsServletException, IOException {
String name= request.getParameter("name");
String phone= request.getParameter("phone");
String address= request.getParameter("address");
CriteriaCustomer cc= newCriteriaCustomer(name, address, phone);//1.调用CustomerDAO的getAll()方法,得到Customer的集合
List customers =customerDAO.getForListWithCriteriaCustomer(cc);//2.把customer集合放入request中
request.setAttribute("customers", customers);//3.转发页面到index.jsp,不能用重定向
request.getRequestDispatcher("/index.jsp").forward(request, response);
}private voiddeleteCustomer(HttpServletRequest request, HttpServletResponse response)throwsServletException, IOException {
String idStri= request.getParameter("id");int id = 0;//try...catch... 防止idStri不能转为int类型,若不能转,id=0,不进行任何删除操作
try{
id=Integer.parseInt(idStri);
customerDAO.delete(id);
}catch(Exception e) {
}
response.sendRedirect("query.do");
System.out.println("delete");
}private void edit(HttpServletRequest request, HttpServletResponse response) throwsServletException, IOException {
System.out.println("edit");
}
}
JSP
jQuery 提示:
确定要删除 xx 的信息吗?
Insert title here$(function() {
$(".delete").click(function() {varcontent=$(this).parent().parent().find("td:eq(1)").text();varflag=confirm("确定要删除"+content+"的信息吗?");returnflag;
});
});
CustomerName: | |
Address: | |
Phone: | |
Add New Customer |
customers=(List)request.getAttribute("customers");if(customers != null &&customers.size()> 0){%>
IDCustomerNameAddressPhoneUPDATE\DELETE
for(Customer customer: customers){%>
UPDATE
"class="delete">DELETE
request的getParameter(String name)方法获取表单里面的name信息
只有设置了 name 属性的表单元素才能在提交表单时传递它们的值,因为服务端获取表单提交的数据是通过表单元素的 name 属性的值而得到的,没有 name 属性就无法得到表单元素提交给服务端的值
2.6 新增
流程
效果:点击Add New Customer 超链接,连接到 newcustomer.jsp
创建newcustomer.jsp
Insert title hereCustomerName: | "> |
Address: | |
Phone: | |
success.jsp
Insert title here操作成功!
Return...
修改addCustomer 方法
CustomerServlet 的 addCustomer 方法
packagecom.aidata.mvcapp.servlet;importjava.io.IOException;importjava.lang.reflect.InvocationTargetException;importjava.lang.reflect.Method;importjava.util.List;importjavax.servlet.ServletException;importjavax.servlet.http.HttpServlet;importjavax.servlet.http.HttpServletRequest;importjavax.servlet.http.HttpServletResponse;importcom.aidata.mvcapp.dao.CriteriaCustomer;importcom.aidata.mvcapp.dao.CustomerDAO;importcom.aidata.mvcapp.dao.impl.CustomerDAOJdbcImpl;importcom.aidata.mvcapp.domain.Customer;public class CustomerServlet extendsHttpServlet {private static final long serialVersionUID = 1L;private CustomerDAO customerDAO = newCustomerDAOJdbcImpl();publicCustomerServlet() {
}protected voiddoGet(HttpServletRequest request, HttpServletResponse response)throwsServletException, IOException {
doPost(request, response);
}protected voiddoPost(HttpServletRequest request, HttpServletResponse response)throwsServletException, IOException {
String servletPath=request.getServletPath();
String methodName= servletPath.substring(1);
methodName= methodName.substring(0, methodName.length() - 3);
System.out.println(methodName);
Method method;try{
method= getClass().getDeclaredMethod(methodName, HttpServletRequest.class, HttpServletResponse.class);
method.invoke(this, request, response);
}catch (NoSuchMethodException |SecurityException e) {//TODO Auto-generated catch block
e.printStackTrace();
}catch(IllegalAccessException e) {//TODO Auto-generated catch block
e.printStackTrace();
}catch(IllegalArgumentException e) {//TODO Auto-generated catch block
e.printStackTrace();
}catch(InvocationTargetException e) {//TODO Auto-generated catch block
e.printStackTrace();
}
}private voidaddCustomer(HttpServletRequest request, HttpServletResponse response)throwsServletException, 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方法获取name是否在数据库中存在
long count =customerDAO.getCountWithName(name);//2.2 若返回值大于0,则响应newcustomer.jsp页面://通过转发的方式响应newcustomer.jsp
if (count > 0) {//2.2.1 要求在newcustomer.jsp页面显示一个错误消息:用户名name已经被占用,请重新选择!//在request中放入一个属性,比如message:用户名name已经被占用,请重新选择!,//在页面上通过request.getAttribute("message")的方式显示
request.setAttribute("message", "用户名" + name + "已经被占用,请重新选择!");//2.2.2 newcustomer.jsp的表单值可以回显//jsp中,value="//2.2.3 结束方法:return
request.getRequestDispatcher("/newcustomer.jsp").forward(request, response);return;
}//3. 若验证通过,则把表单参数封装为一个Customer对象customer
Customer customer = newCustomer(name, address, phone);//4. 调用CustomerDAO的save方法,执行保存操作
customerDAO.save(customer);//5. 重定向到success.jsp页面
response.sendRedirect("success.jsp");
}private void query(HttpServletRequest request, HttpServletResponse response) throwsServletException, IOException {
String name= request.getParameter("name");
String phone= request.getParameter("phone");
String address= request.getParameter("address");
CriteriaCustomer cc= newCriteriaCustomer(name, address, phone);//1.调用CustomerDAO的getAll()方法,得到Customer的集合
List customers =customerDAO.getForListWithCriteriaCustomer(cc);//2.把customer集合放入request中
request.setAttribute("customers", customers);//3.转发页面到index.jsp,不能用重定向
request.getRequestDispatcher("/index.jsp").forward(request, response);
}private voiddeleteCustomer(HttpServletRequest request, HttpServletResponse response)throwsServletException, IOException {
String idStri= request.getParameter("id");int id = 0;//try...catch... 防止idStri不能转为int类型,若不能转,id=0,不进行任何删除操作
try{
id=Integer.parseInt(idStri);
customerDAO.delete(id);
}catch(Exception e) {
}
response.sendRedirect("query.do");
}private void edit(HttpServletRequest request, HttpServletResponse response) throwsServletException, IOException {
System.out.println("edit");
}
}
执行流程图
2.7 修改
先显示(SELECT 操作)修改的页面,再进行修改(update)
显示修改页面
Update 的超链接:UPDATE
index.jsp
Insert title here$(".delete").click(function() {
var content= $(this).parent().parent().find("td:eq(1)").text();
var flag= confirm("确定要删除"+content+"的信息吗?");returnflag;
});
});
CustomerName: | |
Address: | |
Phone: | |
Add New Customer |
customers = (List)request.getAttribute("customers");if(customers != null && customers.size() > 0){%>
ID | CustomerName | Address | Phone | UPDATE\DELETE |
---|
for(Customer customer: customers){%>
edit 方法:
private void edit(HttpServletRequest request, HttpServletResponse response) throwsServletException, IOException {
String forwardPath= "/error.jsp";//1. 获取请求参数id
String idStr = request.getParameter("id");//2.调用customerDAO的customerDAO.get(id)获取和id对应的Customer对象
try{
Customer customer=customerDAO.get(Integer.parseInt(idStr));if (customer != null) {
forwardPath= "updatecustomer.jsp";//3.将customer放入request中
request.setAttribute("customer", customer);
}
}catch(Exception e) {
}//4.响应updatecustomer.jsp页面:转发
request.getRequestDispatcher(forwardPath).forward(request, response);
}
JSP 页面
获取请求域中的 Customer 对象,调用对应的字段的 get 方法来显示值。
使用隐藏域来保存要修改的 Customer 对象的 id:"/>。虽然没有修改id,当然也不能改,但依然少不了,id用来判断到底是哪个customer。
使用隐藏域来保存 oldName:"/>,oldName保存修改前的名字,name会更新为提交的名字。
关于隐藏域:和其他的表单域一样可以被提交到服务器,只不过在页面上不显示提交到 update.do
updatecustomer.jsp:
Insert title hereObjectmsg=request.getAttribute("message");if(msg != null){%>
Customer customer=(Customer)request.getAttribute("customer");if(customer != null){//如果没有出错,从edit方法过来的,customer不为空
id=customer.getId()+ "";//这里name和oldName一样,但是后面提交的时候,name会提交,即更新,而oldName保持不变,从而可以比较
oldName=customer.getName();
name=customer.getName();
address=customer.getAddress();
phone=customer.getPhone();
}else{//如果出错,即提交了重复的名字,会出现提示信息,会停留在本页面,没有edit方法了,也就没有customer属性了//只能从之前提交的request中得到id等
id=request.getParameter("id");
oldName=request.getParameter("oldName");//name=request.getParameter("oldname");
address=request.getParameter("address");
phone=request.getParameter("phone");
}%>
" />
" />
CustomerName: | " /> |
Address: | " /> |
Phone: | " /> |
隐藏域的问题
回显的问题
Newcustomer.jsp 和 updateCustomer.jsp 能汇总到一个页面吗 ?
修改操作
Update 方法:
private void update(HttpServletRequest request, HttpServletResponse response) throwsServletException, IOException {
// 1. 获取表单参数:name,address,phone
String id = request.getParameter("id");
String name = request.getParameter("name");
String phone = request.getParameter("phone");
String address = request.getParameter("address");
String oldName = request.getParameter("oldName");
// 2. 检验name是否已经被占用
// 2.1 比较name和oldName是否相同,若相同说明name可用
// 2.1 若不相同,调用customerDAO的getCountWithName方法获取name是否在数据库中存在
if (!oldName.equalsIgnoreCase(name)) {
// 如你输入了A,以前已经有了a,java的equals会认为两者不同,于是进入该if
// 但是mysql认为A和a相同,于是返回了1,即已经存在了,从而引发message
// 忽略大小写,不进入if,直接进行后面的update
long count =customerDAO.getCountWithName(name);
// 2.2 若返回值大于0,则响应updatecustomer.jsp
if (count > 0) {
// 2.2.1 在updatecustomer.jsp页面显示一个错误信息:用户名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
return;
}
}
// 3. 若验证通过,则把表单参数封装为一个Customer对象customer
Customer customer = newCustomer(name, address, phone);
customer.setId(Integer.parseInt(id));
// 4. 调用CustomerDAO的update(Customer customer)执行更新操作
customerDAO.update(customer);
// 5. 重定向到query.do
response.sendRedirect("query.do");
}
}
完整Servlet
packagecom.aidata.mvcapp.servlet;importjava.io.IOException;importjava.lang.reflect.InvocationTargetException;importjava.lang.reflect.Method;importjava.util.List;importjavax.servlet.ServletException;importjavax.servlet.http.HttpServlet;importjavax.servlet.http.HttpServletRequest;importjavax.servlet.http.HttpServletResponse;importcom.aidata.mvcapp.dao.CriteriaCustomer;importcom.aidata.mvcapp.dao.CustomerDAO;importcom.aidata.mvcapp.dao.impl.CustomerDAOJdbcImpl;importcom.aidata.mvcapp.domain.Customer;public class CustomerServlet extendsHttpServlet {private static final long serialVersionUID = 1L;private CustomerDAO customerDAO = newCustomerDAOJdbcImpl();publicCustomerServlet() {
}protected voiddoGet(HttpServletRequest request, HttpServletResponse response)throwsServletException, IOException {
doPost(request, response);
}protected voiddoPost(HttpServletRequest request, HttpServletResponse response)throwsServletException, IOException {
String servletPath=request.getServletPath();
String methodName= servletPath.substring(1);
methodName= methodName.substring(0, methodName.length() - 3);
System.out.println(methodName);
Method method;try{
method= getClass().getDeclaredMethod(methodName, HttpServletRequest.class, HttpServletResponse.class);
method.invoke(this, request, response);
}catch (NoSuchMethodException |SecurityException e) {//TODO Auto-generated catch block
e.printStackTrace();
}catch(IllegalAccessException e) {//TODO Auto-generated catch block
e.printStackTrace();
}catch(IllegalArgumentException e) {//TODO Auto-generated catch block
e.printStackTrace();
}catch(InvocationTargetException e) {//TODO Auto-generated catch block
e.printStackTrace();
}
}private voidaddCustomer(HttpServletRequest request, HttpServletResponse response)throwsServletException, 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方法获取name是否在数据库中存在
long count =customerDAO.getCountWithName(name);//2.2 若返回值大于0,则响应newcustomer.jsp页面://通过转发的方式响应newcustomer.jsp
if (count > 0) {//2.2.1 要求在newcustomer.jsp页面显示一个错误消息:用户名name已经被占用,请重新选择!//在request中放入一个属性,比如message:用户名name已经被占用,请重新选择!,//在页面上通过request.getAttribute("message")的方式显示
request.setAttribute("message", "用户名" + name + "已经被占用,请重新选择!");//2.2.2 newcustomer.jsp的表单值可以回显//jsp中,value="//2.2.3 结束方法:return
request.getRequestDispatcher("/newcustomer.jsp").forward(request, response);return;
}//3. 若验证通过,则把表单参数封装为一个Customer对象customer
Customer customer = newCustomer(name, address, phone);//4. 调用CustomerDAO的save方法,执行保存操作
customerDAO.save(customer);//5. 重定向到success.jsp页面
response.sendRedirect("success.jsp");
}private void query(HttpServletRequest request, HttpServletResponse response) throwsServletException, IOException {
String name= request.getParameter("name");
String phone= request.getParameter("phone");
String address= request.getParameter("address");
CriteriaCustomer cc= newCriteriaCustomer(name, address, phone);//1.调用CustomerDAO的getAll()方法,得到Customer的集合
List customers =customerDAO.getForListWithCriteriaCustomer(cc);//2.把customer集合放入request中
request.setAttribute("customers", customers);//3.转发页面到index.jsp,不能用重定向
request.getRequestDispatcher("/index.jsp").forward(request, response);
}private voiddeleteCustomer(HttpServletRequest request, HttpServletResponse response)throwsServletException, IOException {
String idStri= request.getParameter("id");int id = 0;//try...catch... 防止idStri不能转为int类型,若不能转,id=0,不进行任何删除操作
try{
id=Integer.parseInt(idStri);
customerDAO.delete(id);
}catch(Exception e) {
}
response.sendRedirect("query.do");
}private void edit(HttpServletRequest request, HttpServletResponse response) throwsServletException, IOException {
String forwardPath= "/error.jsp";//1. 获取请求参数id
String idStr = request.getParameter("id");//2.调用customerDAO的customerDAO.get(id)获取和id对应的Customer对象
try{
Customer customer=customerDAO.get(Integer.parseInt(idStr));if (customer != null) {
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) throwsServletException, IOException {//1. 获取表单参数:name,address,phone
String id = request.getParameter("id");
String name= request.getParameter("name");
String phone= request.getParameter("phone");
String address= request.getParameter("address");
String oldName= request.getParameter("oldName");//2. 检验name是否已经被占用//2.1 比较name和oldName是否相同,若相同说明name可用//2.1 若不相同,调用customerDAO的getCountWithName方法获取name是否在数据库中存在
if (!oldName.equalsIgnoreCase(name)) {//如你输入了A,以前已经有了a,java的equals会认为两者不同,于是进入该if//但是mysql认为A和a相同,于是返回了1,即已经存在了,从而引发message//忽略大小写,不进入if,直接进行后面的update
long count =customerDAO.getCountWithName(name);//2.2 若返回值大于0,则响应updatecustomer.jsp
if (count > 0) {//2.2.1 在updatecustomer.jsp页面显示一个错误信息:用户名name已经被占用,请重新选择!//在request中放入一个属性,比如message:用户名name已经被占用,请重新选择!,//在页面上通过request.getAttribute("message")的方式显示
request.setAttribute("message", "用户名" + name + "已经被占用,请重新选择!");//2.2.2 updatecustomer.jsp的表单值可以回显//address,phone显示提交表单的新的值,而name显示oldName,而不是新提交的name
request.getRequestDispatcher("update.jsp").forward(request, response);
// 2.2.3 结束方法:return
return; // 重定向跳转后必须加上return,要不然页面虽然跳转了,但是还会执行跳转后面的语句
}
}//3. 若验证通过,则把表单参数封装为一个Customer对象customer
Customer customer = newCustomer(name, address, phone);
customer.setId(Integer.parseInt(id));//4. 调用CustomerDAO的update(Customer customer)执行更新操作
customerDAO.update(customer);//5. 重定向到query.do
response.sendRedirect("query.do");
}
}
2.8 更换底层存储源
深入理解面向接口编程:在类中调用接口的方法,而不必关心具体的实现。这将有利于代码的解耦,使程序有更好的可移植性和可扩展性。
需要修改源码
src下新建customes.xml
Tom
Beijing123
新建实现类,功能暂时省略
packagecom.aidata.mvcapp.dao.impl;importjava.util.List;importcom.aidata.mvcapp.dao.CriteriaCustomer;importcom.aidata.mvcapp.dao.CustomerDAO;importcom.aidata.mvcapp.domain.Customer;public class CustomerDAOXMLImpl implementsCustomerDAO {
@Overridepublic ListgetForListWithCriteriaCustomer(CriteriaCustomer cc) {//TODO Auto-generated method stub
return null;
}
@Overridepublic ListgetAll() {//TODO Auto-generated method stub
return null;
}
@Overridepublic voidsave(Customer customer) {//TODO Auto-generated method stub
}
@OverridepublicCustomer get(Integer id) {//TODO Auto-generated method stub
return null;
}
@Overridepublic voiddelete(Integer id) {//TODO Auto-generated method stub
}
@Overridepublic voidupdate(Customer customer) {//TODO Auto-generated method stub
}
@Overridepublic longgetCountWithName(String name) {//TODO Auto-generated method stub
return 0;
}
}
只需要在CustomerServlet中修改一行语句
private CustomerDAO customerDAO = new CustomerDAOXMLImpl();
使用工厂模式,不修改源码
如果一行语句也不用修改怎么做?
使用属性文件
动态修改 Customer 的存储方式:通过修改类路径下的 switch.properties 文件的方式来实现
src下创建switch.properties
#type=xml
type=jdbc
创建Servlet读取配置文件
当Web 应用在启动的时候,InitServlet 被创建,并由 Servlet 容器调用其 init() 方法:
InitServlet
com.aidata.mvcapp.servlet.InitServlet
1
读取类路径下的 switch.properties 文件,获取 switch.properties 的 type 属性值,赋给了 CustomerDAOFactory 的 type 属性值
packagecom.aidata.mvcapp.servlet;importjava.io.IOException;importjava.io.InputStream;importjava.util.Properties;importjavax.servlet.ServletException;importjavax.servlet.http.HttpServlet;importjavax.servlet.http.HttpServletRequest;importjavax.servlet.http.HttpServletResponse;importcom.aidata.mvcapp.dao.factory.CustomerDAOFactory;public class InitServlet extendsHttpServlet {private static final long serialVersionUID = 1L;
@Overridepublic void init() throwsServletException {
CustomerDAOFactory.getInstance().setType("jdbc");
InputStream in= getServletContext().getResourceAsStream("/WEB-INF/classes/switch.properties");
Properties properties= newProperties();try{
properties.load(in);
String type= properties.getProperty("type");
CustomerDAOFactory.getInstance().setType(type);
}catch(IOException e) {
e.printStackTrace();
}
}}
需要通过一个类的一个方法来获取具体的实现类的对象:
packagecom.aidata.mvcapp.dao.factory;importjava.util.HashMap;importjava.util.Map;importcom.aidata.mvcapp.dao.CustomerDAO;importcom.aidata.mvcapp.dao.impl.CustomerDAOJdbcImpl;importcom.aidata.mvcapp.dao.impl.CustomerDAOXMLImpl;public classCustomerDAOFactory {private Map daos = new HashMap();privateCustomerDAOFactory() {
daos.put("jdbc", newCustomerDAOJdbcImpl());
daos.put("xml", newCustomerDAOXMLImpl());
}private static CustomerDAOFactory instance = newCustomerDAOFactory();public staticCustomerDAOFactory getInstance() {returninstance;
}private static String type = null;public voidsetType(String type) {this.type =type;
}publicCustomerDAO getCustomerDAO() {returndaos.get(type);
}
}
创建 CustomerServlet 时,为 customerDAO 属性赋值是通过 CustomerDAOFactory 的 getCustomerDAO() 方法完成的 。此时的 type 已经在 InitServlet 中被赋值了。
private CustomerDAO customerDAO = CustomerDAOFactory.getInstance().getCustomerDAO();