Spring和SpingMVC的整合
目的是消除配置文件
starter是核心
要选择使用GA版本
普通创建项目
配置pom文件
配置父工程
父工程配置了大量的版本号
配置启动器 spring有各种启动器,它帮我们定义了各种第三方框架(非常方便)
requestmapping
配置主配置类
@SpringBootApplication 注解--加在Controller,service等注解配节
---@SpringBootConfiguration
---------@configuration注解(没听懂)
用于定义配置类,替换xml文件,相当于< beans>,里面包含多个含有@Bean的注解。
----@EnableAutoConfiguration 开启自动配置
-----------@AutoconfigurationPackage 自动扫描包,扫描主配置类所在目录里所有的包 -----------@Import 导入加载自动配置
将项目打包成jar用于测试,里面内置tomcat服务器
SpringBoot配置文件
默认在resources里,名称application.properties/application.yml/application.yaml
属性:【空格】值
默认不加引号,加双引号识别转义字符,加单引号原样输出
server:
port: 8080
servlet:
context-path: /my --项目根路径
实体类的注解
@ConfigurationProperties(prefix="yml文件里的属性名,表示将yml的值插入到对象中")
测试类的注解
@SpringBootTest
当yml和properties文件里有相同属性时,以properties文件内容为准。
springboot会依次读取两种配置文件,只要找到一个即可。
自定义对象增加提示效果
@value赋值方式
${yml中属性名}
spel表达式 #{}
直接赋值
@ConfigurationProperties(prefix="") 加在class上面。可以给对象赋值,不能使用spel表达式和直接赋值。
@PropertySource() 放在类上,指定配置文件
@ImportSource(value=("classpath:beans.xml")) ---导入spring配置文件
packing选项:pom--父工程,war--网页,jar--普通java工程
//一般属性
spring.application.name=compute-service
server.port=80
server.tomcat.uri-encoding=GBK
//自定义属性
com.blog.name=博客
com.blog.uri=博客地址
加@Bean,id等于方法名
按以下顺序先后加载,所有文件都会加载,形成互补
java -jar xxxx.jar --spring.config.location=D:/kawa/application.yml
项目根目录/config(不会打包)
项目根目录(不会打包)
resource/config
resource
三种环境下的配置文件优先级比默认的高
首先创建三种环境下的配置文件
application-dev/prod/test.properties
指定配置文件方式
-
在application.properties里指定配置文件
spring.profiles.active=dev/prod/test
-
虚拟机配置(优先级最高)
-Dspring.profiles.active=dev/prod/test
- 执行jar时指定配置文件 -spring.profiles.active=dev/prod/test
直接在一个yml文件里编辑
也同样适用虚拟机配置和jar配置
spring:
profies:
active:dev
---
server:
port:8086
spring:
profiles:test
---
server:
port:8087
spring:
profiles:dev
---
server:
port:8088
spring:
profiles:prod
//不同参数用空格隔开
java -jar xxxx.jar --server.port=8080 --server.serverlet.context-path=/demo
java -jar xxxx.jar --spring.config.location=D:/kawa/application.yml
log4j-日志系统,出来较早
slf4j--日志框架
通过中间的适配,可以通过slf4j操作各种日志,我们只要学习slf4j的API即可
日志级别:
- Trace--最全
- Debug--开发
- Info--生产
- Warn
- Error
设置日志级别
输出日志到文件
logging:
level:
com.woniu: trace
file: G/my/springboot.log //输出到指定目录
path: /spring/log //输出到项目所在目录
//两个目录都会输出
两种日志配置文件
log4j.properties--针对log4j的日志配置文件
logback.xml--针对logback的日志配置文件
springboot引入日志logback.xml,放在resource目录,可以设置文件输出目录,输出格式等,也可以用springboot的日志名logback-spring.xml
logback-spring.xml里的环境和运行环境必须相同,否则会报错。
logback-spring.xml里只需要改路径、级别,日志大小
webjars.com --寻找静态资源
用依赖的形式导入jquery
两个路径的关系
springboot会自动扫描着四个目录,用于存放静态资源
resource
--META-INF/resources(不行)
--public --存放html 可以
--static 可以
--resources 可以
jva
--static 存放sj
访问时不需要添加这四个文件夹路径
classpath --resouces目录
把favicion.ico放在静态目录即可
必须要做,扩展MVC功能
如果在类上添加@EnableWebMvc,会使所有自动配置失效
设置controller和页面跳转
添加静态资源访问
修改文件后按ctrl F9 build
restful
添加mysql驱动
DataSourceConfiguration配置了多个数据源,它们实现了DataSource接口,DataSourceConfiguration由spring提供
通过DataSource接口,可以获得连接对象,并且进行CRUD
DataSource配置文件
读取配置文件
关闭资源
导入
配置yml文件
spring.datasource.username=root
spring.datasource.password=123456
spring.datasouce.url=jdbc:mysql:///0308?useUnicode=true&characterEncoding=utf8&serverTimezone=UTC
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
优点:不需要配置
缺点:不能使用动态sql
@Mapper 创建接口的代理对象
get-查询
post-保存
delete-删除
put-更新
新增数据后返回ID
为什么有红线,因为是接口,没有实现类。但是程序一旦运行就会个接口创建代理对象。解决方法是DeptMapper.java添加@Repository注解
- yml添加
mybatis:
config-location: classpath:mybatis/mybatis-config.xml
mapper-location: classpath:mybatis/mapper/*.xml
-
在resouces目录创建mybatis目录,存放mybatis的xml配置文件,添加分页插件的依赖
-
创建mapper.xml文件,resouces/mybatis/mapper
@Mapper 通过接口生成代理对象
- 可以不适用@Mapper接口,在启动类中添加@MapperScan(value="com.woniu.mapper")
- 在mapper.xml里将emp和数据库表映射
insert返回ID,resultType必须加,否则会报错
- 配置c3p0Config.java,生成c3p0对象,并且将yml里的属性载入进去
-
配置依赖
<dependency> <groupId>org.mybatis.generator</groupId> <artifactId>mybatis-generator-core</artifactId> <version>1.3.7</version> </dependency>
-
拷贝mbg.xml到根目录
&要用&代替
-
拷贝生成java
//在service上添加注解
@Transactional
//在主配置类添加注解
@EnableTransactionManagement
实现ConfigurableServletWebServerFactory接口
中央控制器通过路径来访问控制器
实现Filter接口(注意包),然后在myConfigurableServletWebServerFactory中注册
contextInitialized方法常用语加载配置文件
destroy常用于清空缓存
实现特定的listener接口,然后
web依赖里排除tomcat,引入其它web容器,比如jetty,undertow
tomcat | jetty | undertow | |
---|---|---|---|
jsp | 支持 | 不支持 | |
长连接 | 不好 | 较好 | 中等 |
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
Controller里,默认会在返回值里添加**/templates/**前缀和.html后缀
- Map
- Model
- ModelAndView
<span th:text="${name}">admin</span> //以文本显示,如果${name}获取不到则显示admin
th:text="张三"
th:text="111aaa"
th:utext="${}" //以HTML效果显示
//格式化时间
${#dates.format(date, 'dd/MMM/yyyy HH:mm')}
th:object="${user}" //定义子标签的对象
th:text="*{uname}" //父对象的属性
th:if="" //优先级比较高
//直接修改标签属性
th:id=
th:class=
th:each="u:${lists}" th:if="$"
th:each="u,stat:${lists}" //stat可以获取下标
th:text="${stat.index}" //输出序号
${session.info} session对象
${#strings.isEmpty()} //判断字符串是否为空
//字符串拼接
th:include
@{/js/jquery3.1.js} //使用绝对路径引用资源
th:href="@{http://www.baidu.com(name="peter",pass="1234")}" //url传参,等于www.baidu.com?name=peter&pass=1234
//行内写法
[[#{login.remember}]]
使用@{}引用图片会出现无法引用的情况,因为target不编译图片目录
放在内
spring:
thymeleaf:
cache:false
在resouces目录创建i18n,里面创建properties文件
spring.messages.basename=i18n.login,注意messages在spring的下一级
使用#{login.btn} 读取配置文件文字
yml配置
//设置超链接,login.html不是页面,而是路径
th:href="@{/login.html(lang=zh_CN)}"
//创建自定义解析器,实现LocalResolver接口
拦截请求,获取lang的值,通过字符串分隔得到国家和语言
实现LocaleResolver接口,根据获取的lang值设置Locale对象
@Configuration
public class MyLocaleResolver implements LocaleResolver {
@Override
public Locale resolveLocale(HttpServletRequest request) {
String language=request.getParameter("lang");
System.out.println("language="+language);
Locale locale=Locale.getDefault();
if(!StringUtils.isEmpty(language)){
String[] s=language.split("_");
locale=new Locale(s[0], s[1]);
}
return locale;
}
@Override
public void setLocale(HttpServletRequest request, HttpServletResponse response, Locale locale) {
}
}
在配置类,添加自定义的解析器
@Bean
public LocaleResolver localeResolver(){
return new MyLocaleResolver();
}
前面是html页面名称,后面是fragment名称
th:insert
:保留自己的主标签,保留th:fragment的主标签。th:replace
:不要自己的主标签,保留th:fragment的主标签。th:include
:保留自己的主标签,不要th:fragment的主标签。(官方3.0后不推荐)
login.html 不是页面,只是路径
图片,css,js 加th:href th:link @{}
pom里添加打包静态资源
requestMapping两级路径一定要加/
@PostMapping --只接收post请求
springboot 1.x 自动静态资源映射 但是2.X后拦截
经过拦截器需要添加static
修改左侧dashboard链接
在链接里添加参数flag
在链接的class类判断flag字段
restuful风格传参
方法1
方法2
Controller里要用集合来获得数据
搜索的反显
新增功能
不能使用转发
日期属性添加注解
修改功能
修改按钮向后传值
删除功能
del方法里通过ajax传送到后台
restful风格传参
-
配置c3p0 注意url要加时区
-
逆向工程
-
mybatis
生日属性
首页数据封装到一个类里
question里封装cate属性,封装用户(id,名称,头像)
answer里封装user,question
映射对象属性可以用automapping
启动类在其它位置
vue
beforeMount 渲染前查询
enctype
multipartfile
- 首页分类显示
- 首页链接能点进去
- 在问-显示所有问题
- 个人中心
- 待回答
- 我的提问
- 我的回答
- 修改个人资料
- 拦截器
- 发问题
- 回答问题
- 评论
上午阶段考试,下午项目验收
周三多线程
周四--四阶段开始
用于处理数据,包括关系型数据库和非关系型数据库
无视持久层框架
我们不需要编写实现,只要操作接口和提供sql语句。
本质是操作JPA接口。
适用于中小型系统,大型系统不适用
JPA接口的作者是hibernate的作者
ORM映射:把数据和模型对应起来
O:Object
R:relation
M:model
mybatis没有实现JPA标准
JPA底层使用Hibernate
-
配置pom jdbc jpa springdata
-
配置yml
-
创建entity
- 在实体类class上添加@Entity注解,代表这是和数据库映射的实体
- 在实体类class上添加@Table(name="表名")
- 在实体类class上添加@Proxy(lazy=true/false)延迟加载,使用对象的时候才查询
- 在主键上添加@Id
- 主键添加生成策略@GeneratedValue(AUTO/SEQUENSE/IDENTITY) 自增长
- @Column(name="",length=,unique=,nullable) 指定列名,指定长度,是否为空等参数
- @Tempral 指定时间类型:Date,Time,TimeStamp
-
dao层继承 findStudentBySnameAnd/OrAge
findStudentBySnameLike()
-
调用3中创建的类的方法
创建外键的注解
save 保存
saveAndFlush 保存和修改
级联操作
- 一对一关系
自动先保存丈夫,然后保存妻子
所有的双向关系都只需要维护一方
husband.class 不需要配置注解
- 一对多关系
狗:
- 多对对关系
通过第三张表
比如学生和课程
--实际存放在map里
applicationContext
生成bean工程的时候就已经生成了对象
注入:
set注入值,注入对象
@ComponentScan
西安,高鹏老师 26中设计模式讲的很好
手工创建BeanFactory
IOC原理:
利用反射创建对象,利用工厂模式获取对象
把通用功能封装起来(不是创建工具类),主动提供,甚至使用者都不知道AOP的存在,作用是解耦合
概念
通知:封装的通用功能
连接点:加通知的方法
切入点:连接点组合
切面:切入点+通知
织入:把通知加入到连接点的过程
通知类型
before:方法前执行
after:方法后执行,无论方法是否报错
returnAfter:方法正常执行后执行
错误通知:报错后执行
around:方法前后都会执行
如何选择切入点:
execution表达式
事务的隔离级别
-
ORM映射
类id----主键
类对象关系---外键关系
-
原理
- sqlSessionFactory,一个数据供只有一个,线程安全
- 通过sqlSessionFactory创建sqlSession对象,是mybatis中的一级缓存
- sqlSession创建executor(statement)
- 调用sqlSession中的方法,进行操作数据库的操作(selectOne,selectList,insert,update,delete)
-
#和$的区别 #是占位符方式,不能防止sql注入,字符串自动单引号
-
参数的传递
封装成map集合,在接口的参数前添加@Param
映射文件中通过list arrays param[0] args[0]
-
xml中如何封装属性对象
association--封装单个对象
collection--集合
resultMap--自定义对象
resultType--
-
缓存
/:前面加上服务器地址http://localhost:8080,其实也是相对路径,相对于服务器根目录
webapp-root ---web根路径
thymeleaf的@{/***}会自动添加webroot路径,也就是服务器路径+项目路径
相对于URL地址映射地址,而不是服务器内的文件地址,也就是会在路径前添加当前文件的所在路径。
- a链接
- thymeleaf
-
以上两种方法后台可以通过对象来接收参数,需要添加@RequestBody,
3.1 前台json对象传送到后台用@RequestBody接收,前台必须用JSON.stringfy() 格式化
时间片--最小的时间单位
上下文切换--进程/线程之间切换的时间
线程--CPU调度的最小单位,真正干活的是线程
并行--同一时刻能处理的事情数量,取决于硬件性能
并发--单位时间内,可以处理事情的数量,在相同并行条件下,衡量处理能力。
JVM原生是多线程的
配置文档注释
-
继承Thread,适用于批量产生线程
重写run方法,然后通过start方法调用run方法
final 修饰不能重写
线程名Thread-X 0开始
缺点:单继承,扩展不方便
-
实现Runnable接口 Runnable的实现类不是接口,只是规范了run方法
启动线程方法:
run和start的区别:run在main线程,start新建了线程
方便后期扩展,可以再继承其它类
JDK1.8之后接口由默认方法,可以有实现
函数式接口:只能有一个抽象方法,使用注解@FunctionalInterface标注
lambda 表达式,替换匿名内部类写法
接口 变量名=(形参) -> {方法体}
-
通过Callable接口(没听完整) 重写call()
两种方式创建:普通和匿名内部类
**面试题:**runnable和callable的区别:前者的run()没有返回值,后者有返回值
创建匿名内部类一定要指定泛型
- 创建Callable对象(可以用lambda简化,需指定返回值)
- 用FutureTask封装
- 创建Thread,futureTask作为形参
runnable解决了Thread的单继承问题
Callable解决了单继承和没有返回值的问题
sleep和wait的区别:sleep不释放锁,wait释放锁
优先级:1-10,默认5,优先级越高,获得CPU时间片的概率越大。线程优先级不可靠,不作为开发的手段。
中断标志位:isInterrupted()
setDaemon(true/false) 设置是否为守护线程
守护线程和主线程同生共死,确保主线程的安全
用途:保证主线程的正常运行,资源释放,服务启动
注意:当调用setDaemon方法后,守护线程中的finally方法不会执行
过时的方式
thread.stop():已过时,暴力停止
thread.resume():已过时,暴力暂停
thread.suspend():已过时,暴力停止
以上三个方法会导致线程不释放资源,资源一直被占用导致死锁,所以不适用
推荐的方式
interrupt():将中断标志位设置为true,
如果出中断异常,会将中断标志位改为false,如果要再次中断,需要
响应式中断(重要,没听懂)
- 不推荐锁方法
- 如果锁普通方法,对象就是this
- 如果锁静态方法,对象就是当前类的字节码对象
- java中任意对象都可以作为锁
- 注意:使用this作为锁的时候只能有一个对象
- run方法里调用方法,可以实现方法的复用
- 可以使用private static final 对象当做锁,但是浪费空间(不推荐)
- 推荐使用类的字节码对象作为锁:xxx.class
- if(stock<=0) 临界值判断
- ++i,--i 不是单步原子性操作,它有三个步骤:取i,i+1,赋值给i
- 直接锁方法
内置原子类
- 里面所有操作都具有单步原子性
- 原理:CAS(Compare and Swap,比较再交换)
- 使用了原子类就不用加锁了,仍然是线程安全的
-
可以实现响应中断
-
需要手动获取锁和解锁
-
isLock() ,tryLock()
native:代表C语言实现的方法
不能使用wait,notify
步骤
方法
signal--唤醒
condition和方法是如何绑定的?
17:15之前的没听到
哪里等待就在哪里唤醒
notify()不靠谱,notifyAll() 靠谱
锁对象和wait,notify等调用对象不一致
synchronied如何产生死锁?如何解决?
ReentrantLock如何产生死锁?如何解决?