Novice web development simple summary (eight)-database HSQLDB instance

table of Contents

I. Introduction

Two examples

1. Create a project

2. Part of the example code

Three summary

 


I. Introduction

In the previous article, a simple summary of web development by Xiaobai novices (7)-database HSQLDB learned what an HSQLDB database is. This article uses an example to see how the web application reads the HSQLDB database. Although the code used in it is not necessarily the most accurate, but through this example, I have accumulated some more knowledge points for web application development.

Two examples

1. Create a project

At present, it is not clear what project should be created for a specific web application. I have been creating a webapp project at the beginning, but found that I don’t know why the created Sevelet cannot be accessed after packaging. So after many explorations, I think that the creation should be created as follows The project that comes out is the most suitable.

  • (1) Through File -> new -> project... the following dialog box pops up, select Java Enterprise, and click Next

  •  (2) Set the directory and name of the project, and set the required Artiface related information

After the above steps, you can see a basic project structure. After clicking Run, you can run the project according to the configuration of Tomcat (of course, IDEA is required to be a professional version, and the community version does not have this option). In this way, the default URL of the homepage displayed by the browser is http://localhost:8080/sql-web-war-exploded/, which leads to the need to add the string when adding a new Servlet later It can be accessed successfully. Later, I thought of removing the fixed strings in these two places, but I didn't expect it to succeed. Here we have to study why this is the case in the future. Here are the steps to remove sql-web-war-exploded/:

  • (1) Open Edit Configurations through the following icon

  • (2) The main changes are shown in the two places as shown in the figure

In this way, you can directly access the set Servlet through http://localhost:8080/

During the Run process, I also encountered a problem: the following error message was displayed on the terminal interface. This error message was big at first, because this error was also thrown when running the company’s project at that time. I ran a successful project through IDEA’s Tomcat, but this time I bit my head and analyzed the error carefully, and suddenly found the key error message "Caused by: java.net.BindException: Address already in use" (because it was previously in order to be able to create a suitable Project, running multiple projects), and then suddenly realized that port 8080 is occupied? ?

26-Feb-2021 10:43:59.686 信息 [main] org.apache.catalina.core.AprLifecycleListener.lifecycleEvent 在java.library.path:[/Users/j1/Library/Java/Extensions:/Library/Java/Extensions:/Network/Library/Java/Extensions:/System/Library/Java/Extensions:/usr/lib/java:.]上找不到基于APR的Apache Tomcat本机库,该库允许在生产环境中获得最佳性能
26-Feb-2021 10:43:59.949 信息 [main] org.apache.coyote.AbstractProtocol.init 初始化协议处理器 ["http-nio-8080"]
26-Feb-2021 10:43:59.971 严重 [main] org.apache.catalina.util.LifecycleBase.handleSubClassException 初始化组件[Connector[HTTP/1.1-8080]]失败。
	org.apache.catalina.LifecycleException: 协议处理程序初始化失败
		at org.apache.catalina.connector.Connector.initInternal(Connector.java:1042)
		at org.apache.catalina.util.LifecycleBase.init(LifecycleBase.java:136)
		at org.apache.catalina.core.StandardService.initInternal(StandardService.java:558)
		at org.apache.catalina.util.LifecycleBase.init(LifecycleBase.java:136)
		at org.apache.catalina.core.StandardServer.initInternal(StandardServer.java:1057)
		at org.apache.catalina.util.LifecycleBase.init(LifecycleBase.java:136)
		at org.apache.catalina.startup.Catalina.load(Catalina.java:724)
		at org.apache.catalina.startup.Catalina.load(Catalina.java:746)
		at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
		at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
		at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
		at java.lang.reflect.Method.invoke(Method.java:498)
		at org.apache.catalina.startup.Bootstrap.load(Bootstrap.java:302)
		at org.apache.catalina.startup.Bootstrap.main(Bootstrap.java:472)
