Several problems encountered by SSM simple projects (the last problem, although it can run, but I can't find out where the problem is)

These questions have bothered me for a long time.

Mainly because of the example in the book, it returns to the jsp layer through the controller layer. However, the last SSM project uses the controller to return information to the Service layer, and then the Service layer returns to the Jsp layer.

Practice: Write a project for fuzzy name query. Display query information on another show.jsp page.

Step by step:

First return to the JSP layer through the controller layer.

First question: (iterator not found, or not iterator type)

javax.servlet.ServletException: javax.servlet.jsp.JspTagException: Don't know how to iterate over supplied "items" in <forEach>

The code information corresponding to show.jsp:

<%--querylist.account is prompted. Only list.account is not prompted. (Indicating that list is not an iterable object) --%> 

<c:forEach items="${ queryList }" var="user"> 
    ${user.account}<br> 
    ${user.password}<br> 
    ${user.sex}<br> 
    ${user.name}<br> 
</c:forEach>
  
  

This is the code corresponding to show.jsp. This information indicates that the traverser of querylist does not have this object. Explain that the problem is that querylist is not an iterable object. We return to the Controller file that defines this queryList and find:

// The problem lies in user, queryList is a collection object, but user is a class object, so it cannot be used c:foreach 
        model.addAttribute("queryList",user);

Solution: replace user with an iterator object. (For example, the method of the service layer we defined earlier is a list type, which is an iterator object.) (Additional: When using the Service layer as the layer returned with JSP, I suspect that the reason why the error has been reported before is that the return type of the Service layer was replaced by String type)

After modification, user query information can be displayed in show.jsp.

Second problem: bean "query2" not found. Clearly defined query2

I try to put the information obtained from the user information query under the query.jsp page, that is, query.jsp provides the query function, and put the information under query.jsp.

My first attempt was to change the method originally returned to show to query.

In query.jsp, copy the code of show.jsp. However, it turned out that there was a big problem, which I found after searching for a long time:

java.lang.IllegalStateException: Neither BindingResult nor plain target object for bean name 'query2' available as request attribute

This error message indicates that Spring was unable to find the bean named when processing the request query2.

The original code of JSP is: (here you need to change the query to input)

<form:form method="post" action="${pageContext.request.contextPath}/user/query" modelAttribute="query2">

Because, we use two methods to express query and display in the Controller, and the general process is as follows:

First, we enter /input in the browser.

Return POJO information to query.jsp in /input. Bind the form information of POJO and query.jsp through the attribute of query2.

Then in query.jsp, submit the user information, and the action is /query.

/query returns the information obtained from the database to query.jsp. However, at this time, in query.jsp, the form information will be read again, and the attribute query2 of the form information is not defined at this time. Therefore, IDEA prompts an error: the bean "query2" cannot be found.

 
 

after modification:

Approximate process:

First, the browser enters /input.

It returns POJO information to query.jsp. Note that POJO has not been bound to the name of query.jsp at this time. So the data returned by the database is null at this time.

It also returns the data retrieved from the database to query.jsp. (also null)

In user query.jsp, it submits action as /input.

So it is the same as the above information. At this time, the user is {"null", "null", "null", "Li"}

Finally return to query.jsp. At this point, there is information in the querylist in the jsp. At this time, the querylist is {"2020", "1234", "Male", "Li XX"}

The third question: test tracking process to find problems (very important)

(Learning this way, you don't need to integrate and test spring and Mybatis first.) I want to track the output of this process through some testing methods. By searching for information, it can be obtained that it can be output in log mode.

Method: import `org.slf4j.Logger` class

Not the `org.apache.commons.logging.Log` class`. The `info` method of the Log` class accepts only one parameter and cannot use the placeholder `{}` to format the message. (Before, I learned to use the org.apache.commons.logging.Log` class, using logger.info("login successful") to print information like this) If you want to use placeholders to format the message, you can change the `Log` class to the `org.slf4j.Logger` class, and use `org.slf4j.LoggerFactory` to get the logger (logger) object. For example, you could modify your code to the following:
 

In fact, add two sentences in the controller class:

private static final Logger logger = LoggerFactory.getLogger(Query2Controller.class);

logger.info("User info: {}", user); //Test whether the user object has obtained data.

//If you still want to test whether the queryList gets data, you can also write it like this.

package controller;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import po.User;
import service.Query2;

@Controller
@RequestMapping("/user")
public class Query2Controller {

    private static final Logger logger = LoggerFactory.getLogger(Query2Controller.class);
    @Autowired
    private Query2 query2;

    @RequestMapping("/input")
    public String input(Model model, User user){
        logger.info("User info: {}", user);
        model.addAttribute("query2",user);
        model.addAttribute("queryList",query2.query2list(user));
        return "query";
    }
}

Before adding methods, you need to import the relevant dependency packages.

And because our project is configured through log4j, the file outputs log information, so we need to bind SLF4J and log4j.

There are only two dependent packages: a SLF4j dependent package, which is matched with the previous output log information.

One is to bind the dependency package of log4j. Realize the output of log information in the log4j configuration file.

使用`log4j`作为日志记录实现,您需要在应用程序的类路径中添加`SLF4J`到`log4j`的绑定库。您可以通过添加以下依赖项来实现这一点:
<!-- for Maven -->
<dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>slf4j-log4j12</artifactId>
    <version>1.7.32</version>
</dependency>

此外,您还需要在应用程序的类路径中添加`log4j`库。您可以通过添加以下依赖项来实现这一点:
<!-- for Maven -->
<dependency>
    <groupId>log4j</groupId>
    <artifactId>log4j</artifactId>
    <version>1.2.17</version>
</dependency>

Finally, configure the log4j configuration file,

However, this file, we have already added it in mybatis study when we created the project.

After adding dependencies, you need to configure `log4j` to specify logging behavior. You can create a file named `log4j.properties` in your application's classpath and specify the logging configuration there. For example, you can add the following to your configuration file:
# Global logging configuration
log4j.rootLogger=DEBUG, stdout

# Console output...
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%5p [%t] - %m%n

In the above example, we configured a console logger (appender) called `stdout`, which outputs log information to the console. You can change the configuration as needed.

The result is as follows:

user info This information is the user object information we obtained.

Through the console information, let's analyze again:

This whole process:

First enter the browser: /user/input. Enter the input interface.

At this time, two model.addrbute are run, and the information stored in the first user is null. The information stored in the first querylist is also null. At this time, the information displayed on the querylist is null. That is, it is empty.

Then give these data to query.jsp

In query.jsp, it submits the action as /user/input. It continues back to this input interface.

At this time, run two model.addrbute again, but the information stored in the first one contains more name information. The information stored in the first querylist is a complete piece of data.

Finally, display querylist information.

This is the first time, the browser accesses the input information:

This is the second time, in the input interface, the information after clicking the button: (action:/input)

Finally, back to the original question. Submit it to the service layer through the controller and then hand it over to the JSP layer.

JSP information is returned by the service layer: (the initial confusion)

In the last relatively large SSM project in the book, the service. method is returned through the controller layer. Then in the service, return return ".jsp".

This is a bit different from what we learned at the beginning to return data through the controller layer. return ".jsp"

The first question: the error is that the thread problem, in fact, the real problem is not this,

05-Jul-2023 16:42:54.580 淇℃伅 [mysql-cj-abandoned-connection-cleanup] org.apache.catalina.loader.WebappClassLoaderBase.checkStateForResourceLoading Illegal access: this web application instance has been stopped already. Could not load []. The following stack trace is thrown for debugging purposes as well as to attempt to terminate the thread which caused the illegal access.
    java.lang.IllegalStateException: Illegal access: this web application instance has been stopped already. Could not load []. The following stack trace is thrown for debugging purposes as well as to attempt to terminate the thread which caused the illegal access.
 

Find the location of the file. It turns out that my mybatis-context.xml file is deployed. It is deployed in dao.userDao. It should be deployed to specify mybatis/UserMapper.xml

The second question: the unsolved mystery, the model attribute passed from the service layer, in the JSP, does not prompt to obtain the model attribute, but the final result can still be obtained.

 

 

Let's compare the data returned to JSP through the controller layer:

 

What is the reason? Try to trace the output through the log to see how the information is passed from the service layer to the view layer.

Under the log4j file, output the following information.

 

Finally, enter in the service layer:

Data can be obtained on the console. Note that data transfer is no problem.

So why is the model attribute prompt of JSP not obtained? ? ? If it didn't get it, how did it get the final result? ? ?

unsolved puzzle 

Guess you like

Origin blog.csdn.net/qq_55928086/article/details/131547564