JavaWeb学习笔记(四)

JavaWeb学习笔记(四)一个MVCDAO小项目

注:本文内容是建立在佟刚老师的JavaWeb教程上写的,如有侵犯,联系删除

项目效果

项目所用技术

采取 MVC 设计模式及难点

使用到的技术:

  1. MVC 设计模式:JSP、Servlet,POJO
  2. 数据库使用 MySQL
  3. 连接数据库需要使用 C3P0 数据库连接池
  4. JDBC 工具采用 DBUtils
  5. 页面上的提示操作使用 jQuery

技术难点:

  1. 多个请求如何使用一个 Servlet ?
  2. 如何模糊查询 ?
  3. 如何在创建 或 修改 的情况下,验证用户名是否已经被使用,并给出提示?

项目流程图 及 idea工程

JavaWeb学习笔记(四)_第1张图片

JavaWeb学习笔记(四)_第2张图片

项目的实现

数据表建立

sql语句

Create table customers(
	id int primary key auto_increment,
	name varchar(30) not null unique,
	address varchar(30),
	phone varchar(30)
);

建立C3P0数据连接池

ps:这部分不是很明白

1、现在src目录下建立一个 c3p0-config.xml ,在里面添加如下代码




    
    
        com.mysql.jdbc.Driver
        jdbc:mysql://localhost:3306/data?serverTimezone=GMT
        
        root
        123456
        
        10
        
        30
        
        100
        
        10
        
        200
        

    


2、JdbcUtils工具类实现连接池的链接和关闭

public class JdbcUtils {

    /**
     * 释放Connection 连接
     * @param connection
     */
    public static void releaseConnection(Connection connection){

    }

    private static DataSource dataSource = null;

    static {
        dataSource = new ComboPooledDataSource("mvcapp");
    }

    /**
     * 返回一个Connection 对象
     * @return
     */
    public static Connection getConnection(){
        Connection conn=null;
        try {
            conn=dataSource.getConnection();
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return conn;
    }

}

注意:c3p0-config.xml的 < named-config name="mvcapp"> 应该与JdbcUtils的dataSource = new ComboPooledDataSource("mvcapp");相匹配

源码

编写 DAO、JdbcUtils工具类 、 CustomerDAO 接口和CustomerDAO 接口的实现类:CustomerDAOJDBCImpl,请见源码。

实现的一些难点

多个请求使用同一个 Servlet

多个请求使用一个Servlet有两种方法:
1、在同一个Servlet后面接不同的method,例如:

JavaWeb学习笔记(四)_第3张图片
在CustomerServlet里实现如下:

@Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        
        //获取对应的操作方式,例如:customerServlet?method=delete
		String method = req.getParameter("method");

        switch (method){
            case "add": add(req,resp);break;
            case "query": query(req,resp);break;
            case "delete": delete(req,resp);break;
            case "update": update(req,resp);break;
        }
    }
    
//add、query、delete分别是CustomerDAO的具体实现方法

private void delete(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        String idStr = req.getParameter("id");
        int id = 0;

        //try-catch 作用防止id不能转化为整数;若不能,则id=0
        try {
            id = Integer.parseInt(idStr);
            customerDAO.delete(id);
        } catch (NumberFormatException e) {
            e.printStackTrace();
        }

        resp.sendRedirect("query.do");
    }

虽然这种方法也经常被使用,但是有明显的缺点:
①、当添加一个请求时,需要在 Servlet 中修改两处代码:switch、添加方;
②、在请求后面暴露了请求的方式,不私密,存有安全隐患。

2、利用 *do 的Servlet映射方式,实现多个请求使用一个Servle
JavaWeb学习笔记(四)_第4张图片
在这里要注意一下,Servlet映射的配置样式*.do

 
        customerServlet
        cqy.dao.mvc.servlet.CustomerServlet
    
    
        customerServlet
        *.do
    

在CustomerServlet里实现如下(这部分的反射调用对应的方法不是很理解):

@Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //1、获取ServletPath:/edit.do 或 addCustomer.do 等
        String servletPath = req.getServletPath();
        //System.out.println(servletPath);
        //2、去除 / 和 do, 得到类似于 edit 或 addCustomer 这样的字符串
        String methodName = servletPath.substring(1);
        methodName = methodName.substring(0,methodName.length()-3);
        //System.out.println(methodName);

        try {
            //3、利用反射获取methodName 对应的方法
            Method method = getClass().getDeclaredMethod(methodName,HttpServletRequest.class,HttpServletResponse.class);
            //4、利用反射调用对应的方法
            method.invoke(this,req,resp);
        } catch (Exception e){
            resp.sendRedirect("error.jsp");
        }
    }
    
//method.invoke(this,req,resp);是调用delete等方法

 private void delete(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        String idStr = req.getParameter("id");
        int id = 0;

        //try-catch 作用防止id不能转化为整数;若不能,则id=0
        try {
            id = Integer.parseInt(idStr);
            customerDAO.delete(id);
        } catch (NumberFormatException e) {
            e.printStackTrace();
        }

        resp.sendRedirect("query.do");
    }   

模糊查询的实现

根据页面上name,address和phone来进行匹配,调用CustomerDAOpublic List getForListWithCriteriaCustomer(CriteriaCustomer cc)来实现

JavaWeb学习笔记(四)_第5张图片
在CustomerServlet中的query方法:

 private void query(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

        // 获取模糊查询的请求参数
        String name = req.getParameter("name");
        String address = req.getParameter("address");
        String phone = req.getParameter("phone");

        //封装成 CriteriaCustomer
        CriteriaCustomer criteriaCustomer = new CriteriaCustomer(name,address,phone);
        //1、调用CustomerDAO 的 getAll()方法 得到 Customer 的集合
        //List customers = customerDAO.getAll();
        List customers =customerDAO.getForListWithCriteriaCustomer(criteriaCustomer);

        //2、把Customer 的集合放入request中
        req.setAttribute("customers",customers);

        //3、转发页面到 index.jsp(不能使用重定向)
        req.getRequestDispatcher("/index.jsp").forward(req,resp);
}

上面的方法与普通的查询方法无异,下面才是我们实现模糊查询的重点
public List getForListWithCriteriaCustomer(CriteriaCustomer cc)在CustermDAOJdbcImpl实现类的实现

@Override
    public List getForListWithCriteriaCustomer(CriteriaCustomer cc) {
        String sql = "SELECT id,name,address,phone FROM customers where " +
                " name like ? and address like ? and phone like ?";
        //cc.getName()==null?"%%":"%"+cc.getName()+"%"
        // 修改了CriteriaCustomer 的getter 方法:使其返回的字符串中含有  "%%"
        //若返回值为 null 则返回 "%%"  ,若不为 null 则返回 “%” + value + “%” ,value 位原来的值
        return getForList(sql,cc.getName(),cc.getAddress(),cc.getPhone());
    }

注意到上面的SQL语句:

   String sql = "SELECT id,name,address,phone FROM customers where " +
                " name like ? and address like ? and phone like ?";

采用了的方法来匹配
而且采用了一个 CriteriaCustomer 类来把搜索的数据收集打包起来,CriteriaCustomer 类包括name、address和phone等私有成员,这些成员的setter方法为(以getName为例):

public String getName() {
        if(name == null)
            name = "%%";
        else
            name = "%" + name +"%";
        return name;
    }

为什么采取这样的setter方法呢?
这样是为了使得SQL语句中 ***%%***匹配(相似)方法得以实现。

JSP 上的 jQuery 提示

在这一部分,由于佟刚老师的IDE是eclipse,而用的idea,在MVC工程中引入jQuery的方式不一样,导致我被坑了好久T_T
那么在idea工程中,在JSP中改如何引入jQuery呢?
最简单的添加方式就是,直接在JSP中写入:


然后,将鼠标光标放在这行代码上按下Alt+enter。具体可以看这个教程(传送门)。

不过,引入后可能还要到一个地方删除掉,这个要看到时候是否会报什么错误。
js+jQuery实现:“确定要删除 xx 的信息吗?”
方法①




方法②



至此,这个MVC小项目就结束啦!

JavaWeb学习笔记–其他文章

你可能感兴趣的:(Servlet,MVC,JSP,JavaWeb)