文章目录
- MVC参数检验 注解由JSR 和 Hibernate提供
- MVC文件上传处理
- MVC文件下载处理
- DispatcherServlet init()周期
- MyBatis配置
- MyBatis 创建代理对象调用方法执行sql语句
- @Test注解@org.junit.jupiter.api.Test 形式
- MyBatis 中的工厂和建造者 SqlSessionFactory / builder
- MyBatis Session 工具类建造一个全局唯一的SqlSessionFactory
- 从SQL编写执行角度对比MyBatis和前身
- JDK动态代理Demo
MVC参数检验 注解由JSR 和 Hibernate提供
JSR303:
@Null
被注释的元素必须为 null
@NotNull
被注释的元素必须不为 null
@AssertTrue
被注释的元素必须为 true
@AssertFalse
被注释的元素必须为 false
@Min(value)
被注释的元素必须是一个数字,其值必须大于等于指定的最小值
@Max(value)
被注释的元素必须是一个数字,其值必须小于等于指定的最大值
@DecimalMin(value)
被注释的元素必须是一个数字,其值必须大于等于指定的最小值
@DecimalMax(value)
被注释的元素必须是一个数字,其值必须小于等于指定的最大值
@Size(max, min)
被注释的元素的大小必须在指定的范围内
@Digits (integer, fraction)
被注释的元素必须是一个数字,其值必须在可接受的范围内
@Past
被注释的元素必须是一个过去的日期
@Future
被注释的元素必须是一个将来的日期
@Pattern(value)
被注释的元素必须符合指定的正则表达式
被注释的元素必须是电子邮箱地址
@Length
被注释的字符串的大小必须在指定的范围内
@NotEmpty
被注释的字符串的必须非空
@Range
被注释的元素必须在合适的范围内
public class User {@NotNull(message = "名字不能为空")private String name;@Email(message = "邮箱格式错误")private String email;public String getName() {return name;}public void setName(String name) {this.name = name;}public String getEmail() {return email;}public void setEmail(String email) {this.email = email;}// 各种getter / setter / 构造器
}
MVC文件上传处理
导入依赖:commons-fileupload
配置spring.xml
配置web.xml
编写Handler
MVC文件下载处理
输入流转输出流
@GetMapping("download")
public void download(HttpServletResponse response) throws I0Exception {//读取项目下的文件的输入流string realPath =servletcontext.getRealPath("/imgs/lyf.png");FileInputstream fis =new FileInputstream(realPath);//2.设置一些参数response.setHeader//使用响应字节输出流写回文件即可ServletOutputstream ops=response.get0utputstream();byte [l buffer=new byte[8*1024];int len=-1;while((len=fis.read(buffer))!=-1){ops.write(buffer,oll:0,len);}if(fis != null){fis.close():
}
}
响应头设置浏览器去下载,因为浏览器支持的格式会直接打开。
DispatcherServlet init()周期
MyBatis配置
导入依赖
编写实体类
配置mybatis-config.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configurationPUBLIC "-//mybatis.org//DTD Config 3.0//EN""http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration><!-- environments表示配置Mybatis的开发环境,可以配置多个环境,在众多具体环境中,使用default属性指定实际运行时使用的环境。default属性的取值是environment标签的id属性的值。 --><environments default="development"><!-- environment表示配置Mybatis的一个具体的环境 --><environment id="development"><!-- Mybatis的内置的事务管理器 --><transactionManager type="JDBC"/><!-- 配置数据源 --><dataSource type="POOLED"><!-- 建立数据库连接的具体信息 --><property name="driver" value="com.mysql.cj.jdbc.Driver"/><property name="url" value="jdbc:mysql://localhost:3306/mybatis-example"/><property name="username" value="root"/><property name="password" value=""/></dataSource></environment></environments><mappers><!-- Mapper注册:指定Mybatis映射文件的具体位置 --><!-- mapper标签:配置一个具体的Mapper映射文件 --><!-- resource属性:指定Mapper映射文件的实际存储位置,这里需要使用一个以类路径根目录为基准的相对路径 --><!-- 对Maven工程的目录结构来说,resources目录下的内容会直接放入类路径,所以这里我们可以以resources目录为基准 --><mapper resource="mapper/EmpMapper.xml"/></mappers></configuration>
配置mapper.xml(开启别名映射)
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""https://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.qxy.mapper.EmpMapper"><select id="selectEmpById" resultType="com.qxy.pojo.Employee">select emp_id empId,emp_name empName,emp_salary empSalary from t_emp where emp_id = #{empId}</select>
</mapper>
MyBatis 创建代理对象调用方法执行sql语句
1.输入配置文件路径转为输入流
2.根据输入流建造工厂
3.开启sql会话(开启事务自动提交)
4.会话映射mapper
5.结果集映射
6.提交事务
7.关闭资源
public void testDMLDelete() throws IOException {//1.声明配置文件路径String mybatisConfigFilePath = "config/mybatis-config.xml";//2.注入输入流InputStream inputStream = Resources.getResourceAsStream(mybatisConfigFilePath);//3.创建SqlSessionFactorySqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);//4.获取SqlSessionSqlSession sqlSession = sqlSessionFactory.openSession(true);//5.创建代理对象EmployeeMapper employeeMapper = sqlSession.getMapper(EmployeeMapper.class);//6.调用方法int rows = employeeMapper.deleteEmployeeById(4);/*sqlSession.commit();*///7.关闭连接sqlSession.close();}public void testDMLSelect() throws IOException {String mybatisConfigFilePath = "config/mybatis-config.xml";InputStream ips = Resources.getResourceAsStream(mybatisConfigFilePath);SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(ips);SqlSession sqlSession = sqlSessionFactory.openSession(true);EmpMapper empMapper = sqlSession.getMapper(EmpMapper.class);Employee employee = empMapper.selectEmpById(1);System.out.println("employee = " + employee);sqlSession.close();}
@Test注解@org.junit.jupiter.api.Test 形式
如果你在同一个项目中同时使用JUnit 4和JUnit 5的依赖库,可能会遇到命名空间冲突的问题。为了避免这种冲突,通常需要显式地指定完整的包路径来区分这两个注解。
MyBatis 中的工厂和建造者 SqlSessionFactory / builder
builder负责输入流解析并为工厂配置属性
sqlSessionFactory = new SqlSessionFactoryBuilder().build(ips);
public SqlSessionFactory build(InputStream inputStream, String environment, Properties properties) {SqlSessionFactory var5;try {XMLConfigBuilder parser = new XMLConfigBuilder(inputStream, environment, properties);var5 = this.build(parser.parse());} catch (Exception var14) {Exception e = var14;throw ExceptionFactory.wrapException("Error building SqlSession.", e);} finally {ErrorContext.instance().reset();try {if (inputStream != null) {inputStream.close();}} catch (IOException var13) {}}
MyBatis Session 工具类建造一个全局唯一的SqlSessionFactory
public class MybatisUtils {private static SqlSessionFactory sqlSessionFactory;private static String mybatisConfigPath = "config/mybatis-config.xml";static{InputStream ips = null;try {ips = Resources.getResourceAsStream(mybatisConfigPath);} catch (IOException e) {throw new RuntimeException(e);}sqlSessionFactory = new SqlSessionFactoryBuilder().build(ips);}public static SqlSession openSessionAutoCommit(){return sqlSessionFactory.openSession(true);}public static SqlSession openSession(){return sqlSessionFactory.openSession();}
}
从SQL编写执行角度对比MyBatis和前身
IBatis 不需要写Mapper接口,直接创建xml文件编写sql语句,通过sqlSession.crud 调用数据库,其中,crud方法至多有两个参数:(String statement,Object param)
- statement:xml sql id标识
- param:传参 #{field}
所以IBatis就是不用配置环境和连接池参数等等,以及DAO实现类的造轮子行为。几乎只需要编写SQL语句。
IBatis限制:
- SQL语句无告警
- 参数限制1个
- 结果集不确定
在MyBatis中执行SQL是通过JDK动态代理生成的代理对象去调用sqlSession.crud 执行SQL,statement替换成了namespace和id的拼接字符串。
好处:
- 检查SQL语法
- 参数与接口传参一致(底层是收集参数放到Map中)
- 返回值与接口返回值一致
JDK动态代理Demo
动态代理的invoke方法调用method方法前后
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
// 定义一个代理类,这个代理必须要实现invocaHandler 接口,用以指定这个类为一个代理类
public class MyProxy implements InvocationHandler {private Object target;public MyProxy( Object target){this.target=target;}// 实现 invoke方法,这个方法将是后面代码中实际执行的方法@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {System.out.println("开始执行动态代理");Object result=method.invoke(target,args);return result;}// Proxy类为反射机制中的一个类,用于获得代理对象public <T> T getProxy(){/* newProxyInstance方法的参数解释:** 被代理对象的类加载器:target.getClass().getClassLoader()** 被代理的方法:target.getClass().getInterfaces()**代理对象:this*/return (T) Proxy.newProxyInstance(target.getClass().getClassLoader(),target.getClass().getInterfaces(),this);}
}