/其实这里是报错的主要原因,太开心了,终于找到问题了!!!!!!!!
	Caused by: java.net.BindException: Address already in use
		at sun.nio.ch.Net.bind0(Native Method)
		at sun.nio.ch.Net.bind(Net.java:433)
		at sun.nio.ch.Net.bind(Net.java:425)
		at sun.nio.ch.ServerSocketChannelImpl.bind(ServerSocketChannelImpl.java:223)
		at sun.nio.ch.ServerSocketAdaptor.bind(ServerSocketAdaptor.java:74)
		at org.apache.tomcat.util.net.NioEndpoint.initServerSocket(NioEndpoint.java:228)
		at org.apache.tomcat.util.net.NioEndpoint.bind(NioEndpoint.java:211)
		at org.apache.tomcat.util.net.AbstractEndpoint.bindWithCleanup(AbstractEndpoint.java:1159)
		at org.apache.tomcat.util.net.AbstractEndpoint.init(AbstractEndpoint.java:1172)
		at org.apache.coyote.AbstractProtocol.init(AbstractProtocol.java:592)
		at org.apache.coyote.http11.AbstractHttp11Protocol.init(AbstractHttp11Protocol.java:80)
		at org.apache.catalina.connector.Connector.initInternal(Connector.java:1039)
		... 13 more
26-Feb-2021 10:43:59.972 信息 [main] org.apache.catalina.startup.Catalina.load 服务器在[477]毫秒内初始化
26-Feb-2021 10:44:00.002 信息 [main] org.apache.catalina.core.StandardService.startInternal 正在启动服务[Catalina]
26-Feb-2021 10:44:00.002 信息 [main] org.apache.catalina.core.StandardEngine.startInternal 正在启动 Servlet 引擎:[Apache Tomcat/9.0.41]
26-Feb-2021 10:44:00.011 信息 [main] org.apache.catalina.startup.Catalina.start [39]毫秒后服务器启动
Connected to server
[2021-02-26 10:44:00,145] Artifact sql-web:war exploded: Artifact is being deployed, please wait...
[2021-02-26 10:44:00,454] Artifact sql-web:war exploded: Artifact is deployed successfully
[2021-02-26 10:44:00,454] Artifact sql-web:war exploded: Deploy took 310 milliseconds
26-Feb-2021 10:44:10.015 信息 [Catalina-utility-2] org.apache.catalina.startup.HostConfig.deployDirectory 把web 应用程序部署到目录 [/Users/j1/Documents/java/apache-tomcat-9.0.41/webapps/manager]
26-Feb-2021 10:44:10.047 信息 [Catalina-utility-2] org.apache.catalina.startup.HostConfig.deployDirectory Web应用程序目录[/Users/j1/Documents/java/apache-tomcat-9.0.41/webapps/manager]的部署已在[32]毫秒内完成

Immediately verify my thoughts, find all the processes on port 8080 through "lsof -i:8080", and found that several processes in it are occupying port 8080, and finally kill each process through "kill -9 process pid". Finally, it was found that there was no process occupying port 8080, and the project was run through run tomcat again, and it was found that the project ran successfully. When the operation is completed, the content of the home page will be automatically loaded in the browser.

MacBook-Pro:bin j1$ lsof -i:8080
COMMAND    PID USER   FD   TYPE             DEVICE SIZE/OFF NODE NAME
?\x81?   375   j1   19u  IPv4 0xbf83bb36d15dbe79      0t0  TCP 172.16.20.11:49239->157.255.245.177:http-alt (ESTABLISHED)
?\x81?   375   j1   32u  IPv4 0xbf83bb36d15ddc19      0t0  TCP 172.16.20.11:49241->reverse.gdsz.cncnet.net:http-alt (ESTABLISHED)
?\x81?   375   j1  131u  IPv4 0xbf83bb36d2ccd0d9      0t0  TCP 172.16.20.11:50159->157.255.245.177:http-alt (ESTABLISHED)
java      2632   j1   37u  IPv6 0xbf83bb36d7b03069      0t0  TCP *:http-alt (LISTEN)
MacBook-Pro:bin j1$ kill -9 375
MacBook-Pro:bin j1$ kill -9 2632
MacBook-Pro:bin j1$ lsof -i:8080
MacBook-Pro:bin j1$

