Class and object initialization-part2

本文深入探讨了Java中类初始化和对象初始化的过程,包括类初始化器、块初始化器的作用,类初始化与类层次的关系,对象初始化的两种类型及其实现方式。
Page 2 of 4

After studying ClassInitializationDemo4's source code, you might wonder how useful class block initializers are. After all, you could easily move all code from ClassInitializationDemo4's class block initializer to its main() method. Nevertheless, class block initializers are useful. For example, Sun's JDBC (Java Database Connectivity) API uses class block initializers to simplify database driver registration. Consider the following code fragment:

Class.forName ("sun.jdbc.odbc.JdbcOdbcDriver");      

The code fragment calls Class's forName() method to load the JdbcOdbcDriver class (located in the sun.jdbc.odbc package). Once that code fragment completes, the class loads, and the database driver associated with the JdbcOdbcDriver class registers with JDBC. What causes that registration to occur? The answer is Java statements that comprise JdbcOdbcDriver's class block initializer. (I have more to say about JDBC in a future article.)

When working with class block initializers, keep in mind two more items: First, any variable that you declare in a class block initializer is local to that block. No code outside the block can access the variable. Second, Java permits you to declare a constant class field without a class field initializer as long as you explicitly initialize that constant in a class block initializer. Furthermore, within the class block initializer, you must initialize the constant before you attempt to read its value. Listing 7 illustrates both points:

Listing 7. ClassInitializationDemo5.java

// ClassInitializationDemo5.java
import java.io.*;
class ClassInitializationDemo5
{
   final static double PI;
   static
   {
      PI = 3.14159;
      int i;
      for (i = 0; i < 5; i++)
           System.out.println (i);
   }
   static int j = i;
   public static void main (String [] args)
   {
      System.out.println ("PI = " + PI);
   }
}

When you compile ClassInitializationDemo5, the compiler reports an error when it encounters static int j = i; because it cannot find i -- i is local to the class block initializer. However, if you comment out static int j = i; and recompile, you don't receive a compiler error. Instead, you receive the following output:

0
1
2
3
4
PI = 3.14159

You might think it bizarre to see the declaration of constant PI without a class field initializer to initialize that constant. However, as long as PI explicitly initializes to3.14159 in either a class field initializer or in a class block initializer, the compiler does not complain.

Class initialization and class hierarchies

Thus far, you have only seen class field initializers and class block initializers in the context of a single class. How does class initialization work in the context of a class hierarchy? When a class hierarchy is involved, the compiler creates a separate<clinit> method for each class in that hierarchy. At runtime, the JVM loads all hierarchy classes and calls their <clinit> methods in a top-to-bottom order. That means the highest superclass's <clinit> method (which is Object's <clinit> method) executes first. After Object's <clinit> method completes, the next highest superclass's<clinit> method executes. The process continues in a top-down fashion until the class with the main() method's <clinit> method (if present) executes. Listing 8 demonstrates the <clinit> execution order:

Listing 8. ClassInitializationDemo6.java

// ClassInitializationDemo6.java
class Parent
{
   static int a = 1;
   static
   {
      System.out.println ("a = " + a);
      System.out.println ("Parent initializer");
   }
}
class ClassInitializationDemo6 extends Parent
{
   static int b = 2 + a;
   static
   {
      System.out.println ("b = " + b);
      System.out.println ("Child initializer");
      System.out.println ("a = " + a);
   }
   public static void main (String [] args)
   {
   }
}

ClassInitializationDemo6 introduces a pair of classes: Parent andClassInitializationDemo6. Each class's <clinit> method executes the byte code instructions comprising that class's class field initializer and class block initializer. To prove to yourself that Parent's <clinit> method executes beforeClassInitializationDemo6's <clinit> method, examine the followingClassInitializationDemo6 output:

a = 1
Parent initializer
b = 3
Child initializer
a = 1

The output shows that Parent's class field initializer = 1; executes first. Next, Parent's class block initializer executes. Moving on, ClassInitializationDemo6's class field initializer = 2 + a; executes. Finally, ClassInitializationDemo6's class block initializer executes. And that is pretty much all there is to know regarding class initialization and class hierarchies.

Object initialization

Now that you have seen class initialization at work, it is time to focus on object initialization. As you will discover, the initializers that perform object initialization mirror those initializers that perform class initialization. As with class initialization, the simplest kind of object initialization is automatic initialization of object fields to default values. Listing 9 illustrates that type of initialization:

Listing 9. ObjectInitializationDemo1.java

// ObjectInitializationDemo1.java
class ObjectInitializationDemo1
{
   boolean b;
   byte by;
   char c;
   double d;
   float f;
   int i;
   long l;
   short s;
   String st;
   public static void main (String [] args)
   {
      ObjectInitializationDemo1 oid1 = new ObjectInitializationDemo1 ();
      System.out.println ("oid1.b = " + oid1.b);
      System.out.println ("oid1.by = " + oid1.by);
      System.out.println ("oid1.c = " + oid1.c);
      System.out.println ("oid1.d = " + oid1.d);
      System.out.println ("oid1.f = " + oid1.f);
      System.out.println ("oid1.i = " + oid1.i);
      System.out.println ("oid1.l = " + oid1.l);
      System.out.println ("oid1.s = " + oid1.s);
      System.out.println ("oid1.st = " + oid1.st);
   }
}

ObjectInitializationDemo1 mirrors ClassInitializationDemo1 in that it introduces a variety of fields -- object fields, to be exact. Furthermore, no explicit values assign to any of those fields.

You see the following output when ObjectInitializationDemo1 runs:

b = false
by = 0
c =  
d = 0.0
f = 0.0
i = 0
l = 0
s = 0
st = null

This time, the JVM zeroes all object fields' bits. Unlike class fields, which the JVM zeroes after a class loads and is verified, the JVM only zeroes the bits of a class's object fields when a program creates an object from that class. That activity should come as no surprise when you consider that object fields bind to objects. Therefore, object fields do not exist until a program creates an object. Furthermore, each object receives its own copies of a class's object fields.

Object field initializers

The next simplest kind of object initialization is the explicit initialization of object fields to values. Each object field explicitly initializes to a value via an object field initializer. Listing 10 shows several object field initializers:

Listing 10. ObjectInitializationDemo2.java

// ObjectInitializationDemo2.java
class ObjectInitializationDemo2
{
   boolean b = true;
   byte by = 1;
   char c = 'A';
   double d = 1.2;
   float f = 3.4f;
   int i = 2;
   long l = 3;
   short s = 4;
   String st = "abc";
   public static void main (String [] args)
   {
      ObjectInitializationDemo2 oid2 = new ObjectInitializationDemo2 ();
      System.out.println ("oid2.b = " + oid2.b);
      System.out.println ("oid2.by = " + oid2.by);
      System.out.println ("oid2.c = " + oid2.c);
      System.out.println ("oid2.d = " + oid2.d);
      System.out.println ("oid2.f = " + oid2.f);
      System.out.println ("oid2.i = " + oid2.i);
      System.out.println ("oid2.l = " + oid2.l);
      System.out.println ("oid2.s = " + oid2.s);
      System.out.println ("oid2.st = " + oid2.st);
   }
}

