Novice web development simple summary (ten)-summary of database HSQLDB instance problems

 

table of Contents

One problem summary

1. The instantiation of these JavaBeans such as Book and DbOperation

Question 1: @ComponentScan has a scanning range

Question 2: Using @Autowired annotated instance in HttpServlet, report "NullPointerException"

2. EL expression

Question 1: Use of c:foreach

Question 2: Using $() has always been invalid

3.JDBC

Second summary


A simple summary of the novice web development in Xiaobai (8)-Database HSQLDB instance The code in the example above 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. This article is mainly to summarize some of the problems encountered.

One problem summary

1. The instantiation of these JavaBeans such as Book and DbOperation

For some of these JavaBeans, there are dependencies, so it involves the management process of instantiation and loading of these JavaBeans. It is easy for me to think that I can learn from the simple summary of the novice web development in Xiaobai (6)-Spring The IoC container mentioned annotated way to manage these JavaBeans.

Due to the previous accumulation, the first thing that comes to mind is Spring to manage JavaBeans. It needs to instantiate AnnotationConfigApplicationContext and instantiate it when the web application starts. It is natural to think of implementing a ServletContextListener class, as follows:

@Configuration
@ComponentScan //扫描所在类的包以及子包,来创建@Component的类
public class SpringContextListener implements ServletContextListener {

    @Override
    public void contextInitialized(ServletContextEvent sce) {
        System.out.println("SpringContextListener context Initialized!!! ");
        // bookManagerService.createBookTable();
        //初始化所有的@Component的类
        new AnnotationConfigApplicationContext(SpringContextListener.class);
    }

    @Override
    public void contextDestroyed(ServletContextEvent sce) {
        System.out.println("SpringContextListener context Destroyed!!! ");
    }
}

Through this code, when the web application is started, the AnnotationConfigApplicationContext is initialized, then @Component, @Autowired, etc. annotations can be used, and it is also thought that the listener needs to be configured in web.xml:

    <listener>
         <listener-class>com.wj.hsqldb.SpringContextListener</listener-class>
    </listener>

I thought that everything was in place and a successful operation project could be completed, but I never expected that various problems would ensue.

Question 1: @ComponentScan has a scanning range

I first wrote about the four classes Book, DbOperation, JdbcConfiguration and BookManagerService. I added the testDb() method in the SpringContextListener to verify the correctness of the addition, deletion, modification, and checking of the HSQLDB database. For the detailed code, see The detailed code in com.wj.hsqldb.listener.SpringContextListener unexpectedly reported the following error:


rg.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'com.wj.hsqldb.db.JdbcConfiguration' available
		at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBean(DefaultListableBeanFactory.java:354)
		at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBean(DefaultListableBeanFactory.java:345)
		at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1126)
		at com.wj.hsqldb.model.SpringContextListener.testDb(SpringContextListener.java:44)
		at com.wj.hsqldb.model.SpringContextListener.contextInitialized(SpringContextListener.java:29)
		at org.apache.catalina.core.StandardContext.listenerStart(StandardContext.java:4716)
		at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5177)
  • problem analysis

The general analysis from the above error may be that @Component, @Autowired these annotations are invalid, I suddenly remembered that @ComponentScan has a scanning scope, and it scans the package in which the class is located and the classes under sub-packages by default. And my current project structure is as follows:

Now that the SpringContextListener is placed under the com.wj.hsqldb.listener package, how can it be possible to scan for other classes?

  • solution:

Modify the @ComponentScan of the SpringContextListener class to @ComponentScan("com") . Run the project again, and the home page content successfully appeared.

Question 2: Using @Autowired annotated instance in HttpServlet, report "NullPointerException"

After verifying that there was no error in the addition, deletion, and modification of the database, I started adding HttpServlet code one after another. The general idea is to implement the code:


@WebServlet(name = "BookListServlet", value = "/booklist")
public class BookListController extends HttpServlet {
    @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);
    }
}