2. Part of the example code

A book management system: There are two main interfaces: one is the interface for entering book information; the other is the interface for enumerating all the entered book lists. Because I think these two operations can just be used to modify the database under the actual code.

  • (1) Add project dependencies

    <dependencies>
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <version>4.0.1</version>
            <scope>provided</scope>
        </dependency>

        <!--IoC容器-->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>5.2.6.RELEASE</version>
        </dependency>
        <!--使用里面的一些帮助类如SpringBeanAutowiringSupport -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-web</artifactId>
            <version>5.2.6.RELEASE</version>
        </dependency>
        <!--通过注解标记不同类的功能,让IoC容器管理对应的对象-->
        <dependency>
            <groupId>javax.annotation</groupId>
            <artifactId>javax.annotation-api</artifactId>
            <version>1.3.2</version>
        </dependency>
        <!--jdbc接口-->
        <!--        <dependency>-->
        <!--            <groupId>org.springframework</groupId>-->
        <!--            <artifactId>spring-jdbc</artifactId>-->
        <!--            <version>5.2.5.RELEASE</version>-->
        <!--        </dependency>-->
        <!--hsqldb数据库-->
        <dependency>
            <groupId>org.hsqldb</groupId>
            <artifactId>hsqldb</artifactId>
            <version>2.5.0</version>
        </dependency>
        <!-- 与jsp中的C标签相关的依赖-->
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>jstl</artifactId>
            <version>1.2</version>
        </dependency>
        <dependency>
            <groupId>taglibs</groupId>
            <artifactId>standard</artifactId>
            <version>1.1.2</version>
        </dependency>

    </dependencies>

See the code comments for the specific corresponding dependency-related functions.

  • (2) To create a Book object, it is very simple to have four attributes: id, book name, price, and shelf time

The code here is relatively simple, so I won’t add it here, I will upload all the code to github

  • (3) Create the operation database configuration class JdbcConfiguration to read the related configuration information of the database
@Configuration
@PropertySource("classpath:/config/jdbc.properties")
public class JdbcConfiguration {
    @Value("${jdbc.url}")
    public String jdbcUrl ; //= "jdbc:hsqldb:file:db/hsqldb/xbook";
    @Value("${jdbc.user}")
    public String jdbcUser;// = "SA";
    @Value("${jdbc.password}")
    public String jdbcPassword;// = "";
    @Value("${jdbc.table}")
    public String jdbcTable;// = "book";

    public Connection connection;

    @PostConstruct
    public void init(){
        System.out.println("创建Jdbc 。。。。。。 ");

    }

    public Statement createStatement() {
        try {
            Class.forName("org.hsqldb.jdbcDriver");
        } catch (ClassNotFoundException e) {
            System.out.println("jdbcDriver not found!!!");
            return null;
        }
        try {
            //JDBC不支持自增,创建或连接数据库
            connection = DriverManager.getConnection(jdbcUrl, jdbcUser, jdbcPassword);
            if (connection == null) {
                return null;
            }
            //创建里面的表
            Statement statement = connection.createStatement();
            return statement;
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }
        return null;
    }

    public void closeConnection(){
        if (connection == null){
            return;
        }
        try {
            connection.close();
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }
    }
}

Here is a simple summary of the novice web development for Xiaobai (7)-The creation method of a process mode database in the database HSQLDB and a simple summary of the novice web development for Xiaobai (6)-Spring's IoC container  is read through the @PropertySource annotation The related content of the resources configuration file, and the subsequent instantiation of all classes are also marked by @Component, and all JavaBeans are loaded through Spring. At the same time, you need to add jdbc.properties under resources/config to configure the basic information of the HSQLDB database. The configuration content is as follows:

#hsqldb的相关配置
#最后会在apache/bin的目录下生成该数据库
jdbc.url = jdbc:hsqldb:file:db/hsqldb/xbook
jdbc.user = SA
jdbc.password =
jdbc.table = book
  • (4) Add, delete, modify, and check operation class DbOperation of the database
@Component
public class DbOperation {
    @Autowired
    public JdbcConfiguration jdbcConfiguration;

    /**
     * 创建表
     *
     * @param sql
     * @return
     */
    public int createTable(String sql) {
        Statement statement = jdbcConfiguration.createStatement();
        try {
            int result = statement.executeUpdate(sql);
            System.out.println(String.format("创建表的结果为 %d", result));
            return result;
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }
        System.out.println("创建表失败了!!!");
        return -1;

    }

    /**
     * 查询
     *
     * @param sql
     * @return
     */
    public ResultSet query(String sql) {
        Statement statement = jdbcConfiguration.createStatement();
        try {
            ResultSet set = statement.executeQuery(sql);
            return set;
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }
        return null;
    }

    /**
     * 插入
     *
     * @param sql
     * @return
     */
    public int insert(String sql) {
        Statement statement = jdbcConfiguration.createStatement();
        try {
            int set = statement.executeUpdate(sql);
            return set;
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }
        return -1;
    }

    public void closeTable() {
        jdbcConfiguration.closeConnection();
    }

}

I think spring-jdbc, etc. can directly replace this part of the operation. Some framework things introduced in the project are all to make these processes more efficient and better. I am here mainly to learn a basic process of operating the database, so I first verify these contents according to my own ideas.

  • (5) Enter a book related to business logic and get all the books in the database
@Component
public class BookManagerService {
    @Autowired
    public DbOperation dbOperation;

    @Value("#{jdbcConfiguration.jdbcTable}")
    private String jdbcTable;


    @PostConstruct
    public void createBookTable() {
        System.out.println("BookManagerService 初始化 自动创建表!!!");
        String sql = String.format("CREATE TABLE IF NOT EXISTS %s " +
                "(id INTEGER PRIMARY KEY , name VARCHAR(50) NOT NULL, price DOUBLE, online DATE)", jdbcTable);
        int result = dbOperation.createTable(sql);
        System.out.println(String.format("BookManagerService 创建 %s 表的结果为 %d", jdbcTable, result));
    }

    public int addBook(Book book) {
        //  因为暂时不知道让id自加1,所以用这种笨方法先记录下
        String sql = String.format("SELECT * FROM %s ", jdbcTable);
        int count = 0;
        try {
            ResultSet set = dbOperation.query(sql);
            while (set.next()) {
                count++;
            }
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }
        //在总行数的基础上在加1,得到新数据的id
        int id = count + 1;
        // 插入新的数据
        String insert = String.format("INSERT INTO %s \n" +
                "(id, name, price, online)\n" +
                "VALUES (%d , '%s', %f,'%s' )", jdbcTable, id, book.name, book.price, book.online);
        int result = dbOperation.insert(insert);

        System.out.println(String.format("%s已经成功加入数据库,目前数据库总共有%d条数据 ", book.name, result));
        return result;
    }

    public List<Book> getBook() {
        List<Book> books = new ArrayList<>();
        String sql = String.format("SELECT * FROM %s ", jdbcTable);
        ResultSet set = dbOperation.query(sql);
        if (set == null) {
            return books;
        }
        try {
            while (set.next()) {
                Book book = new Book();
                book.id = set.getInt(1);
                book.name = set.getString(2);
                book.price = set.getFloat(3);
                book.online = set.getDate(4).toString();
                System.out.println("查询的数据为:" + book.toString());
                books.add(book);
            }
            return books;
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return books;
    }

    @PreDestroy
    public void closeBookTable() {
        System.out.println("BookManagerService初始化自动关闭表!!!");
        dbOperation.closeTable();
    }
}

The code logic here is very simple, that is, read and write the database through the DbOperation class above.

