Loading... ## IDEA创建SpringBoot New Project → Spring Initializr → Lombok+Spring Web+Thymeleaf+Mybatis Framework+MySQL Driver 【BUG】: Maven没有完全下载依赖导致 `@SpringBootApplication`不存在,刷新Maven仍无效。在Settings找到Maven,选择自带的Maven以及仓库,解决。 --- ## pom.xml解读 1.SpringBoot全部都是打成jar包 2.从pom父类<parent> → `<artifactId>spring-boot-starter-parent</artifactId>`的父类中可查看到到**版本仲裁中心**(整合了目前依赖的版本号,避免版本冲突,后续引入依赖不需要指定版本) 3.`spring-boot-starter-web`**web场景启动器**,整合了web所需的各种jar包(json、tomcat、starter等) 【解读】: SpringBoot将各个应用/三方框架设置成了一个个“场景”stater,以后要用哪个,只需要引入那个场景即可。选完之后,SpringBoot就会将 该场景所需要的所有依赖自动注入。如此次用的web。 --- ## @SpringBootApplication解读 `@SpringBootApplication`是SpringBoot的主配置类,包含如下部分注解: ### 一、@SpringBootConfiguration `@SpringBootConfiguration`里面包含 `@Configuration` 【解读】: 1.该类是一个配置类 2.加了 `@Configuration`注解的类,会自动纳入Spring容器(相当于spring中的 `@Component`) ### 二、@EnableAutoConfiguration (1)、`@EnableAutoConfiguration`里面包含 `@AutoConfigurationPackage`,此注解内包含 `@Import(AutoConfigurationPackages.Registrar.class)`,该 `Registrar.class`实现了获取当前包名 `cn.ctx.boot`的方法. ```Java /** * {@link ImportBeanDefinitionRegistrar} to store the base package from the importing * configuration. */ static class Registrar implements ImportBeanDefinitionRegistrar, DeterminableImports { @Override public void registerBeanDefinitions(AnnotationMetadata metadata, BeanDefinitionRegistry registry) { register(registry, new PackageImport(metadata).getPackageName()); } @Override public Set<Object> determineImports(AnnotationMetadata metadata) { return Collections.singleton(new PackageImport(metadata)); } } ``` 【解读】: `@AutoConfigurationPackage`可以找到 `@SpringBootApplication`所在类的包,并将**该包及所有的子包**全部纳入spring容器 (2)、`@EnableAutoConfiguration`里面包含 `@Import(AutoConfigurationImportSelector.class)`,实现获取第三方依赖(jar/配置) ```Java @Override public String[] selectImports(AnnotationMetadata annotationMetadata) { if (!isEnabled(annotationMetadata)) { return NO_IMPORTS; } AutoConfigurationMetadata autoConfigurationMetadata = AutoConfigurationMetadataLoader .loadMetadata(this.beanClassLoader); AutoConfigurationEntry autoConfigurationEntry = getAutoConfigurationEntry(autoConfigurationMetadata, annotationMetadata); return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations()); } ``` 其中 `getAutoConfigurationEntry`中的 `getCandidateConfigurations`中的 `SpringFactoriesLoader.loadFactoryNames()`存在 `Enumeration<URL> urls = classLoader != null ? classLoader.getResources("META-INF/spring.factories") : ClassLoader.getSystemResources("META-INF/spring.factories");` 【解读】: 在SpringBoot启动时,根据 `META-INF/spring.factories`找到相应的三方依赖,并将这些依赖引入本项目 ### 总结 编写项目时,一般会对自己写的代码以及三方依赖进行配置。但是spring boot可以自动进行配置: **a.**自己写的代码,spring boot通过 `@SpringBootConfiguration`自动帮我们配置; **b.**三方依赖通过 `spring-boot-autoconfigure-2.0.3.RELEASE.jar`中的 `META-INF/spring.factories`进行声明,然后通过 `@EnableAutoConfiguration`开启使用即可。该jar包中包含了J2EE整合体系中 需要的依赖。 **c.**如何自动装配(以 `HttpEncoding`为例) ```Java @Configuration //标识此类是一个配置类、将此类纳入spring ioc容器 @EnableConfigurationProperties(HttpEncodingProperties.class) //该注解内部给了默认编码utf8,并且提供了prefix+属性名的方式供我们修改编码。 @ConditionalOnProperty(prefix = "spring.http.encoding", value = "enabled", matchIfMissing = true) //当属性满足要求时,此条件成立(如果没有配置spring.http.encoding.enabled=xxx, 则成立) ``` 每一个 `XxAutoConfiguration`都有很多条件 `@ConditionalOnXxx`,当这些条件都满足时,则此配置自动装配生效。但是我们可以手动修改自动装配:`properties/yml`文件中的**`prefix名.属性名=value`** 如何知道spring boot开启了哪些自动装配、禁止了哪些自动装配: `application.properties`中**`debug=true`** `Positive matches`列表 表示 spring boot自动开启的装配 `Negative matches`列表 表示spring boot在此时 并没有启用的自动装配。 --- ## 配置文件properties/yml ### 注入值 * `application.properties`: k=v ```Java student.name=zs student.age=23 ``` * `application.yml`: **k:空格v、通过垂直对齐指定层次关系** 或 **行内写法**<br>`(k: v(简单类型),[Set/List/数组], {map/对象类型的属性},并且 []可省,{}不能省)`<br>默认可以不写引号; `""`会将其中的转义符进行转义,其他(单引号)不会<br><br>简单类型=八种基本类型+String+Data ```yml student: sex: true birthday: 2019/02/12 location: {province: "陕222西",city: '西\n安',zone: 莲湖\n区} # map 行内写法 #province: 陕西1 #city: 西安1 #zone: 莲湖区1 hobbies: [足球2,篮球22] # 数组 行内写法 []可省略 # - 足球 # - 篮球 skills: 编程333,金融33 # list 行内写法 # - 编程 # - 金融 pet: {nick-name: wc555,strain: hsq} # 对象 行内写法 ``` ### JavaBean绑定 `@ConfigurationProperties(yml/properties)`和 `@Value("xx")` 二者可以互补 ```Java @Component //将此Javabean放入spring容器 @ConfigurationProperties(prefix="student") public class Student { @Value("10000@qq.com") private String email ; } ``` | **功能** | **@ConfigurationProperties** | **@Value** | | ------------------ | ----------------------------------------------------------------- | -------------------------------------- | | 注值 | 批量注入 | 单个 | | 松散语法(驼峰命名) | 支持<br>`stuName:stu-name` | 不支持 | | SpEL | 不支持 | 支持<br>`@Value("${student.uname}")` | | JSR303数据校验 | 支持<br>`@Email`<br>需要开启jsr303数据校验的注解 `@Validated` | 不支持 | | 注入复杂类型 | 支持 | 不支持 | ### 占位符表达式 a.随机数 * `${random.uuid}`:uuid * `${random.value}`:随机字符串 * `${random.int}`:随机整型数 * `${random.long}`:随机长整型数 * `${random.int(10)}`:10以内的整型数 * `${random.int[1024,65536]}`:指定随机数范围 b.引用变量值 ```yml student: name: ${student.user.name:无名} ``` 实际引用的是properties中的student.user.name=zl67,若name不存在则显示 `无名` --- ## @PropertySource spring boot启动时,会默认加载 `application.properties/application.yml`文件中的数据;若修改 `application`此名称则需要在JavaBean中加入该注解才能识别。例如: ```Java @PropertySource(value={"classpath:conf.properties"}) public class Student { ... } ``` 加载 `conf.properties`文件中的数据;但是,`@PropertySource`只能加载 `properties`,不能加载 `yml` --- ## @ImportResource spring等配置文件默认会被spring boot自动给配置好。spring boot默认不识别自己编写spring.xml等配置文件,如果需要识别,则需要在spring boot**主配置类**上通过 `@ImportResource`指定配置文件的路径: ```Java @ImportResource(locations={"classpath:spring.xml"}) @SpringBootApplication public class HelloWorldApplication { public static void main(String[] args) { SpringApplication.run(HelloWorldApplication.class, args); } } ``` 但是不推荐手写spring.xml等配置文件,而是通过注解配置: **写类**、**@Configuration**、**@Bean**,一般放在与主配置类同级的 `config`文件夹下(`config.WebConfig.java`) ```Java @Configuration public class AppConfig { @Bean public StudentService stuService(){//<bean id="xxxxxxxxxxxxx"> StudentService stuService = new StudentService(); // StudentDao stuDao = new StudentDao() ; // stuService.setStudentDao(stuDao); return stuService;//返回值 <bean class="xxxxxxxxxxxxx"> } } ``` 常用写法: ```Java @Configuration public class WebConfig implements WebMvcConfigurer { @Override public void addResourceHandlers(ResourceHandlerRegistry registry) { registry.addResourceHandler("/static/**").addResourceLocations("classpath:/static/"); } } ``` 验证是否成功写入到spring的ioc容器中: ```Java @RunWith(SpringRunner.class) @SpringBootTest public class HelloWorldApplicationTests { @Autowired ApplicationContext context ;//spring ioc容器 @Test //查看指定 public void test(){ StudentService stuService = (StudentService)context.getBean("stuService") ; System.out.println(stuService); } //查看全部 @Test public void test2(){ String[] beanDefinitionNames = context.getBeanDefinitionNames(); for(String beanDefinitionName : beanDefinitionNames){ System.out.println(beanDefinitionName); } } } ``` --- ## 多环境切换 application-环境名.properties/yml application-dev.properties/yml application-test.properties/yml 默认boot会读取application.properties/yml环境 **a.properties** 如果要选择某一个具体的环境:`application.properties`中指定:`spring.profiles.active=环境名(test/dev)` **b.yml** ```yml server: port: 8883 #spring: # profiles: # active: dev --- server: port: 8884 spring: profiles: dev --- server: port: 8885 spring: profiles: test ``` **c.动态切换环境** i:通过运行参数指定环境 (1)Tomcat:Run Configuration - Argument - program Argument `--spring.profiles.active=环境名` (2)命令行方式: `java -jar 项目名.jar --spring.profiles.active=环境名` ii:通过vm参数指定环境 Tomcat :Run Configuration - Argument - VM `-Dspring.profiles.active=环境名` --- ## 配置文件位置 **配置项目名** 默认端口访问时不需要项目名,可在 `application.propertie`s文件中配置 `server.servlet.context-path=/boot` **项目内部的配置文件:** **properties和yml中的配置,相互补充;如果冲突,则properties优先级高。** spring boot默认能够读取的application.properties/application.yml,这2个文件 可以存在于以下4个地方: * file:项目根目录/config * file:项目根目录 * classpath:项目根目录/config * classpath:项目根目录 【注意】: a.如果某项配置冲突,则优先级从上往下 b.如果不冲突,则互补结合使用 **项目外部的配置文件: (补救/大范围修改配置文件)** 1.编译器 Run/Debug Configurations → Configuration → argumenets: `--spring.config.location=D:/application.properties` 2.命令行 `java -jar 项目.jar --spring.config.location=D:/application.properties` **项目运行参数: (补救/修改个别配置参数)** 1.编译器 Run/Debug Configurations → Configuration → argumenets: `--server.port=8883` 2.命令行 `java -jar 项目.jar --server.port=8883` 【注意】: 修改多个参数用**空格**隔开 **优先级** 命令参数(运行参数 > 调用外部的配置文件 )> 内部文件 (properties > yaml) (具体参考官方文档:[24. Externalized Configuration](https://docs.spring.io/spring-boot/docs/2.0.4.RELEASE/reference/htmlsingle/#boot-features-external-config)) --- ## 日志 **日志框架:** UCL、JUL、jboss-logging、logback、log4j、log4j2、slf4j... SpringBoot默认选用:`slf4j`、`logback` **日志级别:** TRACE < DEBUG < INFO < WARN < ERROR < FATAL < OFF SpringBoot默认的日志级别是INFO(即只打印INFO及之后级别的信息) 可以自定义级别, ```application #properties: logging.level.主配置类所在包=级别 logging.level.cn.ctx.boot=warn #yml logging: level: cn.ctx.boot: warn ``` **日志位置:** * 存储到文件中(项目根目录):`logging.file.name=springboot.log` * 存储到文件中(指定路径):`logging.file.name=D:/springboot.log` * 存储到文件夹中(默认文件名 `spring.log`):`logging.file.path=D:/log/` **日志格式** ```application #控制台: logging.pattern.console=%d{yyyy-MM-dd} [%thread] %-5level %logger{50} - %msg%n #文件: logging.pattern.file=%d{yyyy-MM-dd} [%thread] %-5level %logger{50} - %msg%n ``` * `%d`:日期时间 * `%thread`:线程名 * `%-5level`:显示日志级别,-5表示从左显示5个字符宽度 * `%logger{50}`:设置日志长度,不够显示则头名称缩写,例如**o.s.w.s.m.m.a.** * `%msg`:日志消息 * `%n`:回车 默认的日志格式,是在 jar包中相应包的xml文件中进行配置。[【日志的具体使用规范】](https://docs.spring.io/spring-boot/docs/2.0.4.RELEASE/reference/htmlsingle/#boot-features-custom-log-configuration) --- ## SpringBoot开发Web项目 ### Webjars存放静态资源 通过 `WebMvcAutoConfiguration`类底下的 `addResourceHandlers()`推出 `/webjars/`: ```Java @Override public void addResourceHandlers(ResourceHandlerRegistry registry) { if (!this.resourceProperties.isAddMappings()) { logger.debug("Default resource handling disabled"); return; } if (!registry.hasMappingForPattern("/webjars/**")) { ResourceHandlerRegistration registration = registry.addResourceHandler("/webjars/**") .addResourceLocations("classpath:/META-INF/resources/webjars/"); configureResourceCaching(registration); customizeResourceHandlerRegistration(registration); } String staticPathPattern = this.webFluxProperties.getStaticPathPattern(); if (!registry.hasMappingForPattern(staticPathPattern)) { ResourceHandlerRegistration registration = registry.addResourceHandler(staticPathPattern) .addResourceLocations(this.resourceProperties.getStaticLocations()); configureResourceCaching(registration); customizeResourceHandlerRegistration(registration); } } ``` WebJars是将Web前端JQuery和Bootstrap等资源打包成Java的Jar包,这样在Java Web开发中我们可以借助Maven这些依赖库的管理。 项目中需要的JQuery和Bootstrap的Maven依赖可以去[WebJars官网](https://www.webjars.org/)找到相应的Maven依赖添加到 `pom.xml`中 【引入】从Jar目录结构的webjars开始写: `http://localhost:8080/webjars/jquery/3.3.1/jquery.js` `<link th:href="@{/webjars/bootstrap/4.1.3/css/bootstrap.css}" rel="stylesheet">` ### SpringBoot存放静态资源 ```Java public class ResourceProperties { private static final String[] CLASSPATH_RESOURCE_LOCATIONS = { "classpath:/META-INF/resources/", "classpath:/resources/", "classpath:/static/", "classpath:/public/" }; } ``` 从上可知,SpringBoot的约定:SpringBoot将一些目录结构设置成静态资源存放目录,我们的静态资源直接放入这些目录即可。 **【注意】:** 在以上目录存放资源文件后,访问时不需要加前缀,直接访问即可:`http://localhost:8080/world.html` **自定义静态资源目录** Properties文件中的 prefix+属性,自定义静态资源目录后 以前默认的目录会失效: `spring.resources.static-locations=classpath:/res/, classpath:/img/` ### 欢迎页/Logo **默认欢迎页:** 从 `WebMvcAutoConfiguration`类中的 `welcomePageHandlerMapping()` → `getIndexHtml()` → `location + "index.html"`,可知,任意一个静态资源目录中的 `index.html`就是欢迎页 **默认Logo:** 网站中网页标签的Logo是固定名字 :`favicon.ico` 阅读源码得知 :只需要将favicon.ico文件放入**任意静态资源目录**中即可。 ### 访问static静态资源失效/无法访问templates问题 **访问static静态资源失效:** 从源码可知classpath下默认可以访问,若无法访问则在项目底下添加 `config/WebConfig` ```Java /** * WebMvc配置 */ @Configuration public class WebConfig implements WebMvcConfigurer { @Override public void addResourceHandlers(ResourceHandlerRegistry registry) { registry.addResourceHandler("/static/**").addResourceLocations("classpath:/static/"); } } ``` **无法访问templates问题:** SpringBoot默认不能直接访问templates下的资源文件,可以通过 `Controller`修改所有. ```Java @Controller public class PageController { @RequestMapping("{module}/{url}.html") public String module(@PathVariable("module") String module, @PathVariable("url") String url){ return module + "/" + url; } } ``` --- ## SpringBoot整合JSP开发【了解】 SpringBoot整合JSP开发,需要单独配置一个外置的Tomcat,并且项目打war包 1.新建SpringBoot项目,选择War包,并修改Tomcat依赖 ```Java <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-tomcat</artifactId> <scope>provided</scope> </dependency> ``` 2.建立基本的web项目所需要的目录结构 `webapps/WEB-INF` `webapps/index.jsp` 3.创建Tomcat实例、部署项目 访问:**域名:端口/项目名/文件名** `localhost:8080/SbJSP/index.jsp` 【分析】 如果是一个war包的SpringBoot项目,在启动服务器Tomcat时,会自动调用 `ServletInitializer`类中 的 `configure()`方法,`configure()`方法会调用SpringBoot的主配置类从而启动SpringBoot。即在启动Tomcat服务器时,会先启动Tomcat,再自动启动SpringBoot Last modification:August 12, 2022 © Allow specification reprint Like 0 喵ฅฅ