原理:
值得一直深究
自动装配:META-INF/spring.factories 自动配置的核心文件
1.pom.xml中,存放的是核心依赖,可以顺着parent点进去,可以看到里面管理这大量的jar包,包括配置文件yml/yaml/properties 等
2.pom.xml中有很多的启动器,也就是带有starter的依赖
3.主程序: Configuration 英文解释:配置 EnableAuto 英文解释:自动
@SpringBootApplication:标注这个类是个springboot的程序,启动类下的资源都会被导入,下面的run(静态方法)是启动方法
@SpringBootConfiguration(核心注解) :springboot的配置
@Configuration:说明这个类是springboot的配置类
@Component:说明这是spring的组件
@EnableAutoConfiguration(核心注解):自动配置
@AutoConfigurationPackage:自动配置包
@Import(AutoConfigurationPackages.Registrar.class):自动配置 包注册
点进去Registrar.class,可以看到 实现了Import Bean Definition Registrar(导入Bean定义注册商),
重写了方法registerBeanDefinitions,用来注册元数据(AnnotationMetadata),以及Bean定义注册商(BeanDefinitionRegistry)
@Import(AutoConfigurationImportSelector.class) 自动配置导入选择
selectImports方法:选择组件,主要就是选择pom.xml中的依赖
getAutoConfigurationEntry:获取配置:获取所有的配置List<String> configurations = getCandidateConfigurations(annotationMetadata, attributes);
获取候选的配置具体的方法:protected List<String> getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) {
List<String> configurations = SpringFactoriesLoader.loadFactoryNames(getSpringFactoriesLoaderFactoryClass(),
getBeanClassLoader());
Assert.notEmpty(configurations, "No auto configuration classes found in META-INF/spring.factories. If you "
+ "are using a custom packaging, make sure that file is correct.");
return configurations;
}
在继续往下点getSpringFactoriesLoaderFactoryClass,最终指向EnableAutoConfiguration.class,也就是说,只要@EnableAutoConfiguration标注的嘞,都会加载进来,也就是说,启动类下的资源都会被导入
另一情况就是指向自动配置的核心文件,META-INF/spring.factories,在依赖中的org-springframework.boot:spring-boot-autoconfigure下面,里面有所有的自动转配的包
springboot所有的自动配置都是在启动的时候被扫描加载,但是不一定生效,需要注解判断条件是否满足才生效,所有的自动配置都在/spring.factories中,只有判断是否导入的start之后,才会生效,不然就不生效,生效之后,才会被加载生效
项目的结构:
结果:springboot的启动类,要跟controller、service等这些程序放到同一级的目录下
原因:启动类上有@SpringBootApplication注解扫描,这个注解默认的是扫描启动类同包下的
1.关于Mapper和Mapper.xml的问题:一些类似于bingingExecption,等等
1.首先看,启动打包成的target有没有打包到mapper.xml文件,如果没有,那么需要加一些配置文件,
方法1:.yml中加扫描路径
方法2:在pom.xml中加扫描路径 网上一大堆
2.如果打的包里面有,但是还是不行
方法1:mapper和mapper.xml放在一个文件夹下面,把自己写的mapper和mapper.xml放在vo文件夹下面,但是要保证在一个文件夹下面
方法2:mapper方法的src/main/java下面,mapper.xml放在 src/main/resources下面,父类文件夹名称要一直(官方推荐)
2.请求访问的时候,跨域的问题:
方式1:每次请求controller的时候,加上跨域的请求,也就是每个controller开头都加上这个东西
response.setHeader("Access-Contro-Allow-Origin","*")
final HttpHeaders headers=new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON)
就可以了
方式2:集中管理:
拦截器(网上方法甚多比如:@CrossOrigin注解,这里说我自己用的)
定义一个方法使用@Component,实现Filter接口,重写doFilter方法,doFilter里面就可以写跨域请求了,所有的请求都会被拦截在这里,跨域统一管理
传值的问题:
post方式:
@RequestMapping(value="/test",method = RequestMethod.POST) //接收参数的方式
@ResponseBody
public void test(@RequestBody User user){} //用@RequestBody来标注参数
Get 方式
以问号拼接的:例子:http://localhost:8080/test/a?id=1
接收方式:
@RequestMapping(value="/test",method = RequestMethod.GET)
@ResponseBody
public void test(String id ){ }
以/这种restful这种方式接收,例子:http://localhost:8080/test/a/{id}
接收方式:
@RequestMapping(value="/test/{id}",method = RequestMethod.GET)
@ResponseBody
public void test(@PathVariable("id")String id){ }
拦截器的实现:
步骤1:手写方法,implements(实现) HandlerInterceptor,重写 preHandle方法,返回false.意思是拦截
步骤2:
手写方法,implements(实现) WebMvcConfigurer 重写addInterceptors方法,另外把第一不的方法用@Autowired或者@Bean 的方式注入进来,
方法体:registry.addInterceptor(第一步的方法).addPathPatterns("/**").excludepathpatterns("/a/*");
意思是,加载自定义的拦截器,拦截/**的请求,放行/a/*的请求。
访问静态资源的方式:
方式一:
配置文件的方式: 我想访问的路径是 resources/file/a.xlsx 文件
application.properties:
spring.mvc.static-path-pattern=/file/**
spring.resources.static-locations=class:/file
方式二:重写mvc方法实现
步骤:手写方法,implements(实现) WebMvcConfigurer,重写addResourceHandlers方法,方法体:
registry.addResourceHandler("/file/**").addResourceLocations("classpath:/file/*")
两种的访问方式:
http://licalhost:8080/file/a.xlsx
springboot部署linux(这里是自己之前的真实情况)
打包(idea):
快捷方式:
右侧mavan --选择package,这样就直接打包成功,在target下 (前提,所有的打包依赖齐全,否则,报错信息缺什么包,自行下载)
不快捷方式,待测试
把打好的包,部署到远程linux上去(我这里是用的部署工具 winSCP.exe)
前提测试:
查看jdk的安装版本:java -version
如果不符合要求
步骤:1 下载linux版本的jdk 比如jdk-8u161-linux-x64.tar
2.部署到 linux服务器上 ,解压命令:tar -zxvf + 需要解压的东西
3.检测之前的jdk版本 命令 :rpm -qa | grep java
4.如果有之前的版本,需要删除 :命令: rpm -e --nodeps +包名
5.配置环境变量:路径: vim etc/profile
具体配置如下:export JAVA_HOME=/usr/lib/java/jdk1.8.0_151 后面是具体的自己解压jdk的路径
pexport PATH=$PATH:$JAVA_HOME/bin
然后保存退出 esc键+:+w+q+回车(这个是保存然后退出) esc键+:+w+q+!+回车(保存强制退出),
后者如果出现错误,会产生一个隐藏的文件,这个时候,再次修改这个文件,会有报错提示,解决办法是删除错误提示的那个隐藏文件,再次修改
6. 修改的文件需要立即生效,不然,就得重启生效:source /etc/profile
7. 查看现在的jdk版本 命令 : java -version
8. 然后启动之前部署的jar包,
启动方式1:java java -jar jar包 这个 关闭窗口之后就会删除,未测试
启动方式2:nohup java -jar jar包 & 这个关闭窗口之后后台会继续运行
9.测试项目是否启动成功,访问接口,看行不行
遇到的错误:
所有的步骤都进行完成之后,第9不如论如何都不成功,服务器也能ping成功,这个时候,需要查看服务器的防火墙,命令:systemctl status firewalld 查看防火墙状态 systemctl status 是查看服务的状态 ;firewalld 是防火墙 也可以是别的服务
查看防火墙状态:systemctl status firewalld
关闭防火墙:systemctl stop firewalld
关闭防火墙:systemctl start firewalld
注意:查看mysql状态的时候,firewalld改为mysql就可以了
springboot自动装配的原理:
@EnableAutoConfiguration 开始自动配置的功能
@SpringBootConfiguration 表明该类是一个spring的配置类
@ComponentScan 表示扫描注解
@MapperScan 表示扫描mapper注解
@configuration注解代表这个类就是一个配置文件,功能等同于在spring中的Application.xml文件,通常搭配@Bean使用,比如:一个类上使用@configuration,相当于xml文件中的<beans>,然后类中的方法或者属性,加上@Bean注解,相当于<baen>,这样,就注入到容器中了
自动装配:就是找到@EnableAutoConfiguration注解的类,把所需要的类都加载到容器中,然后通过@EnableConfigurationProperties(xxxProperties.class)来配置属性所需要的值,但是还要进入这个类通过@ConfigurationProperties(prefix = “xxx”)来把配置文件中的配置导入进来。
springboot的缓存:
基于注解的缓存
步骤:
1.pom文件中引入spring-boot-starter-cache
2.启动类上加@EnableCaching 来表明开启基于注解的缓存
3.在需要缓存的方法上加注解@Cacheable(value={"a"}) 这个注解的意思,就是加入缓存,可以自定缓存的地方,比如redis等等,还可以起key,网上解释很多
4.需要删除缓存的方法上加@CacheEvict(value={"a"}) 这个注解的意思,就是删除加入的a这个缓存
注意:一定要在加缓存之前把之前的缓存全部清除,不然,就会报错,因为,在走接口的过程中,如果遇到注解,那么就会直接查询缓存中有没有数据,如果有的话,不论对错,都不再走接口
另外:
这个还可以跟别的缓存公用,比如redis,需要指定具体的缓存Manager,这样缓存的东西就直接会存到redis中
一定要注意@CacheEvict(value={"a"},allEntries=true,beforeInvocation=true)中的beforeInvocation属性的使用,allEntries=true是删除所有的该节点的缓存,beforeInvocation=true 这个是默认方法执行前删除缓存,这样就有一个问题,是应该方法执行之后,还是执行之前删除缓存,需要自己斟酌,我这里本来应该是方法之前之后删除缓存,然后,我自己没有想清楚,然后加上这个,导致程序一直报错
@Transactional注解:事务
@Transactional 可以作用在接口、类、类方法。
放在类上,说明这个类的所有pulic的方法都配置了属性相同的事务
放在方法上,说明这个方法也配置了事务属性
放在接口上,待定
属性:
Propagation.REQUIRED:如果当前存在事务,则加入该事务,如果当前不存在事务,则创建一个新的事务
Propagation.SUPPORTS:如果当前存在事务,则加入该事务;如果当前不存在事务,则以非事务的方式继续运行。
Propagation.MANDATORY:如果当前存在事务,则加入该事务;如果当前不存在事务,则抛出异常。
Propagation.REQUIRES_NEW:重新创建一个新的事务,如果当前存在事务,暂停当前的事务。
Propagation.NOT_SUPPORTED:以非事务的方式运行,如果当前存在事务,暂停当前的事务。
Propagation.NEVER:以非事务的方式运行,如果当前存在事务,则抛出异常。
Propagation.NESTED :和 Propagation.REQUIRED 效果一样。
springboot继承ES
ES是基于Lucene(一套信息检索的工具包,jar包,不包含搜索引擎,又java开发)的底层,做了一些封装和增强,ES是高扩展分布式的全文搜索引擎
安装ES:
在官网下载版本ES:https://www.elastic.co/cn/downloads/elasticsearch
在官网下载版本Kibana可视化工具:https://www.elastic.co/cn/downloads/kibana
在github下载ES可视化工具head:https://github.com/mobz/elasticsearch-head(前提,必须安装好nodejs,需要用到命令)
解压就即可使用
注意点:如有需要,配置跨域:
在elasticsearch里面的配置文件elasticsearch.yml,配置如下:
http.cors.enabled: true //可以跨域
http.cors.allow-origin: “*” //允许所搜的访问方式
ES启动:/bin/elasticsearch.bat
head启动命令:/run start
spring中使用事务的注解@Transactional(机制:当发生 Error 或者 RuntimeException 的时候,才会回滚)
加上@Transactional主要作用:
情况1:当注解的方法完成没有错误的事情,操作数据库会加入到数据库中
情况2:当方法出现错误的时候,该注解会把错误之前已经插入数据库的,回滚
前提:必须在使用@Transactional的时候,先要开启事务管理,也就是加上@EnableTransactionManagement,如果用springboot框架,不需要加@EnableTransactionManagement,那是因为springboot启动类上家伙是哪个@springbootApplication注解其实就是多个注解测组合,当中已经自动装配上了@EnableTransactionManagement
@Transactional的属性
传播类型属性: Propagation
Propagation.REQUIRED:默认的属性
如果当前存在事务,则加入该事务,如果当前不存在事务,则创建一个新的事务。
Propagation.SUPPORTS
如果当前存在事务,则加入该事务;如果当前不存在事务,则以非事务的方式继续运行。
Propagation.MANDATORY
如果当前存在事务,则加入该事务;如果当前不存在事务,则抛出异常。
Propagation.REQUIRES_NEW
重新创建一个新的事务,如果当前存在事务,暂停当前的事务。
Propagation.NOT_SUPPORTED
以非事务的方式运行,如果当前存在事务,暂停当前的事务。
Propagation.NEVER
以非事务的方式运行,如果当前存在事务,则抛出异常。
Propagation.NESTED
和 Propagation.REQUIRED 效果一样
超时属性:timeout
默认:-1 就是没有时间限制
只读属性:readOnly
flase:默认 不做限制
ture: 只能执行读取操作
异常回滚属性:rollbackFor:
可以指定触发回滚的异常类型,支持多个
不支持回滚的属性:noRollbackFor
指定那些类型的异常不会滚,支持多个
@Transactional失效的情况:
1.非springboot框架未开始事务管理@EnableTransactionManagement
2.@Transactional主机的方法里面有try{}catch(Exexprion e){} ,把异常捕获了,这也就意味着@Transactional的作用被屏蔽了
3.还有就是报错不是因Error或者RuntimeException 的时候,违反@Transactional触发机制
4.