• [Servlet 4]Bean与DAO设计模式


    本次属于Java Servlet/JSP 最后的笔记内容了,常见的几大板块均以结束了。这一模块是Java Bean与DAO设计模式,这个是相当重要的。主要是涉及到类的编写与数据库操作上面。
    这里对JavaEE部分做一个总结,供大家学习参考,每篇博客也非常详实,希望对你有所帮助:
    环境配置
    JSP基础知识
    Servlet请求与响应
    Servlet会话管理与监听器,过滤器

    其中Java Bean就是类,本博客以一个Product 类层层递进,并在DAO设计模式中完成了主要的增删改查部分,是一个小型的CRUD练手项目,快速掌握DAO的例子。

    DAO设计模式,主要是为了降低耦合度,易于理解,也是非常容易入门的设计模式。在实际开发中,DAO设计模式虽然过时,但是其思想依旧深远!

    本次模块结束后,将会抽时间综合前面的内容完成一个简易的系统内容。(主要也是恶补一下前端知识了),预计最快这周,如果比较紧将会在下周如约而至。等相应的模块结束后,就得紧跟着了进行Spring大家庭了!

    Java Bean

    基本概念

    开发软件过程中,尽量将业务逻辑和表现层分开,从而达到解耦,这是软件分层设计的基本理念。在JSP中,经常利用Java Bean实现核心的业务逻辑,而JSP页面用于表现层。

    在这种设计模式下,JSP页面只用于接收用户的输入以及显示处理之后的结果,因此不需要在JSP嵌入大量的Java代码,不但提高了系统的可维护性,而且方便工作的分工。
    下面以一个例子来说明:

    public class User implements Serializable {
    	private String username;
    	private String passwd;
    	private String sex;
    
    	public User(){}
    
    	//下面是get 和 set 方法,必须是public
    	public String getUsername() {
    		return username;
    	}
    	
    	public void setUsername(String username){
    		this.username = username;
    	}
    	...
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    这就是一个Java Bean 的基本结构,遵循的规范:必须是public类,提供给JSP页面调用的方法,属性必须提供get/set,必须拥有不带参数的构造方法。

    JSP 使用Bean

    在JSP页面中使用Bean:1.规范定义Bean,给出get 和set 2.在页面中导入Bean类。 3.利用jsp:useBean使用Bean类
    规范定义Bean类:新增一个类就可以。一种将Bean的class文件部署在Web服务器公共目录中;另一种将Class文件部署在特定目录,Web-INF\classess
    在JSP页面中导入相应的Bean类:

    <jsp:useBean
    	id="beanInstanceName">
    
    • 1
    • 2
    属性值说明
    idBean变量名
    classBean的类路径,严格的package.class
    scopeBean有效范围,取值为page ,request,session,application
    beanName实例化的类名或序列化模板名称
    typeMap,HashMap

    访问Bean属性

    设置属性:

    <jsp:setProperty
    name = "beanInstanceName"
    {
    property = "*" |
    }
    />
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    表达式设置属性

    利用表达式来设置Bean属性值,意思就是在jsp中使用value来进行set

    # product.jsp
    <%@ page  contentType="text/html;charset=UTF-8" language="java"  import="java.util.*" %>
    <jsp:useBean id="product" class ="BeanTest.Product" scope="page"/>
    <html>
    <head>
      <title>Title</title>
    </head>
    <body>
    <jsp:setProperty name="product" property="product_name" value="Book"/>
    产品名称:
    <%=product.getProduct_name()%>
    
    </body>
    </html>
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    上述代码只是简单设置了Bean值,导入Bean类,分别设定了Bean属性值和获取Bean属性值

    package BeanTest;
    
    import java.io.Serializable;
    
    public class Product implements Serializable {
        private static  final  long serialVersionUID = 1L;
        private  String product_id;
        private  String product_name;
        private  double price;
        private  String info;
    
        public Product(){
            super();
        }
    
        public String getProduct_name() {
            return product_name;
        }
        public void setProduct_name(String name) {
            this.product_name = name;
        }
        public String getProduct_id() {
            return product_id;
        }
        public void setProduct_id(String id) {
            this.product_id = id;
        }
        public double getPrice() {
            return price;
        }
        public void setPrice(double price) {
            this.price = price;
        }
    
        public String getInfo() {
            return info;
        }
        public void setInfo(String info) {
            this.info = info;
        }
    }
    
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43

    表单设置属性

    通过表单参数来设置属性值
    这样就不用设置value值。

    # product.jsp
    # Bean类不用修改
    <body>
      <form action="" method="post">
          输入产品名称:<input name="product_name" />
          <input type="submit" value="submit"/>
      </form>
      <jsp:setProperty name="product" property="product_name"/>
      <%=product.getProduct_name()%>
      或者以下的方法,只是通过参数值来设置的
      <jsp:setProperty name="product" property="productname" param="product_name"/>
    </body>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    取得属性

    name就是Bean名字,值必须是jsp:useBean中的id值

    <jsp:getProperty name="beanInstacnceName" property="propertyName"/>
    
    • 1

    Bean的作用域

    Bean的作用域有4个:page request session application,作用范围有scope,默认是page,即该Bean在当前页有效。

    # 写一个请求的param
    <%
    	String r = request.getParameter("radius");
    	if(r == null || r.equals("")) r ="1";
    	double rad = Double.parseDouble(r);
    	circle.setR(rad);
    %>
    <body>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    DAO 设计模式

    这是一个值得学习的设计模式。虽然如今有很多成熟的框架了,例如Spring MVC ,Struts等
    信息系统的开发架构如下:
    客户层—显示层—业务层—数据层—数据库
    客户层:客户端浏览器
    显示层:利用JSP和Servlet进行页面显示
    业务层:对数据层原子性DAO操作进行整合
    数据层:数据增删改查
    数据库:保存数据库信息
    DAO:Data Access Object。主要是对数据进行操作,对于上面层级就是数据层。在数据操作中,主要以面向接口编程为主。一般DAO分为:
    VO(Value Object),DatabaseConnection,DAO-implements,DAOImpl,DAOproxy,DAOFactory
    DAO命名规则:XxxDAO.

    DAO开发

    首先建一个产品表

    use dao_product
    
    create table product(
        idc varchar(20) not null ,
        product_name varchar(20) default null,
        price decimal(6,2) default  null,
        info varchar(100) default null,
        primary key (idc)
    )
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    在src/TestBean文件如下:
    在这里插入图片描述
    首先是DBConnection类,只要是执行对数据库的连接配置,注意这里驱动最好写成com.mysql.cj.jdbc.Driver,这里用于获取数据库连接.

    DBConnection

    package BeanTest;
    
    import java.sql.Connection;
    import java.sql.DriverManager;
    
    public class DBConnection {
        private  static  final  String Driver = "com.mysql.cj.jdbc.Driver";
        private  static  final  String URL = "jdbc:mysql://127.0.0.1:3306/dao_product";
        private static  final  String USER = "root";
        private  static  final  String PASSWORD = "qazwsx123";
        private Connection conn = null;
    
        //数据库连接
        public DBConnection() throws  Exception {
            try{
                Class.forName(Driver); //反射加载驱动
                this.conn = DriverManager.getConnection(URL,USER,PASSWORD);
            }catch (Exception e) {
                throw e;
            }
        }
    
        //取得连接
        public Connection getConnection() {
            return this.conn;
        }
    
        public void close() throws Exception{
            if(this.conn != null) {
                try{
                    this.conn.close();
                }catch (Exception ex) {
                    ex.printStackTrace();
                }
            }
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38

    新建DAO接口类,接口类在DAO设计模式中极其重要。定义接口类之前,需要分析业务的需求,分析清楚系统需要哪些功能,方法。本例只完成新增,查询等简单功能。

    ProductDao

    package BeanTest;
    import java.util.List;
    
    public interface ProductDao {
    
        public boolean addProduct(Product product) throws Exception;
    
        public List<Product> findAll(String product_name) throws Exception;
    
        public  Product findByProductID(String product_id) throws  Exception;
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    在DAO接口定义完成后需要定义其实现类,为降低耦合度(耦合度就是模块与模块之间的关联),需要有实现类。一种是数据操作实现类,另一种是业务操作实现类。

    ProductDaoImpl

    数据操作实现类,完成的是具体的数据库操作。

    package BeanTest;
    
    import sun.dc.pr.PRError;
    
    import java.sql.Connection;
    import java.sql.PreparedStatement;
    import java.sql.ResultSet;
    import java.util.ArrayList;
    import java.util.List;
    
    public class ProductDaoImpl implements  ProductDao{
        private Connection conn = null;
        private PreparedStatement pstmt = null;
    
        public ProductDaoImpl(Connection conn) {
            this.conn = conn;
        }
    
        @Override
        public boolean addProduct(Product product) throws Exception {
            boolean flag = false;
            String sql = "insert  into product(idc,product_name,price,info) values(?,?,?,?)";
            this.pstmt = this.conn.prepareStatement(sql);
            this.pstmt.setString(1,product.getProduct_id());
            this.pstmt.setString(2,product.getProduct_name());
            this.pstmt.setDouble(3,product.getPrice());
            this.pstmt.setString(4,product.getInfo());
            int t = this.pstmt.executeUpdate();
            //System.out.println(t);
            if(t>0) {
                flag = true;
            }
            this.pstmt.close();
            return flag;
        }
    
        @Override
        public List<Product> findAll(String product_name) throws Exception {
            List<Product> list = new ArrayList<Product>();
            String sql = "select idc ,product_name,price,info from product";
            if(product_name != null &&!"".equals(product_name)) {
                sql ="select idc,product_name,price,info from product where product_name like ?";
                this.pstmt = this.conn.prepareStatement(sql);
                this.pstmt.setString(1,"%" +product_name+"%");
               
            }else {
                this.pstmt = this.conn.prepareStatement(sql);
            }
            ResultSet rs = this.pstmt.executeQuery();
            Product product = null;
            while(rs.next()) {
                product = new Product();
                product.setProduct_id(rs.getString(1));
                product.setProduct_name(rs.getString(2));
                product.setPrice(rs.getDouble(3));
                product.setInfo(rs.getString(4));
                list.add(product);
            }
            this.pstmt.close();
            return list;
        }
    
        @Override
        public Product findByProductID(String product_id) throws Exception {
            Product product = null;
            String sql = "select idc,product_name,price,info from product where idc = ?";
            this.pstmt = this.conn.prepareStatement(sql);
            this.pstmt.setString(1,product_id);
            ResultSet rs = this.pstmt.executeQuery();
            if(rs.next()) {
                product = new Product();
                product.setProduct_id(rs.getString(1));
                product.setProduct_name(rs.getString(2));
                product.setPrice(rs.getDouble(3));
                product.setInfo(rs.getString(4));
            }
    
            this.pstmt.close();
            return product;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81

    ProductService

    对数据库的打开和关闭由业务操作实现类完成。业务操作类ProductService:

    package BeanTest;
    
    import java.util.List;
    import BeanTest.ProductDaoImpl;
    
    public class ProductService implements  ProductDao{
        private  DBConnection dbconn = null;
        private  ProductDao dao = null;
    
        public ProductService() throws  Exception {
            this.dbconn = new DBConnection();
            this.dao = new ProductDaoImpl(this.dbconn.getConnection());
        }
    
        @Override
        public boolean addProduct(Product product) throws Exception {
            boolean flag = false;
    
            try{
                if(this.dao.findByProductID(product.getProduct_id()) == null) {
                    //如果插入的产品编号不存在,那么就新增一条产品
                    flag = this.dao.addProduct(product);
                }
            }catch (Exception ex) {
                ex.printStackTrace();
            }finally {
                this.dbconn.close();
            }
    
            return flag;
        }
    
        @Override
        public List<Product> findAll(String product_name) throws Exception {
            List<Product> all = null;
            try{
                all = this.dao.findAll(product_name);
            }catch (Exception ex) {
                ex.printStackTrace();
            }finally {
                this.dbconn.close();
            }
            return all;
        }
    
        @Override
        public Product findByProductID(String product_id) throws Exception {
            Product product = null;
            try{
                product = this.dao.findByProductID(product_id);
            }catch (Exception ex) {
                ex.printStackTrace();
            }finally {
                this.dbconn.close();
            }
            return product;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58

    DAOFactory

    编写DAO工厂类,用来获得业务操作类,在后续的客户端可以直接通过工厂获得DAO接口的实例对象:

    package BeanTest;
    
    public class DAOFactory {
        public static ProductDao getIEmpDAOInstance() throws Exception {
    
            return new ProductService(); //取得业务操作
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    这是一个测试文件:

    package BeanTest;
    
    public class TestInsertProduct {
        public static  void main(String[] args) {
            Product product = null;
            try{
                for(int i=99;i<105;i++) {
                    product = new Product();
                    product.setProduct_id("000"+i);
                    product.setProduct_name("水杯"+i);
                    product.setPrice(100+i);
                    product.setInfo("这是杯子"+i);
                    DAOFactory.getIEmpDAOInstance().addProduct(product);
                }
            }catch (Exception ex) {
                ex.printStackTrace();
            }
            System.out.println("suss");
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    JSP调用DAO

    编写一个DAO后,可以结合JSP一起实现前台的显示。

    # product_insert.jsp
    <%@ page import="java.util.*" contentType="text/html;charset=UTF-8" language="java" %>
    <%@ page import="BeanTest.DAOFactory" import ="BeanTest.Product" %>
    <%
        request.setCharacterEncoding("utf-8");
    %>
    <html>
    <head>
        <title>Title</title>
    </head>
    <body>
        <%
            Product product = new Product();
            product.setProduct_id(request.getParameter("product_id"));
            product.setProduct_name(request.getParameter("product_name"));
            product.setPrice(Double.parseDouble(request.getParameter("price")));
            product.setInfo(request.getParameter("info"));
            boolean flag = DAOFactory.getIEmpDAOInstance().addProduct(product);
            if(flag){
        %>添加成功
        <%
            }else{
        %>添加失败
        <%
            }
        %>
    </body>
    </html>
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29

    提交信息并跳转:

    # product_add.jsp
    <%@ page contentType="text/html;charset=UTF-8" language="java" import="java.util.*" %>
    <html>
    <head>
        <title>Add Info</title>
    </head>
    <body>
    <form action="product_insert.jsp"  method="post">
        产品编号: <input name ="product_id"/><br>
        产品名称: <input name ="product_name"/><br>
        产品价格: <input name ="price"/><br>
        产品信息: <textarea rows="" cols="" name="info" ></textarea><br>
        <input type="submit" value="添加">
        <input type="reset" value="重置">
    </form>
    </body>
    </html>
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    查询页面:

    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <%@page import="java.util.*"  %>
    <%@ page import="BeanTest.Product" %>
    <%@ page import="BeanTest.DAOFactory" %>
    <%
        request.setCharacterEncoding("utf-8");
    %>
    <html>
    <head>
        <title>Title</title>
    </head>
    <body>
    <%
        String product_name = request.getParameter("product_name");
        List<Product> list = DAOFactory.getIEmpDAOInstance().findAll(product_name);
    
    %>
    <form action="product_list.jsp" method="post">
        输入产品名称: <input name ="product_name"/>
        <input type="submit" value="提交">
    </form>
    <table border="1">
        <tr>
            <td>产品编号</td>
            <td>产品名称</td>
            <td>产品价格</td>
            <td>产品信息</td>
        </tr>
        <%
            for(int i=0;i<list.size();i++) {
              Product   p =list.get(i);
    
        %>
        <tr>
            <td><%=p.getProduct_id()%></td>
            <td><%=p.getProduct_name()%></td>
            <td><%=p.getPrice()%></td>
            <td><%=p.getInfo()%></td>
        </tr>
        <% } %>
    </table>
    </body>
    </html>
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44

    Bug小插曲

    在编写DAO类的时候,一直遇到这个问题,Duplicate entry ‘00099’ for key ‘PRIMARY’,我是真的醉了,把每一个类重新看了n遍。由于这是插入值抛出的异常。
    当然了,正常思维还是搜索,有很多人说是因为主键插了重复的值原因,但是我根本没有重复值。
    后来得益于这篇博客的启发,点击此处,在insert的时候使用insert ignore,这时候确实成功了。上面这篇博客也说可以设置一个自增主键id,那我索性也就设置了,后来运行出来没有那个问题了。

    但当我重新审计代码时候,发现在实现接口的部分,在add部分犯了致命的错误,方法返回值是false,而不是flag.当我重新改了这个错误的时候,成功运行出来了。

    不过一开始抛出来的Duplicate entry primary确实让我迷惑了很久,没想到不是这个问题(简直把我往错误的方向跑了)。看来日后code仍需要仔细啊!

    以上就是全部内容了,希望有所帮助。

  • 相关阅读:
    vue3 ElementUI Switch before-change自动调用问题
    通过 urllib 结合代理IP下载文件实现Python爬虫
    关于springboot的优雅停机和健康检查配置(用于k8s服务重启)
    Django的message组件(源码分析)
    ctfshow 反序列化篇(下)
    人工智能在医疗领域的革命性应用
    ssm基于Java的微小企业人事管理系统的设计与实现毕业设计源码231012
    [含毕业设计论文+PPT+源码等]ssm后勤服务|会议室预约|办公管理管理系统小程序+Java后台管理系统|前后分离VUE
    国标视频平台搭建(七)配置https访问
    项目之利用 V4L2应用程序框架 进行视频录制
  • 原文地址:https://blog.csdn.net/QAZJOU/article/details/126682339