  • (6) HttpServlet and jsp cooperate for page rendering

BookListController inherits HttpServlet, which is used to receive the request sent by the browser and process the request back to the browser.

@WebServlet(name = "BookListServlet", value = "/booklist")
public class BookListController extends BaseHttpServlet {
    @Autowired
    public BookManagerService bookManagerService;

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        List<Book> books = bookManagerService.getBook();
        System.out.println("book size = " + books.size());
        req.setAttribute("book", books);
        req.getRequestDispatcher("/book/booklist.jsp").forward(req, resp);
    }
}

The booklist.jsp mainly renders the book list page. 

<%@ page import="java.util.List" %>
<%@ page import="com.wj.hsqldb.model.Book" %><%--
  Created by IntelliJ IDEA.
  User: j1
  Date: 2021/2/25
  Time: 16:33
  To change this template use File | Settings | File Templates.
--%>
<%--需要导入C标签该包--%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>

<html>
<head>
    <title>图书列表</title>
</head>
<body>

<table width="50%" border="1px" style="margin-top: 50px;" title="${display}">

    <tr> <!--加粗-->
        <th>Book id</th>
        <th>Book name</th>
        <th>Book price</th>
        <th>Book online</th>
    </tr>

    <%--    使用el的条件:如果用的servlet-api.jar包低于javax.servlet-api-3.0.1版本,web版本必须是3.0之前的。--%>
    <c:forEach items="${book}" var="it">

        <tr style="color: red;alignment: center">
            <td>${it.id}</td>
            <td>${it.name}</td>
            <td>${it.price}</td>
            <td>${it.online}</td>
        </tr>
    </c:forEach>

</table>


<input type="button" value="添加图书"
       style="color: aqua; width: 10%;height: 5%;font-size: larger;margin-top: 50px;background: yellow;"
       onclick="window.location.href='/book/addbook.jsp'">
</body>
</html>

Here is only one logic of listing a book list page separately, that is, to display a table of the book list, and other specific codes can be downloaded directly from the git address to see. The github address is: https://github.com/wenjing-bonnie/sql-web.git .

  • (7) Configure web.xml

This step is very important, and it is also a key point in solving some problems that arise later.

<?xml version="1.0" encoding="UTF-8"?>

<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
         version="4.0">

    <display-name>Sql-Web</display-name>
    <!--这种处理方式是错误的-->
    <!--    <listener>-->
    <!--        <listener-class>com.wj.hsqldb.SpringContextListener</listener-class>-->
    <!--    </listener>-->
    <!--用来配置Spring的配置文件-->
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:config/application-context.xml</param-value>
    </context-param>
    <!--用来创建Spring的IoC容器,并完成与ServletContext的绑定-->
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>

</web-app>

After the above several processes, start the project through IDEA's tomcat, it will automatically load http://localhost:8080 in the browser, and see the effect you want. The database created inside will generate the database in the bin directory of the apache local default.

The code has been uploaded to the github address: https://github.com/wenjing-bonnie/sql-web.git . Because the code is always being updated, the tag of the code here is marked as example8 (because the project is always being updated, this time the code is marked by tagging) , namely

You need to switch the code to this tag, and the code before this tag will continue to learn the optimized code later.

Three summary

The code in the above example is the final code that I can successfully run the project after repeatedly solving various problems. These codes are not the focus of my summary. Because it is Android development, it is too simple to write these Java codes. I mainly want to summarize some of the problems encountered in this process, and also make me have a deeper impression of web development. Of course, I also have some questions, and I need to go later. Solve one by one.

There will be a separate summary later, a simple summary of novice web development for novices (ten)-a summary of database HSQLDB instance problems .

 

Guess you like

Origin blog.csdn.net/nihaomabmt/article/details/114119786