I thought that now all JavaBeans can be loaded with Spring, then I can use these JavaBeans directly in HttpServlet, but I did not expect to report the following error:

  • problem analysis

The problem is very simple, that is, the bookManagerService is not instantiated. I found in the initialization method of BookManagerService (marked with @PostConstruct) that the JavaBean was also instantiated, but why does the HttpServlet report a null pointer?

  • solution

Later, I checked various materials and found the essence of the reason: these HttpServlets are instantiated in the Servlet container, and these JavaBeans like BookManagerService are instantiated in the Spring IoC container, so this JavaBean instance cannot be obtained in the HttpServlet . I saw some solutions on the Internet, which is to rewrite the init(config) method of HttpServlet and add the following code in it:

    @Override
    public void init(ServletConfig config) throws ServletException {
        super.init(config);
        ServletContext application = this.getServletContext();     
SpringBeanAutowiringSupport.processInjectionBasedOnServletContext(this,application);
    }

Unexpectedly, something unexpected happened here again, and the following error was reported:

I immediately thought of the simple summary of the novice web development in the previous summary (2)-What is the role of the ContextLoaderListener in web.xml ? This ContextLoaderListener reads the configuration file specified by the contextConfigLocation when the web application is started, automatically The ApplicationContext is assembled, and this ApplicationContext is Spring's IoC, and the ApplicationContext will be bound to the ServletContext. So I deliberately studied the source code of ContextLoaderListener, see Xiaobai novice web development brief summary (9)-ContextLoaderListener .

So the ultimate solution to this problem 2 is the first part: introduce the ContextLoaderListener listener in web.xml.

    <!--用来配置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>

Simply introducing this listener cannot ultimately solve this problem. From the source code, you can see that these JavaBeans are configured through configuration files by default. I added the <bean> through the configuration file at the beginning, but there are still problems like this. When I first came into contact with Spring MVC, I could directly use some @Controller, @Autowired and other annotations, so the effort paid off, and finally I found the second part of the solution : that is, the configuration corresponding to the contextConfigLocation The following content is added to the file:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">
    <!--可通过注解配置JavaBean-->
    <context:annotation-config/>
    <context:component-scan base-package="com.wj"/>
</beans>

At this time, @Controller and @Autowired can be used in non-HttpServlet. There is no problem, but the problem of using the JavaBean in the Serlvet container is still not solved. This requires the third part of the solution : rewriting the init(config of HttpServlet) ) Method , add the following code in it:

    @Override

    public void init(ServletConfig config) throws ServletException {
        super.init(config);
        ServletContext application = this.getServletContext();    
SpringBeanAutowiringSupport.processInjectionBasedOnServletContext(this,application);
    }

After the above three parts, the problem was finally solved 2: The instance of @Autowired annotation in HttpServlet was reported as "NullPointerException".

2. EL expression

Question 1: Use of c:foreach

When using c:foreach, it has been unable to achieve the desired effect

  • problem causes

The .jsp file has something different from Android development, such as using c:foreach. Since tablib was not introduced at the beginning, it has not worked when using this tag, but it does not report compilation errors, but the project is running unsuccessful.

  • solution

Later, I searched for various materials and found that the loop for making list collections in the .jsp file is to use c:foreach. Later I saw that to use this kind of c:foreach, we need to introduce tablib tags.

The first part: In the introduction of the c tag, you need to add the following code in the .jsp file:

<%--需要导入C标签该包--%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>

Part 2: Add the following dependencies in pom.xml:

 <!-- 与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>

Through the configuration of these two parts, c:foreach can be used in the .jsp file.

Question 2: Using $() has always been invalid

${} can easily get the content of the corresponding field in .jsp, but the content of the corresponding field can't be read all the time. For example, there is the following code in booklist.jsp before:

<%

    List books = (List) request.getAttribute("book");
    boolean isEmpty = books.isEmpty();
    String display = isEmpty ? "none" : "block"; //display: ${display}