In contrast to ObjectInitializationDemo1, in ObjectInitializationDemo2 an object field initializer explicitly assigns a nondefault value to each object field. Essentially, an object field initializer consists of the assignment operator (=) and an expression that evaluates during object creation. The assignment operator assigns the expression's value to the associated object field. When run, ObjectInitializationDemo2 produces the following output:

oid2.b = true
oid2.by = 1
oid2.c = A
oid2.d = 1.2
oid2.f = 3.4
oid2.i = 2
oid2.l = 3
oid2.s = 4
oid2.st = abc

What is responsible for executing the object field initializers? Would you believe that the constructor is? As strange as it might seem, the compiler inserts byte code instructions into a class's constructor to execute object field initializers. But there's more: When you look at a constructor from the JVM's perspective, you no longer see a constructor. Instead, you see what the JVM refers to as an <init> method.

During class compilation, the compiler generates an <init> method for each of that class's constructors. If that class contains no constructors (as inObjectInitializationDemo2), the compiler generates an <init> method that matches the default no-argument constructor. It is important to realize that each constructor has its own corresponding <init> method and that the compiler places byte code instructions, apart from the instructions you specify (via Java source code), into that method. Some of those instructions serve to execute object field initializers.

Take a close look at Listing 10. You cannot see its presence, but a constructor does exist. If you could see that constructor, it would probably look like the following code fragment:

ObjectInitializationDemo2 ()
{
}

That's right! The constructor would appear empty. Suppose you disassembleObjectInitializationDemo2's class file. In that disassembly, you would encounter a no-argument <init> method that matches the default no-argument constructor. And what instructions would you find in that method? Take a look at Listing 11:

Listing 11. ObjectInitializationDemo2's no-argument <init> method

 0        aload_0
 1        invokespecial java/lang/Object/<init>()V
 4        aload_0
 5        iconst_1
 6        putfield ObjectInitializationDemo2/b Z
 9        aload_0
10        iconst_1
11        putfield ObjectInitializationDemo2/by B
14        aload_0
15        bipush 65
17        putfield ObjectInitializationDemo2/c C
20        aload_0
21        ldc2_w #1.200000
24        putfield ObjectInitializationDemo2/d D
27        aload_0
28        ldc #3.400000
30        putfield ObjectInitializationDemo2/f F
33        aload_0
34        iconst_2
35        putfield ObjectInitializationDemo2/i I
38        aload_0
39        ldc2_w #3
42        putfield ObjectInitializationDemo2/l J
45        aload_0
46        iconst_4
47        putfield ObjectInitializationDemo2/s S
50        aload_0
51        ldc "abc"
53        putfield ObjectInitializationDemo2/st Ljava/lang/String;
56        return

