MyBatis,Spring,SpringMvc,单元测试框架,日志框架Log4J
思维导图源文件获取,用xmind 8 打开github
MyBatis框架
概述
- MyBatis是一个持久层框架/ORM框架,会对结果集(查询)映射,对JDBC简单的封装
- insert
- update
- delete
- selectOne
- selectList
- 持久化
- 狭义:将数据永久的保存到数据库/磁盘等媒介
- 广义:针对于数据的操作都称之持久化操作
- 实体Bean == 持久化类
- 需要的jar包
- mybatis-3.4.6.jar
- mysql-connector-java-5.1.45-bin.jar
CRUD操作
针对于CUD操作,MyBatis需要手动提交事务
MyBatis的API调用过程
package com.hs.util;
/**
- 知识点:
- final修饰类:不能被继承
- 修饰方法:不能被重写
- 修饰变量:常量不可用变,但如果是对象,对象里的值可以变
*
*/
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 java.io.IOException;
import java.io.InputStream;
>
public class MyBatisUtils {
>
private MyBatisUtils() { } //不允许实例化
>
private static final String PATH = “mybatis-config.xml”;
private static InputStream inputStream;
private static SqlSessionFactory sqlSessionFactory;
>
static { //1.静态代码块,只是加载一次
try {
//输入流 读文件
//1.读取核心配置文件
inputStream = Resources.getResourceAsStream(PATH);
//2.创建SqlSession工厂(SqlSessionFactory)相当于Connection
sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
} catch (IOException e) {
e.printStackTrace();
throw new RuntimeException(“加载核心配置文件失败”);
}
}
/**
*3.获取SqlSession 相当于 执行SQL语句对象PreparedStament预处理对象
- SqlSession完成所有的持久化操作CRUD
*/
public static SqlSession getSqlsession() {
>
return sqlSessionFactory.openSession();
}
/**
*6.关闭资源
*/
public static void closeSqlSession(SqlSession sqlSession) {
>
if (sqlSession != null) {
sqlSession.close();
}
}
>
}
-
>
1.读取核心配置文件 classpath(src)/mybatis-config.xml
加载数据库信息属性文件jdbc.properties,${key}获取值
自定义设置类型的别名
配置数据库的环境
加载映射文件
2.创建SqlSession工厂 == SqlSessionFactory
3.获取SqlSession
连接数据库
完成针对于数据的CRUD操作
4.执行定制的SQL语句
-
传统方式
- 命名空间namespace持久化类的全路径
- .
- 映射文件的ID
-
接口代理模式——推荐
- 命名空间namespace固定必须为接口的全路径
- 映射文件中的ID需要跟接口中的方法名保持一致
- 查询操作:根据你的接口的返回值
- selectOne
- selectList
5.事务的提交
Spring框架中有事务的管理
6.关闭资源
-
提取公共的字段代码
无别名
role_id,role_name,role_key,status
有别名
{alias}.role_name,{alias}.status
概要: 如何用
>
-
查询操作
结果集的处理方式
resultType
resultMap
结果集可以处理成什么方式?
-
返回Map类型
- resultType=”map”或者resultType=”java.util.Map”
- resultMap属性去找resultMap标签
- 默认情况是自动映射
- 可以设置别名
-
返回List类型–>依旧使用Map处理结果
- 只是在调用方法的时候使用selectList即可
-
返回对象
可以使用别名方式,保证查询的字段名称和类中的属性名称一致即可使用resultType完成对象的映射
重点resultMap属性
-
一对一和多对一的关联标签association
select方式
结果集映射方式
resultMap id=”JoinResultMapper” type=”User” extends=”BaseResultMapper”>
动态的SQL语句
-
在映射文件中获取数据的方式
- #()
- #()默认是预处理模式
- $()
- $()默认是直接拼接到SQL语句当中,并且需要提供KEY值,推荐在排序使用
-
if标签
- test属性 test=”类中属性或者Map中的KEY或者使用@Param指定KEY”
-
where标签
如果有内容,在内容的最前面加入where关键字,并且去掉内容最前面的and或者or
传递多个参数
/**
传递多个参数
1.当你的形参传递>1个的时候,parameterType不写,让其自动处理
2.#{值},默认为arg0,arg1…..或param1,param2,,,
若在dao注解了@xxx(相当于指明了key值),即也可以写xxx,默认的也可以写,相当于3个值
*/
User getUser(@Param(“account”) String account, @Param(“password”) String password);
接口代理模式和传统模式
接口代理模式
只需要写接口,在测试类中调用,接口编程: 什么是接口? 简单理解:接口就是定义规范
>
接口返回类型跟你设置的resultMap或者resultType对应上即可,但是会根据你返回的类型完成selectone或者selectList操作
>
接口里方法如何写:sql语句返回的结果集类型 sql语句的id(要传的值);
>
eg:List getSkillLike02(String name);
>
List为SQL语句返回的结果集类型,getSkillLike02为映射文件中SQL语句的id,String name是传给映射文件的值
>
映射文件命名空间为接口的全路径
>
可以根据接口的返回类型自动判断使用selectOne还是selectList
>
eg:返回的是一个对象的为one,返回的是list的就是List,如果是List,也是List
传统模式
需要写接口,接口实现类,测试类,
映射文件命名空间为持久化类的全路径
单元测试框架
概述
- 单元(方法)就是对类中方法的测试
- 命名规则
- 类名 UserDaoTest
- 方法 testLoadMethod
需要的jar包
- hamcrest-core-1.3.jar
- junit-4.12.jar
如何使用
@Before
@Before //再每个单元测试运行之前都要进行这个方法
public void init() {
this.arithmeticService = new ArithmeticServiceImpl(); //想用哪个功能就实例化哪个
}
@Test
@Test //测试这个方法
public void test01() {}
日志框架Log4J
概述
- 在MyBatis中显示出SQL语句,信息等,放在classpath路径下log4j.properties
需要的jar包
- log4j-1.2.17.jar
如何使用
Global logging configuration
log4j.rootLogger=ERROR, stdout
MyBatis logging configuration…
如果要显示SQL语句,那么这个位置需要配置为命名空间
log4j.logger.com.shxt.model.Skill=TRACE
Console output…
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%5p [%t] - %m%n
SpringMVC框架
概述
-
核心配置文件DispatcherServlet的规则
默认情况下:WEB-INF/[servlet-name]-servlet.xml
springmvc
org.springframework.web.servlet.DispatcherServlet
2
springmvc
需要的jar包
- spring-aop-4.3.6.RELEASE.jar
spring-beans-4.3.6.RELEASE.jar
spring-context-4.3.6.RELEASE.jar
spring-context-support-4.3.6.RELEASE.jar
spring-core-4.3.6.RELEASE.jar
spring-expression-4.3.6.RELEASE.jar
spring-web-4.3.6.RELEASE.jar
spring-webmvc-4.3.6.RELEASE.jar
commons-logging-1.2.jar
控制器专题
控制传递的参数
@RequestMapping(path = “/param02”,params = {“hs!=tomcat”,”method=add”})
-
形参
- 默认会对形参中的类进行自动的实例化操作
-
页面跳转方式
- 默认请求转发,能访问WEB-INF下
- 重定向,不能访问WEB-INF下
- 概要: 指明前缀,请求转发”forward:/hs011.jsp”,重定向redirect:/xxx
-
返回类型
ModelAndView
JSP的请求转发的视图解析器
静态资源(图片、js、css)排除方案,不经过DispatcherServlet
客户端传递数据转换成服务端对应的数据类型
@RequestParam注解
public ModelAndView test02(@RequestParam(value = “user_name”, required = false) String name,
@RequestParam(name = “user_id”, required = false, defaultValue = “1111”) Integer id) {
System.out.println(“姓名” + name);
System.out.println(“ID” + id);
return null;
-
}
- name=”” | value=”“对应传递数据的名称
- required=”true”默认值
- defaultValue=”设置默认值”
简写方式 推荐:传递的name和形参中的名称保持一致即可
-
数组
超链接获取数组
>
@GetMapping(“/client04”)
public ModelAndView test01(@RequestParam(name = “role_id”) Integer[] roles) {
System.out.println(Arrays.asList(roles));
return null;
}
复选框传递数组
篮球
足球
看书
简写方式
>
@GetMapping(“/client05”)
public ModelAndView test02(String[] hobby) {
if (hobby != null) {
System.out.println(Arrays.asList(hobby));
} else {
System.out.println(“您没有爱好!”);
}
>
return null;
}
文本框传递数据
简写方式
>
@GetMapping(“/client06”)
public ModelAndView test03(String[] hobby) {
System.out.println(Arrays.asList(hobby));
return null;
}
多选列表传递数组
音乐
看书
足球
简写方式
>
@GetMapping(“/client07”)
public ModelAndView test04(String[] hobby) {
if (hobby != null) {
System.out.println(Arrays.asList(hobby));
} else {
System.out.println(“您没有爱好!!”);
}
return null;
}
-
对象
简单对象,只是需要你传递的名称跟类中的属性名保持一致即可
@GetMapping(“/client08”)
public ModelAndView test01(User user, String user_name, String sex) {
System.out.println(user);
System.out.println(“—–依然可以使用简单方式—-“);
System.out.println(user_name);
System.out.println(sex);
return null;
}
多个对象如果属性不相同,那么SpringMvc框架会帮我们自动完成转换
@GetMapping(“/client09”)
public ModelAndView test02(User user, Role role) {
System.out.println(user);
System.out.println(“—–角色—-“);
System.out.println(role);
return null;
}
关联对象,一个对象里有另外一个对象
public class User {
>
private Role role;
-
后台处理
@GetMapping(“/client10”)
public ModelAndView test03(User user, Role role) {
//设置关联关系
user.setRole(role);
System.out.println(user);
return null;
}
前台处理
多个对象进行关联方式二:前台处理
姓名:
性别:
角色名称:<%–name=类中.属性–%>
提交数据
@GetMapping(“/client11”)
public ModelAndView test04(User user) {
System.out.println(user);
return null;
}
多个对象如果出现同属性问题,需要借助第三方类来区分数据的归属情况
不同对象同属性传递借助第三方类
用户
姓名:
性别:
角色信息:
学生
姓名:
性别:
提交数据
>
@GetMapping(“/client12”)
public ModelAndView test05(HsModel hsModel) {
System.out.println(hsModel.getStudent());
System.out.println(hsModel.getUser());
return null;
}
>
-
第三方类含这些类
public class HsModel {
>
private User user;
private Student student;
Map
姓名:>
性别:
提交数据
@GetMapping(“/client13”)
public ModelAndView test01(HsModel hsModel) {
System.out.println(hsModel.getQuery());
return null;
-
}
需要借助第三方类的支持
public class HsModel {
>
private Map
客户端传递数据中文乱码
-
get请求
tomcat7
-
全局设置
在tomcat里的sever.xml中修改
这一行加入URIEncoding=”UTF-8”
单项目设置
user_name = new String(user_name.getBytes(“ISO8859-1”),”UTF-8”);
tomcat8
默认为UTF-8,不需要修改
-
post请求
在web.xml中配置过滤器
characterEncodingFilter
org.springframework.web.filter.CharacterEncodingFilter
encoding
UTF-8
forceRequestEncoding
true
forceResponseEncoding
true
characterEncodingFilter
/*
服务端传递数据到客户端
-
返回类型ModelAndView传递数据
指明KEY
@GetMapping(“/server02”)
public ModelAndView test02() {
ModelAndView mav = new ModelAndView();
>
// mav.addObject() 没有指明KEY
//一步一步的追源码,发现一个ModelMap的类实例化对象.用它的addAttribute方法添加,ModelMap又是继承了HashMap
mav.addObject(“title”, “通过ModelAndView传递数据”);
mav.addObject(“hs”, “中国和尚”);
mav.addObject(“class”, “计算机计科”);
mav.addObject(“number”, 11);
mav.setViewName(“jsp/result02”); //请求转发,通过视图解析器
return mav;
}
没有指明KEY,默认传递数据的KEY的名称为类名的首字母小写
@GetMapping(“/server03”)
public ModelAndView test03() {
ModelAndView mav = new ModelAndView();
mav.addObject(“integer”, 100);
mav.addObject(200);
>
mav.addObject(“string”, “字符串”);
mav.addObject(“悟空”);
// 规则:客户端获取没有加key的数据,默认key正常是数据对应的类型的首字母小写 Integer—integer String—string
// 两个key一样的,只认最后一个
// double是关键字,不能{requestScope[“double”] }
>
double a = 123.123;
mav.addObject(a);
>
User user = new User();
user.setMydate(new Date());
mav.addObject(user);
>
mav.setViewName(“jsp/result03”); //请求转发,通过视图解析器
return mav;
}
-
返回类型String传递数据
Map
@GetMapping(“/server04”)
public String test01(Map
文件的上传和下载
上传
<%@ page contentType=”text/html;charset=UTF-8” language=”java” %>
Title
单文件上传
标题:
文件:
文件上传
$(function () {
>
//元素选择器
$(“button”).click(function () {
//1.获取上传文件的对象,是数组,获取的第一个
var myfile = $(“#myfile”).prop(“files”)[0];
//2.判断文件是否有
if (myfile) {
//3.获取文件名称
var fileName = myfile.name;
//4.获取文件的后缀名称
var ext = fileName.substring(fileName.lastIndexOf(“.”) + 1);
//5.设置允许上传的文件后缀名称
var allowFileTypes = [“jpg”, “png”, “gif”, “jpeg”, “dmp”, “rar”];
//6.设置一个标识,用来做判断
var flag = false;
//循环判断上传格式是否正确
for (var i = 0; i < allowFileTypes.length; i++) {
if (ext == allowFileTypes[i]) {
flag = true;
break;
}
}
if (!flag) {
alert(“您上传的文件格式不正确,允许的格式为:” + allowFileTypes.join(” | “));
return false;
}
//7.判断文件的大小
if (myfile.size > 20 * 1024 * 1024) {
alert(“您上传的文件过大,请重新选择”)
}
return false;
//8.表单提交
${“#uploadForm”}.submit();
}
else {
alert(“请选择您要上传的文件”);
return false;
}
})
})
-
要求
form表单传递数据
- 请求必须为POST请求
- 使用二进制流的方式传递数据 enctype=”multipart/form-data”
文件域
工具
Servlet3.0
Commons-FileUpload
@PostMapping(“/upload01”)
public ModelAndView test01(String title, MultipartFile myfile, HttpServletRequest request) throws IOException {
ModelAndView mav = new ModelAndView();
// System.out.println(title);
//1.获取上传文件的名称
String fileName = myfile.getOriginalFilename();
mav.addObject(“fileName”, fileName);
//2.判断文件名称是否有值,isEmpty是这个字符串的length=0为true
if (!fileName.isEmpty()) {
//3.获取服务器的绝对路径
String path = request.getServletContext().getRealPath(“/upload”);
//4.建立联系
File folder = new File(path);
//5.判断该文件是否存在,不存在则创建文件夹
if (!folder.exists()) {
folder.mkdirs(); //创建文件夹
}
//6,获取上传文件的后缀名称
String ext = FilenameUtils.getExtension(fileName);
//7.创建新的文件名称
//String newFileName = UUID.randomUUID().toString() + “.” + ext;
//或者用时间戳创建名称
String newFileName = new Date().getTime() + “_” + new Random().nextInt(100000) + “.” + ext;
mav.addObject(“newFileName”, newFileName);
// System.out.println(newFileName);
//8.文件上传,File.separator为斜线
myfile.transferTo(new File(path + File.separator + newFileName));
}
mav.addObject(“hs”, “和尚”);
mav.setViewName(“jsp/result”);
/*System.out.println(“测试是否可以获取正常的数据:”+title);
System.out.println(“=====”);
System.out.println(“文件的MIME类型 :”+myfile.getContentType());
System.out.println(“文件NAME属性对应的值 :”+myfile.getName());
System.out.println(“上传文件的名称 :”+myfile.getOriginalFilename());
System.out.println(“上传文件的大小 :”+myfile.getSize());*/
return mav;
-
}
- commons-fileupload-1.3.1.jar
下载
@GetMapping(“/download”)
public ResponseEntity
异常处理
-
注解方式
- 局部处理@ExceptionHandler
- 全局处理@[email protected]
XML方式
jsp/error
jsp/error
jsp/error
jsp/error
拦截器
- 拦截器有且只能拦截Controller
Spring框架
概述
- Spring是IoC(DI)和AOP的容器框架
IoC #控制反转:白话:让别人为我们服务,帮我new对象
- 管理Bean的声明周期
- 范围Scope
- 默认情况下是单例模式single
- 多例模式prototype
- request
- session
- 实现方式有两种
- 注解方式
- @Component
- @Controller
- @Service
- @Repository
DI(注入方式) #白话:注入就是实例化,赋值
-
Setter方式–推荐
- XML方式
- com.hs.model.User类中的属性必须要提供set方法
- 形式如下
- ref引用对象
- 标准写法
- 缩写
- p方式(p方式的引用)
- 各个类型如何注入
- 普通属性的值 value
- 集合 list/set/array
- map/props
- 自定义类型
- 内部使用
- 外部实例化,内部使用ref进行引用
- 外部实例化,使用p:xxx-ref引用
- 接口注入实现类(接口回调)
- 外部定义接口实现类实例化,内部使用进行引用
- 外部定义接口实现类实例化,使用p:xxx-ref引用
- util:list | set | map | properties—-不常用
- 内部定义,内部引用
- 外部定义,p引用
- 注解方式
- @Autowired–推荐
- @Qualifier(“bookDaoImpl”),指明具体的id
- @Resource
- 概要: 区别
- @Autowired先按类型再按照名称查找
- @Resource先按名称再按照类型查找
-
构造函数注入方式
- XML方式
- 标准写法
- 缩写
- 各个类型如何注入
- 普通属性的值 value
- 集合 list/set/array
- map/props
- 自定义类型
- 内部使用
- 外部实例化,内部使用ref进行引用
- 接口注入实现类(接口回调)
- 外部定义接口实现类实例化,内部使用进行引用
- 注解方式
- @Autowired–推荐
- @Resource
@Value注解注入值
@Value(“我是其他属性”)
private String anotherValue;
-
或者写在set方法上
- 注入普通字符串
- 注入操作系统属性
- 注入表达式运算结果
- 注入其他bean的属性。
- 注入文件内容。
- 注入网址信息。
- 注入属性文件。
AOP #白话:在不改变原来代码的基础上,增加新的功能,AOP的底层的实现就是使用的是Java的动态代理
-
概念
- Aspect Oriented Programming with Spring 面向切面(方面)编程
- 面向切面编程是面向对象编程的一个补充而已
- 白话:我的理解—->在不改变原来的代码的基础上增强(增加)新的功能
静态代理
动态代理
CGLIB动态代理
proxy-target-class=”true”
-
切面
- @Aspect
-
连接点
- 表达式 execution(* com.hs..service.Service.(**)
-
切点
- @PointCut
JdbcTemplate工具类
配置数据源
配置工具类
-
SQL语句
查询
返回Map数据
@Test
public void test01() {
/String sql = “select from oa_user where user_id = 3”;
Map
事务
-
事务
- 概念
- 一个工作单元由多个动作组成,只有动作全部正确的时候才能执行成功,如果有一个动作错了,其他的动作都是无效的(回滚)
- 关键属性(ACID)
- 原子性(atomicity):事务是一一个原子操作,由一系列动作组成,事务的原子性确保动作要么全部完成要么完全不起作用
- 一致性(consistency):一旦所有事务动作完成,事务就被提交,数据和资源就处于一种满足业务规则的一-致性状态中.
- 隔离性(isolation):可能有许多事务会同时处理相同的数据,因此每个事物都应该与其他事务隔离开来,防止数据损坏
- 持久性(durability): 一旦事务完成,无论发生什么系统错误,它的结果都不应该受到影响,通常情况下,事务的结果被写到持久化存储器中
-
事务管理
- 事务管理就是管理事务,用来确保数据的完整性和一致性.
-
事务管理器
- 就是对事务管理的实现,数据的完整性和一致性(数据库—>数据源)
-
传播性
- 当你事务方法被另一个事务方法调用的时候,需要检查其事务的传播性
-
调用过程
XML版—推荐 #XML版本完成事务,需要跟AOP配合使用
配置事务管理器
告知哪些方法是需要被事务管理器进行管理的