%>   
<table>
 <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>
  • problem analysis

It should be caused by the wrong way of using it.

  • solution

When BookListController jumps to the .jsp file, it is directly set to the attribute through setAttribute.

      req.setAttribute("book", books);
      req.getRequestDispatcher("/book/booklist.jsp").forward(req, resp);

It turns out that EL can only get attributes from request, session, page, and application, and can directly read the content from the keys written in the four domains.

(1) Related to domain attributes

requestScope: Find the corresponding key from the request scope or domain attribute space, such as ${requestScope.name}

sessionScope: Find the corresponding key from the session scope or domain attribute space, such as ${sessionScope.name}

pageScope: Find the corresponding key from the pageScope scope or domain attribute space, such as ${pageScope.name}

applicationScope: check the corresponding key from the application scope or domain attribute space, such as ${applicationScope.name}

The content corresponding to these keys must be written into the corresponding fields by means of setAttribute("key", "value").

(2) Other objects

pageContext: It is the same object as the built-in pageContext of jsp. Through this object, objects such as request, response, session, servletContext, etc. can be obtained. For example, the request object can be obtained directly through ${pageContext.request}; the root of the web application can be obtained through ${pageContext.request.contextPath}, so that it can be directly Just add the jump path at the back,


<form action="${pageContext.request.contextPath}/addbook" method="get">
 
</form>

And in the simple summary of novice web development (eight)-database HSQLDB instance example, the value obtained is "".

param: The specified parameter of the obtained request, which is equivalent to request.getParameter(), such as ${param.name}

paramValues: Get the index value of the specified parameter of the request, which is equivalent to request.getParameterValues()

Because of the limitations of EL expressions, these logics can often be implemented directly by adding java code in .jsp.

3.JDBC

JDBC (Java DataBase Connectivity). The standard interface for Java to access the database. Many of our applications directly access the database. In order to be compatible with the databases provided by different database vendors, they all access the database through the JDBC interface. The database manufacturer provides JDBC drivers. These JDBC drivers contain the logic of accessing the database through the network and the underlying network communication, so that the web application can directly access the JDBC driver through the JDBC interface to complete the database access.

JDBC transaction: The transaction of the database is composed of a number of SQL statements to form a sequence of operations. That is to say, in some business requirements, a series of SQL statements must be executed. If there is an error in the execution of a SQL statement, all SQL must be cancelled. Therefore, the operation of these multiple SQL statements as a whole is called a transaction. The database system guarantees that all SQL in a transaction is executed or not executed at all.

Second summary

Through a simple summary of the novice web development by Xiaobai (8)-Database HSQLDB instance, a simple example, and some new understanding of a web application development:

1. A web application development needs to configure ContextLoaderListener in web.xml to initialize Spring's IoC container and bind the container to SerlvetContext;

2. You can load and manage JavaBeans through annotations by adding <context:annotation-config/>, and configure <context:component-scan base-package="com.wj"/> to set the scanned package ;

3. The JavaBean object instantiated by Spring cannot be used directly in HttpServlet, because it is two different things, but the annotation can be bound to ServletContext through SpringBeanAutowiringSupport.processInjectionBasedOnServletContext();

4. The EL expression only obtains the attribute values ​​set by request, session, page, and application;

5. @ComponentScan has a scan range, you can directly set the scan package range by @ComponentScan("package name")

6. The c tag not only needs to be introduced in the jsp, but also needs to be added to the dependency before the c tag can be used

Of course, some problems remain:

1. Some of the files in .jsp are not too standardized and need to be studied later;

2. Those better frameworks should replace DbOperation, Book and other classes;

3. Did not pay attention to database resource management, like closing links, etc.

4. In the way of loading and managing JavaBeans by configuring <bean> in xml, there are also problems encountered before verification.

The next article is to summarize the simple summary of the novice web development of Xiaobai (11)-related optimization of database connection (DataSource) 

Guess you like

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