Apart from Listing 11's byte code instructions executing ObjectInitializationDemo2's object field initializers, a close examination of Listing 11 reveals some interesting items about how Java works:

  • Note the aload_0 instruction. That instruction pushes an address onto a stack. And what address does that instruction push? The current object address -- as keywordthis represents in source code. The invokespecial and putfield instructions pop that address from the stack and use the address to identify the proper object when making a call to an object method or writing to an object field.
  • Note the invokespecial java/lang/Object/<init>()V instruction. That instruction calls the default no-argument constructor -- to be precise, the default no-argument <init>method -- in the Object superclass. (Remember keyword super's use in calling a superclass constructor? You are seeing how Java uses that keyword at the byte code level.)
  • Note the location of invokespecial java/lang/Object/<init>()V. It is no accident that the compiler places that instruction as the second instruction (after aload_0) in the default no-argument <init> method. In accordance with the way Java works, a constructor must first either call another constructor in the same class or a constructor in its superclass. If a constructor does not explicitly call another constructor in the same class (via this) or a constructor in a superclass (via super), the compiler generates byte code instructions that are the equivalent of placing super ();at a constructor's start.

We will explore the second and third items in the above list later in this section, when we examine object initialization and class hierarchies. But first, we need to explore object field initializers and forward references, along with object block initializers.

As with class fields, some programs require object fields to refer to previously declared object fields. Java supports that activity by allowing you to specify the name of a previously declared object field in the expression portion of a subsequently declared object field's initializer. However, just as you cannot use forward references with class field initializers, you cannot use forward references with object field initializers. Listing 12 demonstrates both concepts:

Listing 12. ObjectInitializationDemo3.java

// ObjectInitializationDemo3.java
class ObjectInitializationDemo3
{
//   int forwardReference = first;
   int first = 3;
   int second = 1 + first;
   public static void main (String [] args)
   {
      ObjectInitializationDemo3 oid3 = new ObjectInitializationDemo3 ();
      System.out.println ("oid3.first = " + oid3.first);
      System.out.println ("oid3.second = " + oid3.second);
   }
}
"E:\buka resource\Tomcat 9.0\Tomcat 9.0\bin\catalina.bat" run [2025-09-15 02:17:00,236] Artifact 9.14_homework:war: Waiting for server connection to start artifact deployment... Using CATALINA_BASE: "C:\Users\asus\AppData\Local\JetBrains\IntelliJIdea2021.1\tomcat\571f7d60-cc7b-4657-a774-118f50351c2c" Using CATALINA_HOME: "E:\buka resource\Tomcat 9.0\Tomcat 9.0" Using CATALINA_TMPDIR: "E:\buka resource\Tomcat 9.0\Tomcat 9.0\temp" Using JRE_HOME: "C:\Program Files\Java\jdk1.8.0_211" Using CLASSPATH: "E:\buka resource\Tomcat 9.0\Tomcat 9.0\bin\bootstrap.jar;E:\buka resource\Tomcat 9.0\Tomcat 9.0\bin\tomcat-juli.jar" Using CATALINA_OPTS: "" Connected to the target VM, address: '127.0.0.1:59280', transport: 'socket' 15-Sep-2025 14:17:01.205 信息 [main] org.apache.catalina.startup.VersionLoggerListener.log Server.服务器版本: Apache Tomcat/9.0.54 15-Sep-2025 14:17:01.205 信息 [main] org.apache.catalina.startup.VersionLoggerListener.log 服务器构建: Sep 28 2021 13:51:49 UTC 15-Sep-2025 14:17:01.205 信息 [main] org.apache.catalina.startup.VersionLoggerListener.log 服务器版本号: 9.0.54.0 15-Sep-2025 14:17:01.205 信息 [main] org.apache.catalina.startup.VersionLoggerListener.log 操作系统名称: Windows 10 15-Sep-2025 14:17:01.205 信息 [main] org.apache.catalina.startup.VersionLoggerListener.log OS.版本: 10.0 15-Sep-2025 14:17:01.205 信息 [main] org.apache.catalina.startup.VersionLoggerListener.log 架构: amd64 15-Sep-2025 14:17:01.205 信息 [main] org.apache.catalina.startup.VersionLoggerListener.log Java 环境变量: C:\Program Files\Java\jdk1.8.0_211\jre 15-Sep-2025 14:17:01.205 信息 [main] org.apache.catalina.startup.VersionLoggerListener.log Java虚拟机版本: 1.8.0_211-b12 15-Sep-2025 14:17:01.205 信息 [main] org.apache.catalina.startup.VersionLoggerListener.log JVM.供应商: Oracle Corporation 15-Sep-2025 14:17:01.205 信息 [main] org.apache.catalina.startup.VersionLoggerListener.log CATALINA_BASE: C:\Users\asus\AppData\Local\JetBrains\IntelliJIdea2021.1\tomcat\571f7d60-cc7b-4657-a774-118f50351c2c 15-Sep-2025 14:17:01.205 信息 [main] org.apache.catalina.startup.VersionLoggerListener.log CATALINA_HOME: E:\buka resource\Tomcat 9.0\Tomcat 9.0 15-Sep-2025 14:17:01.205 信息 [main] org.apache.catalina.startup.VersionLoggerListener.log 命令行参数: -Djava.util.logging.config.file=C:\Users\asus\AppData\Local\JetBrains\IntelliJIdea2021.1\tomcat\571f7d60-cc7b-4657-a774-118f50351c2c\conf\logging.properties 15-Sep-2025 14:17:01.205 信息 [main] org.apache.catalina.startup.VersionLoggerListener.log 命令行参数: -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager 15-Sep-2025 14:17:01.205 信息 [main] org.apache.catalina.startup.VersionLoggerListener.log 命令行参数: -agentlib:jdwp=transport=dt_socket,address=127.0.0.1:59280,suspend=y,server=n 15-Sep-2025 14:17:01.205 信息 [main] org.apache.catalina.startup.VersionLoggerListener.log 命令行参数: -javaagent:C:\Users\asus\AppData\Local\JetBrains\IntelliJIdea2021.1\captureAgent\debugger-agent.jar 15-Sep-2025 14:17:01.205 信息 [main] org.apache.catalina.startup.VersionLoggerListener.log 命令行参数: -Dcom.sun.management.jmxremote= 15-Sep-2025 14:17:01.205 信息 [main] org.apache.catalina.startup.VersionLoggerListener.log 命令行参数: -Dcom.sun.management.jmxremote.port=1099 15-Sep-2025 14:17:01.205 信息 [main] org.apache.catalina.startup.VersionLoggerListener.log 命令行参数: -Dcom.sun.management.jmxremote.ssl=false 15-Sep-2025 14:17:01.205 信息 [main] org.apache.catalina.startup.VersionLoggerListener.log 命令行参数: -Dcom.sun.management.jmxremote.password.file=C:\Users\asus\AppData\Local\JetBrains\IntelliJIdea2021.1\tomcat\571f7d60-cc7b-4657-a774-118f50351c2c\jmxremote.password 15-Sep-2025 14:17:01.205 信息 [main] org.apache.catalina.startup.VersionLoggerListener.log 命令行参数: -Dcom.sun.management.jmxremote.access.file=C:\Users\asus\AppData\Local\JetBrains\IntelliJIdea2021.1\tomcat\571f7d60-cc7b-4657-a774-118f50351c2c\jmxremote.access 15-Sep-2025 14:17:01.205 信息 [main] org.apache.catalina.startup.VersionLoggerListener.log 命令行参数: -Djava.rmi.server.hostname=127.0.0.1 15-Sep-2025 14:17:01.205 信息 [main] org.apache.catalina.startup.VersionLoggerListener.log 命令行参数: -Djdk.tls.ephemeralDHKeySize=2048 15-Sep-2025 14:17:01.205 信息 [main] org.apache.catalina.startup.VersionLoggerListener.log 命令行参数: -Djava.protocol.handler.pkgs=org.apache.catalina.webresources 15-Sep-2025 14:17:01.205 信息 [main] org.apache.catalina.startup.VersionLoggerListener.log 命令行参数: -Dignore.endorsed.dirs= 15-Sep-2025 14:17:01.205 信息 [main] org.apache.catalina.startup.VersionLoggerListener.log 命令行参数: -Dcatalina.base=C:\Users\asus\AppData\Local\JetBrains\IntelliJIdea2021.1\tomcat\571f7d60-cc7b-4657-a774-118f50351c2c 15-Sep-2025 14:17:01.205 信息 [main] org.apache.catalina.startup.VersionLoggerListener.log 命令行参数: -Dcatalina.home=E:\buka resource\Tomcat 9.0\Tomcat 9.0 15-Sep-2025 14:17:01.205 信息 [main] org.apache.catalina.startup.VersionLoggerListener.log 命令行参数: -Djava.io.tmpdir=E:\buka resource\Tomcat 9.0\Tomcat 9.0\temp 15-Sep-2025 14:17:01.205 信息 [main] org.apache.catalina.core.AprLifecycleListener.lifecycleEvent 在java.library.path:[C:\Program Files\Java\jdk1.8.0_211\bin;C:\WINDOWS\Sun\Java\bin;C:\WINDOWS\system32;C:\WINDOWS;C:\Program Files (x86)\NVIDIA Corporation\PhysX\Common;C:\Program Files (x86)\Common Files\Oracle\Java\javapath;C:\Windows\system32;C:\Windows;C:\Windows\System32\Wbem;C:\Windows\System32\WindowsPowerShell\v1.0\;C:\Windows\System32\OpenSSH\;C:\Program Files\Microsoft SQL Server\150\Tools\Binn\;C:\Program Files\Microsoft SQL Server\Client SDK\ODBC\170\Tools\Binn\;C:\Program Files\dotnet\;D:\Windows Kits\10\Windows Performance Toolkit\;C:\Program Files\Bandizip\;C:\WINDOWS\system32;C:\WINDOWS;C:\WINDOWS\System32\Wbem;C:\WINDOWS\System32\WindowsPowerShell\v1.0\;C:\WINDOWS\System32\OpenSSH\;E:\MYSql\mysql-8.0.30-winx64\bin;D:\app\mysql xx\bc\bin;C:\Program Files\NVIDIA Corporation\NVIDIA App\NvDLISR;C:\Users\asus\AppData\Local\Microsoft\WindowsApps;C:\Users\asus\.dotnet\tools;D:\app\idea\IntelliJ IDEA 2023.3.4\bin;;;.]上找不到基于APR的Apache Tomcat本机库,该库允许在生产环境中获得最佳性能 15-Sep-2025 14:17:01.380 信息 [main] org.apache.coyote.AbstractProtocol.init 初始化协议处理器 ["http-nio-8080"] 15-Sep-2025 14:17:01.380 信息 [main] org.apache.catalina.startup.Catalina.load 服务器在[333]毫秒内初始化 15-Sep-2025 14:17:01.411 信息 [main] org.apache.catalina.core.StandardService.startInternal 正在启动服务[Catalina] 15-Sep-2025 14:17:01.411 信息 [main] org.apache.catalina.core.StandardEngine.startInternal 正在启动 Servlet 引擎:[Apache Tomcat/9.0.54] 15-Sep-2025 14:17:01.417 信息 [main] org.apache.coyote.AbstractProtocol.start 开始协议处理句柄["http-nio-8080"] 15-Sep-2025 14:17:01.427 信息 [main] org.apache.catalina.startup.Catalina.start [40]毫秒后服务器启动 Connected to server [2025-09-15 02:17:01,807] Artifact 9.14_homework:war: Artifact is being deployed, please wait... 15-Sep-2025 14:17:04.092 信息 [RMI TCP Connection(3)-127.0.0.1] org.apache.jasper.servlet.TldScanner.scanJars 至少有一个JAR被扫描用于TLD但尚未包含TLD。 为此记录器启用调试日志记录,以获取已扫描但未在其中找到TLD的完整JAR列表。 在扫描期间跳过不需要的JAR可以缩短启动时间和JSP编译时间。 14:17:04.188 [RMI TCP Connection(3)-127.0.0.1] INFO org.springframework.web.context.ContextLoader - Root WebApplicationContext: initialization started 14:17:04.267 [RMI TCP Connection(3)-127.0.0.1] DEBUG org.springframework.web.context.support.XmlWebApplicationContext - Refreshing Root WebApplicationContext 14:17:04.457 [RMI TCP Connection(3)-127.0.0.1] DEBUG org.springframework.context.annotation.ClassPathBeanDefinitionScanner - Identified candidate component class: file [E:\buka resource\Tomcat 9.0\Tomcat 9.0\webapps\ROOT\WEB-INF\classes\com\buka\service\ClassService.class] 14:17:04.457 [RMI TCP Connection(3)-127.0.0.1] DEBUG org.springframework.context.annotation.ClassPathBeanDefinitionScanner - Identified candidate component class: file [E:\buka resource\Tomcat 9.0\Tomcat 9.0\webapps\ROOT\WEB-INF\classes\com\buka\service\StuService.class] 14:17:04.489 [RMI TCP Connection(3)-127.0.0.1] DEBUG org.springframework.beans.factory.xml.XmlBeanDefinitionReader - Loaded 11 bean definitions from class path resource [application.xml] 14:17:04.537 [RMI TCP Connection(3)-127.0.0.1] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'org.springframework.context.annotation.internalConfigurationAnnotationProcessor' 14:17:04.584 [RMI TCP Connection(3)-127.0.0.1] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'org.mybatis.spring.mapper.MapperScannerConfigurer#0' 14:17:04.631 [RMI TCP Connection(3)-127.0.0.1] DEBUG org.apache.ibatis.logging.LogFactory - Logging initialized using 'class org.apache.ibatis.logging.slf4j.Slf4jImpl' adapter. 14:17:04.631 [RMI TCP Connection(3)-127.0.0.1] DEBUG org.mybatis.spring.mapper.ClassPathMapperScanner - Identified candidate component class: file [E:\buka resource\Tomcat 9.0\Tomcat 9.0\webapps\ROOT\WEB-INF\classes\com\buka\dao\ClassDao.class] 14:17:04.631 [RMI TCP Connection(3)-127.0.0.1] DEBUG org.mybatis.spring.mapper.ClassPathMapperScanner - Identified candidate component class: file [E:\buka resource\Tomcat 9.0\Tomcat 9.0\webapps\ROOT\WEB-INF\classes\com\buka\dao\Studao.class] 14:17:04.631 [RMI TCP Connection(3)-127.0.0.1] DEBUG org.mybatis.spring.mapper.ClassPathMapperScanner - Creating MapperFactoryBean with name 'classDao' and 'com.buka.dao.ClassDao' mapperInterface 14:17:04.631 [RMI TCP Connection(3)-127.0.0.1] DEBUG org.mybatis.spring.mapper.ClassPathMapperScanner - Creating MapperFactoryBean with name 'studao' and 'com.buka.dao.Studao' mapperInterface 14:17:04.647 [RMI TCP Connection(3)-127.0.0.1] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'org.springframework.context.support.PropertySourcesPlaceholderConfigurer#0' 14:17:04.663 [RMI TCP Connection(3)-127.0.0.1] DEBUG org.springframework.jndi.JndiTemplate - Looking up JNDI object with name [java:comp/env/jdbc.driver] 14:17:04.663 [RMI TCP Connection(3)-127.0.0.1] DEBUG org.springframework.jndi.JndiLocatorDelegate - Converted JNDI name [java:comp/env/jdbc.driver] not found - trying original name [jdbc.driver]. javax.naming.NameNotFoundException: 名称[jdbc.driver]未在此上下文中绑定。找不到[jdbc.driver]。 14:17:04.663 [RMI TCP Connection(3)-127.0.0.1] DEBUG org.springframework.jndi.JndiTemplate - Looking up JNDI object with name [jdbc.driver] 14:17:04.663 [RMI TCP Connection(3)-127.0.0.1] DEBUG org.springframework.jndi.JndiPropertySource - JNDI lookup for name [jdbc.driver] threw NamingException with message: 名称[jdbc.driver]未在此上下文中绑定。找不到[jdbc.driver]。. Returning null. 14:17:04.663 [RMI TCP Connection(3)-127.0.0.1] DEBUG org.springframework.core.env.PropertySourcesPropertyResolver - Found key 'jdbc.driver' in PropertySource 'localProperties' with value of type String 14:17:04.663 [RMI TCP Connection(3)-127.0.0.1] DEBUG org.springframework.jndi.JndiTemplate - Looking up JNDI object with name [java:comp/env/jdbc.password] 14:17:04.663 [RMI TCP Connection(3)-127.0.0.1] DEBUG org.springframework.jndi.JndiLocatorDelegate - Converted JNDI name [java:comp/env/jdbc.password] not found - trying original name [jdbc.password]. javax.naming.NameNotFoundException: 名称[jdbc.password]未在此上下文中绑定。找不到[jdbc.password]。 14:17:04.663 [RMI TCP Connection(3)-127.0.0.1] DEBUG org.springframework.jndi.JndiTemplate - Looking up JNDI object with name [jdbc.password] 14:17:04.663 [RMI TCP Connection(3)-127.0.0.1] DEBUG org.springframework.jndi.JndiPropertySource - JNDI lookup for name [jdbc.password] threw NamingException with message: 名称[jdbc.password]未在此上下文中绑定。找不到[jdbc.password]。. Returning null. 14:17:04.663 [RMI TCP Connection(3)-127.0.0.1] DEBUG org.springframework.core.env.PropertySourcesPropertyResolver - Found key 'jdbc.password' in PropertySource 'localProperties' with value of type String 14:17:04.663 [RMI TCP Connection(3)-127.0.0.1] DEBUG org.springframework.jndi.JndiTemplate - Looking up JNDI object with name [java:comp/env/jdbc.url] 14:17:04.663 [RMI TCP Connection(3)-127.0.0.1] DEBUG org.springframework.jndi.JndiLocatorDelegate - Converted JNDI name [java:comp/env/jdbc.url] not found - trying original name [jdbc.url]. javax.naming.NameNotFoundException: 名称[jdbc.url]未在此上下文中绑定。找不到[jdbc.url]。 14:17:04.663 [RMI TCP Connection(3)-127.0.0.1] DEBUG org.springframework.jndi.JndiTemplate - Looking up JNDI object with name [jdbc.url] 14:17:04.663 [RMI TCP Connection(3)-127.0.0.1] DEBUG org.springframework.jndi.JndiPropertySource - JNDI lookup for name [jdbc.url] threw NamingException with message: 名称[jdbc.url]未在此上下文中绑定。找不到[jdbc.url]。. Returning null. 14:17:04.663 [RMI TCP Connection(3)-127.0.0.1] DEBUG org.springframework.core.env.PropertySourcesPropertyResolver - Found key 'jdbc.url' in PropertySource 'localProperties' with value of type String 14:17:04.663 [RMI TCP Connection(3)-127.0.0.1] DEBUG org.springframework.jndi.JndiTemplate - Looking up JNDI object with name [java:comp/env/jdbc.username] 14:17:04.663 [RMI TCP Connection(3)-127.0.0.1] DEBUG org.springframework.jndi.JndiLocatorDelegate - Converted JNDI name [java:comp/env/jdbc.username] not found - trying original name [jdbc.username]. javax.naming.NameNotFoundException: 名称[jdbc.username]未在此上下文中绑定。找不到[jdbc.username]。 14:17:04.663 [RMI TCP Connection(3)-127.0.0.1] DEBUG org.springframework.jndi.JndiTemplate - Looking up JNDI object with name [jdbc.username] 14:17:04.663 [RMI TCP Connection(3)-127.0.0.1] DEBUG org.springframework.jndi.JndiPropertySource - JNDI lookup for name [jdbc.username] threw NamingException with message: 名称[jdbc.username]未在此上下文中绑定。找不到[jdbc.username]。. Returning null. 14:17:04.663 [RMI TCP Connection(3)-127.0.0.1] DEBUG org.springframework.core.env.PropertySourcesPropertyResolver - Found key 'jdbc.username' in PropertySource 'localProperties' with value of type String 14:17:04.663 [RMI TCP Connection(3)-127.0.0.1] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'org.springframework.context.event.internalEventListenerProcessor' 14:17:04.663 [RMI TCP Connection(3)-127.0.0.1] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'org.springframework.context.event.internalEventListenerFactory' 14:17:04.663 [RMI TCP Connection(3)-127.0.0.1] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'org.springframework.context.annotation.internalAutowiredAnnotationProcessor' 14:17:04.663 [RMI TCP Connection(3)-127.0.0.1] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'org.springframework.context.annotation.internalCommonAnnotationProcessor' 14:17:04.679 [RMI TCP Connection(3)-127.0.0.1] DEBUG org.springframework.ui.context.support.UiApplicationContextUtils - Unable to locate ThemeSource with name 'themeSource': using default [org.springframework.ui.context.support.ResourceBundleThemeSource@3a0a0d1e] 14:17:04.679 [RMI TCP Connection(3)-127.0.0.1] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'classService' 14:17:04.710 [RMI TCP Connection(3)-127.0.0.1] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'classDao' 14:17:04.726 [RMI TCP Connection(3)-127.0.0.1] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'sqlsessionFactory' 14:17:04.726 [RMI TCP Connection(3)-127.0.0.1] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'dataSource' Logging initialized using 'class org.apache.ibatis.logging.stdout.StdOutImpl' adapter. 14:17:04.901 [RMI TCP Connection(3)-127.0.0.1] DEBUG org.mybatis.spring.SqlSessionFactoryBean - Parsed configuration file: 'class path resource [mybatis-config.xml]' 14:17:04.965 [RMI TCP Connection(3)-127.0.0.1] DEBUG org.mybatis.spring.SqlSessionFactoryBean - Parsed mapper file: 'file [E:\buka resource\Tomcat 9.0\Tomcat 9.0\webapps\ROOT\WEB-INF\classes\mapper\ClassMapper.xml]' 14:17:04.965 [RMI TCP Connection(3)-127.0.0.1] DEBUG org.mybatis.spring.SqlSessionFactoryBean - Parsed mapper file: 'file [E:\buka resource\Tomcat 9.0\Tomcat 9.0\webapps\ROOT\WEB-INF\classes\mapper\StuMapper.xml]' 14:17:04.981 [RMI TCP Connection(3)-127.0.0.1] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'stuService' 14:17:04.981 [RMI TCP Connection(3)-127.0.0.1] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'studao' 14:17:05.020 [RMI TCP Connection(3)-127.0.0.1] DEBUG org.springframework.jndi.JndiTemplate - Looking up JNDI object with name [java:comp/env/spring.liveBeansView.mbeanDomain] 14:17:05.020 [RMI TCP Connection(3)-127.0.0.1] DEBUG org.springframework.jndi.JndiLocatorDelegate - Converted JNDI name [java:comp/env/spring.liveBeansView.mbeanDomain] not found - trying original name [spring.liveBeansView.mbeanDomain]. javax.naming.NameNotFoundException: 名称[spring.liveBeansView.mbeanDomain]未在此上下文中绑定。找不到[spring.liveBeansView.mbeanDomain]。 14:17:05.020 [RMI TCP Connection(3)-127.0.0.1] DEBUG org.springframework.jndi.JndiTemplate - Looking up JNDI object with name [spring.liveBeansView.mbeanDomain] 14:17:05.020 [RMI TCP Connection(3)-127.0.0.1] DEBUG org.springframework.jndi.JndiPropertySource - JNDI lookup for name [spring.liveBeansView.mbeanDomain] threw NamingException with message: 名称[spring.liveBeansView.mbeanDomain]未在此上下文中绑定。找不到[spring.liveBeansView.mbeanDomain]。. Returning null. 14:17:05.020 [RMI TCP Connection(3)-127.0.0.1] INFO org.springframework.web.context.ContextLoader - Root WebApplicationContext initialized in 832 ms 14:17:05.028 [RMI TCP Connection(3)-127.0.0.1] DEBUG org.springframework.web.filter.CharacterEncodingFilter - Filter 'charset' configured for use [2025-09-15 02:17:05,044] Artifact 9.14_homework:war: Artifact is deployed successfully [2025-09-15 02:17:05,044] Artifact 9.14_homework:war: Deploy took 3,237 milliseconds 14:17:06.043 [http-nio-8080-exec-2] INFO org.springframework.web.servlet.DispatcherServlet - Initializing Servlet 'springMVC' 14:17:06.043 [http-nio-8080-exec-2] DEBUG org.springframework.jndi.JndiTemplate - Looking up JNDI object with name [java:comp/env/spring.profiles.active] 14:17:06.043 [http-nio-8080-exec-2] DEBUG org.springframework.jndi.JndiLocatorDelegate - Converted JNDI name [java:comp/env/spring.profiles.active] not found - trying original name [spring.profiles.active]. javax.naming.NameNotFoundException: 名称[spring.profiles.active]未在此上下文中绑定。找不到[spring.profiles.active]。 14:17:06.043 [http-nio-8080-exec-2] DEBUG org.springframework.jndi.JndiTemplate - Looking up JNDI object with name [spring.profiles.active] 14:17:06.043 [http-nio-8080-exec-2] DEBUG org.springframework.jndi.JndiPropertySource - JNDI lookup for name [spring.profiles.active] threw NamingException with message: 名称[spring.profiles.active]未在此上下文中绑定。找不到[spring.profiles.active]。. Returning null. 14:17:06.043 [http-nio-8080-exec-2] DEBUG org.springframework.jndi.JndiTemplate - Looking up JNDI object with name [java:comp/env/spring.profiles.default] 14:17:06.043 [http-nio-8080-exec-2] DEBUG org.springframework.jndi.JndiLocatorDelegate - Converted JNDI name [java:comp/env/spring.profiles.default] not found - trying original name [spring.profiles.default]. javax.naming.NameNotFoundException: 名称[spring.profiles.default]未在此上下文中绑定。找不到[spring.profiles.default]。 14:17:06.043 [http-nio-8080-exec-2] DEBUG org.springframework.jndi.JndiTemplate - Looking up JNDI object with name [spring.profiles.default] 14:17:06.043 [http-nio-8080-exec-2] DEBUG org.springframework.jndi.JndiPropertySource - JNDI lookup for name [spring.profiles.default] threw NamingException with message: 名称[spring.profiles.default]未在此上下文中绑定。找不到[spring.profiles.default]。. Returning null. 14:17:06.043 [http-nio-8080-exec-2] DEBUG org.springframework.web.context.support.XmlWebApplicationContext - Refreshing WebApplicationContext for namespace 'springMVC-servlet' 14:17:06.073 [http-nio-8080-exec-2] DEBUG org.springframework.context.annotation.ClassPathBeanDefinitionScanner - Identified candidate component class: file [E:\buka resource\Tomcat 9.0\Tomcat 9.0\webapps\ROOT\WEB-INF\classes\com\buka\controller\ClassController.class] 14:17:06.073 [http-nio-8080-exec-2] DEBUG org.springframework.context.annotation.ClassPathBeanDefinitionScanner - Identified candidate component class: file [E:\buka resource\Tomcat 9.0\Tomcat 9.0\webapps\ROOT\WEB-INF\classes\com\buka\controller\StuController.class] 14:17:06.120 [http-nio-8080-exec-2] DEBUG org.springframework.beans.factory.xml.XmlBeanDefinitionReader - Loaded 26 bean definitions from class path resource [springmvc-config.xml] 14:17:06.120 [http-nio-8080-exec-2] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'org.springframework.context.annotation.internalConfigurationAnnotationProcessor' 14:17:06.170 [http-nio-8080-exec-2] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'org.springframework.context.event.internalEventListenerProcessor' 14:17:06.170 [http-nio-8080-exec-2] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'org.springframework.context.event.internalEventListenerFactory' 14:17:06.170 [http-nio-8080-exec-2] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'org.springframework.context.annotation.internalAutowiredAnnotationProcessor' 14:17:06.170 [http-nio-8080-exec-2] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'org.springframework.context.annotation.internalCommonAnnotationProcessor' 14:17:06.170 [http-nio-8080-exec-2] DEBUG org.springframework.ui.context.support.UiApplicationContextUtils - Unable to locate ThemeSource with name 'themeSource': using default [org.springframework.ui.context.support.DelegatingThemeSource@2e74de95] 14:17:06.170 [http-nio-8080-exec-2] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'classController' 14:17:06.170 [http-nio-8080-exec-2] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'stuController' 14:17:06.170 [http-nio-8080-exec-2] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'mvcContentNegotiationManager' 14:17:06.183 [http-nio-8080-exec-2] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping' 14:17:06.231 [http-nio-8080-exec-2] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'mvcCorsConfigurations' 14:17:06.231 [http-nio-8080-exec-2] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'org.springframework.web.servlet.handler.MappedInterceptor#0' 14:17:06.231 [http-nio-8080-exec-2] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'org.springframework.format.support.FormattingConversionServiceFactoryBean#0' 14:17:06.320 [http-nio-8080-exec-2] DEBUG _org.springframework.web.servlet.HandlerMapping.Mappings - c.b.c.ClassController: { [/menu]}: index(Clazz,ModelAndView) { [/addClass]}: addClass(Clazz,ModelAndView) { [/]}: home() 14:17:06.325 [http-nio-8080-exec-2] DEBUG _org.springframework.web.servlet.HandlerMapping.Mappings - c.b.c.StuController: { [/addStu]}: addStu(Student,ModelAndView) 14:17:06.325 [http-nio-8080-exec-2] DEBUG org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping - 4 mappings in 'org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping' 14:17:06.325 [http-nio-8080-exec-2] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter' 14:17:06.373 [http-nio-8080-exec-2] DEBUG org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter - ControllerAdvice beans: none 14:17:06.420 [http-nio-8080-exec-2] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'mvcUriComponentsContributor' 14:17:06.420 [http-nio-8080-exec-2] DEBUG org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter - ControllerAdvice beans: none 14:17:06.420 [http-nio-8080-exec-2] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'org.springframework.web.servlet.mvc.method.annotation.ExceptionHandlerExceptionResolver#0' 14:17:06.436 [http-nio-8080-exec-2] DEBUG org.springframework.web.servlet.mvc.method.annotation.ExceptionHandlerExceptionResolver - ControllerAdvice beans: none 14:17:06.436 [http-nio-8080-exec-2] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'org.springframework.web.servlet.mvc.annotation.ResponseStatusExceptionResolver#0' 14:17:06.436 [http-nio-8080-exec-2] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'org.springframework.web.servlet.mvc.support.DefaultHandlerExceptionResolver#0' 14:17:06.436 [http-nio-8080-exec-2] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping' 14:17:06.452 [http-nio-8080-exec-2] DEBUG _org.springframework.web.servlet.HandlerMapping.Mappings - 'org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping' {} 14:17:06.452 [http-nio-8080-exec-2] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter' 14:17:06.452 [http-nio-8080-exec-2] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter' 14:17:06.452 [http-nio-8080-exec-2] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'localeResolver' 14:17:06.452 [http-nio-8080-exec-2] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'themeResolver' 14:17:06.452 [http-nio-8080-exec-2] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'viewNameTranslator' 14:17:06.452 [http-nio-8080-exec-2] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'flashMapManager' 14:17:06.452 [http-nio-8080-exec-2] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'multipartResolver' 14:17:06.468 [http-nio-8080-exec-2] DEBUG org.springframework.web.servlet.DispatcherServlet - Detected CommonsMultipartResolver 14:17:06.468 [http-nio-8080-exec-2] DEBUG org.springframework.web.servlet.DispatcherServlet - Detected AcceptHeaderLocaleResolver 14:17:06.468 [http-nio-8080-exec-2] DEBUG org.springframework.web.servlet.DispatcherServlet - Detected FixedThemeResolver 14:17:06.468 [http-nio-8080-exec-2] DEBUG org.springframework.web.servlet.DispatcherServlet - Detected org.springframework.web.servlet.view.DefaultRequestToViewNameTranslator@2bd4fa16 14:17:06.468 [http-nio-8080-exec-2] DEBUG org.springframework.web.servlet.DispatcherServlet - Detected org.springframework.web.servlet.support.SessionFlashMapManager@53592927 14:17:06.468 [http-nio-8080-exec-2] DEBUG org.springframework.jndi.JndiTemplate - Looking up JNDI object with name [java:comp/env/spring.liveBeansView.mbeanDomain] 14:17:06.468 [http-nio-8080-exec-2] DEBUG org.springframework.jndi.JndiLocatorDelegate - Converted JNDI name [java:comp/env/spring.liveBeansView.mbeanDomain] not found - trying original name [spring.liveBeansView.mbeanDomain]. javax.naming.NameNotFoundException: 名称[spring.liveBeansView.mbeanDomain]未在此上下文中绑定。找不到[spring.liveBeansView.mbeanDomain]。 14:17:06.468 [http-nio-8080-exec-2] DEBUG org.springframework.jndi.JndiTemplate - Looking up JNDI object with name [spring.liveBeansView.mbeanDomain] 14:17:06.468 [http-nio-8080-exec-2] DEBUG org.springframework.jndi.JndiPropertySource - JNDI lookup for name [spring.liveBeansView.mbeanDomain] threw NamingException with message: 名称[spring.liveBeansView.mbeanDomain]未在此上下文中绑定。找不到[spring.liveBeansView.mbeanDomain]。. Returning null. 14:17:06.468 [http-nio-8080-exec-2] DEBUG org.springframework.web.servlet.DispatcherServlet - enableLoggingRequestDetails='false': request parameters and headers will be masked to prevent unsafe logging of potentially sensitive data 14:17:06.468 [http-nio-8080-exec-2] INFO org.springframework.web.servlet.DispatcherServlet - Completed initialization in 425 ms 14:17:06.492 [http-nio-8080-exec-2] DEBUG org.springframework.web.servlet.DispatcherServlet - GET "/menu", parameters={} 14:17:06.496 [http-nio-8080-exec-2] DEBUG org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping - Mapped to com.buka.controller.ClassController#index(Clazz, ModelAndView) Creating a new SqlSession SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@50162767] was not registered for synchronization because synchronization is not active 14:17:06.548 [http-nio-8080-exec-2] DEBUG org.springframework.jdbc.datasource.DataSourceUtils - Fetching JDBC Connection from DataSource 14:17:06.594 [http-nio-8080-exec-2] INFO com.alibaba.druid.pool.DruidDataSource - {dataSource-1} inited JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@d2e8721] will not be managed by Spring ==> Preparing: select cid,cname,teacher from class ==> Parameters: <== Columns: cid, cname, teacher <== Row: 1, 1班, zhangsan <== Row: 19, 2班, lisi <== Total: 2 Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@50162767] 14:17:07.225 [http-nio-8080-exec-2] DEBUG org.springframework.web.servlet.view.JstlView - View name 'menu.jsp', model {clazz=Clazz{cid=0, cname='null', teacher='null'}, org.springframework.validation.BindingResult.clazz=org.springframework.validation.BeanPropertyBindingResult: 0 errors, modelAndView=ModelAndView [view="menu.jsp"; model={classist=[Clazz{cid=1, cname='1班', teacher='zhangsan'}, Clazz{cid=19, cname='2班', teacher='lisi'}]}], org.springframework.validation.BindingResult.modelAndView=org.springframework.validation.BeanPropertyBindingResult: 0 errors, classist=[Clazz{cid=1, cname='1班', teacher='zhangsan'}, Clazz{cid=19, cname='2班', teacher='lisi'}]} 14:17:07.243 [http-nio-8080-exec-2] DEBUG org.springframework.web.servlet.view.JstlView - Forwarding to [menu.jsp] 14:17:07.370 [http-nio-8080-exec-2] DEBUG org.springframework.web.servlet.DispatcherServlet - Completed 200 OK 14:17:07.386 [http-nio-8080-exec-4] DEBUG org.springframework.web.servlet.DispatcherServlet - GET "/menu", parameters={} 14:17:07.386 [http-nio-8080-exec-4] DEBUG org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping - Mapped to com.buka.controller.ClassController#index(Clazz, ModelAndView) Creating a new SqlSession SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@726f97db] was not registered for synchronization because synchronization is not active 14:17:07.386 [http-nio-8080-exec-4] DEBUG org.springframework.jdbc.datasource.DataSourceUtils - Fetching JDBC Connection from DataSource JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@d2e8721] will not be managed by Spring ==> Preparing: select cid,cname,teacher from class ==> Parameters: <== Columns: cid, cname, teacher <== Row: 1, 1班, zhangsan <== Row: 19, 2班, lisi <== Total: 2 Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@726f97db] 14:17:07.386 [http-nio-8080-exec-4] DEBUG org.springframework.web.servlet.view.JstlView - View name 'menu.jsp', model {clazz=Clazz{cid=0, cname='null', teacher='null'}, org.springframework.validation.BindingResult.clazz=org.springframework.validation.BeanPropertyBindingResult: 0 errors, modelAndView=ModelAndView [view="menu.jsp"; model={classist=[Clazz{cid=1, cname='1班', teacher='zhangsan'}, Clazz{cid=19, cname='2班', teacher='lisi'}]}], org.springframework.validation.BindingResult.modelAndView=org.springframework.validation.BeanPropertyBindingResult: 0 errors, classist=[Clazz{cid=1, cname='1班', teacher='zhangsan'}, Clazz{cid=19, cname='2班', teacher='lisi'}]} 14:17:07.386 [http-nio-8080-exec-4] DEBUG org.springframework.web.servlet.view.JstlView - Forwarding to [menu.jsp] 14:17:07.386 [http-nio-8080-exec-4] DEBUG org.springframework.web.servlet.DispatcherServlet - Completed 200 OK 14:17:07.540 [http-nio-8080-exec-6] DEBUG org.springframework.web.servlet.DispatcherServlet - GET "/menu", parameters={} 14:17:07.542 [http-nio-8080-exec-6] DEBUG org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping - Mapped to com.buka.controller.ClassController#index(Clazz, ModelAndView) Creating a new SqlSession SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@600acfdb] was not registered for synchronization because synchronization is not active 14:17:07.542 [http-nio-8080-exec-6] DEBUG org.springframework.jdbc.datasource.DataSourceUtils - Fetching JDBC Connection from DataSource JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@d2e8721] will not be managed by Spring ==> Preparing: select cid,cname,teacher from class ==> Parameters: <== Columns: cid, cname, teacher <== Row: 1, 1班, zhangsan <== Row: 19, 2班, lisi <== Total: 2 Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@600acfdb] 14:17:07.547 [http-nio-8080-exec-6] DEBUG org.springframework.web.servlet.view.JstlView - View name 'menu.jsp', model {clazz=Clazz{cid=0, cname='null', teacher='null'}, org.springframework.validation.BindingResult.clazz=org.springframework.validation.BeanPropertyBindingResult: 0 errors, modelAndView=ModelAndView [view="menu.jsp"; model={classist=[Clazz{cid=1, cname='1班', teacher='zhangsan'}, Clazz{cid=19, cname='2班', teacher='lisi'}]}], org.springframework.validation.BindingResult.modelAndView=org.springframework.validation.BeanPropertyBindingResult: 0 errors, classist=[Clazz{cid=1, cname='1班', teacher='zhangsan'}, Clazz{cid=19, cname='2班', teacher='lisi'}]} 14:17:07.549 [http-nio-8080-exec-6] DEBUG org.springframework.web.servlet.view.JstlView - Forwarding to [menu.jsp] 14:17:07.549 [http-nio-8080-exec-6] DEBUG org.springframework.web.servlet.DispatcherServlet - Completed 200 OK 15-Sep-2025 14:17:11.430 信息 [Catalina-utility-1] org.apache.catalina.startup.HostConfig.deployDirectory 把web 应用程序部署到目录 [E:\buka resource\Tomcat 9.0\Tomcat 9.0\webapps\manager] 14:17:11.459 [http-nio-8080-exec-9] DEBUG org.springframework.web.servlet.DispatcherServlet - POST "/addStu", parameters={masked} 14:17:11.461 [http-nio-8080-exec-9] DEBUG org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping - Mapped to com.buka.controller.StuController#addStu(Student, ModelAndView) 14:17:11.469 [http-nio-8080-exec-9] DEBUG org.springframework.web.method.HandlerMethod - Could not resolve parameter [0] in public org.springframework.web.servlet.ModelAndView com.buka.controller.StuController.addStu(com.buka.po.Student,org.springframework.web.servlet.ModelAndView): org.springframework.validation.BeanPropertyBindingResult: 1 errors Field error in object 'student' on field 'sid': rejected value [null]; codes [typeMismatch.student.sid,typeMismatch.sid,typeMismatch.int,typeMismatch]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [student.sid,sid]; arguments []; default message [sid]]; default message [Failed to convert value of type 'null' to required type 'int'; nested exception is org.springframework.core.convert.ConversionFailedException: Failed to convert from type [null] to type [int] for value 'null'; nested exception is java.lang.IllegalArgumentException: A null value cannot be assigned to a primitive type] 14:17:11.472 [http-nio-8080-exec-9] WARN org.springframework.web.servlet.mvc.support.DefaultHandlerExceptionResolver - Resolved [org.springframework.web.method.annotation.ModelAttributeMethodProcessor$1: org.springframework.validation.BeanPropertyBindingResult: 1 errors<EOL>Field error in object 'student' on field 'sid': rejected value [null]; codes [typeMismatch.student.sid,typeMismatch.sid,typeMismatch.int,typeMismatch]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [student.sid,sid]; arguments []; default message [sid]]; default message [Failed to convert value of type 'null' to required type 'int'; nested exception is org.springframework.core.convert.ConversionFailedException: Failed to convert from type [null] to type [int] for value 'null'; nested exception is java.lang.IllegalArgumentException: A null value cannot be assigned to a primitive type]] 14:17:11.472 [http-nio-8080-exec-9] DEBUG org.springframework.web.servlet.DispatcherServlet - Completed 400 BAD_REQUEST 15-Sep-2025 14:17:11.490 信息 [Catalina-utility-1] org.apache.jasper.servlet.TldScanner.scanJars 至少有一个JAR被扫描用于TLD但尚未包含TLD。 为此记录器启用调试日志记录,以获取已扫描但未在其中找到TLD的完整JAR列表。 在扫描期间跳过不需要的JAR可以缩短启动时间和JSP编译时间。 15-Sep-2025 14:17:11.492 信息 [Catalina-utility-1] org.apache.catalina.startup.HostConfig.deployDirectory Web应用程序目录[E:\buka resource\Tomcat 9.0\Tomcat 9.0\webapps\manager]的部署已在[62]毫秒内完成
09-16
--- ## ✅ 问题分析 从你的 Tomcat 启动日志和请求日志中,我们发现以下关键信息: ### ❗关键错误日志: ```log Field error in object 'student' on field 'sid': rejected value [null]; codes [typeMismatch.student.sid,typeMismatch.sid,typeMismatch.int,typeMismatch]; arguments [...]; default message [Failed to convert value of type 'null' to required type 'int'; ...] ``` --- ## ✅ 问题本质 ### ❗`Student` 类中 `sid` 是 `int` 类型(基本类型),但表单中没有提供 `sid` 字段,Spring MVC 无法将 `null` 赋值给 `int` 类型。 --- ## ✅ 代码分析 ### `Student` 类: ```java public class Student { private int sid; // ❗基本类型 int,不能为 null private String name; private String xuehao; private int cid; } ``` ### 表单页面 `addStu.jsp`: ```jsp <form action="/addStu" method="post"> 学生名:<input name="name" type="text"><br/> 学号:<input name="xuehao" type="text"><br/> 班级id:<input name="cid" type="text"><br/> <input type="submit" value="提交"> </form> ``` 表单中 **没有 `sid` 字段**,而 `sid` 是 `int` 类型,**Spring MVC 无法将空值转换为 `int` 类型**。 --- ## ✅ 解决方案 ### ✅ 方法一:将 `sid` 改为 `Integer` 类型(推荐) ```java public class Student { private Integer sid; // ✅ 改为包装类型,可以为 null private String name; private String xuehao; private Integer cid; // getter / setter } ``` 这样,当表单中没有提交 `sid` 时,Spring 会自动将其设为 `null`,而不是抛出转换错误。 --- ### ✅ 方法二:在表单中添加隐藏的 `sid` 字段(不推荐) 如果你希望由用户手动输入或由后台生成: ```jsp <input type="hidden" name="sid" value=""> ``` 但更推荐让数据库自动生成 `sid`(如使用自增主键)。 --- ### ✅ 方法三:配置 `@InitBinder` 忽略字段(可选) 如果你不想修改 `Student` 类,也可以在控制器中忽略 `sid` 字段的绑定: ```java @InitBinder public void initBinder(WebDataBinder binder) { binder.setDisallowedFields("sid"); // 忽略 sid 字段绑定 } ``` --- ## ✅ 额外建议 ### ✅ 使用 `@Valid` 验证数据(可选) 你可以在控制器方法中添加验证: ```java @RequestMapping("/addStu") public String addStu(@Valid Student student, BindingResult result) { if (result.hasErrors()) { return "addStu.jsp"; // 返回表单页面并显示错误 } stuService.addStu(student); return "redirect:/menu"; } ``` --- ## ✅ 总结 | 问题 | 原因 | 解决方案 | |------|------|----------| | `Failed to convert value of type 'null' to required type 'int'` | `Student.sid` 是 `int` 类型,不能为 `null` | 将 `int` 改为 `Integer` | | 表单提交失败 | Spring 无法绑定空值到基本类型 | 使用包装类型或忽略字段绑定 | | 数据插入失败 | 表单字段与实体类字段不匹配 | 检查字段名、类型、是否为空值 | --- ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值