作为秋招上岸的 Java 实习生,我刚入职时曾对着 MyBatis 的Mapper.xml和 Spring 的配置文件发呆 —— 明明看文档知道 XML 是 “标记语言”,但一到实际配置就报错:要么属性没加引号导致解析失败,要么大小写写错让 SQL 查不到数据,甚至因为没处理&符号让整个接口崩了…

后来才发现,咱们 Java 实习生学 XML 不用啃厚厚的教程,重点抓 “基础语法 + 工作常用场景 + 避坑点” 就行。今天就把这份 “实习生专属 XML 笔记” 分享出来,帮你快速搞定工作中 90% 的 XML 需求~

一、先搞懂:为什么 Java 实习生绕不开 XML?

很多同学会疑惑:“现在都用注解了,为啥还要学 XML?” 其实在日常开发中,XML 还在大量使用,尤其是这两个场景,咱们躲不开:

  • MyBatis 配置:写 SQL 的Mapper.xml(比如定义查询语句、结果映射);
  • Spring 配置:老项目的applicationContext.xml(定义 Bean、配置数据源);
  • 其他场景:比如接口文档的swagger.xml、日志配置log4j.xml,甚至有些公司的接口参数格式也是 XML。

简单说:XML 是 “配置文件的常用格式”,搞懂它才能看懂项目配置、改对 SQL 映射 —— 这是咱们实习生上手干活的基础。

二、XML 基础语法:5 个核心规则,记牢不踩语法坑

XML 的语法很严谨,哪怕一个空格、一个引号错了,都会导致 “配置失效” 或 “解析报错”。咱们先把最核心的规则吃透,用表格 + 例子讲明白,方便你直接对照用。

1. 必须有 XML 声明(可选但建议加)

XML 声明要放在文档第一行,告诉解析器 “这是 XML 文件,用什么版本和编码”。

  • 语法:<?xml version="1.0" encoding="utf-8"?>
  • 说明:
    • version="1.0":XML 的版本(目前主流是 1.0,不用改);
    • encoding="utf-8":文件编码(和项目编码保持一致,避免中文乱码)。
  • 错误示例:如果把声明放在根元素后面,会直接报错:
    <!-- 错误:声明不在第一行 -->
    <mapper namespace="com.test.mapper.UserMapper">
    <?xml version="1.0" encoding="utf-8"?>
    </mapper>
    

2. 必须有且只有一个根元素

XML 文档就像 “一棵大树”,根元素是 “树干”,所有其他元素都是 “树枝”,不能没有根,也不能有多个根

  • 正确示例(MyBatis 的 Mapper.xml,根元素是<mapper>):
    <?xml version="1.0" encoding="utf-8"?>
    <!-- 根元素:mapper -->
    <mapper namespace="com.test.mapper.UserMapper">
      <!-- 子元素:select -->
      <select id="getUserById" parameterType="int" resultType="User">
        SELECT * FROM user WHERE id = #{id}
      </select>
    </mapper>
    
  • 错误示例:多个根元素(<mapper><user>并列),解析器会报错:
    <?xml version="1.0" encoding="utf-8"?>
    <mapper namespace="com.test.mapper.UserMapper">...</mapper>
    <user>...</user> <!-- 错误:多个根元素 -->
    

3. 元素规则:大小写敏感 + 正确嵌套

这是实习生最容易踩的坑!XML 对大小写 “零容忍”,嵌套也必须严格对应。

  • 核心规则:

    1. 大小写敏感<User><user>是两个不同元素(比如 Spring 配置里<bean>不能写成<Bean>);
    2. 必须闭合:要么成对闭合(<select>...</select>),要么自闭合(<property name="url" value="jdbc:mysql://localhost:3306/test"/>);
    3. 不能交叉嵌套:比如<a><b></a></b>是错误的,必须是<a><b></b></a>
  • 正确示例(Spring 的 Bean 配置):

    <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
      <!-- 自闭合元素:property -->
      <property name="driverClassName" value="com.mysql.cj.jdbc.Driver"/>
      <property name="url" value="jdbc:mysql://localhost:3306/test"/>
    </bean> <!-- 正确闭合bean元素 -->
    
  • 错误示例:

    <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
      <property name="driverClassName" value="com.mysql.cj.jdbc.Driver"> <!-- 错误:没闭合property -->
    </Bean> <!-- 错误:bean写成Bean,大小写错了 -->
    

