笔记3
# ssm 自己的理解
> spring springmvc mybatis
# maven
作用: 项目管理工具(管理jar包)
仓库: 中央/镜像/本地
> 创建springboot工程 使用的2.3.12版本
> SpringMVC 前后端整合起来
# SpringBoot
> 基于maven机制 是mavne的扩展
> springboot项目存在父工程 springboot spirng+spirngmvc都在工程中
创建model 添加web依赖spring-boot-starter-web
pom.xml 依赖文件
Application.java 启动类 @SpringBootApplication
> 添加了web依赖测试
写类 方法
类上添加@RestController @RequestMapping("/boot/")
方法添加@GetMapping
SpringMVC中 ------方法添加返回值-会打印在页面中------
> 使用SpringMVC 控制层方法的返回值给页面传值
# SpringMVC
> web依赖 webmvc依赖
[作用:-]
> 接收浏览器发来的请求 服务器获取请求
> 给浏览器响应数据 服务器返回给客户端数据
[Springmvc]
松耦合 : 改一个地方的代码另一个地方不会有影响
当前端请求 先工作的是SpringMVC 梳理请求
>>>>>>>>>>>>>>>> __SpringMVC内部工作流程 有哪些组件__ >>>>>>>>>>>>>>>>>>>>>>>>>>
>1. servlet机制
Servlet(Server Applet)是Java Servlet的简称,称为小服务程序或服务连接器,用Java编写的服务器端程序,具有独立于平台和协议的特性,主要功能在于交互式地浏览和生成数据,生成动态Web内容。
概念: java实现前后端数据交互的一种机制
核心对象: Request对象(存储提交的数据) 浏览器 -> java后端
Response对象(服务器端返回数据信息) java后端 -> 浏览器
>>>>> 后端路由 / 后端返回页面 页面在class中写
@Controller
配置: mvc-
>2. springmvc 执行流程/调用流程图
> 组件
1. 前端控制器 DispatcherServlet 实现请求的流转
2. 处理器映射器 实现了请求路径与方法之间的映射.
3. 处理器适配器 处理器的管理器 内部有N个处理器. 针对不同的用户请求 调用不同的处理器完成任务
4. 视图解析器 直线页面路径的拼接
> 父子容器
父子容器概念:
1.Spring容器(内存中的一大块空间)由于IOC/DI的机制,可以作为第三方的管理者 所以作为父级.
2.SpringMVC容器,其中只负责Controller层的相关的对象的管理.
说明: 当SpringMVC容器启动时,提前将SpringMVC中的所有请求路径方法方法完成映射.
> 流程
1. 用户发起请求时,第一步经过前端控制器,
2. 但是前端控制器 只负责请求的转发和响应.不做任何业务处理.将请求转发给处理器映射器.
3. 处理器映射器接收到前端控制器的请求之后,查询自己维护的服务列表信息.
如果服务列表中没有这个URL的key. 该程序不能处理用户的请求,则返回特定数据,前端控制器接收之后响应用户404.
如果服务列表中有该URL key 则说明请求可以正常执行. 将该方法的对象返回给前端控制器.
4. 前端控制器将返回的方法进行接收,但是由于前端控制器只负责转发和响应,不能直接执行该方法.所以交给处理器适配器执行.
5. 处理器适配器根据方法的类型(xml配置文件/注解/其他方法),处理器适配器在自己的处理器库中挑选一个最为合适的处理器去执行该方法. 当处理器执行该方法时标识业务开始. 将最终的处理的结果通过ModelAndView对象进行包裹,返回给前端控制器.
ModelAndView: Model: 代表服务器返回的业务数据 View: 服务器端返回的页面的名称
6. 视图解析器 将View中的数据进行解析 拼接一个完整的页面路径 前缀/hello后缀
7. 视图渲染: 将数据与页面进行绑定. 这样用户就可以在页面中看到具体的数据.
8. 由于现在流行前后端分离. 所以SpringMVC省略了视图解析和视图渲染.只有前5步. 核心注解: @ResponseBody 省略6-7步
> @RequestMapping
获取/对url进行处理
> @RestController
接收请求
如果执行的方法有返回值 springmvc会自动把返回结果java对象解析为json字符串
> 解析参数的值
http://localhost:8614/car/get2?id=10&name=BMW&price=9.9
springmvc的注解 获取请求
注解所在方法 中添加参数 即可在方法中使用请求中的参数
--form表单提交到url后端通过springmvc注解获取 参数
--包装类型 和 基本类型
-基本类型 访问url中必须有参数
-包装类型 访问url中可以没有参数
@GetMapping("get2")
public Car get2(Car car){
return car;
}
前端提交表单, 给指定url,后端就能获取url中的参数
> url参数
get 提交方式
http://localhost:8614/car/get2?id=10&name=BMW&price=9.9
获取参数
直接在方法参数中定义 public Car get2(Car car)
RestFul 提交方式
url方式 : http://localhost:8614/car/get2/10/BMW/9.9
获取参数
使用注解 @PathVariable
@GetMapping("get31/{id}/{name}/{price}")
public String get31(@PathVariable Integer id, @PathVariable String name,@PathVariable Double price){
return "[{"+"\""+"id"+"\""+":"+"\""+id+"\""+", "+"\""+"name"+"\""+":"+name+","+"\""+"price"+"\""+":"+"\""+price+"\""+"}]";
}
# tomcat
[pojo日期格式]
> @DateTimeFormat(pattern = "yyyy-MM-dd")
1.前端页面 form提交的数据为String类型的
2.日期需要date类型
3.使用@DateTimeFormat 描述date类型的属性
@JsonFormat(pattern = "yyyy-MM-dd",timezone = "GMT+8")
// 出参格式化
// 从服务端传给客户端展示,按指定格式展示, 时区
@DateTimeFormat(pattern = "yyyy-mm-dd")
// 入参格式化
// 从request中获取到的日期格式是String类型, 此注解会把String类型转换为java.util.Date类型
@JsonFormat 转 json 时按指定格式转换 --日期格式向前端展示时间时按指定格式
# ---
> 使用ajax发起请求
form表单 点击提交按钮
1. 改成 普通按钮
2. 添加点击事件submit
3. form添加id
4. 添加jquery包 --ajax是jquery的功能 <script src="https://cdn.staticfile.org/jquery/2.0.0/jquery.min.js"></script>
5. 写点击事件的功能
form method="post" id="form"
input type="button" onclick="submit()" value="保存"
function sub(){
$.ajax({
url:"http://localhost:8614/student/add",
data:$("#form").serialize(),
success:function (data){
console.log(data);
}
});
}
> 跨域问题
当前程序 访问 其他程序 具有不同的ip 或 不同端口
权限
StudentController.java
--类加注解 @CrossOrigin(springmvc提供) 放行所有请求
# 点击注册之后 提交表单 跳转到登录页面
# 点击登录之后 提交表单 跳转到用户界面
> ---使用ajax 属性 success:function(data){} 跳转页面
> 使用json接收数据
# ---
# spring
> 1. 概念
作用: 管理Bean --把所有的类看做一个bean
1. 创建对象
2. 设置对象关联关系
> 2 . 核心概念
>> BeanFactory (就是类)
>> ApplicationContext 外部应用调用 bean容器
>> Ioc 控制反转 框架实现了反转 无需new对象(不用创建对象,单例模式),使用容器获取User user= context.getBean(user)
>> DI 依赖注入 对象直接依赖
>> AOP 面向切面编程
>>> bean context ioc core
-- Bean就是object , context 数据的环境 并发现bean之间的关系(注解) , 关系集合叫做ico容器 , core 发现 建立 维护 bean之间关系所需的工具
> 3. IoC
Inversion of control 对象的创建和生命周期交给spring管理
>> 如何完成
1. .xml 配置文件
applicationContext.xml ( spring config文件 )
bean标签 指定类的信息
属性:class 指定类的全路径(包名.类名) id bean的唯一标识
由一个初始化的xml配置文件来创建,也就是由spring容器来创建。遍历xml配置文件,读取到<bean>,获取到class属性的类的全路径,利用反射创建这个类。
2. 注解
@Component 配置<context:component-scan base-package="com.cy"/>
> 4. DI
在创建对象的过程中spring可以依据对象的关系, 自动把其他对象注入
@Autowired
> 5. 注解
>>> 接口是一种规范
> 6. 分层结构
pojo 对象类 --业务层 controller层都会用到
业务层
web层
-- spring进行扫描 把具有注解的类进行ioc管理
-- @SpringBootApplication启动类所在包 以及子包
> 7. AOP 面向切面编程
>> . 通知 就是在某个位置插入的方法
>> . 定义 切面-Aspect
.. 通过 通知-Advice 做具体的事情 方法
... .通知类型 before after around afterReturning afterThrowing
.. 通过 切点-PointCut 配置切入点表达式 指定在哪个类
. 注解
.. @Aspect 描述类 定义切面
@Component
public class TimeAspect{}
.. @Pointcut("execution( * cn.tedu.mvc..*.*(..))")
// 在这里只指定了某个包 会不会执行所有类的所有方法 不会 原因: 执行的是触发的方法
public void pointcut(){}
.. @Around("pointcut()") 具体执行功能
public Object doAround(ProceedingJoinPoint joinPoint){}
>> . aop 结合 注解
# mybatis
> 1. 概念 : mybatis 支持普通sql查询 存储过程 高级映射 持久层框架 --简化/封装jdbc --更好的完成ORM(对象关系映射 -表和类)
1.jdbc 2.ORM
> 2. 使用过程
依赖 : mybatis-spring-boot-starter
配置数据库 : 两种方式
1.xml 2.spring配置
: 配置内容
1.url 2.username 3.password 4.mybatis.mapper-location=classpath:/mapper/*.xml */
映射文件 :
头文件
mapper属性 : namespace-映射文件的唯一标识,映射的文件操作文件 ,
select属性 : id-方法名,每条SQL的唯一标识 parameterType/resultType-完成ORM,把表里每个字段的值 自动映射给 类里的属性
> 3. resultType / resultMap
resultType 可以在 类的属性名和表里的字段名一致时 自动完成ORM
当不一样时 使用resultMap
<resultMap id="user" type="com.cy.sys.pojo.Userinfo">
主键
<id property="id" column="id">
普通
<result property="username" column="user_name">
</resultMap>
<select id="select" resultMap="personORM">select * from car</select>
> 4. sql标签 动态sql
sql/include ---sql提取共性标签 片段 include哪里用向哪里插入 引用片段
<sql id="columns">id,name,color,price</sql>
select * from car --> select <include refid="columns"/> from car
where ---过滤 --自动删除条件前面的and或者or
<where></where>
if ---判断
<if test="name!=null and name!=''"> name = #{name} </if>
set ---update中设置新的值 --如果最后一个set条件多余逗号,会自动删除
<set></set>
foreach ---循环
dao接口方法 : List<Car> selectByIds(@Param("ids") Integer... id);
select * from car where id in (1,2,3,4,?,?,..);
id in
<foreach collection="ids" open="(" close=")" separator="," item="item">#{item}</foreach>
> 5. 知识点
.0. -------
mybatis的一级缓存 : mybatis 重复执行相同的sql语句 , 只会与数据库查询一次 , 放在缓存中 . 前提: 同一个会话session
@BeforeEach 在测试类中 在测试方法之前执行
.1. # 和 $
#: 使用#{parameterName}引用参数的时候,Mybatis会把这个参数认为是一个字符串,
传入参数是"Smith",那么在SQL(Select * from emp where name = #{employeeName})使用的时候就会转换为Select * from emp where name = 'Smith'。
$: 不做字符串拼接,
SQL(Select * from emp where name = ${employeeName})使用的时候就会转换为Select * from emp where name = Smith。此时,如果字段是varchar类型直接抛出SQL异常。
.2. 特殊字符
<![CDATA[ ?? ]]> 在xml文件中得到表达式,不被xml文件解析
在 XML 元素中,"<" 和 "&" 是非法的。
"<" 会产生错误,因为解析器会把该字符解释为新元素的开始。
"&" 也会产生错误,因为解析器会把该字符解释为字符实体的开始。
<![CDATA[<=]]> 在xml文件中表示 小于等于
.3. 别名alias
写在MybatisConfig.xml中 在映射文件使用指定对象时可以直接写-别名-使用
<typeAliases>
<typeAlias type="cn.mybatis.pojo.User" alias="User"/>
</typeAliases>
JDBC和MyBatis的区别?
XML和接口方式的区别?
接口方式怎么找到xml执行的?
> 6. 实现
----------------
使用mybatis配置文件 实现
1. 配置文件 configuration --配置数据库 --配置映射文件路径
2. 映射文件 1. mapper --namespace 2. sql语句 例如select标签 --id,paramterType,resultType
3. pojo对象
4. 测试
读取配置文件 , 创建SqlSessionFactory , 初始化SqlSession , 从SqlSession中获取指定sql语句执行sql
InputStream resourceAsStream = Resources.getResourceAsStream("MybatisConfig.xml");
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream);
SqlSession sqlSession = sqlSessionFactory.openSession();
List<User> list = sqlSession.selectList("user.selectUsers");
----------------
----------------
使用dao接口 实现
1. 配置文件 configuration --配置数据库 --配置映射文件路径
2. 映射文件 1. mapper --namespace 接口路径+名 2. sql语句 例如select标签 --id,paramterType,resultType
3. pojo对象
4. 接口文件
5. 测试
读取配置文件 , 创建SqlSessionFactory , 初始化SqlSession , 从sqlSession中获取接口
InputStream resourceAsStream = Resources.getResourceAsStream("MybatisConfig.xml");
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream);
SqlSession sqlSession = sqlSessionFactory.openSession();
DeptDao deptDao = sqlSession.getMapper(DeptDao.class);
----------------
----------------
文件 :
mybatis配置文件 MybatisConfig.xml
pojo对象 User.java 类
dao接口 UserDao.java 接口
映射文件 mapper/UserMapper.xml
测试文件 UserDaoTests.java Test
----------------
# java
oracle公司的
# Spring
框架 javaBean提供具有控制反转特性的容器 可以应用在服务器端 web应用
# SpringMVC
mvc框架 Spring中为构建web应用提供功能全面的框架 通过url请求并返回的核心组件
# SpringBoot
基于Spring4.0设计
简化Spring的配置,简化了Spring应用的整个搭建和开发过程
解决依赖包版本冲突,引用的不稳定性
# mybatis
apache公司的
持久层框架 支持定制化SQL,存储过程,高级映射
.. 几乎避免了所用jdbc代码 手动设置参数 获取结果集
.. 使用简单xml 注解 来配置和映射原生信息 将java的pojo映射成数据库中的记录 pojo--plain oridinary java object 普通java对象
# servlet
小服务程序 服务连接器
主要功能: 交互式的浏览和生成数据 生成动态web内容
大多数情况 servlet用于扩展基于http协议的web服务器
# tomcat
apache公司
tomcat支持servlet和jsp规范
web应用服务器
# ??? servlet 和 tomcat 在哪里能体现到 使用 ???
spring 中 容器Bean 机制IoC AOP
IoC 实现方式 DI 依赖查找
spring容器通过 DI实现IoC
DI 注入方式 Setter注入 构造器注入
# Spring
.. 应用开发框架
.. 使用本身的功能,也可以结合第三方框架
.. 本质 : 管理软件中的对象,创建对象和维护对象之间的关系
**- IoC AOP -**
.. 将组件的耦合度降到最低,解耦
> 主要功能
DAO AOP Web ORM JEE Core
## Bean
在spring中, 任何java类和javaBean都被当成Bean处理, 这些Bean通过容器管理和应用
> 容器 BeanFactory ApplicationContext
## IoC
.. Inversion of Control 控制反转
.. 指的是对象的获取发生反转,由new方式创建 变为由第三方框架创建,注入
. 第三方框架一般是通过配置方式指定注入哪一个具体实现, 从而降低了对象之间的耦合度
> 实现方法
**- 依赖注入DI 依赖查找 -**
.. spring容器采用DI方式实现IoC IoC是Spring框架基础和核心
### DI
> 基本原理 :
将一起工作具有关系的对象, 通过构造方法参数或方法参数传入建立关联,
因此容器的工作就是创建bean时注入哪些依赖关系
> 注入方式 :
**- Setter注入 构造器注入 -**
#### Setter注入
无参构造器 或 无参static工厂方法实例化bean后, 调用该bean的setter方法 实现setter方式注入
xml中配置 注入参数
#### 构造器注入
调用带参数的构造器来实现的
## 自动装配
Autowire
Spring IoC容器可以自动装配相互协作bean之间的关联关系, autowrie对单个bean进行设置
减少xml的注入配置
自动装配规则 :
no byName byType constructor autodetect
## 组件扫描
指定一个包路径, Spring会自动扫描该包机器子包所有组件类, 当发现组件类定义前有特定的注解标记时, 就将该组件纳入到Spring容器
指定扫描类路径xml文件中 : <mapper namespace="com.cy.pj.notice.dao.SysNoticeDao"></mapper>
注解标记 : @Component 通用注解 @Name 通用注解 @Repository 持久层组件注解 @Service 业务层组件注解 @Controller 控制层组件注解
@Scope("protetype") Spring管理组件的范围
指定依赖注入 : @Resource @Autowired/@Qualifier @Inject/Named
@Resource 字段定义或setter方法 首先按名称匹配注入,然后类型匹配注入
@Autowired字段定义或setter方法 按类型匹配注入
? 遇到多个匹配Bean时注入会发生错误, @Autowired @Qualifier("myUserDao") private UserDao userDao; @Autowired 和 @Qualifier 配额使用
@Autowired public void setUserDao(@Qualifier("myUserDao") userDao dao){this.userDao=dao;}
@Inject/@Named 和 @Autowired/@Qualifier 用法相同
@Value 注解可以注入Spring表达式值,使用方法
application.properties bootstrap.yml 从配置文件中获取 配置文件中的信息
@Value("${server.port}")
# Spring Web MVC
## MVC
.. M Model 模型 业务逻辑 包含: 业务数据Dao 业务处理逻辑Service
.. V View 视图 显示界面,用户交互 属于视图的组件不包含业务逻辑和控制逻辑的 JSP
.. C Controller 控制器 是模型层和视图层之间的桥梁 用于控制流程
## Spring web mvc
是Spring框架非常重要的功能模块,
实现了mvc结构,便于简单,快速开发mvc结构的web程序
Spring web mvc提供的api封装了web开发中常用的功能,简化了web过程
## 核心组件
> DispatcherServlet 控制器,请求入口
> HandlerMapping 控制器,请求派发
> Controller 控制器,请求处理流程
> ModelAndView 模型,封装业务处理结果和视图
> ViewResolver 视图,视图显示处理器
过程:
request (/car/get) 必须进入核心分发器 DispatcherServlet (做校验 安全)
URL 进入 处理器映射HandlerMapping (找到ControllerClassName)
通过controllerClassName 进入处理器适配器HandlerAdapator(找到对应的controller内容)
通过Controller控制器 传递给 Service业务层 进行业务处理
通过Repository持久层在Database数据库中找到响应的数据
返回给Repository 给Service 处理业务
返回给 Controller 形成 ModelAndView 传递给 HandlerAdapator 形成 ModelAndView
传递给 ViewResolver 形成 Model 传递给 VIew(h5+css+Vue) 返回json字符串
好处:
MVC封装 代码量
单一职责 , 分层 职责明晰(每个部分有每个部分的作用 清楚各部分内容) (controller 业务逻辑 数据交互) 为大项目做,方便团队开发(前端,后端,数据库DBA)
组件:
1)DispatcherServlet,本质封装Servlet,核心分发器,请求转发
2)HandlerMapping, 处理器映射,解析url,/car/get,包括参数封装 name,age,hobby,Student
3)HandlerAdapator,处理器适配器,负责找到对应Controller,CarController,底层解析 @RequestMapping("/car/get"),找到这个所对应方法,反射
4)执行完成Controller,把数据封装Model对象中
5)ViewResolver,视图解析器,把model传递页面jsp,把model转成json字符串,返回页面
### 使用注解配置
@RequestMapping("/notice/") 请求url
@Controller 声明controller组件
@Requestparam("pwd") 接收请求参数
@ModelAttribute("user") 向页面传值
### 重定向
redirect
### 拦截器
必须实现HandlerInterceptor接口
### 异常
Spring MVC提供的简单异常处理器 SimpleMappingExceptionResolver
实现HandlerExceptionResolver接口 自定义异常
使用@ExceptionHandler注解实现异常处理
### Spring mvc 文件上传简介
笔记1
# 2021-02-20 day01--------------------------------------
### 知识回顾
#### vue+element-ui前端界面
element-ui 很多大公司采用,写法,语法 Vue 数据驱动,组件化Item.vue
1)数据驱动,体系开发者关心不在是代码api,只关心数据(业务)
2)组件化,复用,一旦创建好一个组件,这个组件就可以给其他人共享
#### 自己定义一个组件 Item.vue
1).vue文件,它有3部分组成
a. template 模板,html+vue片段(SPA单页面开发,它只是这个页面一部分)
b. script 脚本,形式 export default{},本质js脚本,数据区,方法区
c. style 样式 只对自己组件有效!避免不同的组件冲突。
2)注册,Vue项目(工程),所有组件都是App.vue根组件的子组件。
import导入,注意路径,相对路径 ./当前目录、../上级目录
3)使用 <Item></Item>标签
现今开发拿来主义,站在巨人肩膀上开发,好处开发效率高
组件:element-ui 完美,它形成一套完整的ui界面,比html原生美观很多
#### 列表
<table><tr><td>
要写两行,表格头,表格行内容(单元格) 内容是死的
<el-table><el-table-column>
只写一行 label表格头 prop单元格
表格内容是活的, 数据源(js对象,json,数据库结果集)
js对象 :data="list" data中的list : 是指list为变量不是字符串
解析list对象中的内容,vue+element-ui底层实现 对应table中内容
json JSON.parse(jsonstr) js对象
把data中的list内容换成json请求 最终都是就是对象 list
ajax请求后台java(springmvc)把后台从数据库返回结果集封装到java对象中
把java对象转换json字符串(jackson工具包api),
返回给ajax ajax底层把json字符串转换js对象
scucess方法返回js对象
拿到js对象 ,对象数组 foreach( o in array) v-for( o,i in list)
>> 添加
toadd事件, 清空form this.m数据 打开对话框 设置新增flag
>> 修改
获取同一行 底层可以获取相邻元素,父元素tr
所在td 获取到tr 从而获取本tr中的所有td 拼成row对象{}
同一对象的引用 使用JSON.parse(JSON.stringify(row))获得不同对象,相同内容
>> 保存 确认按钮
添加 和 修改 中包含很多相同功能 使用同一个方法复用
复用后 有冲突 使用flag isUpdata 判断是否新增 修改
>> this.list.splice(索引位置,删除条数,新增js对象)
添加 0,0,m list.length-1
修改 index,1,m
删除 index,1
>> 获取索引值
slot-scope = "s" 插槽
v-for="row,index in list"
################# 后端
>>>>>maven+springboot+tomcat+ssm
Maven SpringBoot Tomcat SpringMVC Spring Mybaits
HTML Ajax Web Service MySQL
控制层 解析请求(ajax 浏览器) Controller SpringMVC
业务层 处理解析后的请求 业务逻辑 Service Spring
持久层 从数据库拿取业务需要的 Mapper Mybaits
h5 bootstrap element-ui vue
tomcat nodejs
ajax java sql json
### Maven
项目管理工具:
1.管理jar包
复制jar包 java工程 lib目录jar包复制进去 build path引用
Maven 管理jar 中央仓库,镜像仓库,本地仓库
Maven解决依赖版本冲突问题(半,你去解决部分问题,阿里dubbo,自己处理)、
SpringBoot在Maven基础上(全面解决版本冲突,99%由spring组织解决)
习惯:ssm xml方式,注解方式,springboot,tomcat
2.依赖 坐标
3.命令 mvn各阶段操作
#### 管理jar包
仓库 依赖 坐标 命令
maven.jar 安装配置 setting.xml 在eclipse中配置
http://maven.apache.org/download.html
D:\Git\env\apache-maven-3.6.3
******....默认本地仓库 Default: ${user.home}/.m2/repository
在setting.xml 中修改掉
<localRepository>D:\Git\env\mvnrepo</localRepository>
******...镜像仓库 默认远程 中央仓库
<mirror>
<id>alimaven</id>
<name>aliyun maven</name>
<url>http://maven.aliyun.com/nexus/content/groups/public/</url>
<mirrorOf>central</mirrorOf>
</mirror>
阿里云的镜像仓库可能有问题 需要切换到中央仓库下载个别jar包
eclipse
超级文本 配置
#### 使用 创建
maven project 工程 pom.xml 配置文件 <标签>内容</标签>
添加依赖
选择maven project create a simple project
>> 坐标 小写
group id 组id 域名倒写 cn.tedu
artifact id 工程名称 jk2012(项目名称)
version 版本号(默认值)
packaging jar
scope compile编译 test测试
>> jdbc2012 文件目录
约定大于配置 目录进行分类 (减少开发配置量)
pom.xml 核心配置文件
main 业务代码
test 测试代码
java 源代码文件 *.java
resources 资源 图片 css js 配置文件
target 临时目录 *.class jar(拷贝) 每次编译自动产生
maven project 使用坐标管理
>> 测试maven项目搭建成功
jdbc TestTT.java
依赖 需要用的jar包 中 用到第三方文件 maven自动加载
<!-- 通过依赖方式 增加jar包
Dependencies -> add
通过坐标输入需要的坐标
<dependencies>
<dependency>
</dependency>
</dependencies>
-->
>>>>>>>>>>>>>>>
1)加入jdbc的驱动包
2)把数据库测试java文件,复制过来,测试是否成功
写坐标是一个jar,mysql.jar为什么会出现两个呢?
这就是maven带来好处,传统工程要一个一个加
maven自动去找它所依赖jar(pom.xml),它会自动下载
使用springboot创建项目过程:
怎么导入依赖?
http://start.spring.io
使用依赖后,maven自动给我们下载jar,jar怎么来的?
1)它是你配置的maven环境,它默认到中央仓库(镜像仓库:阿里云)下载
2)下载后保存在哪了?
下载后就放在本地仓库目录中
下载非常多的jar包?怎么区分它们,万一重名怎么呢?
坐标就是区分它们,每级坐标它就是一个目录,最终jar就放在这个多级目录中
cn.tedu 两级目录
Maven发明仓库、依赖、坐标,目的就是来管理jar,自动管理!!!
SpringBoot它利用官网:start.spring.io,输入关键字,加入依赖,它会自动最高版本
一旦使用SpringBoot技术,被牵着鼻子走,2.4.3,它会把所有它做依赖的都是最新
副作用:版本不兼容,需要小的范围修改下个别代码
pom.xml是在保存时,进行自动下载,我配置Maven工作,它就检查语法,没错,就下载所有依赖
更新,提升jdk 1.8
一旦jar包在仓库中,无需再次下载!!
>>>>>>>>>>>>>
>>通过网站添加依赖 https://start.spring.io/
添加元数据metadata add mysql 在线预览
>>jdbc2012 项目 报红叉
右键项目名 maven updata project
Problems中
>>>>坐标
D:\Git\env\mvnrepo\mysql\mysql-connector-java\8.0.21
本地仓库目录
maven 仓库 坐标 依赖 管理jar包 形成本地仓库 自动管理
SpringBoot https://start.spring.io/ 自动最高版本
>>>>>>>>>>> 创建SpringBoot项目
1)创建maven工程
2)官网产生pom.xml覆盖本地pom.xml,增加web依赖(springmvc)
3)创建HelloController.java,创建hello方法,返回字符串,两个注解修饰
4)创建运行类:RunApp.java,两句话,一句注解,一句run方法(固定)
类放在src/main/java中
改端口
8090 缓存 project -. clean 清除缓存
我们创建的springboot项目都是springboot子项目,
为什么需要parent父工程,它就定义好了要或者这些框架的jar包和版本
oracle 10g它会自动启动网页服务,8080端口,端口冲突
换端口
在资源文件目录下,添加:application.yml 纯文本,要求很死
server:
port: 8090
#######总结: 后台java:构建项目 maven,springboot
#### maven替代传统项目方式:
传统项目需要自己拷贝jar包,需要自己去管理jar冲突,复制项目带着jar,项目就很大占用空间。
maven就手工维护jar,变成自动找jar,自动下载,项目中依赖这个jar,但这个文件并不在项目中
maven解决jar冲突,变成它来自己管理,springboot,把这些冲突,它的团队都解决,parent父工程
maven是pom.xml,我把这个文件给你,保存pom.xml它会再从外网下载
#### maven要实现上面功能,新的概念
仓库:远程仓库,镜像仓库,本地仓库
保存pom.xml,maven底层会检查你依赖jar是否存在,如果有就不下载,如果没有就下载
先本地仓库,没有,去镜像仓库,去远程仓库,一旦找到,给镜像仓房复制,然后返回,
本地仓库在复制一份,返回用户
maven发明这套体系值得学习,仓库空,从每一次调用慢慢充满了
依赖:
声明jar,早期你调用的所有jar都需要声明
会通过jar去找它内部要调用jar(依赖)自动把这个依赖的jar也下载
同时,去掉版 本冲突
坐标:
jar很多,怎么区分这些jar,假如同名
坐标:groupId 组ID(域名倒写)、artifactId(项目名称)、version(最高)、scope(编译、测试、运行)默认 形成目录:本地仓库路径/cn/tedu/hello/1.0/星.jar。解决同名问题
命令:mvn一套命令,a,b,c,顺序,mvn c,它会自动执行前面的命令
mvn compile
mvn test
mvn install
#### springboot 替代maven来项目管理
最早目的:引入微服务 springcloud
springboot采用maven机制,完全兼容,是maven扩展!
和maven不同在哪里呢?
springboot自动化依赖,父工程,所以项目都是springboot子项目,继承它整理pom.xml
把spring框架直接继承,springmvc+spring都默认在这个工程里,
解决jar冲突,它的工程师帮我们做了整合,开发者就非常方便,主流
#### springboot 工程
1)直接创建springboot工程,idea和sts(spring eclipse),产生一堆垃圾文件
2)创建maven工程,官网产生pom.xml,覆盖
springmvc 框架,死规矩,自动化
1)HelloController.java
@RestController
@RequestMapping 映射 hello
2)启动main函数
两句话
@SpringBootApplication
SpringApplication.run(RunApp.class, args);
#### 下次课
maven环境
eclipse升级
oracle 升级到新自己配置端口:application.yml 约定,底层springboot会自动找这个文件名,进行加载
>>>>>>>>>
->>下载maven文件
配置conf/setting.xml
镜像仓库
本地仓库位置
->>eclipse 配置 maven
window -. Preferences -. Maven
Download Artifact Sources
-. installations Add apach-maven-
-. User Settings Browse conf/setting.xml
->>创建maven project
Create a simple project
Artifact
->>pom.xml 添加包 依赖
->src/mian/java hello
HelloController.java
@RestController
@RequestMapping({"/","/hello"})
public String hello() {//添加方法返回字符串
return "你好,莹莹 我叫庆庆";
}
->src/mian/java hello
RunApp.java
@SpringBootApplication
SpringApplication.run(RunApp.class, args);
->src/mian/resources
application.yml
server:
(两个空格)port:(一个空格)8090
>>>>>>
仓库 resources -阿里仓库 -setting
依赖 dependency -start.spring.io -pom.xml
坐标 coordinate -分组 项目 版本 -jar包文件路径
命令 mvn cmd
>>>>
项目
hello
jdbc2012
# 2021-02-22 ********************************************
maven
项目管理工具
自动管理jar包
仓库 依赖 坐标 命令
三大框架基础
##&&& 回顾
>>Maven 项目管理工具
1.jar包 修改pom.xml文件添加 依赖 需要的jar包(如果又调用第三方jar包 随之下载)
2.仓库
中央仓库(全球唯一,maven官网,Apache组织)
镜像仓库( 私服 git镜像 阿里码云10分钟更新一次 所以现在使用 *创建项目是开始是空的* 多级镜像)
本地仓库(本机中 在本地仓库总备份一份再给项目使用)
****************************
这种仓库的设计方式 Git
*****************************
3.坐标 多级目录, 防止同名jar包
groupID 组ID 域名倒写 cn.tedu
artifactID 构建ID 项目名
version 版本号
4.命令 a/s/s1 在执行s1时自动执行前面阶段命令
##&&SpringBoot
本质微服务
基于Maven
使用sb 管理 不用他的微服务
它们目标根本就不同
Maven项目构建工具,
SpringBoot本质把开发者引入到SpringCloud微服务路上
SpringBoot基于Maven,它也可以项目构建工具,SSM三大框架项目
>>>好处:*******---------
1.Maven自己维护pom.xml 添加依赖,排除依赖冲突
2.Spring团队事项父项目, 拥有主流的jar包
3.程序运行与maven无关 SpringBoot全面接管项目启动和加载
使用SpringBoot注解 底层做了很多事情
------------------------------------------
*****404 网页连接没有找到, springmvc的controller没有找到
--controller @RestController
--路径
--http://localhost:8080/car/get
--刷新项目 缓存 project/clean
*****400 类型转换错误
@RequestParam("id") 注解要求严格,页面必须有id参数提交,没有就报类型转换错误
日期:英文日期:2020/02/12,中文日期:2020-02-12
---------------------------------------------
####&##&tomcat web中间件***********
nodejs运行javascript容器
tomcat运行java容器(Servlet)
glassesfish、jboss、webspare、weblogic(牛,收费)
分布式,集群,很多机器(几十台,几百台,几千,几万) 微服务架构对资源(硬件、软件环境)减低
####%%##
浏览器 http://localhost:8090/hello 如何找到HelloController.hello方法 调用
????????????
浏览器:http://localhost:8090/hello,怎么找到HelloController.hello方法并且调用
HelloController hc = new HelloController(); //创建对象
hc.hello(); //调用它的hello方法!
在springmvc(spring)框架IoC控制反转,它来管理对象
1)Spring它底层去创建对象
2)它底层去调用方法
3)怎么把http://localhost:8090/hello和hello方法对应呢? 注解:@ReqestMapping("/hello"),规定全局唯一,它是在某个方法之上
------------
浏览器输入http://localhost:8090/hello
请求request(Servlet体系)
浏览器 得到 /hello
解析http://localhost:8090/hello localhost本地 8090端口找到tomcat
tomcat中间件( SpringMVC管理hellocontroller 找到注解@RequestMapping({/hello"})全局唯一 从而找到hellocontroller的hello方法 然后反射这个类(业务写在这个类中) 使用@RestController,返回的String字符串对象底层会使用jackson工具类转换java对象为json字符串,返回给浏览器,浏览器将字符串回显(展示)在页面上。)
---------------
####
模拟底层 注解 标识
######&&&&%%%%%
SpringMVC
>>>>三大框架各自负责
SpringMVC
负责 request ajax json
Spring 框架
业务逻辑
Mybatis
从数据库拿取业务中需要的数据
SpringMVC组件
DispatchServlet 核心分发器 封装 底层java web规范Servlet
HandlerMapping 处理器映射 url解析
HandlerAdapator 处理器适配器 找到controller
CarController 实现请求request映射 调用业务方法 响应reponse
返回ModelAndView被Model(Car),返回java对象
####&&&&&&&案例 1 .......................
http://localhost:8090/car/get
页面展示car的数据json字符串
保时捷718 Cayman T, 红色,641000元
car.java对象 利用@RestController java对象 -> json字符串
/// 请求连接 -> json字符串 -> ajax 请求
把json字符串转换js对象 js对象利用vue解析数,最终在页面展示
....步骤.......................................
项目 依赖web pom.xml
CarController.java
Car.java
.............................
pom.xml
src/main/java
1.cn.tedu.car.pojo package
Car.java 属性
2.cn.tedu.car.controller package
CarController.java
3.cn.tedu.car
RunApp.java
src/main/resources
application.yml
..............................
####&&&&&&&案例 2 .......................
表单中填写数据 提交到后台 SpringMVC
**springmvc 如何接收这些参数**
>表单本身可以提交信息到后台
<form action="url" method="get/post">
所有要提交的表单控件必须放在这个标签中,放在外面是不会提交
习惯在body标签下就写form
还要加一个提交按钮,submit,它点击完成会自动提交action指定的地址
action 提交到后台连接地址
method get/post 请求方式
>>>>提交的按钮 type="submit" 点击后自动提交action指定的地址
http://localhost:8020
/stu/add
?name= 没填 空字符串 null
&age= 没填 空字符串 null
&sex=on on/off 没选 没有提交
单选框男女 设置value 男1 女0
&hobby=on on/off
&edu=6
&button=%E4%BF%9D%E5%AD%98
>--------get请求方式的特点,
html规范自动把表单中的组件所有值拼接成一个字符串
key就是组件name(早期)或者id(新),value就是你填写的值
如果组件名称相同name,id,后台会以一个数组来接收
>----------get和post请求差异:
get是直接可以在浏览器url中看到参数,第一个参数?,后面的多个参数&
http://localhost:8090/stu/add
?name=chen&age=12&sex=0&hobby=%E4%B9%92%E4%B9%93%E7%90%83&hobby=%E7%88%AC%E5%B1%B1&edu=1&submit=%E4%BF%9D%E5%AD%98)
而post请求把这些参数都隐藏,你看不见!!!!会隐藏浏览器请求中,传递后台
http://localhost:8090/stu/add
###%%%%SpringMVC负责把请求中数据传递Controller
1.接收单个 接收id html隐藏框 input type="hidden" 不展示在页面,但会传给后台
2.接收多个 接收name,age,hobby
3.接收对象Student(Model)
4.url特殊RESTFul形式
....步骤.......................................
1)StudentController
a.接收单个参数 pid
b.接收多个参数 name, age, hobby
2)Studenet.java POJO(私有属性,利用对象接收参数)
3)RESTFul (接收少量参数)
****
###小结:
>>1)SpringMVC 帮我们减少工作量,它封装很多开发细节(高级程序员、架构师),坏处不透明
必须死记规则
>>2)注解总结
a. @Controller ,标识这个类controller类,springmvc会增强它
b. @RequestMapping,请求映射,把html里的表单组件text,number,radio,checkbox提交内容,
把http://localhost:8090/car/get,找到对应方法,来利用反射执行这个方法,把html参数值封装到方法参数中
c. @RequestParam("id") String pid,它把页面html中id的值,存放参数pid中,不同时才需要这个注解
d. @DateTimeFormat(pattern="yyyy-mm-dd") 把日期格式yyyy/mm/dd改成yyyy-mm-dd,转换,否则400错误
e. @SpringBootApplication 标识RunApp类是一个springboot项目,底层会做springboot引导
>>3)POJO类
a. 所有属性私有
b. 一堆get/set
c. 为了调整 toString()
>>4)前台和后台如何贯通!
前台:html页面+css+bootstrap,表单和后端来对应
后台:Java的controller来对应,pojo对象
>>5)请求类型:HTTP协议的规定
a. GET,url后面直接显示表单值和参数 name=wang&age=18...,不安全,url长度限制:255
b. POST,url后面干净,没东西,安全,习惯开发就使用POST请求,url长度:8k=8*1024
>>6)开发步骤:
a. 写pojo对象:Student.java,所有属性,产生get/set,产生toString
b. 写controller,StudentController,添加方法,添加RequestMapping,使用pojo对象
c. 复制RunApp.java
>>注解
@RestController 标识注解是controller rest标识返回结果 java对象->json字符串.展示
@RequestMapping("/stu/add") 映射连接
@SpringBootApplication 标识这是一个springboot程序
@DateTimeFormat(pattern="yyyy-mm-dd") 日期格式
@Override 重写
>>项目中的文件
pom.xml 依赖
Student.java 属性 写pojo对象 src/main/java /cn/tedu/stu/pojo
StudentController.java 使用pojo对象 src/main/java /cn/tedu/stu/controller
RunApp.java 标明是SpringBoot程序 src/main/java /cn/tedu/stu
application.yml 改写端口 src/main/resources
>>文件内容
pom.xml https://start.spring.io/ 查找,复制粘贴,依赖
Student.java 属性私有private Integer pid; set/get toString()
StudentController.java @RestController @RequestMapping("/stu/add") add方法
RunApp.java @SpringBootApplication main{SpringApplication.run(RunApp.class, args);}
application.yml server:(换行)(两个空格)port:(一个空格)8090
>>前端页面
<form action="http://localhost:8020/stu/add2" method="post" > 写在body下面
<input type="hidden" name="pid" id="pid" value="0614"/>
<div class="container">
................
<input type="submit" name="submit" value="保存'/>
</div>
<form/>
项目
working
car
stu hbuilder day03/1form2
# 2021-02-23 *********************************************
## 回顾
### SpringMVC
基于Spring
MVC框架(Model,View,Controller(进行Model和View连接))和前台页面交互框架j2ee
Struts1,Struts2(webwork 有很多bug),SpringMVC3.0注解
性能: ???
>>作用 后台如何接参
Servlet规范:处理http请求(web网站)
1)处理请求:request html表单提交数据,servlet规范把这些数据就存放在request对象
request.queryString = "?name=tony&age=18..." 接收到查询串,所有的参数的类型是字符串
String name = request.getParameter("name");
Integer age = (Integer)request.getParameter("age"); 日期
SpringMVC,它内部进行转换,如果转换成功,它会自动放入变量中
(String name, Integer age)
如果转换失败,放弃,变量初始值null
(Student student)
name,判断如果是复杂Object,利用反射获取私有属性,如果发现name属性,就设置值,
如果没有发现name属性,放弃
a. 单个参数,日期@DateTimeFormat(pattern="yyyy-mm-dd")
b. 多个参数
c. 对象
2)处理响应:response 返回,html片段,vue template 返回java对象给jsp页面(ModelAndView) 主流方式前台请求处理完成返回json(java对象序列化),和大前端Vue+NodeJS 方法返回java对象,@ResponseBody标识,底层把java对象进行序列化,json字符串
>>SpringMVC内部工作流程 有哪些组件
localhost: 最终翻译为 IP地址:127.0.0.1: IP地址定位一台机器 外网中都不同(通过外网访问别人的电脑的程序)
过程:
request (/car/get) 必须进入核心分发器 DispatcherServlet (做校验 安全)
URL 进入 处理器映射HandlerMapping (找到ControllerClassName)
通过controllerClassName 进入处理器适配器HandlerAdapator(找到对应的controller内容)
通过Controller控制器 传递给 Service业务层 进行业务处理
通过Repository持久层在Database数据库中找到响应的数据
返回给Repository 给Service 处理业务
返回给 Controller 形成 ModelAndView 传递给 HandlerAdapator 形成 ModelAndView
传递给 ViewResolver 形成 Model 传递给 VIew(h5+css+Vue) 返回json字符串
好处:
MVC封装 代码量
单一职责 , 分层 职责明晰(每个部分有每个部分的作用 清楚各部分内容) (controller 业务逻辑 数据交互 ) 为大项目做,方便团队开发(前端,后端,数据库DBA)
组件:
1)DispatcherServlet,本质封装Servlet,核心分发器,请求转发
2)HandlerMapping, 处理器映射,解析url,/car/get,包括参数封装 name,age,hobby,Student
3)HandlerAdapator,处理器适配器,负责找到对应Controller,CarController,底层解析 @RequestMapping("/car/get"),找到这个所对应方法,反射
4)执行完成Controller,把数据封装Model对象中
5)ViewResolver,视图解析器,把model传递页面jsp,把model转成json字符串,返回页面
#三大框架源码
spring-core.jar
Servlet规范
###### Spring
>>强大
j2ee,EJB 天生是远程传输,分布式结构,3.0完蛋
EJB 2.x (weblogic),写sql查询where,为每一个条件 name=chen and age=18 写的内容很多 每一条都要写
spring作者,写了一本书 spring without EJB
spring3.x 全面引入注解开发,大大简化开发,不是你写,spring底层完成!
口号:不重复发明轮子!
拿过来,这个东西非常强大! spring没有所有都自己实现,它把业界最牛的产品集成!
旧三大框架:struts1 + spring + hibernate
struts2 + spring + hibernate
新三大框架:springmvc + spring + mybatis 小项目
微服务: dubbo 阿里 ,dubbox当当 15,16 ,基于ssm
springcloud
a. netflex 网飞,先开源后闭源
b. 自研 springcloud alibaba spring是真正的王者!
*****不重复发明轮子 把最好的东西结合起来******
>>为什么强大
框架存在设计思想
1.IoC 控制反转 剥夺对象创建权
Car car = new Car(); 自己创建 car = null; java
struts2 使用对象model,car
**Spring剥夺java 创建和管理对象权利 对象的声明权利
---Spring拥有对象的 权利 那其他的框架就依附于Spring框架
SpringMVC参数封装, 无用大量代码spring框架抽象 写了
提高了效率,减少代码量
#*> 把权利方砖,本来是开发者的权利,spring使权利变成框架的权利 <*#
问题:对象依赖
需求: 员工 username deptname
员工对象依赖部门对象
User user = new User(); Dept dept = new Dept();
user.setDept(dept); //依赖关系体现
打印user时也打印了dept
2.DI 依赖注入 dependency injection
user.setDept(dept); 自动执行
注解: @Autowired 注解标识 底层自动执行这句话
>>spring框架两种方式 底层创建对象
xml方式 注解方式
Car car = new Car();
告诉框架car对象 全局限定名 cn.tedu.car.pojo.Car
通过全局限定名,底层通过反射 创建对象
..xml文件中配置 bean (java中万物皆object spring中万物皆bean)
有多少对象就写多少bean声明
..注解 包扫描
一句话n个对象
xml 文件 ..maven 项目 spring-xml-ioc
<!DOCTYPE> 文件头
注解方式 ..maven 项目 spring-annotation-ioc
1)需要配置文件applicationContext.xml,配置包扫描语句,指定扫描目录pojo,所有类会自动创建
2)创建ApplicatContext对象,还是ClassPath......
3)ac.getBean("hello")
>>xml开发步骤.......
1.pom.xml spring框架
2.applicationContext.xml 核心配置文件 文件写死自己找文件 src/main/resources
会自动取resources 下去找
<bean id="hello" class="cn.tedu.pojo.Hello"/>
这句话有多少对象创建多少bean
3.xml文件头
4.Hello.java 普通类 src/main/java/cn.tedu.pojo
5.xml中配置bean标签
属性 id(beanName) :hello(驼峰命名 死规定)
class 全局限定名 包路径.类名 反射
6.TestIoCXml.java src/test/java/test
测试类 ClassPathXmlApplicationContext (xml文件) 创建spring环境
7.返回Hello对象 Hello hello = (Hello)ac.getBean("hello"); 会到spring环境(容器)
8.hello.hi(); 无需创建对象,就可以调用这个对象的方法
>>注解开发步骤.......
1.pom.xml spring框架
2.applicationContext.xml src/main/resources
<context:component-scan base-package="cn.tedu.pojo"/>
这句话只需要写一次就能创建所有对象
3.Hello.java pojo
创建方法 验证 @Component有这个注解spring才会创建实例
4.TestIoCXml.java src/test/java/test
测试类 ClassPathXmlApplicationContext (xml文件) 创建spring环境
main方法中
//创建spring环境,
ApplicationContext ac
= new ClassPathXmlApplicationContext("applicationCOntext.xml");
//获取Hello Bean对象,调用齐方法,底层spring创建对象
Hello hello = (Hello) ac.getBean("hello");
通过反射 得到实例
hello.hi();//直接调用对象方法
>>错误没有bean 就是没实例 注解方式时 在类文件中加上@@Component
No bean named 'hello' available
没有了bean的标签指定,pojo并不是所有的类都需要创建实例?
给一个标识,标识它需要创建实例,@Componet注解!spring检查pojo类,
如果有这个注解才创建实例,如果没有这个注解就不创建对象实例!
可以看到,注解框架一旦搭建好,只写业务代码,而无需再次配置环境!
注解方式优于xml配置方式!
>>spring 底层实现工作原理 ......核心是 初始化, 创建对象, 容器, 匹配,getBean 反射
1.包扫描 拿到对象和包路径
2.创建容器 map(k,v)
3.匹配 创建对象,放入容器
4.创建getBean("hello")
模拟ApplicationContext接口
模拟ClassPathXmlApplicationContext(inti,createObject,getBean)
........步骤........
java工程
ApplicationContext接口
ClassPathXmlApplicationContext类
构造方法 (初始化init,bean定义 BeanDefined类,createObject放入容器)
getBean方法
### DI
.....过程.......
1)创建核心配置文件,设置包扫描(拷贝)
2)创建pojo,dept,user,这两个对象关系,注解@Component,@Autowired
3)写测试类,调用对象
需求:用户的所在部门,怎么在pojo中体现这个关系?
1)传统方式,set注入(利用set方法把关联关系绑定)java编程
2)@Autowired 自动装配,spring自动实现
### 小结
1)spring实现IoC控制反转,把程序创建对象控制权,抓在手里,所有人就必须依赖我
spring提供很多方便功能,而这些功能自己可以写,代码量很多
2)IoC控制反转具体怎么实现的?
a.xml
在applicationContext.xml核心配置文件,通过来实现
每个对象要写一行,xml没有编译,字母写错,位置写错,运行时报错
spring在启动时,找到核心配置文件,解析xml文件,dom4j。拿到所有bean标签
能拿到id=hello和class=cn.tedu.pojo.Hello,创建对象,反射按class进行反射
得到对象实例,然后把它放入容器map.put(id, instance)。怎么获取?getBean(id)
b. annotation 注解方式
在applicationContext.xml核心配置文件中,通过一行代码
包扫描:<context:component-scan base-package="cn.tedu.pojo"
java提供磁盘io一套api,它获取磁盘目录,文件和子目录
文件名:User.class
路径:D:\java\ws\2012\spring-annotation-ioc-2012\src\main\
java\cn\tedu\pojo
路径+文件名:java.cn.tedu.pojo.User(className) 经过api层层转换,获取到全局限定名
user(beanName)
把这两个信息放入BeanDefined对象中,利用反射创建user、dept。。。
把它放入全局成员变量,beanDefinedList中
类的构造方法执行createObject方法
遍历这个list,获取每个bd(beanName,className)
拿到className,利用反射创建对象实例
放入容器map(key=beanName,value=instance)
getBean,从容器中获取,"hello"=key,根据key就获取对应value,获取到对象
3)IoC和DI什么关系?
IoC概念,编程思想(好莱坞原则)
DI具体措施,因为spring要实现IoC,衍生bug!,副作用。来解决问题
Autowired自动装配,实现DI
@Autowired标识,spring通过反射拿到类,拿到类的属性getField();,拿到属性上注解
user
@Autowired
private Dept dept;
如果有这个@Autowired注解,getBean("dept"),获取到容器中dept对象
反射set方法 set(instance, dept);
打印user对象时,getDept就可以拿到值!
作页:
1)xml实现ioc
2)annotation实现ioc
3)annotation实现di
实现ssm整合时,就会用到这些知识
明天任务
1)di源码实现
2)面向切面编程AOP(aspectJ),springmvc 拦截器
>>>>>>>>>
src/main/java 业务
src/main/resources .yml .xml
>>今日项目
spring-xml-ioc
spring-annotation-ioc
working-spring
spring-di-annotation
# 2021-02-24 ********************************************
## 回顾
>>Spring
抓住了面向对象的管理权限 就成为核心
IoC控制反转概念
1.剥夺其他框架创建对象的权利 框架围绕对象model(业务数据)开发
struts1,struts2,springmvc,hibernate,mybatis
这些框架内部都要围绕对象model(业务数据)而进行开发
struts1/struts2/springmvc 只负责后台系统前端(前台后台交互),它不能完成整个系统
hibernate/mybatis 只负责持久层和数据库打交道,它也不能完成整个系统
spring负责把大家聚拢在一起,完成整个项目,小组长,项目经理,部门经理
spring野心,它来管理对象,可以在前台和数据库都需要对象,它可以共享给它们。
2.如何实现ioc
a.反射 在服务开启时就创建了对象,
利用反射来动态创建对象,在服务开启时就创建,map,这个对象已经在内存中,直接获取, 性能要比new性能高
b.DI对象关联(学生类 老师类) 如何关联产生了DI 反射实现set,@Autowried,自动装配
3.注解开发 有很多约定 约定 cn.tedu.pojo,cn.tedu.controller,cn.tedu.service
@Componet、@Controller、@RestController、@Service、@Repository、@Mapper
@RequestMapping("/car/get")、@Autowired 自动装配
>>junit单元测试
1.在要测试的方法上增加注解 @Test
2.第三方jar包 但eclipse支持 @Test错误提示,添加5.x
3.junit专门为测试,
注意: 写在方法之上,public方法,无返回值
一个类有多个@Test 没有执行顺序性
多个@Test 右键运行会执行所有的@Test方法
指定方法运行,双击方法名,右键运行
不能随意几个方法,,,要么一个,要么全部
>>DI核心
获取User对象,遍历它的所有属性
检查每个属性的@Autowired注解,如果没有就没有di,如果有 利用反射对属性.set,把一个对象set到这个属性中
private Dept dept; dept.set(getBean("dept"))
这里有个问题,属性是私有的!必须设置一个开关,开关默认值不允许false 调用代码之前,把开关设置true,可以操作私有属性!
>>>
反射打破了封装
>>>>Spring AOP面向切面编程
面向过程 C
面向对象 Java
面向切面
---面向切面
写日志 动态增加代码
a.可以纵向编程,一下管理所有类 传统编程横向编程
b.可以随时加入,随时移除
c.代码没有侵入性 (给类增加功能,但不在类里写)
注解(紧耦合) 面向切面(松耦合)
d.架构松耦合 随时加,随时移
servlet
springmvc,
spring(Controller,service),AOP面向切面编程,aspectJ(第三方)比Java反射要强大
动态代理技术(类似反射) 编译时 把动态码加入class中(改内存中类) !!!织入
切面可以多个 n个(功能) 性能会降低
每拦截一次执行时间就浪费一点,特殊业务应用时值得消耗
>>>>>> carAOP 实现拦截器 controller AOP service
怎么实现spring的service
增加两个类,添加@Autowired注解!
CarController.java
CarService.java 接口
CarServiceImpl.java 它的实现类
业务获得car信息
把写在controller业务,推到service
>>>>>>为什么写接口
接口是一个规范,公开
实现类隐私,一个接口有多个实现类
jdbc,sun接口规范
mysql驱动,oracle驱动,实现类
面向接口编程,配置driver : com.mysql.jdbc.Driver
>>>>>>拦截器 interceptor
拦截类的方法的执行 car/get方法
三个点
pre 方法执行之前
get
post 方法执行之后
complete 方法返回页面之前
>>具体实现
1.写拦截器 CarInterceptor/UserInceptor 实现接口 HandlerInteceptor
2.告诉spring框架拦截器的存在 注册 实现接口 WebMvcConfigurer
>>>>>>监控每个方法执行时间
TimeInterceptor 1)在方法执行前 pre,记录下当前时间 startTime ,System.currentTime 毫秒值
2)在方法执行后 post,记录下当前时间 endTime
3)执行时间 = endTime-startTime
>>>多个拦截器
形成拦截器链
执行有顺序 谁在前面 谁先执行
我是拦截器 preHandle 第一个 pre
2 pre 第二个 pre
car get 业务方法
2 post 第二个 post
执行耗时96ms 第二个 post
我是拦截器 postHandle 第一个 post
我是拦截器 afterCompletion 第一个 complete
>>>Component注解
标识后,spring底层使用包扫描机制,会自动创建类实例,放在容器中
@Component 不确定这个类分层职责
@Controller springmvc的controller
@Service spring的service
@Mapper Mybatis的Mapper
不配置xml核心文件的包扫描,怎么能执行
base-pakage="cn.tedu.pojo"
SpringBoot项目默认采用自动使用包扫描(注解)
基准路径: RunApp启动时目录,
约定:controller/service所有的都是在这个目录之下 **************
>>>>并发
高并发 当第一个用户 pre方法之后 还没post 第二个用户插进来 pre
n多个用户访问
car/get 方法,只创建一个对象,所有用户及共享这个对象
CarController单例
用户拥有自己的线程 相当于变量用户私有
每个用户拥有独立的线程
--操作系统保证的私有
ThreadLocal 本地线程
使得每个用户拥有自己的线程,
##### 小结
1)spring框架,是所有框架中最强大,
它管理对象声明周期,其他框架需要这个信息,只能从它来获取
不得不依赖它,
2)IoC和DI、拦截器、AOP,它就能增强我们的项目
a. IoC 控制反转,创建对象(启动)注解@Component,
放入容器,创建一次,供多次调用
b. DI 依赖注入,@Autowired体现,绑定对象关系,对象实例注入
c. 拦截器,面向切面编程
面向对象:横向编程,每个类CarController,CarService。关心的是每个类
面向切面:纵向编程,n多类,每个类所有方法的执行时间!
先有面向对象,面向切面是面向对象有益补充,有了更好,没有也没关系。
拦截器:打印日志,时间耗时统计,权限验证
3)拦截器具体怎么实现?
a. 写自己拦截器
1- pre方法,在业务方法执行前执行
2- post方法,在业务方法执行后执行
3- complete 完成方法,在业务方法执行完成,返回页面之前执行
b. 注册这个拦截器
@Configuration spring底层会全局配置
如果多个拦截器,形成一个拦截器,执行顺序,先进后出
4)方法的耗时拦截器实现
优化一下整个项目,性能!
先要找出慢地方?找到系统中慢地方,看合理不,有优化余地,优化系统快!
>>>>>>>>
TestReflect .java
创建对象,执行方法invoke,注解@Autowried(方法使用了就执行,标明)
>>>>>>>>项目文件
working-spring -annotation
test TestReflect
spring.annotation Autowried
hello
carAOP 切面
cn.tedu.car.service
CarService.java
CarServiceImpl.java
cn.tedu.car.controller
CarController.java
cn.tedu.car
RunApp.java
cn.tedu.car.interceptor 拦截器
MyInterceptor.java 实现HandlerInteceptor接口
SysInterceptorConfig.java 配置类
TimeInterceptor.java 方法执行耗时 测试拦截器
>>>>>>??????? 问题
文件与文件之间如何关联的
@Autowired
# 2021-02-25 ********************************************
## 回顾
>>>>DI由于spring实现IoC,改变对象为开发者创建实例,为spring框架去创建对象
随着对象关联关系也变成从开发者主动set注入方式改变di自动装配@Autowired
......底层实现思路,利用设置关联对象属性上面加一个@Autowired
spring进行包扫描创建完成所有类对象实例,放入beans容器中
再次扫描,获取每个类的所有属性,判断属性是否有@Autowired
User
@Autowired
private Dept dept;
private String userName;
dept属性加了注解,而userName是没有加
这个注解就成了是否DI的判断依据,dept进行DI,userName不进行
dept.getName(),去容器中进行Dept dept = getBean("dept")
反射 field.set( getBean("user"), dept)
这个过程非常繁琐,这是spring框架底层去实现,无需开发者写代码,
开发量急剧降低,深受开发者喜爱,主流开发方式提倡注解开发。
企业中程序员,关注点,在于怎么用好框架快速开发,快速迭代,快速交付
@Autowired
>>>>拦截器
面向过程,关注点:写代码开发步骤,函数(怎么查询某个学生)
面向对象,关注点:类(学生类)、对象(实例),怎么查询
CarController,CarServiceImpl,UserController
如果每个类中有相同功能:打印日志,执行方法耗时,权限
面向切面,一次通用结构,新加的内容无需额外编码(复用)
它可以随时干掉(系统测试阶段,试运行阶段:打印日志,执行方法耗时)
一旦系统稳定,这些功能就关闭
servlet规范:filter过滤器
springmvc规范:interceptor拦截器
spring规范:AOP
面向切面编程 相同的功能,写一次通用
>>>>开发拦截器需要步骤:...........
a.写拦截器类 TimeInterceptor
b.注册拦截器 @Configuration
spring框架在方法执行前去调用对应拦截器
post有handler参数,它代表被拦截对象,
handlert="cn.tedu.car.CarController#get"
>>>>所有遇到注解,用在哪里
a. @SpringBootApplication springboot引导项目启动
以前javaWeb项目手动启动tomcat,而且要配置它,项目war
tomcat集成在里面,直接运行springboot.main就可以,
获取这个类上面注解@SpringBootApplication,然后启动spring,初始化类
把所有@Component、@Controller、@RestController、@Service、
创建对象实例,把它放入容器,获取对象快!
b. @Controller和@RestController有什么区别?
后者多一个注解标识:@ResponseBody 响应,
jackson技术api工具包,把java对象转换json字符串,反着来
c. @Autowired 实现DI依赖注入,自动装配
d. @RequestMapping("/car/get")
springmvc中提供,和浏览器上输入url进行匹配
http://localhost:8090/car/get
ip地址找到服务器 :8090/car/get
端口号固定某个服务:tomcat是servlet规范运行环境:web中间件
/car/get
把这个值传给我们的程序:springmvc,DispatcherServlet
DS去找匹配Controller(user/dept/car)
某个controller的方法上写注解
@RequestMapping("/car/get") 唯一值、
spring框架在初始化时,它初始化完毕,springmvc初始化
包扫描,扫描所有controller类,然后获取所有方法,拿到方法上的注解
获取这个注解value属性,都存在一个集合中
Map.key="/car/get",value=class CarController#get
反射ass来创建实例,invoke回调get方法
@RequestMapping({"/","/car/get"})
@RequestMapping(value="/car/get")
@RequestMapping("/car/get")
e. @Service 约定它是描述service层
spring包扫描,创建对象实例,把它放入容器
f. @Override 继承,子类的方法和父类同名,给开发者看到
h. @Configuration spring框架全局配置,全局变量,系统各处进行调用
>>>>>ThreaLocal对象用完要自己释放,remove(),防止内存泄漏!
#####
>>>>AOP
拦截器思想
概念:
通知: advice 五种
1.前置 pre
2.后置 post
3.环绕 pre+业务+post
4.完成业务之后返回前 afterReturn,afterComplete
5.异常 error,exception
aspectJ 比interceptor强大 aspectJ可以应用在各个类,所有系统运行类拦截
interceptor 局限于springmvc
filter局限于servlet
spring集成了aspectJ B/S C/S 嵌入式
项目中 一个地方使用 必会
>>>>开发步骤............
1.导包 springboot 集成了 web(spring+springmvc) 需要手动添加aop
自己添加依赖 spring-boot-starter-aop
2.切面类 TimeAspect.java @Component 关联类 @Aspect
3.空方法 @PointCut("切点表达式") 切点
private void aopPointCut() //空方法
切点表达式(最强大) "execution(public * cn.tedu.car.service..*(..))"
方法说明 public 返回值类型 * 包路径(可以很多) 类 .. 方法 * 多个参数(..)
public Car cn.tedu.service.CarServiceImpl get(){}
public Car cn.tedu.controller.CarController get(){} 不拦截 controller层
判断依据,项目配置一次就行
4.around方法 环绕通知:@Around("aopPointCut()") //
5.around方法参数 JoinPoint连接点: 切面切得谁 信息藏在joinPoint中
6.around方法参数 ProcedingJoinPoint joinPoint 实现类,
7.获取类名和方法名
>............
caraspect
cn.tedu.car.aspect TimeAspect.java
### mybatis
J2EE,EJB框架,hibernate负责java和数据库之间转换
ORM,object relationship mapper,把数据库jdbc,ResultSet结果集,它不是java中model对象
model (pojo ) 属性,代表数据
ResultSet ( rs.getString("name") ); 桥梁转换映射 hibernate/mybatis model name:"tony"
hibernate 完全面向对象,
HQL,对象方式来查询数据,内部最终会转换SQL,利用jdbc操作数据
SQL: select * from tb_item 表
HQL: from Item 对象
ibatis mybatis 投身Google 半面向对象 直接拼接SQL(一套规则) 直接操作jdbc
mybatis 性能高
hibernate 对象状态 OGNL表达式 很难控制 漏洞百出
小型项目使用hibernate 大型项目使用mybatis
>>>>mybatis完成orm映射 规则
jdbc :
String sql = "select * from tb_item";
preparedStatement对象,CRUD方法,executeQuery(sql) 查询:ResultSet对象
查询返回 ResultSet对象
mybatis:
把sql写在xml文件中 ItemMapper.xml
Item.java POJO
<select id="find" resulttype="List" >
select * from tb_item
</select>
按mybatis规则写完后,它底层自动将sql查询完成结果集,自动保存对象中
返回是一个集合,只声明集合元素类型,默认List集合
>>>>mybatis 结构
>>>>开发步骤.........................
1.数据库jtdb-small.sql
2.pojo对象 Item.java
3.映射文件 ItemMapper.xml
4.核心配置文件 sqlMapConfig.xml
测试类
读取配置文件:Resourses
ibatis提供,返回InputStream
SqlSessionFactory=读取sqlMapConfig.xml
builder创建工厂对象
SqlSession执行sql statement = namespace.id(find)
按规则写完,mybatis会把这些按约定规则串接,底层执行xml里sql最终映射到java对象 返回值java对象(model)
创建项目: springboot pom.xml mybatis/web/mysql
jtsmall
创建上面的两个配置文件,如果没有提示,配置一下DTD文件
DTD文件描述xml由哪些标签组成,它会和eclipse配置形成提示
1)sqlMapConfig.xml (配置后不生效 eclipse)
2) ItemMapper.xml
>>>>最爱犯错:
Mapped Statements collection does not contain value for cn.tedu.jt.mapper.ItemMapper.find
1)命名空间和statement参数写的一致不一致
2)sqlMapConfig.xml中忘了导入xml文件
3)调用statement别写错了
unknown datasource property dirver
sqlMapConfig.xml 文件中单词拼写
>>>>项目
caraspect
cn.tedu.car.aspect TimeAspect.java
jtsmall
pom.xml
main/resources sqlMapConfig.xml 环境配置
main/resources/mappers itemMapper.xml sql查询
main/java
cn.tedu.jt.pojo Item.java 私有属性
test/java
test TestMybatis.java
# 2021-02-26 ********************************************
>>>>AOP
j2ee servlet标准(网络请求request和响应response) tomcat实现了
都是拦截方法执行 权限判断
1.servlet 过滤器filter 只能用于servlet
2.springmvc 拦截器interceptor controller(本身不是servlet)
3.spring aop aspectJ b/s c/s 嵌入式 没有请求和响应,没有servlet和controller 直接操作业务方法 从方法的角度出发
***spring aop更加强大,不局限于request和response处理
>>>>AOP 结构
@Aspect 注解,此类为切面类
@Component 告诉spring这个类要进行管理,创建对象实例
@PointCut 切点,谁拦截谁不拦截可选择 判断依据:切点表达式(满足或匹配 放行 false 不处理)
拦截器,所有的请求都拦截
切点表达式 修饰符,返回值,包路径.类,方法,参数
public * cn.tedu.car.service..*(..)
通知:五种 前置pre 后置post 完成返回complete 异常 环绕around
@Around("空方法")
around方法参数 ProceedingJoinPoint joinPoint 获取被拦截对象,也能执行对象方法
>>>>拦截器
在所有类上运行时,动态给类的方法添加代码
动态改变别人类填写代码,
TestMybatis2.java
>>>>mybatis
数据库结构化,sun jdbc规范 结果集对象ResultSet(表,字段name,类型varchar)
java model对象 pojo 数据 name,String
高并发宕机
对象model
转换,hibernate小项目,ibatis,mybatis大中型项目
hibernate 全面向对象ORM框架 HQL
mybatis 半面向对象ORM框架 SQL
mysql面向过程
>>>>使用mybatis
sqlMapConfig.xml 核心配置文件 数据库4个参数
Item.java pojo model对象,暂存数据,传递数据
ItemMapper.xml 核心独有的,发明一套标签,标识CRUD <select>sql语句
SqlSessionFactory 工厂类,产生sqlsession 线程安全支持高并发 单例
SqlSession 线程非安全(高并发会出乱) 解决:私有 多例 原型
.selectList
>>>>卖点sellPoint是null
数据库是sell_point pojo是sellPoint 不能匹配
使用as别名
mysql select sell_point form tb_item
select sell_point as sellPoint form tb_item
select sell_point as sellPoint,t.* form tb_item as t
>>>>解决字段属性不对应
1.sql
select sell_point as sellPoint,t.* form tb_item as t
2.mybatis
自身特性ResultMap强大
使用resultMap定义新的映射规则, pojo 属性名 与 数据库 字段名之间
id id
title id
sell_point> ResultMap写一个映射规则 >sellPint
子定义一个ResultMap,在select标签上引用这个映射规则接口 itemRM
resultMap 新的构造映射规则,使用新的
字段名和属性名相同省略
<resultMap type="cn.tedu.jt.pojo.Item" id="itemRM">
type 指封装的pojo对象名
id 命名,在文件中唯一 itemRM
标签属性
property 值pojo对象id属性
column 数据库表结果集中字段名
<id property="id" column="id" />
<result property="title" column="title" />
<result property="sellPoint" column="sell_point" />
定义了映射 resultMap 规则
使用 在<select>
<select id="find" resultMap="itemRM">
resultMap 标签
如果数据库表的字段和属性一样可以省略
id 表的主键
result 其他,非主键的字段
association 多表查询时 一对一关联
Collection 多表查询时 多对多关联
>>>>resultMap 多表查询
>>>> mybatis 操作 查询数据库
1.xml
2.xml+接口(面向对象)
TestMybatisInterface.java 接口实现查询 //读取资源文件,解析xml文件
ItemMapper.java 接口文件
>>>> 接口,实现类,,,,怎么找到xml中的find
不需要实现类
底层会创建实现类,
加载 执行顺序
sqlMapConfig.xml 数据库配置
ItemMapper.java
mappers/ItemMapper.xml
真正底层是创建了实现类,动态创建,你看不到,内存中
动态代理技术动态产生类:
jdk动态代理($Proxyn),cglib动态代理(cgblib....)
断点:观察变量的值,要看变量后面设置断点
>>>>操作
itemMapper.xml
<select id="find" resultMap="itemRM">
select * from tb_item
</select>
itemMapper.java
public List<Item> find();
TestMybatisInterface.java
@Test
public void mybatis(){
SqlSession session = factory.openSession();
ItemMapper mapper = session.getMapper(ItemMapper.class);
List<Item> list = mapper.find();
for(Item o:list) {
System.out.println(o);
}
}
查询 select
新增 insert
修改 update
删除 delete
获取一条get
查询多条list
mysql默认自动提交为false 手动提交 session.commit(); session数据库
>>>> mybatis 动态标签
配合方法把参数传入,mybatis加入
单值传递 id #{id}
多个 使用对象 item,#{id}=item.id,#{title}=item.title,#{sellPoint}=item.sellPoint
文件中
itemMapper.xml 标签添加属性parameterType sql查询语句的 值设置为#{}
ItemMapper.java 空方法添加参数形参,因为使用方法时动态添加值
TestMybatisInterface.java 调用方法时,添加方法的实参
select
parameterType="string"
select * from tb_item where title like #{title}
insert
parameterType="cn.tedu.jt.pojo.Item" pojo对象
多个值传递进来,pojo对象 参数类型为pojo对象
对象方式接收参数 名称和pojo中属性名一致 默认null
INSERT INTO tb_item
(id,title,sell_point,price,num,cid,STATUS,created,updated)
VALUES(NULL,#{title},#{sellPoint},#{price},#{num},#{cid},1,NOW(),NOW())
新增为多个值 使用pojo中 class item Item对象 设置Item对象的值
Item item = new Item();
item.setTitle("12345689");
update
表中有多少记录
select count(*) from tb_item
>>>>mysql表的主键,int/long支持自增
auto_increment ,数据库会记录当前值,每次新增一条记录时,这个值+1
不需要开发者填写
insert 时 id 为null
## 小结
mybatis 完成ORM,对数据库封装java对象
实现两种方式:
1)xml方式,selectList,insert,update,delete,selectOne
2)接口方式,重点
>>>接口方式开发步骤:
1)写映射xml文件,配置各个标签
2)在接口中增加它的方法,和标签一一对应,
public resultType/resultMap 标签id( parameterType)
public List find(String title);
3)session可以按接口方式调用
ItemMapper mapper = session.getMapper(ItemMapper.class);
mapper.find("%诺基亚%");
>>>映射文件 ItemMapepr.xml
1)namespace命名空间:它要和谁来对应?但是命名空间名字和接口类的名字相同
2)返回值类型:
a. resultType:int/long/string/Item
b. resultMap:对应特有resultMap标签(如果有pojo的属性和结果集字段column不一致)
多表联查 left join, inner join, right join
type=返回值对象(数据放到哪个对象中)Item
3)参数类型:
a. parameterType:int/long/string 单个参数,/Item 对象参数
b. parameterMap:废除,被parameterType替代
参数和返回值需要时声明,不需要时就不写!根据业务需求定。
4)占位符
#{id},代码安全,preparedStatement,?,防止sql注入,安全
${id},代码不安全,拼串 title = 'title'
5)自增主键:mysql直接支持,独有 auto_increment
mysql表会记录最后一次插入值,+1。中间删除了一个id,维护成本过高,舍弃
6)线程安全,和线程非安全
线程安全对象:支持高并发,加锁,阻塞(等待)
SqlSessionFactory,成员变量
线程非安全对象:不支持高并发,不能为成员变量(多个方法共享)
写在方法内容,局部变量,方法私有,
SqlSession,只能放在方法内,每次都要创建
7)单元测试 @Test
4.x @Before
5.x @BeforeEach
双击执行@Test,jUnit它会先执行@BeforeEach方法
>...项目.........................................
jtsmall
TestMybatis2.java
itemMapper.xml 写SQL语句
TestMybatisInterface.java
ItemMapper.java 空方法
# 2021-03-01 ********************************************
### 知识回顾
>>>>mybatis
持久层框架,完成数据库的封装,半面向对象框架
一边关注是xml中如何配置sql(面向过程编程),一边关注是java模型对象(面向对象编程)
半ORM映射框架。
>>mybatis完成数据库表的结果集和java模型对象映射
操作的是结果集,从结果集中获取数据
select sell_point as sellPoint from tbitem t
1)根据jdbc提供元数据:getMeta().getColumneName(),根据列名获取某行值
sell_point,(123)
2)反射,获得pojo的私有属性,
private String sellPoint;
反射 sellPoint.set()
>>>> mybatis 动态 sql
占位符 #{name} select * from tb where title like #{title}
prepareStatement 的 ?
${} 有sql注入问题 字符串拼接 自主拼接''单撇 用户也可以拼接会发生sql注入
#{} 防SQL注入
参数 parameterType mybatis传入参数类型
单值 mybatis提供的 string/int/long java提供的 java.lang.String
多值 pojo对象,复用 传递数据 参数作用
返回值 resultType/resultMap
resultType: string/int/long/pojo
resultMap: 表的字段和pojo名称不同时 定义resultMap映射
标签 xml标签
select(find get count) insert update delete
>>>> mybatis 3中操作方式
xml ItemMapper.xml 使用session.selectList(),selectOne()
接口 ItemMapper.find() 对象方式
它通过cn.tedu.jt.pojo.ItemMapper.find()=xml.namespace(约定)
=cn.tedu.jt.pojo.ItemMapepr,找到映射文件,find找到某个标签id(唯一),获取sql语句来执行
**本质还是执行xml映射文件!
接口+注解 把xml消灭掉(99%)多表联查resultMap,需要映射文件
>>>> jtsmall问题
查询,用户没有输入条件,
删除,删除多个 传递多个参数 in(1.2.3.4)
>>>> 动态SQL
if where set foreach(形成in子查询串,id就可以多个值,批量删除)
作用:
if 判断作用,如果条件成立就出现拼接sql字符串中,如果条件不成立,不出现
null判断条件,空串
where 自动删除条件前面的and或者or
set update修改,如果最后一个set条件多余逗号,会自动删除
foreach批量删除,形成in字查询串
1.查询多个值 select
jtsmall2
itemMapper.xml
ItemMapper.java
TestMybatisInterface.java
if标签 : 条件成立就拼接sql语句 条件不成立就不拼接
利用if可以查询多个 条件
where标签 : 自动删除where条件 前面的and/or
-------
if条件成立时,造成新的错误,sql语法的错误,多了一个and
有两个方式来解决:
1)sql技巧 where 1=1
SELECT * FROM tb_item WHERE 1=1
AND title LIKE '%诺基亚%'
AND sell_point LIKE '%超值特价%'
-------
<select id="find" resultMap="itemRM" parameterType="cn.tedu.jt.pojo.Item">
select * from tb_item
<where>
<if test="title!=null">and title like #{title}</if>
<if test="sellPoint!=null">and sell_point like #{sellPoint}</if>
</where>
</select>
调用方法时使用item对象(有多个值),两个值同时成立
///
2.更新
if标签 : test测试中item中更新的值 少于 itemMapper.xml中查询语句的值
set标签 : 解决 sql语句中where前面的逗号去掉
SQL syntax sql语法错误
//
<update id="update" parameterType="cn.tedu.jt.pojo.Item">
update tb_item
<set>
<if test="title!=null">title=#{title},</if>
<if test="sellPoint!=null">sell_point=#{sellPoint},</if>
<if test="price!=null">price=#{price},</if>
<if test="num!=null">num=#{num},</if>
<if test="cid!=null">cid=#{cid},</if>
<if test="status!=null">status=#{status},</if>
updated=now()
</set>
where id=#{id}
</update>
///
3.删除
in子查询串 实现多条记录删除
万能参数 map
collection集合key item当前元素值 open开始前缀 close结束前缀 separator分隔符
in(1,2,3,4)
ids map的key
id foreach中的 i for(Item i:o){}
(
)
,
///
<delete id="deleteMuch" parameterType="map">
delete from tb_item where id in
<foreach collection="ids" item="id" open="(" close=")" separator=",">
#{id}
</foreach>
</delete>
调用时使用map集合 map<"ids",para> para是数组对应id
///
>>>>
标签
sql定义字符串变量 include引用
<sql id="cols">
id,title,sell_point,price,num,cid,status,created,updated
</sql>
<select id="find2" resultMap="itemRM" parameterType="cn.tedu.jt.pojo.Item">
select <include refid="cols"></include> from tb_item
</select>
pojo 去掉包路径 参数 返回值
cn.tedu.jt.pojo.Item Item
sqlMapConfig.xml 配置全局别名
别名 标签放在最前面
映射文件xml中的配置
所有映射文件中的 用到Item包路径的地方都可以去掉包路径
<typeAliases>
<package name="cn.tedu.jt.pojo"/>
</typeAliases>
>>>> ResultMap
1.如果数据库表字段(结果集)它和POJO属性名不一致,通过它来做映射
2.多表查询 在内存中构建一个大的结果集
表关联: 1:1 1:n n:1 n:n(两个1:n)
resultmap配置 对一association 对多collection
约束:
1)多表联查配置主键 id,需要映射字段result标签(sell_point),同名price可以省略不写
2)要求:返回大大结果集中不能有同名字段,如果有多个id,取第一个,不会报错(坑)
3张表
对多 tb_item_cat 商品分类表 tb_item商品表 一对多
对一 tb_item tb_item_desc商品描述表 一对一
>>>> 实现对多
1)两张表的查询 inner join,写好SQL,构建大结果集
-- 查询某个分类下是商品信息
SELECT c.id, c.name,t.id, t.title, t.price
FROM tb_item_cat c INNER JOIN tb_item t
ON c.id = t.cid
2)创建java工程:springboot
3)创建ItemCat.java POJO对象
4)在映射文件中ItemMapper.xml中添加ResultMapp映射
5)测试
>>>> 实现对一
SELECT t.id,t.title,t.price,d.item_id,d.item_desc
FROM tb_item t INNER JOIN tb_item_desc d
ON t.id = d.item_id
映射接口xml文件 注意:namespace 多表映射使用resultMap
创建接口 空方法 注意:返回值
pojo对象 主对象与从对象 在主对象中关联
测试类
>>>>>>>>>>>>>
>>>> 小结
1)动态SQL 标签
if 和java语言判断作用,
条件成立true,标签中间内容就拼接到sql语句中;条件不成立false,不拼接
where条件,查询条件变化无穷
update,修改某几个字段,其它的值不修改
delete 按某个条件来删除
where
如果前面多余一个and或者or,它会干掉,不多余,忽略
set
只同于修改,干掉最后多余逗号 set title='123',
foreach
用于in子查询,习惯是多个id来删除,
查询语句:select * from tb_item where id in (1,2,3,4);
sql+include,在xml中定义变量,多处引用,大量重复值
2)映射ResultMap
a. 字段和属性不同,通过它来映射
b. 对象关联
表关联:一对一,一对多,多对一,多对多(3张表,中间表)
对象关联:一对一,一对多,多对一,多对多(两个一对多)
老师和学生多对多(一个老师多个学生:一对多;一个学生可以听多个老师课:一对多)
mybatis映射关联:不管主体是谁,只关系和它关系,对多,对一(两种关系)
b1. 对多:collection + ofType
b2. 对一:association
3)什么时候item(属性property,代表对象实例),什么时候Item(类型,类,首字母大写)
属性从pojo对象私有属性而来,对象实例名称
4)配置对象关联都是单向关联
单向关联:
ItemCat 主
private List items; 从
方向:ItemCat > Item
双向关联:
ItemCat 主
private List items; 从
Item 主
private ItemCat itemCat; 从
方向:ItemCat >Item,同时,Item>ItemCat
>-------------------------项目---------------------------------------------
jtsmall2
jtsmall3
pom.xml
src/main/resources sqlMapConfig.xml
src/main/resources Mappers ItemCatMapper.xml
src/main/java cn.tedu.jt.mapper ItemCatMapper.java
src/main/java cn.tedu.jt.pojo Item.java
src/main/java cn.tedu.jt.pojo ItemCat.java
src/test/java test TestMybatis.java
src/main/resources Mappers ItemMapper.xml
src/main/java cn.tedu.jt.mapper ItemMapper.java
src/main/java cn.tedu.jt.pojo ItemDesc.java
# 2021-03-02 ********************************************
### 回顾
>>>> mybatis支持动态SQL
jdbc实现和数据库操作,自己拼接sql语句(字符串)
statement,可能会发生特殊字符,造成sql注入。
preparedStatement,sql分成两个部分,
select * from tb_item where title like '%诺基亚%'
第一个部分:select * from tb_item where title like ? (预编译,速度快)
第二个部分:'%诺基亚%'替换掉?,防止恶意,转码 ''(安全)
优点:快捷
缺点:大量拼接sql字符串;开发者需要专门学习jdbc的api
Connection、PreparedStatement、Executor。。。
jdbc原生它无法直接面对大型项目,sql和java代码混杂,后期不易维护,也不是适合大型团队
>>>> jdbc是啥:?????
>>>> mybatis框架
xml中写sql 调用接口是java代码
----把SQL和java代码分开,方便各层开发 无需了解jdbc的api
>>>> mybatis缓存
自身支持缓存框架 一级框架 二级框架
jdbc耗费资源:请求数据库
mybatis缓存:把每次查询缓存起来, 下一次如果sql一致, 直接返回缓存中的数据 缓存放在内存中
>>>> 框架的约定 约定大于配置
分层开发:开发步骤:
1)全局配置文件sqlMapConfig.xml,
配置jdbc事务、datasource数据源(4个参数)、加载有哪些xml映射文件
(*****三大框架整合ssm,核心配置大多被spring接管,
springboot更加全面接收,配置放在application.yml****)
2)映射文件mybatis核心,它发明了一套支持xml配置方式
操作标签:select、insert、update、delete
动态SQL标签:if、where、set、foreach、sql+include
数据库字段名(数据库的设计规范 sql92:全大写、全小写,多个单词使用下划线隔开)和
POJO的属下名不一致(java面向对象思想,数据封装model对象中,属性(数据)和方法
映射:结果集字段和POJO的属性来映射:ResultMap,人工的做一个映射
3)ResultMap需要两步
a.定义ResultMap,id标签代表主键,result标签代表普通字段,
对一:association 声明关联对象
对多:collection,声明关联对象,搭档,集合标明集合元素类型 ofType
b.使用ResultMap,给标签的返回值,配置定义resultMap的id值
4)提倡面向接口开发,一个接口多个实现类,如果实现类新需求改了,程序升级后,程序报错
约束行为,接口就约束了它的行为。接口中定义方法,参数,返回值 都不能变只能增加
mysql驱动,oracle驱动,底层实现很多不同,java.sql.*,
5)mybatis接口方式发展有两个阶段:
a. 接口假的,它只是利用接口方式调用,最终调用xml映射文件中的配置
接口并没有实现类,,在xml映射中调用的
b. 接口+注解(mybatis plus)
底层实现,使用动态代理技术,动态创建实例,类似反射!
6)测试类调用 session.getMapper...
>>>> namespace工作原理
怎么调用xml映射文件中某个方法呢?????? select id=find
1)给定类的文件ItemMapper.class,可获得类的全路径:cn.tedu.jt.mapper.ItemMapper
2)namespace=cn.tedu.jt.mapper.ItemMapper
3)获得类的全路径,mybatis加载时,会把所有xml映射文件解析(找到所有xml映射文件,里面namespace获取)
还有所有标签select,获取这个标签id,(专门技术:dom4j解析xml文件)
解析得到:namespace=cn.tedu.jt.mapper.ItemMapper,标签的id,find
4)最终两个匹配;
类的全局限定名=namespace
标签的id=执行接口方法
反射,invoke回调,执行接口方法(mybatis创建实现类:动态)
Test中的 Resources.getResourceAsStream("sqlMapConfig.xml");
找到 解析 sqlMapConfig.xml 文件 包含 < mapper resource="mappers/ItemMapper.xml"/>
找到 解析 ItemMapper.xml 获取标签sleect 获得id=find方法 执行 同时得到namespace
>>>> 多表联查
一对多而言:一的表称作主表,多的表称作子表,也称作:主从关系
需求1:一个部门多个员工,部门是主,员工是从
对象关联关系:在部门表中:private List emps;
需求2:一个员工他所在部门,员工是主,部门是从
对象关联关系:在员工表中:private Dept dept;
用户只要实现需求1,单向关联;
用户只要实现需求2,单向关联;
用户需要实现需求1和需求2,两句话都需要配置,双向关联
>>>>
*********************************************
前端
H5
BootStrap
vue+axios
后端
pom.xml
application.yml
控制层
ItemController.java
@RestController
@Autowired
业务层
ItemService.java
ItemServiceImpl.java
@Service
@Autowired
持久层
Item.java pojo
ItemMapper.xml
ItemMapper.java
@Mapper
RunApp.java
MySQL
tb_item
*********************************************
>>>> 链接池
数据库jdbc,,,每个请求会有一个链接Connection
作用: 事先创建多个链接 暂存在池中
使用时 直接从池中获取 没有新的链接对象
结束后 关闭对象 还回池中 可以复用
创建 维护 销毁 交给链接池完成
Hikari HikariCP springcloud默认集成链接池
遵循jdbc 把driver 换成hakari配置
>>>> application.yml springboot配置
把sqlMapConfig.xml文件配置 放在 application.yml中
1.有层次 每个层次前面有两个空格
2.结构 key:value value前面有一个空格
3.中间不能掺杂注释
*******************-文件内容-*******************
tomcat 端口
server:
port: 8060
------------
数据库链接配置 参数 hikari 数据库厂家驱动 jdbc数据库链接
spring:
datasource:
type: com.zaxxer.hikari.HikariDataSource
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3307/jtdb-small?characterEncoding=utf8&serverTimezone=Asia/Shanghai
username: root
password: root
------------
mybatis框架配置 替代sqlMapConfig.xml
配置pojo包路径
指定映射路径 springboot中resources不存在的 .class文件在classpath
java编译后文件在bin目录下
maven编译后 xml文件在 target中classes main的 test-classes
mybatis:
typeAliasesPackage: cn.tedu.ssm.pojo
mapperLocations: classpath:mappers/星.xml
下划线和驼峰规则 自动映射 无需ResultMap
configuration:
map-underscore-to-camel-case: true
------------
打印sql语句 日志信息 log4j
logging:
level:
cn.tedu.ssm.mapper: debug
----------------------------*******************----------------------------
>>>> 错误
400 类型转换错误
404 页面找不到. url @RequestMapping("/item/list")
500 含糊其辞,内部转换错误,代码是否正确
>>>> 前台请求后台 跨域问题
前台8848
后台8060
浏览器输入请求:ajax(axsio)不能从8848去请求8060,只能请求自己的端口
在ItemController.java中@RestController下
@CrossOrigin(origins = "*")
javascript规定,它不允许跨域,为了安全 CORS policy: No 'Access-Control-Allow-Origin
>>>> ${num}和#{num}有什么不同?
内容拼接到sql语句,sql注入,字符串类型,整数是不会有注入的问题
mybatis提供内容拼接到sql语句,sql注入,字符串类型,整数是不会有注入的问题
mybatis提供就可以使用,只是使用,字符串类型时,有注入风险!不是用户输入的就没有注入风险!
${num}
两部分:
第一部分:"SELECT * FROM tb_item LIMIT "
第二部分:${num}这个部分就被替代1
两个字符串拼接:"SELECT * FROM tb_item LIMIT "+1
Preparing: SELECT * FROM tb_item LIMIT 1
-# 内部走的?占位符preparedStatement方式,替换?占位符
Preparing: SELECT * FROM tb_item LIMIT ? 预编译,性能高
Parameters: 1(Integer)
两部分:
第一部分:SELECT * FROM tb_item LIMIT ?
第二部分:参数值1
把第一分部问号?替换成1
SELECT * FROM tb_item LIMIT 1
>>>>> 前台架构
html页面,创建vue对象,发起ajax(axios),在console.log结构打印出来
method定义方法:直接调用
mounted定义方法:加载完dom树,才调用这个,jQuery.Ready(){}
调用时机不同
mounted() { 自定义方法就放在mouted放在中
axios({ axios封装ajax,本质ajax
method: "post", 以post方式发起请求
url: "http://localhost:8070/item/list?num=3"
})
.then( 请求之后响应处理方法,返回对象封装response(res)
res => { 数据:res.data属性 json字符串
console.log( res.data )
}
)
}
>>>> 页面请求的方式:
HTTP协议规定:http://
GET:url参数可以看到,提交参数少url最大长度限制:256,512,不安全
POST:url参数看不到,8k=1024*7,安全,提倡
RESTFul ,请求形式,和get请求结构很相似(get请求)
http://localhost:8070/item/list?num=10 (get请求传参形式)
http://localhost:8070/item/list/10/标题/卖点 安全,数据量get形成多些
除了页面url形式不同,后台controller接收参数地方也要修改
@RequestMapping("/item/list")
1)一个参数
@RequestMapping("/item/list/{num}")
public List list(@PathVariable Integer num)
http://localhost:8060/item/list/5
2)多个参数
@RequestMapping("/item/list/{num}/{title}")
public List list(@PathVariable Integer num, @PathVariable String title)
3)对象参数
@RequestMapping("/item/list/{num}/{title}/{sellPoint}/{num}")
public List list(Item item);
RESTFul参数少,使用它,参数多,使用post传参!
## 小结:
1)数据库,面向SQL题,面试前抱佛脚。看到SQL题目,直接写出SQL语句
2)前端,h5/css/js/jQuery不用去看,看Vue+element,最后整合,照着抄,但是明白每句意思,熟练敲代码
3)三大框架,应用(必须掌握,ssm整合的代码敲熟练),底层源码(了解)
>>>>>>>>
后端整合:ssm+springboot构建项目
前端整合:h5+css3+bootstrap+vue+axios(ajax)
--------项目----------------------------------------------------
ssm20210302
pom.xml
web mybatis mysql
application.yml src/main/resources
Item.java src/main/java cn.tedu.ssm.pojo
ItemMapper.xml
ItemMapper.java
ItemService.java
ItemServiceImpl.java
ItemController.java
RunApp.java
```