前言
之前我用的都是配置类,因为我对于xml是深痛恶绝;但是在教同学用xml配的时候,状况频出,坏了,难道这么简单的我都还不会
首先要知道我们SSM工程中整合的是什么,怎么整合
需要整合的技术:
- spring
- springMvc
- mybatis
- log4j2(或其他日志)
然后我们需要maven的坐标,进行依赖的导入(都SSM,不会还不会maven吧)
<!-- mybatis核心依赖 -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.13</version>
</dependency>
<!-- spring整合mybatis依赖 -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>3.0.2</version>
</dependency>
<!-- mysql驱动 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.33</version>
</dependency>
<!-- 数据库驱动 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>6.0.7</version>
</dependency>
<!-- 数据库连接池HikariCP -->
<dependency>
<groupId>com.zaxxer</groupId>
<artifactId>HikariCP</artifactId>
<version>5.0.1</version>
</dependency>
<!-- servlet依赖 -->
<dependency>
<groupId>org.apache.tomcat</groupId>
<artifactId>tomcat-servlet-api</artifactId>
<version>10.1.11</version>
</dependency>
<!-- springMVC依赖 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>6.0.9</version>
</dependency>
注意!有spring-webmvc就够了,里面包含了spring-context、spring-core等
开整
这就是基本的配置文件了
整合mybatis
配置的思路很简单,spring是大管家,首先我们把数据库相关的交由spring容器管理,再把SqlSessionFactory给spring代理,就能实现和mybatis整合
这里推荐还是把数据库的信息独立成一个配置文件。推荐命名为db.properties或jdbc.properties
ok,独立出我们的数据库配置文件后,就可以愉快 的在spring管理数据源了
<!-- 添加属性文件配置 -->
<context:property-placeholder location="classpath:application.properties" />
<!-- 连接池配置 -->
<bean id="dataSource" class="com.zaxxer.hikari.HikariDataSource" destroy-method="close">
<property name="driverClassName" value="${jdbc.driver}" />
<property name="jdbcUrl" value="${jdbc.url}" />
<property name="username" value="${jdbc.username}" />
<property name="password" value="${jdbc.password}" />
</bean>
这里我使用了Hikari连接池,用啥都行
还记得嘛,mybatis的SqlSessionFactoryBean
需要配置数据源,所以:
<!-- spring管理sessionFactory -->
<bean id="sessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<!-- 注入数据源 -->
<property name="dataSource" ref="dataSource"/>
<!-- 指定MyBatis配置文件的位置 -->
<property name="configLocation" value="classpath:mybatis-config.xml"/>
<!-- 指定mapper文件的路径 -->
<property name="mapperLocations" value="classpath:mapper/*.xml"/>
</bean>
最后我们还需要配置mapper的扫描器,把mybatis代理的mapper进行管理
<!-- mapper扫描器 -->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="com.example.mapper" />
<property name="sqlSessionFactoryBeanName" value="sessionFactory" />
</bean>
mybatis的一些推荐设置与日志整合
话不多说,直接上log4j2的配置
<?xml version="1.0" encoding="UTF-8"?>
<Configuration xmlns="http://logging.apache.org/log4j/2.0/config">
<Appenders>
<Console name="stdout" target="SYSTEM_OUT">
<PatternLayout pattern="%5level [%t] - %msg%n"/>
</Console>
</Appenders>
<Loggers>
<Logger name="com.example.mapper" level="trace"/>
<Root level="error" >
<AppenderRef ref="stdout"/>
</Root>
</Loggers>
</Configuration>
在mybatis里面我们要设置日志的实现为LOG4J2
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"https://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<settings>
<!-- 开启驼峰转换 -->
<setting name="mapUnderscoreToCamelCase" value="true" />
<setting name="logImpl" value="LOG4J2"/>
</settings>
<typeAliases>
<package name="com.example.domain"/>
</typeAliases>
</configuration>
可以看到,我还开启了驼峰转换和配置实体类的包别名,有什么用?
- 根据工程规范,数据库表的字段与实体类字段对应,如uid --> uid,uname --> uname,这样是可以的,但是名字长了就不好命名了。推荐使用数据库字段使用下划线命名,实体类字段使用驼峰命名,如user_id --> userId。
- 配置实体类的包别名,我们在mapper.xml文件中就不用写全限定类名了
整合springMvc
整合springMvc会稍微麻烦一点,需要注意扫描包不要冲突了
我们先来整理一下springMvc中需要配置什么:
- 视图解析器,这是必要的,经过servlet后就到我们springMvc处理了
- 扫描控制层
<!-- 开启注解驱动 -->
<mvc:annotation-driven />
<!-- 配置视图解析器 -->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" id="viewResolver">
<property name="prefix" value="/"></property>
<property name="suffix" value=".html"></property>
</bean>
如果你用配置类来写,会知道RootConfigClasses
和ServletConfigClasses
两个概念,简单来说spring容器和springMvc容器存在父子管理,子容器可以访问父容器,父容器不能访问子容器
而spring容器是父容器!
所以我们扫描控制层,不能和spring扫的重叠了,这里介绍两种写法
第一种
spring配置文件
<!-- Spring容器中注册非@controller注解的Bean -->
<context:component-scan base-package="com.example">
<context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
</context:component-scan>
springMvc配置文件
<!-- SpringMvc容器中注册controller注解的Bean -->
<context:component-scan base-package="com.example" use-default-filters="false">
<context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
</context:component-scan>
第二种
spring配置文件
<!-- 多个扫描路径用逗号分割 -->
<context:component-scan base-package="com.example.service,com.example.domain"></context:component-scan>
springMvc配置文件
<context:component-scan base-package="com.example.controller"></context:component-scan>
web.xml加载spriing和springMvc的生命周期
都是web工程,肯定逃不开配置web.xml的了,除非你用配置类
这里有两个核心:
- spring服务需要在Tomcat一启动就提供,所以我们要配置监听器
- servlet的请求要交由springMvc处理
<!-- 配置Spring监听器启动,在服务器启动的时候最先启动 -->
<listener>
<listener-class>org.springframework.web.context.ContextCleanupListener</listener-class>
</listener>
<!-- servlet请求交由springMvc处理 -->
<servlet>
<servlet-name>springMvc</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>
classpath:springMvc.xml;
classpath:applicationContext.xml;
</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
到现在就配置完了,可以启动你的Tomcat服务器进行测试了
踩坑
1. web.xml配置
一开始配置spring监听器竟然给我报错
Servlet.init() for servlet springDispatcherServlet threw exception。Error creating bean with name ‘userController’: Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory
直接人傻了,在网上找了半圈发现,web.xml中引入配置contextConfigLocation有两种写法,全部写到servlet中的init-parm中就没有问题,部分写到context-parm中就会报上述错误
我原来的web.xml代码
<!-- 配置Spring监听器启动,在服务器启动的时候最先启动 -->
<listener>
<listener-class>org.springframework.web.context.ContextCleanupListener</listener-class>
</listener>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:applicationContext.xml;</param-value>
</context-param>
<!-- servlet请求交由springMvc处理 -->
<servlet>
<servlet-name>springMvc</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>
classpath:springMvc.xml;
</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet
修改后:
<!-- 配置Spring监听器启动,在服务器启动的时候最先启动 -->
<listener>
<listener-class>org.springframework.web.context.ContextCleanupListener</listener-class>
</listener>
<!-- servlet请求交由springMvc处理 -->
<servlet>
<servlet-name>springMvc</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>
classpath:springMvc.xml;
classpath:applicationContext.xml;
</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
2. controller无法正常工作
我进行如下检查:
- springMvc配置文件中注解驱动有没有开启
- springMvc容器扫描的是否和spring容器冲突
- 有没有加上controller注解
- web.xml有没有配置springMvc拦截请求
发现就是web.xml出现了问题,所以有了踩坑1,这里做一个排查思路的分享
3. Tomcat无法解析html文件
因为我配之后使用html文件进行测试,发现怎么都是404
首先,要确保你的html页面不在WEB-INF目录下;
其次,web.xml里放行了html文件:
<servlet-mapping>
<servlet-name>springMvc</servlet-name>
<url-pattern>/</url-pattern>
<url-pattern>*html</url-pattern>
</servlet-mapping>
这样还是无法解决,就去Tomcat的conf
目录下找到web.xml
文件,在大概450行左右,修改成:
感谢以下文章提供解决的思路
- https://blog.csdn.net/weixin_39722651/article/details/88191467
- https://www.cnblogs.com/xiaotong1223/p/9233169.html
如果需要源码,请移步我的gitee仓库