4. 属性值:必须加引号(单引双引都可,别漏!)

和 HTML 不同,XML 的属性值必须用引号包裹(单引号'或双引号"都行),没加引号会直接解析失败。

  • 正确示例(MyBatis 的 resultMap 配置):
    <resultMap id="userResultMap" type="User">
      <!-- 属性column和property都加了双引号 -->
      <id column="user_id" property="userId"/>
      <result column="user_name" property="userName"/>
    </resultMap>
    
  • 错误示例:属性值没加引号,启动项目会报 “XML 解析异常”:
    <result column=user_id property=userName/> <!-- 错误:column和property值没加引号 -->
    

5. 特殊字符:用 “实体引用” 代替

XML 里有些字符有特殊意义(比如<会被当成元素开始),直接写会报错,必须用 “实体引用” 代替。

咱们实习生常用的 5 个实体引用,记牢这张表就行:

实体引用 对应字符 用途场景 示例(正确写法)
&lt; < 比较符号(比如 SQL 里的< salary &lt; 5000(对应 SQL:salary < 5000
&gt; > 比较符号 age &gt; 18(对应 SQL:age > 18
&amp; & URL 参数、SQL 里的& url="jdbc:mysql://localhost:3306/test?useSSL&amp;serverTimezone=UTC"
&apos; ' 单引号 name='Tom &apos;Jerry&apos;'(对应值:Tom 'Jerry'
&quot; " 双引号 title=&quot;Java XML&quot;(对应值:Java XML
  • 错误示例:SQL 里直接写<,导致 Mapper.xml 解析失败:
    <!-- 错误:直接写<,会被当成元素开始 -->
    <select id="getLowSalaryUser" resultType="User">
      SELECT * FROM user WHERE salary < 5000
    </select>
    
  • 正确示例:用&lt;代替<
    <select id="getLowSalaryUser" resultType="User">
      SELECT * FROM user WHERE salary &lt; 5000
    </select>
    

6. 空格保留:XML 不 “吃” 空格

HTML 会把多个连续空格合并成一个,但 XML 会完整保留空格—— 这个特性在配置 “值” 的时候要注意,别多写或少写空格。

  • 示例:如果配置数据库密码时多写了空格:

    <!-- 错误:value值末尾多了个空格 -->
    <property name="password" value="123456 "/>
    

    启动项目会报 “数据库连接失败”,因为实际传递的密码是123456 (带空格),和真实密码不匹配。

  • 正确做法:配置值前后别加多余空格,除非业务明确需要:

    <property name="password" value="123456"/>
    

7. XML 注释:别放错位置

注释格式是<!-- 注释内容 -->,但有个禁忌:不能放在 XML 声明之前,也不能嵌套注释。

  • 正确示例:
    <?xml version="1.0" encoding="utf-8"?>
    <!-- 这是MyBatis的用户Mapper配置 -->
    <mapper namespace="com.test.mapper.UserMapper">
      <!-- 查询用户详情 -->
      <select id="getUserById" resultType="User">
        SELECT * FROM user WHERE id = #{id}
      </select>
    </mapper>
    
  • 错误示例:注释放在 XML 声明前,会导致解析报错:
    <!-- 错误:注释在XML声明前面 -->
    <?xml version="1.0" encoding="utf-8"?>
    <mapper namespace="com.test.mapper.UserMapper">...</mapper>
    

三、Java 实习生必练:XML 实战场景(附代码示例)

学完语法,咱们直接对接工作 —— 这 3 个场景是实习生最常接触的,结合代码例子讲,你可以直接抄模板改。

场景 1:MyBatis 的 Mapper.xml(写 SQL 必备)

咱们写接口时,SQL 基本都放在 Mapper.xml 里,核心是<select>/<insert>标签和resultMap配置。

  • 完整示例(用户查询 + 新增):

    <?xml version="1.0" encoding="utf-8"?>
    <!-- 根元素mapper:namespace要和Mapper接口全路径一致 -->
    <mapper namespace="com.test.mapper.UserMapper">
      <!-- resultMap:解决数据库字段(下划线)和Java实体(驼峰)映射问题 -->
      <resultMap id="userResultMap" type="com.test.entity.User">
        <id column="user_id" property="userId"/> <!-- 主键映射 -->
        <result column="user_name" property="userName"/>
        <result column="user_age" property="userAge"/>
        <result column="create_time" property="createTime"/>
      </resultMap>
    
      <!-- 1. 查询用户:用resultMap映射结果 -->
      <select id="getUserById" parameterType="java.lang.Long" resultMap="userResultMap">
        SELECT user_id, user_name, user_age, create_time
        FROM user
        WHERE user_id = #{userId}
          AND user_age &gt; 18 <!-- 用实体引用代替> -->
      </select>
    
      <!-- 2. 新增用户:useGeneratedKeys获取自增主键 -->
      <insert id="addUser" parameterType="com.test.entity.User" useGeneratedKeys="true" keyProperty="userId">
        INSERT INTO user (user_name, user_age, create_time)
        VALUES (#{userName}, #{userAge}, #{createTime})
      </insert>
    </mapper>
    
  • 关键注意点:

    1. namespace必须和 Mapper 接口的全路径一致(比如接口是com.test.mapper.UserMapper,这里就写这个);
    2. resultMap用来解决 “下划线转驼峰” 问题(比如数据库user_id对应 Java 的userId),不用每次查都写别名;
    3. 新增时用useGeneratedKeys="true"+keyProperty="userId",能把数据库自增的userId回写到 Java 实体里。

场景 2:Spring 配置文件(老项目常用)

虽然现在 Spring Boot 多用注解,但有些老项目还在用applicationContext.xml配置 Bean,咱们要能看懂。

  • 示例(配置数据源 Bean):

    <?xml version="1.0" encoding="utf-8"?>
    <!-- 引入Spring约束:固定格式,复制就行 -->
    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xsi:schemaLocation="http://www.springframework.org/schema/beans
           http://www.springframework.org/schema/beans/spring-beans.xsd">
    
      <!-- 配置Druid数据源Bean:id是Bean的名称,class是全类名 -->
      <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
        <!-- 用property注入属性:name对应Bean的set方法名(比如setDriverClassName) -->
        <property name="driverClassName" value="com.mysql.cj.jdbc.Driver"/>
        <property name="url" value="jdbc:mysql://localhost:3306/test?useSSL&amp;serverTimezone=UTC"/> <!-- &用&amp;代替 -->
        <property name="username" value="root"/>
        <property name="password" value="123456"/>
      </bean>
    
      <!-- 配置Service Bean:依赖注入dataSource -->
      <bean id="userService" class="com.test.service.impl.UserServiceImpl">
        <property name="dataSource" ref="dataSource"/> <!-- ref引用上面的dataSource Bean -->
      </bean>
    </beans>
    
  • 关键注意点:

    1. 开头的xmlns约束是固定的,直接复制项目里的模板就行,不用自己写;
    2. propertyname要和 Bean 类里的set方法对应(比如setDriverClassName对应name="driverClassName");
    3. 引用其他 Bean 用ref(比如ref="dataSource"),直接赋值用value

场景 3:XML 文件的读取(了解基础逻辑)

偶尔需要自己写代码读 XML 配置(比如读自定义的配置文件),用 Java 自带的DOM解析就行,不用学复杂的框架。

  • 示例(读user-config.xml里的用户名):

    import org.w3c.dom.Document;
    import org.w3c.dom.Element;
    import org.w3c.dom.NodeList;
    import javax.xml.parsers.DocumentBuilder;
    import javax.xml.parsers.DocumentBuilderFactory;
    import java.io.File;
    
    public class XmlReader {
        public static void main(String[] args) throws Exception {
            // 1. 创建解析工厂
            DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
            // 2. 创建解析器
            DocumentBuilder builder = factory.newDocumentBuilder();
            // 3. 解析XML文件,得到Document对象
            Document doc = builder.parse(new File("src/main/resources/user-config.xml"));
            
            // 4. 获取根元素
            Element root = doc.getDocumentElement();
            // 5. 查找<username>元素
            NodeList nodeList = root.getElementsByTagName("username");
            if (nodeList.getLength() > 0) {
                // 6. 获取元素内容
                String username = nodeList.item(0).getTextContent();
                System.out.println("配置的用户名:" + username); // 输出:配置的用户名:admin
            }
        }
    }
    
  • 对应的user-config.xml

    <?xml version="1.0" encoding="utf-8"?>
    <user-config>
      <username>admin</username>
      <password>123456</password>
    </user-config>
    

四、实习生 XML 避坑指南:6 个血泪教训

这些坑都是我和同事踩过的,每个坑都附 “错误示例 + 解决方法”,帮你少走弯路。

坑 1:大小写写错,配置 “找不到”

错误场景:把 Spring 的<bean>写成<Bean>,启动项目报 “NoSuchBeanDefinitionException”(找不到 Bean)。原因:XML 对大小写敏感,<Bean><bean>是两个不同元素。解决:严格对照项目里的模板,比如<bean><mapper><resultMap>这些标签,大小写别乱改。

坑 2:属性没加引号,解析报错

错误场景:Mapper.xml 里写<result column=user_id property=userName/>,启动报 “SAXParseException: 元素类型 "result" 的属性 "column" 必须具有值”。原因:XML 属性值必须加引号,不管是单引还是双引。解决:所有属性值都用引号包裹,比如<result column="user_id" property="userName"/>

坑 3:特殊字符没转义,SQL 执行失败

错误场景:SQL 里写WHERE salary < 5000,Mapper.xml 解析时把<当成元素开始,报 “XML 文档结构不正确”。原因<是 XML 的特殊字符,必须转义。解决:用&lt;代替<,比如WHERE salary &lt; 5000;其他特殊字符按 “实体引用表” 转义。

坑 4:注释放在 XML 声明前,文件无法解析

错误场景:在 XML 声明前面加注释<!-- 配置文件 -->,启动项目报 “XML 声明允许出现在文档类型声明之前的唯一内容”。原因:XML 声明必须是文档的第一行内容,前面不能有任何东西(包括注释)。解决:把注释移到 XML 声明后面,比如:

<?xml version="1.0" encoding="utf-8"?>
<!-- 配置文件 -->
<mapper namespace="com.test.mapper.UserMapper">...</mapper>

坑 5:根元素不唯一,解析失败

错误场景:在 Mapper.xml 里写两个根元素<mapper><user>,报 “文档中根元素后面的标记必须格式正确”。原因:XML 必须有且只有一个根元素。解决:所有子元素都放在同一个根元素里,比如 Mapper.xml 的所有内容都放在<mapper>里。

坑 6:空格多余,配置值错误

错误场景:数据库密码配置成<property name="password" value="123456 "/>(末尾多了空格),连接数据库报 “Access denied for user 'root'@'localhost' (using password: YES)”。原因:XML 保留空格,实际密码是123456 (带空格),和真实密码不匹配。解决:配置值前后别加多余空格,写的时候多检查一遍。

五、XML 学习路径:2 周搞定,不用焦虑

咱们实习生学 XML 不用贪多,按这个路径来,1-2 周就能上手干活:

  1. Day1-Day2:吃透基础语法记牢 “声明、根元素、属性引号、实体引用、空格保留” 这 5 个核心规则,用记事本写个简单的 XML 文件练手(比如user.xml),检查是否能正常解析。

  2. Day3-Day5:结合 MyBatis 实战找项目里的 Mapper.xml 当模板,试着改 SQL(比如加个查询条件、改个 resultMap),跑通接口 —— 重点练 “resultMap 映射” 和 “特殊字符转义”。

  3. Day6-Day7:看懂 Spring 配置看老项目的applicationContext.xml,理解<bean><property>的作用,知道 “怎么通过 ref 引用其他 Bean”。

  4. Day8-Day10:总结避坑点把自己踩过的坑记在笔记里(比如大小写错误、属性没加引号),下次遇到类似报错能快速定位。

结尾:XML 不用学太深,实用就好!

最后想跟大家说:咱们 Java 实习生学 XML,重点不是 “精通所有语法”,而是 “能改对配置、能查错”。遇到 XML 报错不用慌,先检查这 3 点:

  1. 看日志:报错信息里一般会写 “第几行有问题”(比如 “Line 10: 属性值必须加引号”);
  2. 查语法:对照本文的 “基础规则”,看是不是大小写、引号、实体引用错了;
  3. 抄模板:项目里肯定有正确的 XML 文件,复制过来改内容,比自己从头写不容易错。

如果这篇笔记帮到你了,欢迎在评论区分享你的 XML 踩坑经历~ 咱们一起在 “实习生加油站” 里慢慢进步!

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