一、MyBatis
-
主要功能:操作数据库
-
ORM
-
只是用MyBatis,打包方式可以为jar包
一、依赖
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.9</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.28</version>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
二、起步(XML)
1. 编写pojo实体类
// 对应表的字段
package com.miao.mybatis.pojo;
public class User {
private Integer id;
private String username;
private String password;
private Integer age;
private String gender;
private String email;
public User() {
}
public User(Integer id, String username, String password, Integer age, String gender, String email) {
this.id = id;
this.username = username;
this.password = password;
this.age = age;
this.gender = gender;
this.email = email;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public String getGender() {
return gender;
}
public void setGender(String gender) {
this.gender = gender;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
@Override
public String toString() {
return super.toString();
}
}
2. 编写核心配置文件(含配置详解)
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<!--配置数据库环境,可以有多个environment,default用来指定使用的数据库的id,如development、production-->
<environments default="development">
<environment id="development">
<!--事务管理,type用来指定事务处理方式,可以用JDBC(原生)/MANAGED(Spring管理)-->
<transactionManager type="JDBC"/>
<!--数据源,type用来指定使用何种技术,
可以用POOLED(使用数据库连接池)/UNPOOLED(不使用)/JNDI(使用上下文数据源,了解即可)-->
<dataSource type="POOLED">
<property name="driver" value="com.mysql.cj.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://101.43.117.227:3308/SSM?serverTimezone=UTC"/>
<property name="username" value="root"/>
<property name="password" value="123456"/>
</dataSource>
</environment>
</environments>
<!--引入mybatis映射文件-->
<mappers>
<mapper resource="mappers/UserMapper.xml"/>
</mappers>
</configuration>
3. 编写mapper接口类
package com.miao.mybatis.mapper;
public interface UserMapper {
int insertUser();
}
4. 编写mapper映射文件
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.miao.mybatis.mapper.UserMapper">
<!--
1. mapper接口类的全类名与映射文件的namespace一致
2. mapper接口类的方法名与标签id保持一致
-->
<!--int insertUser()-->
<insert id="insertUser">
insert into t_user values(null, 'admin', '123456', 23, '男', '123456@qq.com');
</insert>
</mapper>
5. 编写测试类
package com.miao.mybatis.test;
import com.miao.mybatis.mapper.UserMapper;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.Test;
import java.io.IOException;
import java.io.InputStream;
public class MyBatisTest {
@Test
public void testInsert() throws IOException {
// 1.获取核心配置文件输入流
InputStream i = Resources.getResourceAsStream("mybatis-config.xml");
// 2.获取SqlSessionFactoryBuilder对象
SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
// 3.获取SqlSessionFactory对象
SqlSessionFactory sqlSessionFactory = sqlSessionFactoryBuilder.build(i);
// 4.获取sql会话对象,操作数据库
SqlSession sqlSession = sqlSessionFactory.openSession();
// 5.获取接口类UserMapper的代理实现类对象
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
// 6.实现功能
int result = mapper.insertUser();
System.out.println("结果是" + result);
// 7.提交事务
sqlSession.commit();
// 8.关闭会话
sqlSession.close();
}
}
6. 日志功能
#将等级为DEBUG的日志信息输出到console和file这两个目的地,console和file的定义在下面的代码
log4j.rootLogger=DEBUG,console,file
#控制台输出的相关设置
log4j.appender.console = org.apache.log4j.ConsoleAppender
log4j.appender.console.Target = System.out
log4j.appender.console.Threshold=DEBUG
log4j.appender.console.layout = org.apache.log4j.PatternLayout
log4j.appender.console.layout.ConversionPattern=[%c]-%m%n
#文件输出的相关设置
log4j.appender.file = org.apache.log4j.RollingFileAppender
log4j.appender.file.File=./log/logFile.log
log4j.appender.file.MaxFileSize=10mb
log4j.appender.file.Threshold=DEBUG
log4j.appender.file.layout=org.apache.log4j.PatternLayout
log4j.appender.file.layout.ConversionPattern=[%p][%d{yy-MM-dd}][%c]%m%n
#日志输出级别
log4j.logger.org.mybatis=DEBUG
log4j.logger.java.sql=DEBUG
log4j.logger.java.sql.Statement=DEBUG
log4j.logger.java.sql.ResultSet=DEBUG
log4j.logger.java.sql.PreparedStatement=DEBUG
三、配置文件附加标签及模版
一、设置顺序
严格按照该顺序定义标签:properties,settings,typeAliases,typeHandlers,objectFactory,objectWrapperFactory,reflectorFactory,plugins,environments,databaseIdProvider,mappers
二、附加标签
1. properties标签
<!--可以使用${url}方式使用值-->
<properties resource="jdbc.properties"/>
2. typeAliases标签
<!--1. 通过正常方式设置类型别名,可以不用再写全类名类。注意:alias可以不写,默认是取普通类名即也是User(不区分大小写)-->
<!--2. 通过包设置类型别名,包下所有类型拥有默认别名(同上面方法不写alias)-->
<typeAliases>
<!--<typeAlias type="com.miao.mybatis.pojo.User" alias="User"></typeAlias>-->
<package name="com.miao.mybatis.pojo"/>
</typeAliases>
3. mappers标签
<!--1.普通方法引入mybatis映射文件-->
<!--2.包引入映射文件,接口类的包名与映射文件包名一致,即都为mapper,并且接口类名字与其对应映射文件一致,即都为UserMapper-->
<mappers>
<!-- <mapper resource="mappers/UserMapper.xml"/>-->
<package name="com.miao.mybatis.mapper"/>
</mappers>
4. settings标签
<!-- 设置映射,自动将字段名emp_id、emp_name等映射成empId、empName,
所以实体类型的属性也应该设置为empId、empName,即驼峰格式 -->
<settings>
<setting name="mapUnderscoreToCamelCase" value="true"/>
<!-- 懒加载功能和sql语句不执行 -->
<setting name="lazyLoadingEnabled" value="true"/>
<setting name="aggressiveLazyLoading" value="false"/>
<!-- 二级缓存 -->
<setting name="cacheEnabled" value="true" />
</settings>
5. plugins标签
<!-- 设置插件 -->
<plugins>
<plugin interceptor="com.github.pagehelper.PageInterceptor"></plugin>
</plugins>
三. 模版
1. 核心配置文件
- mybatis-config.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<!--jdbc配置文件-->
<properties resource="jdbc.properties"/>
<!--设置映射-->
<settings>
<setting name="mapUnderscoreToCamelCase" value="true"/>
<setting name="lazyLoadingEnabled" value="true"/>
<setting name="aggressiveLazyLoading" value="false"/>
<setting name="cacheEnabled" value="true" />
</settings>
<typeAliases>
<!--实体类所在包-->
<package name="com.miao.mybatis.pojo"/>
</typeAliases>
<!-- 设置插件 -->
<plugins>
<plugin interceptor="com.github.pagehelper.PageInterceptor"></plugin>
</plugins>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="${jdbc.driverClassName}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</dataSource>
</environment>
</environments>
<mappers>
<!--mapper接口类及其映射文件所在包-->
<package name="com.miao.mybatis.mapper"/>
</mappers>
</configuration>
2. 映射文件模版
- xxxMapper.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!--接口类全类名-->
<mapper namespace="com.miao.mapper.UserMapper">
</mapper>
四、获取参数值
一、两种方式
- ${}字符串拼接,存在sq注入,{}中可以写任意的东西(不能写数值),仍然可以接收到,不建议!。
- #{}占位符,不存在sql注入,{}中可以写任意的东西,仍然可以接收到,不建议!。
二、五种情况
一、单个字面量类型的参数
public interface UserMapper {
User getUserByUserName(String username);
}
<select id="getUserByUserName" resultType="User">
SELECT * FROM t_user WHERE username='${username}'; // 需要自己加上''
SELECT * FROM t_user WHERE username=#{username}; // 不需要自己加''
</select>
二、多个字面量类型的参数
public interface UserMapper {
User checkLogin(String username, String password);
}
<!--第二种情况,多个参数。
Mybatis会将参数放在map集合中:
以arg0、arg1...为键,以实参为值;
以param1、param2...为键,以实参为值;
因此只需要访问以上的键就可以得到值
-->
<select id="checkLogin" resultType="User">
SELECT * FROM t_user WHERE username=#{arg0} and password=#{arg1};
</select>
三、map集合类型的参数
public interface UserMapper {
User checkLoginByMap(Map<String, String> map); // 使用map.put("username", "admin");
}
<!--第三种情况,map集合参数。
不能可使用Mybatis提供的map,如arg0、param0
必须直接使用键名取实参值
-->
<select id="checkLoginByMap" resultType="User">
SELECT * FROM t_user WHERE username=#{username} and password=#{password};
</select>
四、实体类类型的参数(推荐)
public interface UserMapper {
int insertUser(User user); // 使用User user = new User(xxx, xxx, xxx...);
}
<!--第四种情况,实体类类型。需要有get和set方法,然后使用他们后面的属性小写形式作为属性名-->
<insert id="insertUser">
INSERT INTO t_user VALUES(#{id}, #{username}, #{password}, #{age}, #{gender}, #{email});
</insert>
五、@param标识的参数(推荐)
public interface UserMapper {
User checkLoginByParam(@Param("username") String username, @Param("password") String password);
}
<!--第五种情况,比第一二三种方式都方便;
Mybatis仍然会把他们放在map集合中,但是键名是@Param中的,
可以使用param0、param1
-->
<select id="checkLoginByParam" resultType="User">
SELECT * FROM t_user WHERE username=#{username} and password=#{password};
</select>
五、查询功能
一、五种情况
一、查询一个实体类对象
public interface UserMapper {
User getUserById(@Param("id") Integer id);
}
<!-- 查询一个实体类对象 -->
<select id="getUserById" resultType="User">
SELECT * FROM t_user WHERE id=#{id};
</select>
二、查询多个实体类对象转为list集合
public interface UserMapper {
List<User> getAllUser();
}
<!-- 查询多个实体类对象为list集合 -->
<select id="getAllUser" resultType="User">
SELECT * FROM t_user;
</select>
三、查询单个数据(如COUNT(),SUM())
public interface UserMapper {
Integer getCount(); // 查询用户总数
}
<!-- 查询单个字段值 -->
<select id="getCount" resultType="Integer">
SELECT COUNT(*) FROM t_user;
</select>
四、查询一条数据转为map集合
public interface UserMapper {
Map<String, Object> getUserByIdToMap(@Param("id") Integer id);
}
<!-- 查询一条数据转为map集合 -->
<select id="getUserByIdToMap" resultType="map">
SELECT * FROM t_user WHERE id=#{id};
</select>
五、查询多条数据转为map集合/多条数据转为map集合再转为List集合
public interface UserMapper {
List<Map<String, Object>> getAllUserToMap();
// @MapKey("id") 必须使用此注解明确map的键,此处以每条数据的id为键,值为每一条记录
// Map<String, Object> getAllUserToMap();
}
<!-- 查询多条数据转为map集合 -->
<select id="getAllUserToMap" resultType="map">
SELECT * FROM t_user;
</select>
六、特殊操作
一、模糊查询
public interface UserMapper {
List<User> getUserByLike(@Param("vague") String vague);
}
<!-- 模糊查询 -->
<select id="getUserByLike" resultType="User">
SELECT * FROM t_user WHERE username LIKE '%${vague}%';
// SELECT * FROM t_user WHERE username LIKE CONCAT('%', #{vague}, '%');
// SELECT * FROM t_user WHERE username LIKE "%"#{vague}"%";
</select>
二、批量删除
public interface UserMapper {
void deleteMoreUser(@Param("id") String ids);
}
<!-- 批量删除 -->
<delete id="deleteMoreUser">
DELETE FROM t_user WHERE id IN(${ids});
</delete>
三、动态设置表名
public interface UserMapper {
List<User> getUserList(@Param("tableName") String tableName);
}
<!-- 动态设置表名 -->
<select id="getUserList" resultType="User">
SELECT * FROM ${tableName};
</select>
四、获取自增主键
public interface UserMapper {
void insertUserKey(User user);
// 实现方式如下
// User user = new User(null, "马超", "123", 20, "男", "123@qq.com");
// mapper.insertUserKey(user);
// System.out.println(user.getId()); // 获取自增的主键
}
<!-- 获取自增的主键, 将主键值放在当前实体类型的id属性中-->
<insert id="insertUserKey" useGeneratedKeys="true" keyProperty="id">
INSERT INTO t_user VALUES(null, #{username}, #{password}, #{age}, #{gender}, #{email});
</insert>
七、自定义映射
- 解决实体类中属性名与数据库字段名不一致问题
一、自动映射
public interface EmpMapper {
Emp getEmpByEmpId(@Param("empId") Integer empId);
}
<!-- 属性名与字段名不一致
1.起别名
2.配置settings
-->
<select id="getEmpByEmpId" resultType="Emp">
SELECT * FROM t_emp WHERE emp_id=#{empId};
</select>
<!-- 设置映射,自动将字段名emp_id、emp_name等映射成empId、empName,
所以实体类型的属性也应该设置为empId、empName,即驼峰格式 -->
<settings>
<setting name="mapUnderscoreToCamelCase" value="true"/>
</settings>
二、resultMap映射
1. 处理主键及普通字段
- 实体类Emp中都为普通类型
public interface EmpMapper {
Emp getEmpByEmpIdResultMap(@Param("empId") Integer empId);
}
<!--
resultMap解决属性名与字段名不一致问题
id可以自定义,type为处理的实体类类型。
其中id标签处理主键,result处理普通字段,association处理多对一,collection处理一对多
-->
<resultMap id="empResultMap" type="Emp">
<id column="emp_id" property="empId"/>
<result column="emp_name" property="empName"/>
<result column="emp_age" property="empAge"/>
<result column="emp_gender" property="empGender"/>
</resultMap>
<!--resultMap填写resultMap标签的id属性-->
<select id="getEmpByEmpIdResultMap" resultMap="empResultMap">
SELECT * FROM t_emp WHERE emp_id=#{empId};
</select>
2. 处理多对一
- 实体类Emp中有private Dept dept;
public interface EmpMapper {
Emp getEmpByEmpIdAndDeptId(@Param("empId") Integer empId); // 多表查询
// 以下两步用于分步查询
Emp getEmpByEmpIdAndDeptIdStepOne(@Param("empId") Integer empId); // 分步查询
Dept getEmpAndDeptStepTwo(@Param("deptId") Integer deptId); // 分步查询
}
1. 级联方式
-
<!-- 1.级联 --> <resultMap id="empAndDept1" type="Emp"> <id column="emp_id" property="empId"/> <result column="emp_name" property="empName"/> <result column="emp_age" property="empAge"/> <result column="emp_gender" property="empGender"/> <!-- 将数据库字段名为dept_id、dept_name映射成实体类属性dept的deptId和deptName --> <result column="dept_id" property="dept.deptId"/> <result column="dept_name" property="dept.deptName"/> </resultMap> <select id="getEmpByEmpIdAndDeptId" resultMap="empAndDept1"> SELECT t_emp.*, t_dept.* FROM t_emp LEFT JOIN t_dept ON t_emp.dept_id = t_dept.dept_id WHERE t_emp.emp_id = #{empId}; </select>
2. association方式
-
<!-- 2.association --> <resultMap id="empAndDept2" type="Emp"> <id column="emp_id" property="empId"/> <result column="emp_name" property="empName"/> <result column="emp_age" property="empAge"/> <result column="emp_gender" property="empGender"/> <!-- javaType设置需要处理的类型 --> <association property="dept" javaType="Dept"> <id column="dept_id" property="deptId"/> <result column="dept_name" property="deptName"/> </association> </resultMap> <select id="getEmpByEmpIdAndDeptId" resultMap="empAndDept2"> SELECT t_emp.*, t_dept.* FROM t_emp LEFT JOIN t_dept ON t_emp.dept_id = t_dept.dept_id WHERE t_emp.emp_id = #{empId}; </select>
3. 分步查询方式
-
需使用settings设置
<setting name="mapUnderscoreToCamelCase" value="true"/>
-
<!-- 3.分步查询 --> <resultMap id="empAndDept3" type="Emp"> <id column="emp_id" property="empId"/> <result column="emp_name" property="empName"/> <result column="emp_age" property="empAge"/> <result column="emp_gender" property="empGender"/> <!-- property为需要赋值的实体类属性,其值由select中方法返回值给的,select为下一步的sql接口方法,column为取上一步sql接口方法查询结果的某一字段作为下一步sql的查询条件 --> <!-- 需要使用settings!!!否则dept为null--> <association property="dept" select="com.miao.mybatis.mapper.EmpMapper.getEmpAndDeptStepTwo" column="dept_id"/> </resultMap> <select id="getEmpByEmpIdAndDeptIdStepOne" resultMap="empAndDept3"> SELECT * FROM t_emp WHERE emp_id=#{empId}; </select> <select id="getEmpAndDeptStepTwo" resultType="Dept"> SELECT * FROM t_dept WHERE dept_id=#{deptId}; </select>
4. 延迟加载
- 全局的分步查询适用,使用fetchType="eager"即可恢复立即加载
<settings>
<setting name="mapUnderscoreToCamelCase" value="true"/>
<!-- 开启延迟加载,若不获取dept(emp.getDept())则不执行它的sql -->
<!-- 实现功能,但语句仍然会执行 -->
<setting name="lazyLoadingEnabled" value="true"/>
<!-- 语句将不会执行 -->
<setting name="aggressiveLazyLoading" value="false"/>
</settings>
3. 处理一对多
-
实体类Dept中有private List emps;
-
public interface EmpMapper { Dept getDeptAndEmpByDeptId(@Param("deptId") Integer deptId); // 多表查询 Dept getStepOne(@Param("deptId") Integer deptId); // 分步查询 List<Emp> getStepTwo(@Param("deptId") Integer deptId); // 分步查询 }
1. collection方式
<resultMap id="deptAndEmpResultMap" type="Dept">
<id column="dept_id" property="deptId"/>
<result column="dept_name" property="deptName"/>
<collection property="emps" ofType="Emp">
<id column="emp_id" property="empId"/>
<result column="emp_name" property="empName"/>
<result column="emp_age" property="empAge"/>
<result column="emp_gender" property="empGender"/>
</collection>
</resultMap>
<select id="getDeptAndEmpByDeptId" resultMap="deptAndEmpResultMap">
SELECT *
FROM t_dept
LEFT JOIN t_emp
ON t_dept.dept_id = t_emp.dept_id
WHERE t_dept.dept_id = #{deptId};
</select>
2. 分步查询方式
<resultMap id="deptStepOne" type="Dept">
<id column="dept_id" property="deptId"/>
<result column="dept_name" property="deptName"/>
<collection property="emps" select="com.miao.mybatis.mapper.EmpMapper.getStepTwo" column="dept_id"/>
</resultMap>
<select id="getStepOne" resultMap="deptStepOne">
SELECT * FROM t_dept WHERE dept_id = #{deptId};
</select>
<select id="getStepTwo" resultType="Emp">
SELECT * FROM t_emp WHERE dept_id = #{deptId};
</select>
八、MyBatis动态SQL
一、if、where、trim标签
- where标签
-
自动生成WHERE关键字
-
去掉前面多余的and,但不能去掉后面的
-
没有条件成立则不会生成WHERE关键字
public interface EmpMapper {
List<Emp> getEmpByCondition(Emp emp);
}
<!-- 动态SQL -->
<select id="getEmpByCondition" resultType="Emp">
SELECT *
FROM t_emp
<where>
<if test="empName != null and empName != ''">
emp_name = #{empName}
</if>
<if test="empAge != null and empAge != ''">
and emp_age = #{empAge}
</if>
<if test="empGender != null and empGender != ''">
and emp_gender = #{empGender}
</if>
</where>
</select>
- trim标签
- prefix、suffix在内容前或后添加指定关键字
- suffixOverrides、prefixOverrides去除前或后的多余东西,如and
<select id="getEmpByCondition" resultType="Emp">
SELECT *
FROM t_emp
<trim prefix="WHERE" suffixOverrides="and">
<if test="empName != null and empName != ''">
emp_name = #{empName}
</if>
<if test="empAge != null and empAge != ''">
and emp_age = #{empAge}
</if>
<if test="empGender != null and empGender != ''">
and emp_gender = #{empGender}
</if>
</trim>
</select>
二、choose-when-otherwise标签
- 相当于if-else if-else
public interface EmpMapper {
List<Emp> getEmpByChoose(Emp emp);
}
<select id="getEmpByChoose" resultType="Emp">
SELECT *
FROM t_emp
<where>
<choose>
<when test="empName != null and empName != ''">
emp_name = #{empName}
</when>
<when test="empAge != null and empAge != ''">
emp_age = #{empAge}
</when>
<when test="empGender != null and empGender != ''">
emp_gender = #{empGender}
</when>
<otherwise>
</otherwise>
</choose>
</where>
</select>
三、foreach标签
public interface EmpMapper {
void insertMoreEmp(@Param("emps") List<Emp> emps);
void deleteMoreEmp(@Param("empIds") Integer[] empIds);
}
1. 批量添加
<!-- separator为分隔符 -->
<insert id="insertMoreEmp">
INSERT INTO t_emp VALUES
<foreach collection="emps" item="emp" separator=",">
(null, #{emp.empName}, #{emp.empAge}, #{emp.empGender}, null)
</foreach>
</insert>
2. 批量删除
<delete id="deleteMoreEmp">
DELETE FROM t_emp WHERE emp_id in
(
<foreach collection="empIds" item="empId" separator=",">
#{empId}
</foreach>
)
</delete>
// open、close属性:循环以(开始,以)结束
// <delete id="deleteMoreEmp">
// DELETE FROM t_emp WHERE emp_id in
// <foreach collection="empIds" item="empId" separator="," open="(" close=")">
// #{empId}
// </foreach>
// </delete>
// separator会在前后加上空格
// <delete id="deleteMoreEmp">
// DELETE FROM t_emp WHERE
// <foreach collection="empIds" item="empId" separator="or">
// emp_id = #{empId}
// </foreach>
// </delete>
四、sql标签
<sql id="empColumns">
emp_id, emp_name, emp_age, emp_gender, dept_id
</sql>
<!-- 引入sql片段 -->
<select id="xxxx" resultType="xxx">
SELECT <include refid="empColumns"/> FROM t_emp;
</select>
九、MyBatis的缓存
一、一级缓存
-
默认开启
-
sqlSession级别,通过同一个sqlSession查询的同一个数据会被缓存,下次就直接从缓存中获取,不再访问数据库
-
失效的四种情况
- 不同sqlSession
- 同一个sqlSession查询时用不同条件
- 同一个sqlSession两次查询期间执行了任意一次增删改操作
- 同一个sqlSession两次查询期间清空了缓存(sqlSession.clearCache())
public interface CacheMapper {
Emp getEmpById(@Param("empId") Integer empId);
}
<select id="getEmpById" resultType="Emp">
SELECT * FROM t_emp WHERE emp_id = #{empId};
</select>
// 有缓存
Emp emp1 = mapper.getEmpById(1);
System.out.println(emp1);
Emp emp2 = mapper.getEmpById(1);
System.out.println(emp2);
// 手动清空缓存,即失效的第四种情况,只能清空一级缓存
Emp emp1 = mapper.getEmpById(1);
System.out.println(emp1);
sqlSession.clearCache();
Emp emp2 = mapper.getEmpById(1);
System.out.println(emp2);
二、二级缓存
-
默认不开启,在settings中设置,并在映射文件中加上
-
sqlSessionFactory级别,通过同一个sqlSessionFactory创建的sqlSession查询的同一个数据会被缓存,下次就直接从缓存中获取,不再访问数据库
-
sqlSession提交或者关闭之后有效
-
查询返回的实体类型必须实现序列化接口(
public class Emp implements Serializable
) -
失效情况:
- 两次查询期间执行了任意一次增删改操作
<setting name="cacheEnabled" value="true" />
<cache/>
<select id="getEmpById" resultType="Emp">
SELECT * FROM t_emp WHERE emp_id = #{empId};
</select>
// 会出现两次重新编译sql语句,必须在任意sqlSession提交或者关闭之后才能触发二级缓存
InputStream i = Resources.getResourceAsStream("mybatis-config.xml");
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(i);
SqlSession sqlSession1 = sqlSessionFactory.openSession(true);
CacheMapper mapper1 = sqlSession1.getMapper(CacheMapper.class);
Emp emp1 = mapper1.getEmpById(1);
System.out.println(emp1);
// sqlSession1.close(); 加上这个才能触发二级缓存
SqlSession sqlSession2 = sqlSessionFactory.openSession(true);
CacheMapper mapper2 = sqlSession2.getMapper(CacheMapper.class);
Emp emp2 = mapper2.getEmpById(1);
System.out.println(emp2);
三、第三方缓存
- 针对二级缓存
十、MyBatis逆向工程
- 代码生成器
一、插件
<build>
<plugins>
<plugin>
<groupId>org.mybatis.generator</groupId>
<artifactId>mybatis-generator-maven-plugin</artifactId>
<version>1.4.1</version>
<!-- 插件的依赖 -->
<dependencies>
<!-- 核心依赖 -->
<dependency>
<groupId>org.mybatis.generator</groupId>
<artifactId>mybatis-generator-core</artifactId>
<version>1.4.1</version>
</dependency>
<!-- MySQL驱动,在上面已经导入,这里不再导入了 -->
</dependencies>
</plugin>
</plugins>
</build>
二、核心配置文件
- generatorConfig.xml
三、简洁版生成器
四、尊享版生成器
十一、MyBatis分页
一、依赖
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper</artifactId>
<version>5.3.0</version>
</dependency>
二、配置分页
<!-- 设置插件 -->
<plugins>
<plugin interceptor="com.github.pagehelper.PageInterceptor"></plugin>
</plugins>
三、简单使用
public interface PageTestMapper {
List<Page> selectByPage();
}
<select id="selectByPage" resultType="Page">
SELECT * FROM t_test
</select>
// 开启分页功能
// 从第一页开始:页码为1,一页3条数据。即SELECT * FROM t_test LIMIT ?, ?
PageHelper.startPage(1, 3);
List<Page> list = mapper.selectByPage();
// 获取分页相关数据
// pageNum=1, pageSize=3, size=3, startRow=1, endRow=3,total=7, pages=3,
// list=Page{count=true, pageNum=1, pageSize=3,startRow=0, endRow=3, total=7, pages=3, reasonable=false,pageSizeZero=false}
// 数据:[Page{name='关羽'}, Page{name='张三'}, Page{name='曹操'}],
// prePage=0, nextPage=2, isFirstPage=true, isLastPage=false,
// hasPreviousPage=false, hasNextPage=true,
// navigatePages=5, navigateFirstPage=1,navigateLastPage=3, navigatepageNums=[1, 2, 3]
// 当前导航分页的页码数为5
PageInfo<Page> pageInfo = new PageInfo<>(list, 3);
System.out.println(pageInfo);
list.forEach(System.out::println);
十二、注解开发
二、MyBatis-Plus
一、依赖
二、起步(XML)
三、JPA
四、SpringIOC
-
主要功能:管理bean
-
五大功能模块:Core Container、AOP&Aspect、Testing、Data Access/Integration、Spring MVC
-
程序使用接口类BeanFactory
-
我们使用接口类ApplicationContext,以下几个是其实现类
- ClassPathXmlApplicationContext:读取类路径下XML格式配置文件创建IOC容器。
- FileSystemXmlApplicationContext:读取文件系统路径下XML格式配置文件创建IOC容器。
- ConfigurableApplicationContext:ApplicationContext的子接口,含有拓展方法:具有启动、关闭和刷新上下文功能。
- AnnotationConfigApplicationContext:加载注解配置文件(@Configuration)创建IOC容器。
- WebApplicationContext:专为Web应用准备,基于Web环境创建IOC容器对象,并引用传递到ServletContext域中。
一、依赖
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.3.19</version>
</dependency>
二、起步(XML)
1. 编写pojo实体类
package com.miao.spring.pojo;
public class HelloWorld {
public void sayHello() {
System.out.println("Hello World! Spring!");
}
}
2. 编写核心配置文件(含配置详解)
<?xml version="1.0" encoding="UTF-8"?>
<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">
<!--
bean:配置一个bean对象,只能是实体类型,因为要实例化
id:bean的唯一标识,不能重复
class:全类名
-->
<bean id="helloworld" class="com.miao.spring.pojo.HelloWorld"></bean>
</beans>
3. 编写测试类
package com.miao.spring;
import com.miao.spring.pojo.HelloWorld;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class SpringTest {
@Test
public void test1() {
// 1.获取IOC容器
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
// 2.获取bean对象
// 法一:通过bean的id
// HelloWorld helloWorld = (HelloWorld) applicationContext.getBean("helloworld");
// 法二:通过类型,只适用于改类型只有一个bean的时候。推荐使用,因为几乎不存在一个类型多个bean的情况
HelloWorld helloWorld = applicationContext.getBean(HelloWorld.class);
// 法三:通过bean的id和类型
// HelloWorld helloWorld = applicationContext.getBean("helloworld", HelloWorld.class);
helloWorld.sayHello();
}
}
三、IOC&DI
一、依赖
- 导入坐标
spring-webmvc 包括了spring-mvc、aop、beans、context
前置1、getBean()
- 参数:传入bean标签的id(“userDao1”,要强制转换类型且可以声明多个相同的bean)
- 参数:传入字节码文件(xxx.class,不需要强制转换但只能声明多个不同的bean)
前置2、API及继承体系
前置3、引入其他配置文件
- import标签
- <import resource=“applicationContext.xml”/>
- ClassPathXmlApplicationContext:从类的根路径读取配置文件(一般直接写配置文件名称)
- FileSystemXmlApplicationContext:从磁盘任意位置读取配置文件(一般是绝对路径)
- AnnotationConfigApplicationContext:注解开发
二、Bean
- 三大方式
- 无参构造方法
- 工厂静态方法
- 工厂实例方法
- bean标签属性
- scope属性,对无状态类则使用singleton,对有状态类使用prototype
- **init-method、destroy-method(singleton才有,因为singleton随着app对象关闭而销毁,而protype会自动销毁,不由我们控制)**属性
- factory-method、factory-bean属性
三、依赖注入
- 三大方式
- set方式注入
- 命名空间注入(官方没有提及)
- 构造方法注入
- 依赖注入类型
- 普通数据类型
- 引用数据类型(一般使用这个)
- 集合数据类型(经常使用)
三、数据源
- 两大方式
- 原生方式连接
- Spring配置连接(<context:property-placeholder location=“jdbc.properties”/>
,${properties}文件一定要符合c3p0(jdbc.driverClassName)或者druid的要求(好像没有要求))
四、XML开发
- XML
1. Dao层
1. 无参构造类
public class UserDaoImpl implements UserDao {
public UserDaoImpl(){
System.out.println("实例化方式一:无参构造方法...");
}
@Override
public void save() {
System.out.println("Dao save...");
}
public void init(){
System.out.println("初始化");
}
public void destroy(){
System.out.println("销毁");
}
}
2. 工厂静态方法类
public class StaticFactory {
public static UserDao getUserDao(){
System.out.println("实例化方式二:工厂静态方法");
return new UserDaoImpl();
}
}
3. 工厂实例化类
public class DynamicFactory {
public UserDao getUserDao(){
System.out.println("实例化方式三:工厂实例方法");
return new UserDaoImpl();
}
}
2. Service层
public class UserServiceImpl implements UserService{
public UserServiceImpl(){
}
// 1.1 set方式注入
public void setUserDao(UserDao userDao){
this.userDao = userDao;
}
// 1.2 命名空间方式注入,只需定义属性一行即可,不需要set和构造方法
private UserDao userDao;
// 1.3 构造方式注入
public UserServiceImpl(UserDao userDao){
this.userDao = userDao;
}
@Override
public void save() {
userDao.save();
}
// 2.1普通数据类型注入
private String username;
private int age;
public void setUsername(String username) {
this.username = username;
}
public void setAge(int age) {
this.age = age;
}
public void show(){
System.out.println(username + ": " + age);
}
// 3.1集合数据类型注入
private List<String> list;
private Map<String, Integer> map;
private Properties properties;
public void setList(List<String> list) {
this.list = list;
}
public void setMap(Map<String, Integer> map) {
this.map = map;
}
public void setProperties(Properties properties) {
this.properties = properties;
}
public void showCollection(){
System.out.println(list);
System.out.println(map);
System.out.println(properties);
}
}
3. Controller层(无Web服务)
// 1.Bean
public class UserDemo1 {
// scope默认为singleton,只要属性是singleton,一旦加载了配置文件,无论是否调用getBean,这个bean都会被创建
// 1.bean实例化方式一:无参构造方法(默认)
@Test
public void demo1(){
ApplicationContext app = new ClassPathXmlApplicationContext("applicationContext.xml");
UserDao userDao = (UserDao) app.getBean("userDao1");
userDao.save();
}
// 2.bean标签的属性之scope:singleton和prototype
// singleton(默认):加载配置文件后可以得到同一个对象,prototype:加载配置文件后且调用getBean可以得到多个对象
@Test
public void demo2(){
ApplicationContext app = new ClassPathXmlApplicationContext("applicationContext.xml");
UserDao userDao1 = (UserDao) app.getBean("userDao1");
UserDao userDao2 = (UserDao) app.getBean("userDao1");
System.out.println(userDao1);
System.out.println(userDao2);
}
// 3.bean标签属性之init-method和destroy-method:方法名
@Test
public void demo3(){
ApplicationContext app = new ClassPathXmlApplicationContext("applicationContext.xml");
UserDao userDao = (UserDao) app.getBean("userDao1");
userDao.save();
// 需要调用关闭函数,才会调用destroy-method对应的方法
((ClassPathXmlApplicationContext) app).close();
}
// 4.bean实例化方式二:工厂静态方法
@Test
public void demo4(){
// 在StaticFactory.java中
ApplicationContext app = new ClassPathXmlApplicationContext("applicationContext.xml");
UserDao userDao = (UserDao) app.getBean("userDao2");
userDao.save();
}
// 5.bean实例化方式三:工厂实例方法
@Test
public void demo5(){
ApplicationContext app = new ClassPathXmlApplicationContext("applicationContext.xml");
UserDao userDao = (UserDao) app.getBean("userDao3");
userDao.save();
}
}
// 2.依赖注入
public class UserDemo2 {
// 1.1 set方式依赖注入,本质是Service层需要使用Dao层的方法
// 一定要从容器中拿,而不是自己new一个
// private UserDao userDap + setUserDao(UserDao userDao)
@Test
public void demo1(){
ApplicationContext app = new ClassPathXmlApplicationContext("applicationContext.xml");
UserService userService = (UserService) app.getBean("userService1");
userService.save();
}
// 1.2 命名空间方式依赖注入
@Test
public void demo2(){
ApplicationContext app = new ClassPathXmlApplicationContext("applicationContext.xml");
UserService userService = (UserService) app.getBean("userService2");
userService.save();
}
// 1.3 构造方式依赖注入
@Test
public void demo3(){
ApplicationContext app = new ClassPathXmlApplicationContext("applicationContext.xml");
UserService userService = (UserService) app.getBean("userService3");
userService.save();
}
// 2.1 普通数据类型注入
@Test
public void demo4(){
ApplicationContext app = new ClassPathXmlApplicationContext("applicationContext.xml");
UserService userService = (UserService) app.getBean("userService4");
userService.show();
}
// 3.1 集合数据类型注入
@Test
public void demo5(){
ApplicationContext app = new ClassPathXmlApplicationContext("applicationContext.xml");
UserService userService = (UserService) app.getBean("userService5");
userService.showCollection();
}
}
// 3.数据源
public class UserDemo3 {
// 1.C3P0
@Test
public void demo1(){
ApplicationContext app = new ClassPathXmlApplicationContext("applicationContext.xml");
ComboPooledDataSource dataSource = (ComboPooledDataSource) app.getBean("dataSource1");
Connection conn = null;
try {
conn = dataSource.getConnection();
System.out.println(conn);
} catch (SQLException e) {
e.printStackTrace();
} finally {
if (conn != null){
try {
conn.close();
} catch (SQLException e){
e.printStackTrace();
}
}
}
}
// 2.Druid
@Test
public void demo2(){
ApplicationContext app = new ClassPathXmlApplicationContext("applicationContext.xml");
DruidDataSource dataSource = (DruidDataSource) app.getBean("dataSource2");
Connection conn = null;
try {
conn = dataSource.getConnection();
System.out.println(conn);
} catch (SQLException e) {
e.printStackTrace();
} finally {
if (conn != null){
try {
conn.close();
} catch (SQLException e){
e.printStackTrace();
}
}
}
}
}
4.applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">
<!--BeanBeanBeanBeanBeanBeanBeanBeanBeanBeanBeanBeanBeanBeanBeanBeanBeanBeanBeanBeanBeanBeanBeanBeanBeanBeanBeanBeanBeanBeanBeanBeanBeanBeanBeanBeanBeanBeanBeanBean-->
<!-- scope默认为singleton,只要属性是singleton,一旦加载了配置文件,无论是否调用getBean,这个bean都会被创建 -->
<bean id="userDao1" class="com.miao.p1_SpringXML.Dao.Impl.UserDaoImpl" scope="prototype" init-method="init" destroy-method="destroy"/>
<!-- 工厂方法是静态方法,可不用实例化工厂对象,可直接调用 -->
<bean id="userDao2" class="com.miao.p1_SpringXML.Factory.StaticFactory" scope="prototype" factory-method="getUserDao"/>
<!-- 工厂方法不是静态方法,所以需要先实例化工厂对象,再调用 -->
<bean id="factory" class="com.miao.p1_SpringXML.Factory.DynamicFactory"/>
<bean id="userDao3" factory-bean="factory" factory-method="getUserDao" scope="prototype"/>
<!--引用类型依赖注入依赖注入依赖注入依赖注入依赖注入依赖注入依赖注入依赖注入依赖注入依赖注入依赖注入依赖注入依赖注入依赖注入依赖注入依赖注入依赖注入依赖注入依赖注入依赖注入依赖注入依赖注入依赖注入依赖注入依赖注入-->
<!--name是set后面的驼峰命名法的值(一般就是属性名),即setUserDao那就是userDao-->
<bean id="userService1" class="com.miao.p1_SpringXML.Service.Impl.UserServiceImpl" scope="prototype">
<property name="userDao" ref="userDao1"/>
</bean>
<!-- 命名空间方式注入,需要 xmlns:p="http://www.springframework.org/schema/p-->
<bean id="userService2" class="com.miao.p1_SpringXML.Service.Impl.UserServiceImpl" p:userDao-ref="userDao2" scope="prototype"/>
<!-- 构造方式注入,需要有参构造。name是形参名-->
<!--还有type(类型),index(0开始),或者空(自动判断)来代替name-->
<bean id="userService3" class="com.miao.p1_SpringXML.Service.Impl.UserServiceImpl" scope="prototype">
<constructor-arg name="userDao" ref="userDao3"/>
</bean>
<!--普通数据类型依赖注入依赖注入依赖注入依赖注入依赖注入依赖注入依赖注入依赖注入依赖注入依赖注入依赖注入依赖注入依赖注入依赖注入依赖注入依赖注入依赖注入依赖注入依赖注入依赖注入依赖注入依赖注入依赖注入依赖注入依赖注入-->
<bean id="userService4" class="com.miao.p1_SpringXML.Service.Impl.UserServiceImpl">
<property name="username" value="张飞"/>
<property name="age" value="18"/>
</bean>
<!--集合数据类型依赖注入依赖注入依赖注入依赖注入依赖注入依赖注入依赖注入依赖注入依赖注入依赖注入依赖注入依赖注入依赖注入依赖注入依赖注入依赖注入依赖注入依赖注入依赖注入依赖注入依赖注入依赖注入依赖注入依赖注入依赖注入-->
<bean id="userService5" class="com.miao.p1_SpringXML.Service.Impl.UserServiceImpl">
<property name="list">
<list>
<value>aaa</value>
<value>bbb</value>
<value>ccc</value>
</list>
</property>
<property name="map">
<map>
<entry key="u1" value="1"/>
<entry key="u2" value="2"/>
</map>
</property>
<property name="properties">
<props>
<prop key="driverClassName">com.mysql.cj.jdbc.Driver</prop>
<prop key="url">jdbc:mysql://101.43.117.227:3307/test?useUnicode=true&characterEncoding=UTF-8</prop>
<prop key="username">root</prop>
<prop key="password">123456</prop>
</props>
</property>
</bean>
<!--数据源数据源数据源数据源数据源数据源数据源数据源数据源数据源数据源数据源数据源数据源数据源数据源数据源数据源数据源数据源数据源数据源数据源数据源数据源数据源数据源数据源数据源数据源数据源数据源数据源数据源数据源-->
<context:property-placeholder location="jdbc.properties"/>
<bean id="dataSource1" class="com.mchange.v2.c3p0.ComboPooledDataSource" scope="prototype">
<property name="driverClass" value="${jdbc.driverClassName}"/>
<property name="jdbcUrl" value="${jdbc.url}"/>
<property name="user" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</bean>
<bean id="dataSource2" class="com.alibaba.druid.pool.DruidDataSource" scope="prototype">
<property name="driverClassName" value="${jdbc.driverClassName}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</bean>
</beans>
五、注解开发
- 用于代替bean标签,需要在配置文件中加入扫描标签<context:component-scan base-package=“com.miao.p2_SpringAnnotation”/>
- 原始注解:使用ClassPathXmlApplicationContext
- Bean
- @Component-三层,万能的
- @Controller-web层
- @Service-service层
- @Repository-dao层
- @PostConstruct-初始化方法,与实现Initializingbean接口后重写afterPropertiesSet()方法功能一致。
- @PreDestroy-销毁方法
- @Scope-生命周期,也可以用在新注解@Bean后面
- 依赖注入
- @Autowired-根据类型注入
- @Qualifier-配合@Autowired使用,根据名称注入
- @Resource-相当于@Autowired+@Qualifier(优先类型后名称),优先名称后类型
- @Value-普通数据类型、集合数据类型注入
- _新注解:使用AnnotationConfigApplicationContext
- @Configuration-当前类是一个Spring配置类
- @ComponentScan-扫描组件,与context:component-scan标签一样的功能
- @Bean-标注在方法上,表示该方法的返回值将放在容器中,与@Configuration一起使用
- @PropertySource-用于加载.porperties文件
- @Import-导入其他配置类
1、原始注解
- 注解+XML
1. Dao层
@Repository("userDao")
public class UserDaoImpl implements UserDao {
@Override
public void save() {
System.out.println("UserDao ...");
}
}
2. Service层
@Service("UserService")
@Scope("singleton")
public class UserServiecImpl implements UserService {
@Value("${jdbc.driverClassName}")
private String driverClassName;
@Value("${jdbc.url}")
private String url;
@Value("${jdbc.username}")
private String username;
@Value("${jdbc.password}")
private String password;
public void showJdbc(){
System.out.println(driverClassName);
System.out.println(url);
System.out.println(username);
System.out.println(password);
}
@Autowired
@Qualifier("userDao")
// @Resource(name = "userDao")
private UserDao userDao;
public void setUserDao(UserDao userDao){
this.userDao = userDao;
}
@Override
public void show(){
userDao.save();
}
@Override
public void save() {
System.out.println("UserService ...");
}
@PostConstruct
public void init(){
System.out.println("初始化方法...");
}
@PreDestroy
public void destroy(){
System.out.println("销毁方法...");
}
}
3. Controller层(无Web服务)
// 4.原始注解开发
public class UserDemo4 {
// 1.需要两个标签,一个是用于扫描注解,一个用于扫描jdbc.properties
// <context:component-scan base-package="com.miao.p2_SpringAnnotation"/>
// <context:property-placeholder location="jdbc.properties"/>
@Test
public void demo1(){
ApplicationContext app = new ClassPathXmlApplicationContext("applicationContext.xml");
UserService userService = (UserService) app.getBean("UserService");
userService.save();
userService.show();
userService.showJdbc();
((ClassPathXmlApplicationContext) app).close();
}
}
4.applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">
<!-- 开启组件扫描,用于注解开发 -->
<context:component-scan base-package="com.miao.p2_OriginalSpringAnnotation"/>
</beans>
2、新注解
- 纯注解
1. 配置类
@Configuration // 表示该类为配置类
@ComponentScan("com.miao.p3_NewSpringAnnotation") // 包扫描
@Import(DataSourceConfiguration.class) // 将配置类或者数据源类加载到容器
public class SpringConfiguration {
}
2. 数据源类
@PropertySource("jdbc.properties")
public class DataSourceConfiguration {
// 1.数据源配置
@Value("${jdbc.driverClassName}")
private String driverClassName;
@Value("${jdbc.url}")
private String url;
@Value("${jdbc.username}")
private String username;
@Value("${jdbc.password}")
private String password;
@Bean("dataSource1")
@Scope("singleton")
public ComboPooledDataSource getDataSource(){
ComboPooledDataSource comboPooledDataSource = new ComboPooledDataSource();
try {
comboPooledDataSource.setDriverClass(driverClassName);
} catch (PropertyVetoException e) {
e.printStackTrace();
}
System.out.println("singleton!我在DataSourceConfiguration中创建了哦!");
comboPooledDataSource.setJdbcUrl(url);
comboPooledDataSource.setUser(username);
comboPooledDataSource.setPassword(password);
return comboPooledDataSource;
}
}
3. Dao层
@Repository("userDao")
public class UserDaoImpl implements UserDao {
@Override
public void save() {
System.out.println("UserDao新注解...");
}
}
4. Service层
@Service("userService")
public class UserServiceImpl implements UserService {
@Autowired
@Qualifier("userDao")
private UserDao userDao;
public void setUserDao(UserDao userDao){
this.userDao = userDao;
}
@Override
public void save() {
System.out.println("UserService新注解...");
}
@Override
public void show() {
userDao.save();
}
}
5. Controller层(无Web服务)
// 5.新注解开发
public class UserDemo5 {
// 1.用全新的注解开发,不需要applicationContext.xml文件了
@Test
public void demo1(){
AnnotationConfigApplicationContext app = new AnnotationConfigApplicationContext(SpringConfiguration.class);
UserService userService = (UserService) app.getBean("userService");
ComboPooledDataSource dataSource = (ComboPooledDataSource) app.getBean("dataSource1");
Connection conn = null;
try {
conn = dataSource.getConnection();
System.out.println(conn);
} catch (SQLException e) {
e.printStackTrace();
} finally {
if (conn != null){
try {
conn.close();
} catch (SQLException e){
e.printStackTrace();
}
}
}
userService.save();
userService.show();
}
}
六、集成Junit
- 导入坐标
spring-test jUnit
- @RunWith-替换原来的运行周期
- @ContextConfiguration-指定配置文件或配置类(@Configuration)
- @Autowired-注入对象
1. 配置类
@Configuration
@ComponentScan("com.miao.p4_jUnit")
public class SpringConfiguration {
}
2. Dao层
@Repository("userDao")
public class UserDaoImpl implements UserDao {
@Override
public void save() {
System.out.println("UserDao jUnit测试");
}
}
3. Service层
@Service("userService")
public class UserServiceImpl implements UserService {
@Autowired
@Qualifier("userDao")
private UserDao userDao;
public void setUserDao(UserDao userDao){
this.userDao = userDao;
}
@Override
public void save() {
userDao.save();
System.out.println("UserService jUnit测试");
}
}
4. Test
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = SpringConfiguration.class)
public class UserDemo6 {
@Autowired
@Qualifier("userService")
private UserService userService;
// 1.直接在此处测试
@Test
public void test(){
userService.save();
}
}
七、集成Web
- 导入坐标
javax.servlet-api spring-webmvc:包括了spring-mvc、aop、beans、context
- 将项目变成web项目,并配置监听器
- __WebApplicationContextUtils工具类+ServletContext或者AnnotationConfigApplicationContext+ServletContext__进行属性封装
- 原有的Spring基础上添加真正的Controller层即可
- 可以用XML、注解+XML、纯注解
1. 配置类
@Configuration
@ComponentScan("com.miao.p5_Web") // 包扫描
public class SpringConfiguration {
}
2. 监听器类
@WebListener
public class Listener implements ServletContextListener {
@Override
public void contextInitialized(ServletContextEvent sce) {
System.out.println("监听器开始。。。");
ServletContext servletContext = sce.getServletContext();
// 将Spring所需的对象放入ServletContext对象中
// 1.XML方式,applicationContext.xml有bean或者包扫描注解
// ApplicationContext app = WebApplicationContextUtils.getWebApplicationContext(servletContext);
// servletContext.setAttribute("app",app);
// 2.注解方式,applicationContext.xml无bean
AnnotationConfigApplicationContext app = new AnnotationConfigApplicationContext(Configuration.class);
servletContext.setAttribute("app", app);
// 判断是否成功放入
UserService userService = (UserService) app.getBean("userService");
userService.save();
}
@Override
public void contextDestroyed(ServletContextEvent sce) {
System.out.println("监听器销毁。。。");
}
}
3. Dao层
@Repository("userDao")
public class UserDaoImpl implements UserDao {
@Override
public void save() {
System.out.println("UserDao Web层...");
}
}
4. Service层
@Service("userService")
public class UserServiceImpl implements UserService {
@Autowired
@Qualifier("userDao")
private UserDao userDao;
@Override
public void save() {
userDao.save();
System.out.println("UserService Web层...");
}
}
5. Controller层(有Web服务)
@WebServlet("/Servlet1")
public class UserServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// app在监听器阶段就获取了
// 1.XML方式
UserService userService = (UserService) ((ApplicationContext)req.getServletContext().getAttribute("app")).getBean("userService");
// 2.注解方式
UserService userService = (UserService) ((AnnotationConfigApplicationContext)req.getServletContext().getAttribute("app")).getBean("userService");
userService.save();
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
6.applicationContext.xml(必须)
<?xml version="1.0" encoding="UTF-8"?>
<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">
1.包扫描注解(本例子用扫描即可)
<context:component-scan
或者
2.手写bean
<bean ....
</beans>
7. web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0">
// 两个都必须要
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:applicationContext.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
</web-app>
八、底层原理
一、getBean步骤
- 实例化UserServiceImpl对象
- 推断构造方法
- 依赖注入
- 初始化(1.UserServiceImpl类实现Initializingbean接口,重写afterPropertiesSet()用于如将数据库的数据取出封装成对象)或者使用@PostConstruct定义初始化方法)
- Aop(判断是否需要AOP,若需要则再实例化一个代理对象来代替刚刚实例化的对象(先生成一个继承UserService的代理类,该代理类重写父类中的AOP方法,再在这个方法内部调用增强方法)),不会对代理对象进行依赖注入!
// 本例子用的是前置增强方法@Before,切面类不再做展示
public class UserServiceImpl{
public void test(){
xxx;
};
}
public class UserServiceImplProxy extends UserServiceImpl{
private UserServiceImpl target;
@Override
public void test(){
切面类.增强方法();
target.test();
}
}
- Bean
二、生成Bean的构造方法
- 存在无参构造方法和有参构造方法,默认调用无参构造方法。
- 只存在一个有参构造方法,则调用该方法。
- 只存在多个有参构造方法,则报错。除非使用@Autowired方法来确定使用哪个方法。
public UserService(OrderService orderService, OrderService orderService1){
xxx
}
@Autowired
// 正常情况会报错,因为不知道使用哪个方法,但加上@Autowired则表明使用这个构造方法来实例化bean
public UserService(OrderService orderService1){
xxx
}
三、单例bean和单例模式
- 单例bean:一个类可以有多个bean,只要其bean的id或者name不同即可,而bean才只能有一个实例。使用Map实现
// 配置类
// 可以看出UserService类有2个bean
@Bean
public UserService UserService1(){
return new UserService();
}
@Bean
public UserService UserService2(){
return new UserService();
}
- 单例模式:一个类只可以有一个实例。
四、@Autowired原理
一、特点
-
先根据__类型__寻找,后根据__变量名称__寻找
- 根据__类型__从容器中寻找bean。第一层筛选,必有的。
- isAutowireCandidate()判断是否为依赖注入候选者。第二层筛选,必有的。
- __@Bean(autowireCandidate = false)__用来取消这个bean作为候选者,所以不会选择它进行依赖注入。第三层筛选,autowireCandidate可选。
- @Qualifier给bean分组,第四层筛选,可选。
- @Primary,第五层筛选,可选,一个类型只能有一个,优先级最高。
- @Priority,第六层筛选,设置优先级,可选。没加此注解的竞争者将被排除。
- 根据__变量名称__选出bean
-
private UserService userService1; 先按类型找bean,若有多个该类型的bean,则按变量名来匹配bean的name为UserService1的bean。
二、作用
- 用于属性依赖注入
- 用于设置生成bean实例的构造方法
五、*@Qualifier原理
一、作用
-
用于辅助@Autowired进行指定bean的name依赖注入
-
用于给bean分组
-
@Bean @Qualifier("xxx") // xxx为组名 public UserService UserService1(){ return new UserService(); } @Autowired @Qualifier("xxx") private UserService uassdfadxas; // 能够成功注入
-
六、*@Primary
一、作用
-
用于给bean设置成最高级
-
@Bean public UserService UserService1(){ return new UserService(); } @Bean @Primary public UserService UserService2(){ return new UserService(); } @Autowired private UserService uassdfadxas; // 注入的是UserService2()中实例化的对象
-
七、*@Priority
一、作用
-
用于给bean设置优先级(值越小,优先级越高),没加此注解的竞争者将被排除。
-
@Bean @Priorit(1) public UserService UserService1(){ return new UserService(); } @Bean @Priorit(2) public UserService UserService2(){ return new UserService(); } @Bean public UserService UserService3(){ return new UserService(); } @Autowired private UserService uassdfadxas; // 注入的是UserService1()中实例化的对象
-
八、@Resource原理
- 推荐使用
一、特点
- 加了name属性,没找到则直接报错。
- 没加name属性,先根据__变量名称__再根据__类型__
- 根据__变量名称__从容器中寻找bean。第一层筛选,必有的。
- 根据类型寻找。
五、SpringAOP
一、AOP概念
- 在程序运行期间,不需要修改源代码就可以对功能进行增强
- 减少代码重复,提高开发效率,便于维护
- Aspect
Aspect:跨多个类的关注点的模块化。事务管理是企业 Java 应用程序中横切关注点的一个很好的例子。在 Spring AOP 中,方面是通过使用常规类(基于模式的方法)或使用 @Aspect 注释(@AspectJ 样式)注释的常规类来实现的。
- Join point
连接点:程序执行过程中的一个点,例如方法的执行或异常的处理。在 Spring AOP 中,一个连接点总是代表一个方法执行。
- Advice
建议:方面在特定连接点采取的行动。不同类型的建议包括“周围”、“之前”和“之后”建议。 (通知类型将在后面讨论。)包括 Spring 在内的许多 AOP 框架将通知建模为拦截器,并在连接点周围维护一个拦截器链。
- Pointcut
切入点:匹配连接点的谓词。 Advice 与切入点表达式相关联,并在与切入点匹配的任何连接点处运行(例如,执行具有特定名称的方法)。切入点表达式匹配的连接点的概念是 AOP 的核心,Spring 默认使用 AspectJ 切入点表达式语言。
- Introduction
简介:代表一个类型声明额外的方法或字段。 Spring AOP 允许您向任何建议的对象引入新接口(和相应的实现)。例如,您可以使用介绍使 bean 实现 IsModified 接口,以简化缓存。 (介绍在 AspectJ 社区中称为类型间声明。)
- Target object
目标对象:一个或多个方面建议的对象。也称为“建议对象”。由于 Spring AOP 是使用运行时代理实现的,因此该对象始终是代理对象。
- AOP proxy
AOP 代理:由 AOP 框架创建的对象,用于实现方面协定(建议方法执行等)。在 Spring Framework 中,AOP 代理是 JDK 动态代理或 CGLIB 代理。
- Weaving
编织:将方面与其他应用程序类型或对象链接以创建建议对象。这可以在编译时(例如,使用 AspectJ 编译器)、加载时或运行时完成。 Spring AOP 与其他纯 Java AOP 框架一样,在运行时执行编织。
- 通知类型
Spring AOP 包括以下类型的通知:
通知前:在连接点之前运行但不能阻止执行流继续到连接点的通知(除非它抛出异常)。
返回通知后:在连接点正常完成后运行的通知(例如,如果方法返回而没有引发异常)。
抛出建议后:如果方法因抛出异常而退出,则运行建议。
在(最终)通知之后:无论连接点以何种方式退出(正常或异常返回),都将运行建议。
围绕建议:围绕连接点的建议,例如方法调用。这是最有力的建议。环绕通知可以在方法调用之前和之后执行自定义行为。它还负责选择是继续到连接点还是通过返回自己的返回值或抛出异常来缩短建议的方法执行。
环绕建议是最一般的建议。由于 Spring AOP 与 AspectJ 一样,提供了全方位的通知类型,因此我们建议您使用可以实现所需行为的最不强大的通知类型。例如,如果您只需要使用方法的返回值来更新缓存,那么您最好实现一个后返回通知而不是一个环绕通知,尽管一个环绕通知可以完成同样的事情。使用最具体的通知类型提供了一个更简单的编程模型,并且出错的可能性更小。例如,您不需要在用于环绕通知的 JoinPoint 上调用proceed() 方法,因此您不能调用它。
所有建议参数都是静态类型的,因此您可以使用适当类型的建议参数(例如,方法执行的返回值的类型)而不是对象数组。
切入点匹配的连接点的概念是 AOP 的关键,这将它与仅提供拦截的旧技术区分开来。切入点使建议的目标独立于面向对象的层次结构。例如,您可以将提供声明性事务管理的环绕建议应用到一组跨越多个对象(例如服务层中的所有业务操作)的方法。
二、应用场景
-
日志记录
-
权限验证
-
效率检查
-
事务管理
-
Exception
三、AOP底层实现
-
动态代理技术
-
jdk代理
- 基于接口的动态代理技术:目标对象->目标接口->代理对象(Java运行时)
- cglib代理
- 基于父类的动态代理技术:目标对象->代理对象(Java运行时)
四、AOP实现
- 前置通知,在目标方法前运行
- 后置通知,在目标方法后运行
- *环绕通知,在目标方法前后都运行
- 异常抛出通知,目标方法异常时运行
- 最终通知,目标方法无论是否异常都运行
一、XML方式
一、依赖
- 导入spring-context和aspectjweaver
二、编写目标类(目标接口及其实现类)
public interface TargetInterface{
void save();
}
public class Target implements TargetInterface{
@Override
public void save() {
System.out.println("save running...");
}
}
三、编写切面类(增强方法)
public class MyAspect {
public void before(){
System.out.println("前置增强");
}
}
四、配置XML
application-config.xml
<!--1.目标对象-->
<bean id="target" class="com.miao.Aop.Target"></bean>
<!--2.切面对象-->
<bean id="myAspect" class="com.miao.Aop.MyAspect"></bean>
<!--3.配置weaving-->
<aop:config>
<!--4.声明切面对象,该对象有advice(增强方法)-->
<aop:aspect ref="myAspect">
<!--5.设置pointcut(即被增强对象)与advice(增强方法,method)-->
<!--前者填增强方法的名称,后者填切点表达式-->
<aop:before method="before" pointcut="execution(public void com.miao.Aop.Target.save())"></aop:before>
</aop:aspect>
</aop:config>
- execution表达式:
- execution表达式抽取:
五、开始测试
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:application-config.xml")
public class AOPtest {
@Autowired
TargetInterface targetInterface;
@Test
public void test1(){
targetInterface.save();
}
}
// 输出:
前置增强
save running...
二、注解开发
-
__必须配置aop自动代理:<aop:aspectj-autoproxy/>__或者使用@EnableAspectJAutoProxy注解
-
通过aop命名空间的<aop:aspectj-autoproxy />声明自动为spring容器中那些配置@AspectJ切面的bean创建代理,织入切面。当然,spring
在内部依旧采用AnnotationAwareAspectJAutoProxyCreator进行自动代理的创建工作,但具体实现的细节已经被<aop:aspectj-autoproxy />隐藏起来了。
一、注解
- @Before
- @After
- @Around
- @AfterThrowing
- @AfterReturning
- @Pointcut:抽取切点表达式
- @Aspect:标准切面类
二、编写目标类
@Component("t")
public class Target2 implements TargetInterface2{
@Override
public void func1() {
System.out.println("我是原始方法");
}
}
public interface TargetInterface2 {
void func1();
}
三、编写切面类
@Component
@Aspect // 表示该类为切面类
public class MyAspect2 {
@Before("execution(public void com.miao.Aop.Target2.func1())")
public void advice(){
System.out.println("我是前置方法");
}
}
四、配置类
@Configuration
@ComponentScan("com.miao.Aop") // 注解扫描
@EnableAspectJAutoProxy // 配置aop自动代理
public class Annotation {
}
五、开始测试
// 注解
@Test
public void test2(){
ApplicationContext app = new AnnotationConfigApplicationContext(Annotation.class);
TargetInterface2 targetInterface2 = (TargetInterface2) app.getBean("t");
targetInterface2.func1();
// 若为false则成功aop
System.out.println(targetInterface2 instanceof Target2);
}
// 输出
我是前置方法
我是原始方法
false
三、补充知识
- XML
aop : advisor 定义 AOP 通知器
aop : after 定义 AOP 后置通知(不管被通知方法是否执行成功)
aop : after-returing 定义 AOP after-returing 通知
aop : after-throwing 定义 AOP after-throwing 通知
aop : around 定义 AOP 环绕通知
aop : aspect 定义切面
aop : aspectj-autoproxy 启动 @AspectJ 注解驱动的切面
aop : before 定义 AOP 前置通知
aop : config 顶层的 AOP 配置元素,大多数 aop : * 元素必须包含在 元素内
aop : declare-parents 为被通知的对象引入额外接口,并透明的实现
aop : pointcut 定义切点
- @Aspect
execution () 用于匹配连接点的执行方法 最常用
args () 限制连接点的指定参数为指定类型的执行方法
@args () 限制连接点匹配参数类型由指定注解标注的执行方法
this () 限制连接点匹配 AOP 代理的 Bean 引用为指定类型的类
target () 限制连接点匹配特定的执行对象,目标对象是指定的类型
@target () 限制连接点匹配特定的执行对象,这些对象对应的类要具备指定类型注解
within() 限制连接点匹配指定类型,比如哪个包下,或哪个类里面
@within() 限制连接点匹配指定注释所标注的类型(当使用 Spring AOP 时,方法定义在由指定的注解所标注的类里)
@annotation 限制匹配带有指定注释的连接点
- 注解写法
@Before("execution(public void com.miao.Aop.Target.save())")
public void before(){
System.out.println("前置增强");
}
// 下面两个方法合在一起功能与上面完全一样
@Pointcut("execution(public void com.miao.Aop.Target.save())")
public void pointcut(){
}
@Before(MyAspect.pointcut())
public void before(){
System.out.println("前置增强");
}
四、切点表达式
execution(modifiers-pattern? ret-type-pattern declaring-type-pattern? name-pattern(param-pattern) throws-pattern?)
?:表示此项可有可无
..:表示一个或多个子包、任意参数
modifiers-pattern:方法的可见性,如public,private,用*表示都可见
?ret-type-pattern:方法的返回类型,如void,int,可以省略则返回任意类型
declaring-type-pattern:方法所在类的全限定名,如com.miao.Aop.Aspect,用*表示所有类的方法都可以
?name-pattern():方法名,如test()
param-pattern:方法的参数类型,如java.lang.String
throws-pattern?:方法抛出异常的类型,如java.lang.ClassNotFound
• The execution of any public method:
execution(public * *(..))
• The execution of any method with a name that begins with set:
execution(* set*(..))
• The execution of any method defined by the AccountService interface:
execution(* com.xyz.service.AccountService.*(..))
• The execution of any method defined in the service package:
execution(* com.xyz.service.*.*(..))
• The execution of any method defined in the service package or one of its sub-packages:
execution(* com.xyz.service..*.*(..))
• Any join point (method execution only in Spring AOP) within the service package:
within(com.xyz.service.*)
• Any join point (method execution only in Spring AOP) within the service package or one of its sub-packages:
within(com.xyz.service..*)
• Any join point (method execution only in Spring AOP) where the proxy implements the AccountService interface:
this(com.xyz.service.AccountService)
this is more commonly used in a binding form. See the section on Declaring
Advice for how to make the proxy object available in the advice body.
• Any join point (method execution only in Spring AOP) where the target object implements the
AccountService interface:
target(com.xyz.service.AccountService)
target is more commonly used in a binding form. See the Declaring Advice
section for how to make the target object available in the advice body.
• Any join point (method execution only in Spring AOP) that takes a single parameter and where
the argument passed at runtime is Serializable:
args(java.io.Serializable)
args is more commonly used in a binding form. See the Declaring Advice
section for how to make the method arguments available in the advice body.
Note that the pointcut given in this example is different from execution(**(java.io.Serializable)). The args version matches if the argument passed at runtime is Serializable, and the execution version matches if the method signature declares a single
parameter of type Serializable.
• Any join point (method execution only in Spring AOP) where the target object has a
@Transactional annotation:
@target(org.springframework.transaction.annotation.Transactional)
You can also use @target in a binding form. See the Declaring Advice section for
how to make the annotation object available in the advice body.
• Any join point (method execution only in Spring AOP) where the declared type of the target
object has an @Transactional annotation:
@within(org.springframework.transaction.annotation.Transactional)
You can also use @within in a binding form. See the Declaring Advice section for
how to make the annotation object available in the advice body.
• Any join point (method execution only in Spring AOP) where the executing method has an
@Transactional annotation:
@annotation(org.springframework.transaction.annotation.Transactional)
You can also use @annotation in a binding form. See the Declaring Advice
section for how to make the annotation object available in the advice body.
• Any join point (method execution only in Spring AOP) which takes a single parameter, and
where the runtime type of the argument passed has the @Classified annotation:
@args(com.xyz.security.Classified)
You can also use @args in a binding form. See the Declaring Advice section how
to make the annotation object(s) available in the advice body.
• Any join point (method execution only in Spring AOP) on a Spring bean named tradeService:
bean(tradeService)
• Any join point (method execution only in Spring AOP) on Spring beans having names that
match the wildcard expression *Service:
bean(*Service)
六、声明式事务
七、SpringMVC
- 主要功能:Web开发
一、基础篇
一、起步
一、组件
1. 前端控制器DispatcherServlet
2. *处理器适配器HandlerAdapter和处理器Handler
3. *视图解析器ViewResolver
4. *处理器映射器HandlerMapping
5. 视图
二、运行
1. 配置前端控制器DispatcherServlet
- org.springframework.web.servlet.DispatcherServlet
-
web.xml <!--1.设置前端控制器--> <servlet> <servlet-name>dispatcherServlet</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <init-param> <!--2.联系到spring-mvc配置文件--> <param-name>contextConfigLocation</param-name> <param-value>classpath:spring-mvc.xml</param-value> </init-param> <!--3.设置前端控制器随着项目启动而启动--> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>dispatcherServlet</servlet-name> <!--解析所有资源,除了jsp--> <url-pattern>/</url-pattern> </servlet-mapping>
-
spring-mvc.xml <!--4.扫描Controller包--> <context:component-scan base-package="com.miao.p1_SpringMVCXML.Controller"></context:component-scan>
2. 配置处理器Handler
-
自己定义
-
配置完即可正常使用
- @Controller,表示该类返回的String类型的值是跳转页面的路径
- @Controller+@ResponseBody,表示该类返回的String类型的值不是跳转页面的路径
- @RestController,与2作用相同
- @RequestMapping,用于映射请求地址
// 这个类的test1()方法就是处理器Handler
@Controller
@RequestMapping("/MyController1")
public class MyController1 {
@RequestMapping("/demo1")
public String test1(){
return "/index.jsp"; // 加上/表示返回绝对路径,返回/index.jsp,否则是/MyController1/index.jsp
}
}
3. 配置视图解析器ViewResolver
- org.springframework.web.servlet.view.InternalResourceViewResolver
- 配置完能更好地使用
- 让处理器更轻松
- 可以配置多个,order属性1-5,越大优先级越高
-
<!--5.设置视图解析器--> <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <property name="prefix" value="/static/"/> <property name="suffix" value=".html"/> </bean>
-
则test1()可以改为以下 @Controller public class MyController1 { @RequestMapping("/demo1") public String test1(){ return "index"; // 返回 /view/index.jsp } }
4. 配置处理映射器和处理适配器
- org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping
- org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter
- 配置完后,返回json、参数验证、处理异常才能正常使用
-
<!--6.设置处理映射器和处理适配器,可用<mvc:annotation-driven/>代替--> <bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping"/> <bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter"/>
三、执行流程
浏览器->Tomcat->web.xml->DispatcherServlet->HandlerMapping+spring-mvc.xml->DispatcherServlet->HandlerAdapter->Handler>DispatcherServlet_->ViewResolver->DispatcherServlet_->渲染视图->浏览器
二、静态资源放行
一、静态资源无法访问原因
- 静态资源无法访问的原因是:DispatcherServclet中的拦截路径是/,表示DispatcherServlet会拦截除jsp外的所有资源,若没有Controller则不放行,而静态资源是没有Controller的。
二、解决方案
-
<!--7.静态资源放行,mapping表示请求url,location表示项目webapp的静态资源目录--> <mvc:resources mapping="/static/**" location="/static/"/>
三、HiddenHttpMethodFilter过滤器(Restful风格)
一、常用注解
- @PathVariable
- @GetMapping
- @PostMapping
- @PutMapping
- @DeleteMapping
二、无法区分请求方式及解决方案
-
<!--8.配置过滤器,用处理PUT和DELETE请求--> <filter> <filter-name>hiddenHttpMthodFilter</filter-name> <filter-class>org.springframework.web.filter.HiddenHttpMethodFilter</filter-class> </filter> <filter-mapping> <filter-name>hiddenHttpMthodFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>
-
@RequestMapping(value = "/demo2/{id}/{name}", method = RequestMethod.DELETE) public String test2(@PathVariable int id, @PathVariable String name){ System.out.println(id + " " + name); return "index"; }
四、参数注入
- @RequestParam:接收GET默认参数
- @PathVariable:接收Restful风格参数
- @RequestBody:接收POST请求参数
- @DateTimeFormat:接收日期类型参数
一、紧耦合(了解)-传统HttpServletRequest
1. 获取简单参数
public void doGet(HttpServletRequest req, HttpServletResponse res){
String username = req.getParameter("username");
String password = req.getParameter("password");`
}
二、松耦合(熟练)-SpringMVC框架
1. 获取简单参数
@RequestMapping("/demo3")
@ResponseBody
public String test3(@RequestParam int id, @RequestParam String name){
System.out.println(id + " " + name);
return "OK";
}
2. 获取POJO类型
- 由__HandlerAdapter__处理请求参数封装成POJO对象,参数名需和对象属性名一致。
public class Person {
private String username;
private String password;
setter、getter和toString
}
@RequestMapping(value = "/demo1", method = RequestMethod.POST)
public String getPojo(Person p){
System.out.println(p);
return "OK1!";
}
3. 获取日期类型
@RequestMapping(value = "/demo2", method = RequestMethod.POST)
public String getDate(@DateTimeFormat(pattern = "yyyy-MM-dd") String birthday){
System.out.println(birthday);
return "OK2";
}
4. 获取List集合
@Controller
public class WxGivingController{
@RequestMapping(value = "/index/del")
@ResponseBody
public ReturnMsg del (@RequestParam(value = "ids[]")List <Integer> ids){
}
5. 获取Map集合
//第一种ajax请求对应的后台接口
@RequestMapping("search_data_detail")
@ResponseBody
public void searchInfo(@RequestParam Map<String,String> map){
Map<String, Object> jsonMap= JsonToMap.jsonToMap(map.get("jsonData"));
for (Map.Entry<String,Object> entry:jsonMap.entrySet()){
System.out.print("得到键为:==="+entry.getKey());
System.out.println("得到值为:==="+entry.getValue());
}
}
//第二种ajax请求后台对应的后台接口
@RequestMapping("search_data_detail")
@ResponseBody
public void searchInfo(@RequestBody Map<String,String> map) {
for (Map.Entry<String,String> entry:map.entrySet()){
System.out.print("得到键为:==="+entry.getKey());
System.out.println("得到值为:==="+entry.getValue());
}
}
五、拦截器
- 实现org.springframework.web.servlet.HandlerInterceptor接口自定义拦截器
一、实现处理器拦截器HandlerInterceptor
- 实现HandlerInterceptor接口
public class MyInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("Hello");
return false; // 若为true则调用下面的方法
}
@Override
public void postHandle
@Override
public void afterCompletion
}
- 配置XML文件
<!--9、处理器拦截器-->
<mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path="/**"/> // 拦截/目录下及其子目录
<mvc:exclude-mapping path="/static/**"/> // 不拦截/static目录下及其子目录
<bean class="com.miao.p1_SpringMVCXML.Interceptor.MyInterceptor"/>
</mvc:interceptor>
</mvc:interceptors>
六、异常处理器
-
org.springframework.web.servlet.handler.SimpleMappingExceptionResovler,解决简单问题
-
实现org.springframework.web.servlet.HandlerExceptionResolver接口自定义异常处理器,解决复杂异常
一、配置简单异常处理器SimpleMappingExceptionResovler
<!--10.简单异常处理器-->
<bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
<!--设置默认错误视图。由于配置视图解析器,所以反回的是/static/error.html,下同/static/error1.html-->
<property name="defaultErrorView" value="error"/>
<property name="exceptionMappings">
<map>
<entry key="MyException" value="error1"/>
<entry key="java.lang.ClassCastException" value="error2"/>
</map>
</property>
</bean>
- 测试
@RequestMapping(value = "/demo3", method = RequestMethod.GET)
public void test1(){
System.out.println("原始除以零异常1");
// 运行时抛出异常
System.out.println(1/0);
}
// 由于没对其进行配置,所以输出默认错误视图error
@RequestMapping(value = "/demo4", method = RequestMethod.GET)
public void test2() throws MyException{
System.out.println("自定义异常");
// 手动抛出异常
throw new MyException();
}
// 对其进行了配置,所以输出错误视图error1
@RequestMapping(value = "/demo5", method = RequestMethod.GET)
// 手动把异常抛出
public void test4(){
System.out.println("原始类转换异常2");
Object a = "abc";
Integer b = (Integer) a;
}
// 对其也进行了配置,所以也输出错误视图error2
二、实现处理器异常程序解析器HandlerExceptionResolver
- 实现HandlerExceptionResolver接口
public class MyResovler implements HandlerExceptionResolver {
@Override
public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {
ModelAndView modelAndView = new ModelAndView();
if (ex instanceof MyException){
modelAndView.setViewName("error1");
} else if (ex instanceof ClassCastException){
modelAndView.setViewName("error2");
} else {
modelAndView.setViewName("error");
}
return modelAndView;
}
}
- 配置XML文件(将自定义异常处理器放入容器)
// 先将简单异常处理器配置注释掉
<!--11.自定义异常处理器-->
<bean class="com.miao.p1_SpringMVCXML.Resovler.MyResovler"/>
- 测试结果与简单异常处理器一致
七、编码处理
- 该过滤器要放在所有过滤器之前
<!--强制请求和响应都为utf-8-->
<filter>
<filter-name>encodingFilter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>utf-8</param-value>
</init-param>
<init-param>
<param-name>forceRequestEncoding</param-name>
<param-value>true</param-value>
</init-param>
<init-param>
<param-name>forceResponseEncoding</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>encodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
八、完整配置文件
- web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0">
<!--*若配置contextClassLoader,则是用于创建一个父容器,而前端控制器生成的是子容器-->
<!--该配置文件中包含了各种Controller层所需的依赖bean-->
<!--该配置文件只包含配置三大器等等-->
<!--1.设置前端控制器-->
<servlet>
<servlet-name>dispatcherServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<!--2.联系到spring-mvc配置文件-->
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring-mvc.xml</param-value>
</init-param>
<!--3.设置前端控制器随着项目启动而启动-->
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>dispatcherServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<!--8.配置过滤器,用处理PUT和DELETE请求-->
<filter>
<filter-name>hiddenHttpMthodFilter</filter-name>
<filter-class>org.springframework.web.filter.HiddenHttpMethodFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>hiddenHttpMthodFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
</web-app>
- spring-mvc.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/mvc https://www.springframework.org/schema/mvc/spring-mvc.xsd">
<!--4.扫描Controller包-->
<context:component-scan base-package="com.miao.p1_SpringMVCXML.Controller"></context:component-scan>
<!--5.设置视图解析器-->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/static/"/>
<property name="suffix" value=".html"/>
</bean>
<!--6.设置处理映射器和处理适配器-->
<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping"/>
<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter"/>
<!--7.静态资源放行,mapping表示请求url,location表示项目webapp的静态资源目录-->
<!--表示请求路径中包含/static/者/static/index.html,都可以访问到/static/目录下的资源-->
<mvc:resources mapping="/static/**" location="/static/"/>
<!--9、处理器拦截器-->
<mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path="/**"/>
<mvc:exclude-mapping path="/static/**"/>
<bean class="com.miao.p1_SpringMVCXML.Interceptor.MyInterceptor"/>
</mvc:interceptor>
</mvc:interceptors>
<!--10.简单异常处理器-->
<!-- <bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">-->
<!-- <!–设置默认错误视图。由于配置视图解析器,所以反回的是/static/error.html,下同/static/error1.html–>-->
<!-- <property name="defaultErrorView" value="error"/>-->
<!-- <property name="exceptionMappings">-->
<!-- <map>-->
<!-- <entry key="MyException" value="error1"/>-->
<!-- <entry key="java.lang.ClassCastException" value="error2"/>-->
<!-- </map>-->
<!-- </property>-->
<!-- </bean>-->
<!--11.自定义异常处理器-->
<bean class="com.miao.p1_SpringMVCXML.Resovler.MyResovler"/>
</beans>
九、底层原理
一、注意点
-
不建议使用一个applicationContext.xml去包含其他三层的文件然后给前端控制器,而是通过ContextLoaderListener建立父容器来管理bean,前端控制器的则是子容器。
-
子容器(/app1)----找bean---->父容器<----找bean----子容器(/app2)
-
<!--父容器,子容器Controller层需要的依赖,直接从父容器这里拿即可,如注入UserService的实现类--> <context-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:spring-context.xml</param-value> </context-param> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> <!--子容器1--> <servlet> <servlet-name>dispatcherServlet</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <init-param> <!--2.联系到spring-mvc配置文件--> <param-name>contextConfigLocation</param-name> <param-value>classpath:spring-mvc.xml</param-value> </init-param> <!--3.设置前端控制器随着项目启动而启动--> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>dispatcherServlet</servlet-name> <url-pattern>/app1/*</url-pattern> </servlet-mapping> <!--子容器2--> <servlet> <servlet-name>dispatcherServlet</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <init-param> <!--2.联系到spring-mvc配置文件--> <param-name>contextConfigLocation</param-name> <param-value>classpath:spring-mvc.xml</param-value> </init-param> <!--3.设置前端控制器随着项目启动而启动--> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>dispatcherServlet</servlet-name> <url-pattern>/app2/*</url-pattern> </servlet-mapping>
八、SSM整合
一、基础篇
- 注意!以下所有整合例子都未整合Restful过滤器、异常处理器和事务!!!
一、SSM整合
一、依赖
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.example</groupId>
<artifactId>SSM</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
</properties>
<packaging>war</packaging>
<dependencies>
<!--结合MVC一起使用-->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>4.0.1</version>
</dependency>
<!--spring+springMVC-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.3.18</version>
</dependency>
<!--配合spring测试一起使用-->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13.2</version>
<scope>test</scope>
</dependency>
<!--spring测试-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>5.3.18</version>
</dependency>
<!--数据库连接池-->
<dependency>
<groupId>com.mchange</groupId>
<artifactId>c3p0</artifactId>
<version>0.9.5.5</version>
</dependency>
<!--数据库连接-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.28</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.mybatis/mybatis-spring -->
<!--spring整合MyBatis-->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>2.0.7</version>
</dependency>
<!--MyBatis-->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.9</version>
</dependency>
<!--用来spring管理数据源-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>5.3.17</version>
</dependency>
</dependencies>
</project>
二、整合方式
- 三种方式都可以混合开发
- 注解方式都不需要在创建SqlsessionFactoryBean时扫描XML文件,会自动匹配。
一、@Mapper注解
一、配置文件
1.applicationContext
- resources/applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?>
<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">
<!--1.导入配置文件-->
<import resource="spring-dao.xml"/>
<import resource="spring-service.xml"/>
<import resource="spring-mvc.xml"/>
</beans>
2.spring-dao
- resources/spring-dao.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mybatis-spring="http://mybatis.org/schema/mybatis-spring"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd http://mybatis.org/schema/mybatis-spring http://mybatis.org/schema/mybatis-spring.xsd">
<!--1.扫描spring-dao层注解-->
<context:component-scan base-package="com.miao.Dao.Impl"/>
<!--2.扫描mybatis的@Mapper注解-->
<mybatis-spring:scan base-package="com.miao.Dao.Mapper"/>
<!--3.配置数据源,以c3p0为例子-->
<context:property-placeholder location="classpath:jdbc.properties"/>
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="driverClass" value="${jdbc.driverClassName}"/>
<property name="jdbcUrl" value="${jdbc.url}"/>
<property name="user" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</bean>
<!--4.注册sql工厂-->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<!--加载数据源-->
<property name="dataSource" ref="dataSource"/>
<property name="typeAliasesPackage" value="com.miao.Dao.POJO"/>
<!--可有可无-->
<property name="mapperLocations" value="classpath:com/miao/Dao/Mapper/*.xml"/>
</bean>
</beans>
3.spring-service
- resources/spring-service.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">
<!--1.扫描spring-service层注解-->
<context:component-scan base-package="com.miao.Service.Impl"/>
</beans>
4.spring-mvc
- resources/spring-mvc.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/mvc https://www.springframework.org/schema/mvc/spring-mvc.xsd">
<!--1.扫描spring-controller层注解-->
<context:component-scan base-package="com.miao.Controller"/>
<!--2.配置视图解析器-->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/static/"/>
<property name="suffix" value=".html"/>
</bean>
<!--3.配置处理器映射器和处理器适配器-->
<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping"/>
<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter"/>
<!--4.静态资源放行-->
<mvc:resources mapping="/static/**" location="/static/"/>
<!--5.拦截器-->
<mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path="/**"/>
<mvc:exclude-mapping path="/static/**"/>
<bean class="com.miao.Interceptor.MyInterceptor"/>
</mvc:interceptor>
</mvc:interceptors>
</beans>
5.web
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0">
<!--1.配置前端控制器-->
<servlet>
<servlet-name>dispatcherServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:applicationContext.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>dispatcherServlet</servlet-name>
<!--拦截所有除了.jsp-->
<url-pattern>/</url-pattern>
</servlet-mapping>
<!--3.配置前端编码过滤器-->
<!--强制请求和响应都为utf-8-->
<filter>
<filter-name>encodingFilter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>utf-8</param-value>
</init-param>
<init-param>
<param-name>forceRequestEncoding</param-name>
<param-value>true</param-value>
</init-param>
<init-param>
<param-name>forceResponseEncoding</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>encodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<!--3.设置首页-->
<welcome-file-list>
<welcome-file>/static/index.html</welcome-file>
</welcome-file-list>
</web-app>
6.jdbc
- resources/jdbc.properties
jdbc.driverClassName=com.mysql.cj.jdbc.Driver
jdbc.url=jdbc:mysql://101.43.117.227:3307/test?useUnicode=true&characterEncoding=UTF-8
jdbc.username=root
jdbc.password=123456
7.UserMapper
- com/miao/Dao/Mapper/UserMapper.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.miao.Dao.Mapper.UserMapper">
<select id="selectAll" resultType="User">
select * from l1 where age=18
</select>
</mapper>
二、类
1.Dao层
- com.miao.Dao
- com.miao.Dao.Impl
- com.miao.Dao.POJO
- com.miao.Dao.Mapper
// UserDao
package com.miao.Dao;
public interface UserDao {
void show();
}
//UserDaoImpl
package com.miao.Dao.Impl;
import com.miao.Dao.UserDao;
import org.springframework.stereotype.Repository;
@Repository
public class UserDaoImpl implements UserDao {
@Override
public void show() {
System.out.println("Hello UserDao...");
}
}
// User
package com.miao.Dao.POJO;
public class User {
private String name;
private Integer age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
@Override
public String toString() {
return "User{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
// UserMapper
package com.miao.Dao.Mapper;
import com.miao.Dao.POJO.User;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Select;
@Mapper
public interface UserMapper {
@Select("select * from l1 where age=18")
User select();
// 报错但是其实是没错的,因为能定位到对应的sql映射文件
User selectAll();
}
2.Service层
- com.miao.Service
- com.miao.Service.Impl
// UserService
package com.miao.Service;
public interface UserService {
void show();
}
// UserServiceImpl
package com.miao.Service.Impl;
import com.miao.Dao.UserDao;
import com.miao.Service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class UserServiceImpl implements UserService {
@Autowired
private UserDao userDao;
@Override
public void show() {
userDao.show();
}
}
3.Controller层
- com.miao.Controller
package com.miao.Controller;
import com.miao.Dao.Mapper.UserMapper;
import com.miao.Service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
@Controller
@RequestMapping("/users")
public class UserController {
@Autowired
private UserService userService;
@Autowired(required = false) // idea的bug,其实只要正确配置,那么这个不可能为null
private UserMapper userMapper;
// 此处用来测试springIOC和MVC的实现
@GetMapping("/SS")
public String test1(){
userService.show();
return "hello";
}
// 此处用来测试mybatis
@GetMapping("/M")
@ResponseBody
public String test2(){
System.out.println(userMapper.selectAll()); // xml
return userMapper.select().toString(); // 注解
}
}
4.拦截器
- com.miao.Interceptor
package com.miao.Interceptor;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class MyInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("拦截了");
return true;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
HandlerInterceptor.super.postHandle(request, response, handler, modelAndView);
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
HandlerInterceptor.super.afterCompletion(request, response, handler, ex);
}
}
三、前端页面
- webapp/static/index.html
- Webapp/static/hello.html
二、@MapperScan注解
一、配置文件
1.applicationContext
- resources/applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?>
<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">
<!--1.导入配置文件-->
<import resource="spring-dao.xml"/>
<import resource="spring-service.xml"/>
<import resource="spring-mvc.xml"/>
</beans>
2.spring-dao
- resources/spring-dao.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mybatis-spring="http://mybatis.org/schema/mybatis-spring"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd http://mybatis.org/schema/mybatis-spring http://mybatis.org/schema/mybatis-spring.xsd">
<!--1.扫描spring-dao层注解-->
<context:component-scan base-package="com.miao.Dao.Impl"/>
<!--2.配置数据源,以c3p0为例子-->
<context:property-placeholder location="classpath:jdbc.properties"/>
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="driverClass" value="${jdbc.driverClassName}"/>
<property name="jdbcUrl" value="${jdbc.url}"/>
<property name="user" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</bean>
<!--3.注册sql工厂-->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<!--加载数据源-->
<property name="dataSource" ref="dataSource"/>
<property name="typeAliasesPackage" value="com.miao.Dao.POJO"/>
<!--可有可无-->
<property name="mapperLocations" value="classpath:com/miao/Dao/Mapper/*.xml"/>
</bean>
</beans>
3.spring-service
- resources/spring-service.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">
<!--1.扫描spring-service层注解-->
<context:component-scan base-package="com.miao.Service.Impl"/>
</beans>
4.spring-mvc
- resources/spring-mvc.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/mvc https://www.springframework.org/schema/mvc/spring-mvc.xsd">
<!--1.扫描spring-controller层注解-->
<context:component-scan base-package="com.miao.Controller"/>
<!--2.配置视图解析器-->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/static/"/>
<property name="suffix" value=".html"/>
</bean>
<!--3.配置处理器映射器和处理器适配器-->
<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping"/>
<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter"/>
<!--4.静态资源放行-->
<mvc:resources mapping="/static/**" location="/static/"/>
<!--5.拦截器-->
<mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path="/**"/>
<mvc:exclude-mapping path="/static/**"/>
<bean class="com.miao.Interceptor.MyInterceptor"/>
</mvc:interceptor>
</mvc:interceptors>
</beans>
5.web
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0">
<!--1.配置前端控制器-->
<servlet>
<servlet-name>dispatcherServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:applicationContext.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>dispatcherServlet</servlet-name>
<!--拦截所有除了.jsp-->
<url-pattern>/</url-pattern>
</servlet-mapping>
<!--2.配置前端编码过滤器-->
<!--强制请求和响应都为utf-8-->
<filter>
<filter-name>encodingFilter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>utf-8</param-value>
</init-param>
<init-param>
<param-name>forceRequestEncoding</param-name>
<param-value>true</param-value>
</init-param>
<init-param>
<param-name>forceResponseEncoding</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>encodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<!--3.设置首页-->
<welcome-file-list>
<welcome-file>/static/index.html</welcome-file>
</welcome-file-list>
</web-app>
6.jdbc
- resources/jdbc.properties
jdbc.driverClassName=com.mysql.cj.jdbc.Driver
jdbc.url=jdbc:mysql://101.43.117.227:3307/test?useUnicode=true&characterEncoding=UTF-8
jdbc.username=root
jdbc.password=123456
7.UserMapper
- com/miao/Dao/Mapper/UserMapper.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.miao.Dao.Mapper.UserMapper">
<select id="selectAll" resultType="User">
select * from l1 where age=18
</select>
</mapper>
二、类
1.Dao层
- com.miao.Dao
- com.miao.Dao.Impl
- com.miao.Dao.POJO
- com.miao.Dao.Mapper
// UserDao
package com.miao.Dao;
public interface UserDao {
void show();
}
//UserDaoImpl
package com.miao.Dao.Impl;
import com.miao.Dao.UserDao;
import org.springframework.stereotype.Repository;
@Repository
public class UserDaoImpl implements UserDao {
@Override
public void show() {
System.out.println("Hello UserDao...");
}
}
// User
package com.miao.Dao.POJO;
public class User {
private String name;
private Integer age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
@Override
public String toString() {
return "User{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
// UserMapper
package com.miao.Dao.Mapper;
import com.miao.Dao.POJO.User;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Select;
public interface UserMapper {
@Select("select * from l1 where age=18")
User select();
// 报错但是其实是没错的,因为能定位到对应的sql映射文件
User selectAll();
}
2.Service层
- com.miao.Service
- com.miao.Service.Impl
// UserService
package com.miao.Service;
public interface UserService {
void show();
}
// UserServiceImpl
package com.miao.Service.Impl;
import com.miao.Dao.UserDao;
import com.miao.Service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class UserServiceImpl implements UserService {
@Autowired
private UserDao userDao;
@Override
public void show() {
userDao.show();
}
}
3.Controller层
- com.miao.Controller
package com.miao.Controller;
import com.miao.Dao.Mapper.UserMapper;
import com.miao.Service.UserService;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
@Controller
@RequestMapping("/users")
@MapperScan("com.miao.Dao.Mapper") // 扫描需要@Mapper的接口并为他们创建实现类
public class UserController {
@Autowired
private UserService userService;
@Autowired(required = false)
private UserMapper userMapper;
// 此处用来测试springIOC和MVC的实现
@GetMapping("/SS")
public String test1(){
userService.show();
return "hello";
}
// 此处用来测试mybatis
@GetMapping("/M")
@ResponseBody
public String test2(){
System.out.println(userMapper.selectAll()); // xml
return userMapper.select().toString(); // 注解
}
}
4.拦截器
- com.miao.Interceptor
package com.miao.Interceptor;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class MyInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("拦截了");
return true;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
HandlerInterceptor.super.postHandle(request, response, handler, modelAndView);
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
HandlerInterceptor.super.afterCompletion(request, response, handler, ex);
}
}
三、前端页面
- webapp/static/index.html
- Webapp/static/hello.html
三、MapperScannerConfigurer
一、配置文件
1.applicationContext
- resources/applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?>
<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">
<!--1.导入配置文件-->
<import resource="spring-dao.xml"/>
<import resource="spring-service.xml"/>
<import resource="spring-mvc.xml"/>
</beans>
2.spring-dao
- resources/spring-dao.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mybatis-spring="http://mybatis.org/schema/mybatis-spring"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd http://mybatis.org/schema/mybatis-spring http://mybatis.org/schema/mybatis-spring.xsd">
<!--1.扫描spring-dao层注解-->
<context:component-scan base-package="com.miao.Dao.Impl"/>
<!--2.配置数据源,以c3p0为例子-->
<context:property-placeholder location="classpath:jdbc.properties"/>
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="driverClass" value="${jdbc.driverClassName}"/>
<property name="jdbcUrl" value="${jdbc.url}"/>
<property name="user" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</bean>
<!--3.注册sql工厂-->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<!--加载数据源-->
<property name="dataSource" ref="dataSource"/>
<property name="typeAliasesPackage" value="com.miao.Dao.POJO"/>
<!--可有可无-->
<property name="mapperLocations" value="classpath:com/miao/Dao/Mapper/*.xml"/>
</bean>
<!--4.注册MapperScannerConfigurer-->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="com.miao.Dao.Mapper"/>
<!--本来可以不需要,但是防止使用多个sql工厂时,导致其不能自动装配-->
<property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/>
</bean>
</beans>
3.spring-service
- resources/spring-service.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">
<!--1.扫描spring-service层注解-->
<context:component-scan base-package="com.miao.Service.Impl"/>
</beans>
4.spring-mvc
- resources/spring-mvc.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/mvc https://www.springframework.org/schema/mvc/spring-mvc.xsd">
<!--1.扫描spring-controller层注解-->
<context:component-scan base-package="com.miao.Controller"/>
<!--2.配置视图解析器-->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/static/"/>
<property name="suffix" value=".html"/>
</bean>
<!--3.配置处理器映射器和处理器适配器-->
<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping"/>
<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter"/>
<!--4.静态资源放行-->
<mvc:resources mapping="/static/**" location="/static/"/>
<!--5.拦截器-->
<mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path="/**"/>
<mvc:exclude-mapping path="/static/**"/>
<bean class="com.miao.Interceptor.MyInterceptor"/>
</mvc:interceptor>
</mvc:interceptors>
</beans>
5.web
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0">
<!--1.配置前端控制器-->
<servlet>
<servlet-name>dispatcherServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:applicationContext.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>dispatcherServlet</servlet-name>
<!--拦截所有除了.jsp-->
<url-pattern>/</url-pattern>
</servlet-mapping>
<!--3.配置前端编码过滤器-->
<!--强制请求和响应都为utf-8-->
<filter>
<filter-name>encodingFilter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>utf-8</param-value>
</init-param>
<init-param>
<param-name>forceRequestEncoding</param-name>
<param-value>true</param-value>
</init-param>
<init-param>
<param-name>forceResponseEncoding</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>encodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<!--3.设置首页-->
<welcome-file-list>
<welcome-file>/static/index.html</welcome-file>
</welcome-file-list>
</web-app>
6.jdbc
- resources/jdbc.properties
jdbc.driverClassName=com.mysql.cj.jdbc.Driver
jdbc.url=jdbc:mysql://101.43.117.227:3307/test?useUnicode=true&characterEncoding=UTF-8
jdbc.username=root
jdbc.password=123456
7.UserMapper
- com/miao/Dao/Mapper/UserMapper.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.miao.Dao.Mapper.UserMapper">
<select id="selectAll" resultType="User">
select * from l1 where age=18
</select>
</mapper>
二、类
1.Dao层
- com.miao.Dao
- com.miao.Dao.Impl
- com.miao.Dao.POJO
- com.miao.Dao.Mapper
// UserDao
package com.miao.Dao;
public interface UserDao {
void show();
}
//UserDaoImpl
package com.miao.Dao.Impl;
import com.miao.Dao.UserDao;
import org.springframework.stereotype.Repository;
@Repository
public class UserDaoImpl implements UserDao {
@Override
public void show() {
System.out.println("Hello UserDao...");
}
}
// User
package com.miao.Dao.POJO;
public class User {
private String name;
private Integer age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
@Override
public String toString() {
return "User{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
// UserMapper
package com.miao.Dao.Mapper;
import com.miao.Dao.POJO.User;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Select;
public interface UserMapper {
@Select("select * from l1 where age=18")
User select();
// 报错但是其实是没错的,因为能定位到对应的sql映射文件
User selectAll();
}
2.Service层
- com.miao.Service
- com.miao.Service.Impl
// UserService
package com.miao.Service;
public interface UserService {
void show();
}
// UserServiceImpl
package com.miao.Service.Impl;
import com.miao.Dao.UserDao;
import com.miao.Service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class UserServiceImpl implements UserService {
@Autowired
private UserDao userDao;
@Override
public void show() {
userDao.show();
}
}
3.Controller层
- com.miao.Controller
package com.miao.Controller;
import com.miao.Dao.Mapper.UserMapper;
import com.miao.Service.UserService;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
@Controller
@RequestMapping("/users")
public class UserController {
@Autowired
private UserService userService;
@Autowired(required = false)
private UserMapper userMapper;
// 此处用来测试springIOC和MVC的实现
@GetMapping("/SS")
public String test1(){
userService.show();
return "hello";
}
// 此处用来测试mybatis
@GetMapping("/M")
@ResponseBody
public String test2(){
System.out.println("哈哈哈");
System.out.println(userMapper.selectAll()); // xml
return userMapper.select().toString(); // 注解
}
}
4.拦截器
- com.miao.Interceptor
package com.miao.Interceptor;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class MyInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("拦截了");
return true;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
HandlerInterceptor.super.postHandle(request, response, handler, modelAndView);
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
HandlerInterceptor.super.afterCompletion(request, response, handler, ex);
}
}
三、前端页面
- webapp/static/index.html
- Webapp/static/hello.html
二、SSMP整合
一、依赖
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.example</groupId>
<artifactId>SSM</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
</properties>
<packaging>war</packaging>
<dependencies>
<!--结合MVC一起使用-->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>4.0.1</version>
</dependency>
<!--spring+springMVC-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.3.18</version>
</dependency>
<!--配合spring测试一起使用-->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13.2</version>
<scope>test</scope>
</dependency>
<!--spring测试-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>5.3.18</version>
</dependency>
<!--数据库连接池-->
<dependency>
<groupId>com.mchange</groupId>
<artifactId>c3p0</artifactId>
<version>0.9.5.5</version>
</dependency>
<!--数据库连接-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.28</version>
</dependency>
<!-- 已经包含mybatis和mybatis-spring -->
<!-- https://mvnrepository.com/artifact/com.baomidou/mybatis-plus -->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus</artifactId>
<version>3.5.1</version>
</dependency>
<!--用来spring管理数据源-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>5.3.17</version>
</dependency>
</dependencies>
</project>
二、整合方式
一、@Mapper
- 同SSM,改造方式同MapperScannerConfigurer
二、@MapperScan
- 同SSM,改造方式同MapperScannerConfigurer
三、MapperScannerConfigurer
一、配置文件
1.applicationContext
- resources/applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?>
<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">
<!--1.导入配置文件-->
<import resource="spring-dao.xml"/>
<import resource="spring-service.xml"/>
<import resource="spring-mvc.xml"/>
</beans>
2.spring-dao
- resources/spring-dao.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mybatis-spring="http://mybatis.org/schema/mybatis-spring"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd http://mybatis.org/schema/mybatis-spring http://mybatis.org/schema/mybatis-spring.xsd">
<!--1.扫描spring-dao层注解-->
<context:component-scan base-package="com.miao.Dao.Impl"/>
<!--2.配置数据源,以c3p0为例子-->
<context:property-placeholder location="classpath:jdbc.properties"/>
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="driverClass" value="${jdbc.driverClassName}"/>
<property name="jdbcUrl" value="${jdbc.url}"/>
<property name="user" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</bean>
<!--3.注册sql工厂,仅有此处与mybatis不同!-->
<bean id="sqlSessionFactory" class="com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean">
<!--加载数据源-->
<property name="dataSource" ref="dataSource"/>
<property name="typeAliasesPackage" value="com.miao.Dao.POJO"/>
<!--可有可无-->
<property name="mapperLocations" value="classpath:com/miao/Dao/Mapper/*.xml"/>
</bean>
<!--4.注册MapperScannerConfigurer-->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="com.miao.Dao.Mapper"/>
<!--本来可以不需要,但是防止使用多个sql工厂时,导致其不能自动装配-->
<property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/>
</bean>
</beans>
3.spring-service
- resources/spring-service.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">
<!--1.扫描spring-service层注解-->
<context:component-scan base-package="com.miao.Service.Impl"/>
</beans>
4.spring-mvc
- resources/spring-mvc.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/mvc https://www.springframework.org/schema/mvc/spring-mvc.xsd">
<!--1.扫描spring-controller层注解-->
<context:component-scan base-package="com.miao.Controller"/>
<!--2.配置视图解析器-->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/static/"/>
<property name="suffix" value=".html"/>
</bean>
<!--3.配置处理器映射器和处理器适配器-->
<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping"/>
<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter"/>
<!--4.静态资源放行-->
<mvc:resources mapping="/static/**" location="/static/"/>
<!--5.拦截器-->
<mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path="/**"/>
<mvc:exclude-mapping path="/static/**"/>
<bean class="com.miao.Interceptor.MyInterceptor"/>
</mvc:interceptor>
</mvc:interceptors>
</beans>
5.web
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0">
<!--1.配置前端控制器-->
<servlet>
<servlet-name>dispatcherServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:applicationContext.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>dispatcherServlet</servlet-name>
<!--拦截所有除了.jsp-->
<url-pattern>/</url-pattern>
</servlet-mapping>
<!--2.配置前端编码过滤器-->
<!--强制请求和响应都为utf-8-->
<filter>
<filter-name>encodingFilter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>utf-8</param-value>
</init-param>
<init-param>
<param-name>forceRequestEncoding</param-name>
<param-value>true</param-value>
</init-param>
<init-param>
<param-name>forceResponseEncoding</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>encodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<!--3.设置首页-->
<welcome-file-list>
<welcome-file>/static/index.html</welcome-file>
</welcome-file-list>
</web-app>
6.jdbc
- resources/jdbc.properties
jdbc.driverClassName=com.mysql.cj.jdbc.Driver
jdbc.url=jdbc:mysql://101.43.117.227:3307/test?useUnicode=true&characterEncoding=UTF-8
jdbc.username=root
jdbc.password=123456
7.UserMapper
- com/miao/Dao/Mapper/UserMapper.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.miao.Dao.Mapper.UserMapper">
<select id="selectAll" resultType="User">
select * from tb_user where id=1
</select>
</mapper>
二、类
1.Dao层
- com.miao.Dao
- com.miao.Dao.Impl
- com.miao.Dao.POJO
- com.miao.Dao.Mapper
// UserDao
package com.miao.Dao;
public interface UserDao {
void show();
}
//UserDaoImpl
package com.miao.Dao.Impl;
import com.miao.Dao.UserDao;
import org.springframework.stereotype.Repository;
@Repository
public class UserDaoImpl implements UserDao {
@Override
public void show() {
System.out.println("Hello UserDao...");
}
}
// User
package com.miao.Dao.POJO;
import com.baomidou.mybatisplus.annotation.TableName;
@TableName("tb_user")
public class User {
private Integer id;
private String username;
private String password;
private String gender;
private String addr;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getGender() {
return gender;
}
public void setGender(String gender) {
this.gender = gender;
}
public String getAddr() {
return addr;
}
public void setAddr(String addr) {
this.addr = addr;
}
@Override
public String toString() {
return "User{" +
"id=" + id +
", username='" + username + '\'' +
", password='" + password + '\'' +
", gender='" + gender + '\'' +
", addr='" + addr + '\'' +
'}';
}
}
// UserMapper
package com.miao.Dao.Mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.miao.Dao.POJO.User;
import org.apache.ibatis.annotations.Select;
public interface UserMapper extends BaseMapper<User> {
@Select("select * from tb_user where id=1")
User select();
// 报错但是其实是没错的,因为能定位到对应的sql映射文件
User selectAll();
}
2.Service层
- com.miao.Service
- com.miao.Service.Impl
// UserService
package com.miao.Service;
public interface UserService {
void show();
}
// UserServiceImpl
package com.miao.Service.Impl;
import com.miao.Dao.UserDao;
import com.miao.Service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class UserServiceImpl implements UserService {
@Autowired
private UserDao userDao;
@Override
public void show() {
userDao.show();
}
}
3.Controller层
- com.miao.Controller
package com.miao.Controller;
import com.miao.Dao.Mapper.UserMapper;
import com.miao.Service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
@Controller
@RequestMapping("/users")
public class UserController {
@Autowired
private UserService userService;
@Autowired(required = false)
private UserMapper userMapper;
// 此处用来测试springIOC和MVC的实现
@GetMapping("/SS")
public String test1(){
userService.show();
return "hello";
}
// 此处来测试mybatis-plus,设置响应体Content-Type,防止前端中文乱码
@GetMapping(value = "/MP", produces = "text/html;charset=utf-8")
@ResponseBody
public String test3(){
System.out.println("MP");
System.out.println(userMapper.selectById(1)); // mp
System.out.println(userMapper.selectAll()); // xml
return userMapper.select().toString(); // 注解
}
}
4.拦截器
- com.miao.Interceptor
package com.miao.Interceptor;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class MyInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("拦截了");
return true;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
HandlerInterceptor.super.postHandle(request, response, handler, modelAndView);
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
HandlerInterceptor.super.afterCompletion(request, response, handler, ex);
}
}
三、前端页面
- webapp/static/index.html
- Webapp/static/hello.html
三、标准整合文件
一、web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0">
<!--1.配置父容器-->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring-context.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<!--2.配置前端控制器及子容器-->
<servlet>
<servlet-name>dispatcherServlcet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring-mvc.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>dispatcherServlcet</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
<!--3.配置前端编码过滤器,只对POST请求有效,但好像没用-->
<!--强制请求和响应都为utf-8-->
<filter>
<filter-name>encodingFilter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>utf-8</param-value>
</init-param>
<init-param>
<param-name>forceRequestEncoding</param-name>
<param-value>true</param-value>
</init-param>
<init-param>
<param-name>forceResponseEncoding</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>encodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<!--4.配置过滤器,让其知道有DELETE、PUT-->
<filter>
<filter-name>hiddenHttpMethodFilter</filter-name>
<filter-class>org.springframework.web.filter.HiddenHttpMethodFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>hiddenHttpMethodFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
</web-app>
二、spring-mvc.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/mvc https://www.springframework.org/schema/mvc/spring-mvc.xsd">
<!--1.包扫描注解-->
<context:component-scan base-package="com.miao.Controller"/>
<!--2.配置视图解析器-->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/static/"/>
<property name="suffix" value=".html"/>
</bean>
<!--3.配置处理器映射器和处理器适配器,两种方式都可以-->
<!--<mvc:annotation-driven/>-->
<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping"/>
<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter"/>
<!--4.静态资源放行,两种方式都可以,mapping表示只能从/开始访问这个资源-->
<!--<mvc:default-servlet-handler/>-->
<mvc:resources mapping="/static/**" location="/static/"/>
<!--5.拦截器-->
<!--6.异常处理器-->
</beans>
三、spring-context.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd">
<!--导入service层的配置文件-->
<import resource="classpath:spring-service.xml"/>
<!--1.配置包扫描-->
<context:component-scan base-package="com.miao.Dao"/>
<!--2.配置数据源-->
<context:property-placeholder location="classpath:jdbc.properties"/>
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="driverClass" value="${jdbc.driverClassName}"/>
<property name="jdbcUrl" value="${jdbc.url}"/>
<property name="user" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</bean>
<!--3.配置SqlSessionFactoryBean-->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource"/>
<property name="typeAliasesPackage" value="com.miao.Dao.Pojo"/>
</bean>
<!--4.配置mapper接口扫描配置器-->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/>
<property name="basePackage" value="com.miao.Dao.Mapper"/>
</bean>
<!--5.事务控制-->
</beans>
四、spring-service.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">
<!--包扫描-->
<context:component-scan base-package="com.miao.Service"/>
</beans>
五、jdbc.properties
jdbc.driverClassName=com.mysql.cj.jdbc.Driver
jdbc.url=jdbc:mysql://101.43.117.227:3307/test?useUnicode=true&characterEncoding=UTF-8
jdbc.username=root
jdbc.password=123456
- 注意!所有整合例子都未整合Restful过滤器、异常处理器和事务!!!