SSM简单项目遇到的几个问题(最后一个问题,虽然能运行,但是我找不出问题出在哪里)

这几个问题,干扰了我很长时间。

主要因为书本的例子,是通过controller层返回到jsp层。但是,最后一个SSM项目,它用的是controller返回信息给Service层,再由Service层返回Jsp层。

实训:编写一个模糊查询姓名的项目。在另一个show.jsp页面显示查询信息。

一步一步:

先通过controller层返回到JSP层。

第一个问题:(未找到迭代器,或者不是迭代器类型)

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

show.jsp对应的代码信息:

<%--querylist.account是有提示的。只有list.account没有提示。(说明list不是一个可迭代器对象)--%>

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

这是show.jsp对应的代码,这个信息表示querylist的遍历器没有这个对象。说明,存在的问题是querylist不是一个可迭代的对象。我们返回到定义这个queryList的Controller文件,发现:

//        问题出在user这里,queryList是一个集合对象,但是user是一个类对象,是用不了c:foreach
        model.addAttribute("queryList",user);

解决方式:将user更换成一个迭代器对象。(例如,前面我们定义的service层的方法是一个list类型,这就是一个迭代器对象。)(额外:在使用 Service层作为与JSP返回的层级时,怀疑之前一直报错的原因,就是Service层的返回类型被我换成了String类型)

修改之后,可以在show.jsp显示用户查询信息。

扫描二维码关注公众号,回复: 15829228 查看本文章

第二个问题:未找到bean  “query2”。明明定义了query2

我尝试将用户信息查询得到的信息放在query.jsp页面下面,也就是query.jsp提供查询功能,并将信息放在query.jsp的下面。

一开始我的尝试:就是将原本返回给show的方法,改为返回给query。

在query.jsp里面,将show.jsp的代码复制过来。但是,结果出现一个很大的问题,我找了很久才发现问题:

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

这个错误信息表明在处理请求时,Spring无法找到名为query2的bean。

JSP原本的代码是:(这里需要将query修改为input)

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

因为,我们将查询和显示,在Controller分别用了两个方法表示,大概流程是这样的:

首先我们在浏览器输入/input。

/input里面返回POJO的信息给query.jsp 。通过query2的属性,将POJO和query.jsp的表单信息进行绑定。

接着在query.jsp里面,提交用户信息,action 为/query 。

/query里面返回从数据库获取的信息给query.jsp。但是,此时query.jsp里面,又会读取一次表单信息,而此时表单信息的属性query2并没有定义。于是,IDEA就提示报错,:找不到bean “query2”。

 
 

修改之后:

大概流程:

首先浏览器输入/input 。

它返回POJO的信息给query.jsp。注意此时POJO还没有和query.jsp的name进行绑定。所以数据库返回的数据此时为null。

它也返回数据库获取的数据给query.jsp。(同样是null)

在用户query.jsp,它提交action 为/input。

于是和上面的信息一样。此时user为{“null”,"null","null","李"}

最后返回给query.jsp。此时,jsp里面的querylist就存在信息了。此时querylist为{“2020”,“1234”,“男”,“李XX”}

第三个问题:测试 跟踪流程去发现问题 (挺重要的)

(学习这个方式,以后就不需要先对spring和Mybatis先进行整合并测试。)我想通过一些测试方法跟踪 这个流程的输出情况。通过查找资料,得出,可以通过日志方式输出。

方法:引入`org.slf4j.Logger`类

不是`org.apache.commons.logging.Log`类`。Log`类的`info`方法只接受一个参数,不能使用占位符`{}`来格式化消息。(在前面,我学过使用org.apache.commons.logging.Log`类,使用打印像logger.info("登录成功")   这样的信息)如果想要使用占位符来格式化消息,您可以将`Log`类更改为`org.slf4j.Logger`类,并使用`org.slf4j.LoggerFactory`来获取日志记录器(logger)对象。例如,您可以将代码修改为以下内容:
 

其实就是在controller类里面添加两句:

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

logger.info("User info: {}", user);  //测试user对象是否获取到数据。

//如果还想测试queryList是否获取数据,也可以这样写。

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";
    }
}

在添加方法之前,需要把有关依赖包导入进来。

又因为我们的项目是通过log4j的那个配置,文件输出日志信息,所以,需要对SLF4J和log4j进行绑定。

就两个依赖包:一个SLF4j的依赖包,和前面的输出日志信息搭配。

一个是绑定log4j的依赖包。实现在log4j的配置文件里面输出日志信息。

使用`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>

最后,配置log4j的配置文件,

不过,这个文件,其实在创建项目的时候,在mybatis的学习里面,我们已经添加过了。

添加完依赖项后,您需要配置`log4j`以指定日志记录行为。您可以在应用程序的类路径中创建一个名为`log4j.properties`的文件,并在其中指定日志记录配置。例如,您可以在配置文件中添加以下内容:
# 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

在上面的示例中,我们配置了一个名为`stdout`的控制台日志记录器(appender),它将日志信息输出到控制台。您可以根据需要更改配置。

结果如下:

user info 这个的信息,就是我们获取的user对象信息。

通过控制台信息,我们再来分析:

这整个流程:

首先浏览器输入:/user/input   。进入input界面。

此时运行两个model.addribute,第一个user存放的信息是null.第一个querylist存放的信息也是null。此时显示querylist的信息是null.即空。

再将这些数据交给query.jsp

在query.jsp里面,它提交action为/user/input。它继续回到这个input界面。

此时再次运行两个model.addribute,不过,第一个存放的信息里面多了name的信息。第一个querylist存放的信息是一条完整的数据。

最后,显示querylist的信息。

这是第一次,浏览器访问input的信息:

这是第二次,在input界面,点击按钮之后的信息:(action:/input)

最后,回到一开始的问题。通过controller 提交给service层 然后再交给JSP层。

由service层返回JSP信息:(最开始的困惑)

在书本最后一个比较大的SSM项目里面,都是通过controller层返回service.方法。然后在service里面,返回return ".jsp" 。

这个和我们一开始学的通过 controller层返回数据有点不同。return "。jsp"

第一个问题:错误是说,线程问题,其实真正问题不是这个,

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.
 

找到文件所在,原来是我的mybatis-context.xml文件部署,给部署到dao.userDao里面去了,应该部署指定mybatis/UserMapper.xml

第二个问题:未解之谜,从service层传递的model属性,在JSP里面,并没有提示到获取了model的属性,但是,仍然可以得到最后的结果。

 

我们来比较一下,通过controller层返回给JSP的数据:

原因出在哪呢?尝试通过日志跟踪输出,查看信息是怎么从service层到View层的。

在log4j文件下,输出如下信息。

最后,在service层输入:

在控制台能够得到 数据。说明,数据传输是没有问题。

那么为什么JSP的model属性 提示没有获取到呢???没有获取到,它又是怎么得到最后的结果的???

未解之谜 

猜你喜欢

转载自blog.csdn.net/qq_55928086/article/details/131547564