SpringBoot 基于Spring4.0 设计,不仅继承了Spring框架原有的优秀特性,而且还通过简化配置来进一步简化了Spring应用的整个搭建和开发过程,另外SpringBoot通过集成大量的框架使得依赖包的版本冲突,以及引用的不稳定性等问题得以解决。Spring Boot是由Pivotal团队提供的全新框架,其设计目的是用来简化新Spring应用的初始搭建以及开发过程。该框架使用了特定的方式来进行配置,从而使开发人员不再需要定义样板化的配置。
Create stand-alone Spring applications
Embed Tomcat, Jetty or Undertow directly (no need to deploy WAR files)
Provide opinionated ‘starter’ dependencies to simplify your build configuration
Automatically configure Spring and 3rd party libraries whenever possible
Provide production-ready features such as metrics, health checks, and externalized configuration
Absolutely no code generation and no requirement for XML configuration
微服务
1.微服务(Microservices)是一种软件架构风格,它是以专注于单一责任与功能的小型功能区块 (Small Building Blocks) 为基础,利用模块化的方式组合出复杂的大型应用程序,各功能区块使用与语言无关 (Language-Independent/Language agnostic)的API集相互通信。
2014年,Martin Fowler 与 James Lewis 共同提出了微服务 的概念,定义了微服务是由以单一应用程序构成的小服务,自己拥有自己的进程与轻量化处理,服务依业务功能设计,以全自动的方式部署,与其他服务使用HTTP API通信。同时服务会使用最小的规模的集中管理 (例如 Docker) 能力,服务可以用不同的编程语言与数据库等组件实现。
1.微服务是一种开发软件的架构和组织方法,其中软件由通过明确定义的 API 进行通信的小型独立服务组成。这些服务由各个小型独立团队负责。
2.整体式架构与微服务架构
通过整体式架构,所有进程紧密耦合,并可作为单项服务运行。这意味着,如果应用程序的一个进程遇到需求峰值,则必须扩展整个架构。随着代码库的增长,添加或改进整体式应用程序的功能变得更加复杂。这种复杂性限制了试验的可行性,并使实施新概念变得困难。整体式架构增加了应用程序可用性的风险,因为许多依赖且紧密耦合的进程会扩大单个进程故障的影响。
使用微服务架构,将应用程序构建为独立的组件,并将每个应用程序进程作为一项服务运行。这些服务使用轻量级 API 通过明确定义的接口进行通信。这些服务是围绕业务功能构建的,每项服务执行一项功能。由于它们是独立运行的,因此可以针对各项服务进行更新、部署和扩展,以满足对应用程序特定功能的需求。
3.微服务的优势
敏捷性
灵活扩展
轻松部署
技术自由
可重复使用的代码
弹性
初识SpringBoot GitHub Spring Boot
Spring initializr
Spring Boot 2.6.4 API
SpringBoot Docs
Spring Boot Reference Documentation
官网 Maven Project 2.6.4 8
IDEA集成
Dependencies
Website
Spring Web:Build web, including RESTful, applications using Spring MVC. Uses Apache Tomcat as the default embedded container.
IDEA
Spring initializr->Dependencies->Web
Maven
1 2 3 4 5 <dependency > <groupId > org.springframework.boot</groupId > <artifactId > spring-boot-starter-web</artifactId > </dependency >
1.官网包如果没有导入依赖和对应文件结构可以在Settings中选择对应Maven位置Plugin
2.org.springframework.boot:spring-boot-maven-plugin: not found(添加版本号)
1 2 3 4 5 <plugin > <groupId > org.springframework.boot</groupId > <artifactId > spring-boot-maven-plugin</artifactId > <version > 2.3.4.RELEASE</version > </plugin >
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 │ .gitignore │ HELP.md │ mvnw │ mvnw.cmd │ pom.xml │ ├─.idea │ .gitignore │ compiler.xml │ encodings.xml │ jarRepositories.xml │ misc.xml │ runConfigurations.xml │ uiDesigner.xml │ workspace.xml │ ├─.mvn │ └─wrapper │ maven-wrapper .jar │ maven-wrapper .properties │ ├─src │ ├─main │ │ ├─java │ │ │ └─com │ │ │ └─example │ │ │ └─demo │ │ │ │ SpringbootDemoApplication.java(程序主入口) │ │ │ │ │ │ │ ├─controller │ │ │ │ HelloController.java │ │ │ │ │ │ │ ├─dao │ │ │ ├─pojo │ │ │ └─service │ │ └─resources │ │ │ application.properties │ │ │ │ │ ├─static │ │ └─templates │ └─test │ └─java │ └─com │ └─example │ └─demo │ SpringbootDemoApplicationTests.java │ └─target ├─classes │ │ application.properties(SpringBoot核心配置文件) │ │ │ └─com │ └─example │ └─demo │ │ SpringbootDemoApplication.class │ │ │ └─controller │ HelloController.class │ ├─generated -sources │ └─annotations ├─generated -test-sources │ └─test-annotations └─test-classes └─com └─example └─demo SpringbootDemoApplicationTests.class (单元测试)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 <?xml version="1.0" encoding="UTF-8"?> <project xmlns ="http://maven.apache.org/POM/4.0.0" xmlns:xsi ="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation ="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd" > <modelVersion > 4.0.0</modelVersion > <parent > <groupId > org.springframework.boot</groupId > <artifactId > spring-boot-starter-parent</artifactId > <version > 2.6.4</version > <relativePath /> </parent > <groupId > com.example</groupId > <artifactId > demo</artifactId > <version > 0.0.1-SNAPSHOT</version > <name > SpringbootDemo</name > <description > Demo project for Spring Boot</description > <properties > <java.version > 1.8</java.version > </properties > <dependencies > <dependency > <groupId > org.springframework.boot</groupId > <artifactId > spring-boot-starter-web</artifactId > </dependency > <dependency > <groupId > org.springframework.boot</groupId > <artifactId > spring-boot-starter-test</artifactId > <scope > test</scope > </dependency > </dependencies > <build > <plugins > <plugin > <groupId > org.springframework.boot</groupId > <artifactId > spring-boot-maven-plugin</artifactId > </plugin > </plugins > </build > </project >
1 2 3 4 5 6 7 8 9 10 11 12 13 package com.example.demo.controller;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RestController;@RestController public class HelloController { @RequestMapping("hello") public String hello () { return "Hello SpringBoot" ; } }
打包(Jar): Maven(右侧)->Lifecycle->package(可在target目录下生成对应jar包)
执行:java -jar demo-0.0.1-SNAPSHOT.jar
1 2 3 4 5 <dependency > <groupId > org.springframework.boot</groupId > <artifactId > spring-boot-devtools</artifactId > </dependency >
Banner 1.自定义Banner
spring boot项目启动时会打印spring boot的ANSI字符画
1.在Spring Boot工程的/src/main/resources目录下创建含有自定义字符画的banner.txt 文件
Spring Boot框架在启动时会按照以下顺序,查找banner信息:
在 Classpath 下查找文件 banner.gif 或 banner.jpg 或 banner.png
以上都没有就在 Classpath 下找 banner.txt
都没找到使用默认 SpringBootBanner
2.重写Banner类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 package com.zero.demo.Banner;import org.springframework.boot.Banner;import org.springframework.core.env.Environment;import java.io.PrintStream;public class MyBanner implements Banner { private static final String BANNER = "\n :) \n" ; @Override public void printBanner (Environment environment, Class<?> sourceClass, PrintStream out) { out.println(BANNER); } }
1 2 3 4 5 6 7 8 9 10 @SpringBootApplication public class DemoApplication { public static void main (String[] args) { SpringApplication springApplication = new SpringApplication(DemoApplication.class); springApplication.setBanner(new MyBanner()); springApplication.run(args); } }
2.隐藏Banner
1 2 3 4 5 6 7 8 9 10 11 12 @SpringBootApplication public class DemoApplication { public static void main (String[] args) { SpringApplication springApplication = new SpringApplication(DemoApplication.class); springApplication.setBannerMode(Banner.Mode.OFF); springApplication.run(args); } }
1 spring.main.banner-mode =off
Run/Debug Configurations->Spring Boot->Hide Banner
SpringBoot自动装配原理
Dependencies
引入大多数SpringBoot应用时不需要版本号,因为Spring-boot-dependenceies含有对应版本参数
Starter using-boot-starter
starter无需用户导入依赖库以及各种配置信息,只需要在maven中引入对应的starter依赖即可,SpringBoot会自动通过classpath路径下的类发现需要的Bean并注册到IOC容器。Spring Boot提供了针对日常企业应用研发各种场景的spring-boot-starter依赖模块。这些依赖模块都遵循着约定成俗的默认配置,并允许调整配置。
Starters are a set of convenient dependency descriptors that you can include in your application. You get a one-stop shop for all the Spring and related technologies that you need without having to hunt through sample code and copy-paste loads of dependency descriptors.
The starters contain a lot of the dependencies that you need to get a project up and running quickly and with a consistent, supported set of managed transitive dependencies.
1.在Spring Boot Framework中,Spring Boot官方的启动器都是以spring-boot-starter-* 命名的,其中*
表示特定类型的应用程序。
2.使用Spring和JPA进行数据库访问,则需要在项目的pom.xml
文件中包含spring-boot-starter-data-jpa
依赖项。而第三方的启动器不能以spring-boot开头命名(Spring Boot官方artifacts),第三方启动器通常以项目名称开头,如mybatis的mybatis-spring-boot-starter。
自定义Starter
1.编写Starter
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 <dependencies > <dependency > <groupId > org.springframework.boot</groupId > <artifactId > spring-boot-starter</artifactId > </dependency > <dependency > <groupId > org.springframework.boot</groupId > <artifactId > spring-boot-autoconfigure</artifactId > <version > 2.0.0.RELEASE</version > </dependency > <dependency > <groupId > org.springframework.boot</groupId > <artifactId > spring-boot-configuration-processor</artifactId > <version > 2.0.0.RELEASE</version > <optional > true</optional > </dependency > <dependency > <groupId > org.apache.maven.plugins</groupId > <artifactId > maven-assembly-plugin</artifactId > <version > 3.0.0</version > </dependency > <dependency > <groupId > org.springframework.boot</groupId > <artifactId > spring-boot-starter-web</artifactId > </dependency > </dependencies > <build > <plugins > <plugin > <artifactId > maven-assembly-plugin</artifactId > <version > 3.0.0</version > <configuration > <descriptorRefs > <descriptorRef > jar-with-dependencies</descriptorRef > </descriptorRefs > </configuration > <executions > <execution > <id > make-assembly</id > <phase > package</phase > <goals > <goal > single</goal > </goals > </execution > </executions > </plugin > </plugins > </build >
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 @ConfigurationProperties( prefix = "spring.zero" ) public class ZeroProperties { private String projectName; private String projectAuthor; private Date projectTime; public ZeroProperties () { } public String getProjectName () { return this .projectName; } public void setProjectName (String projectName) { this .projectName = projectName; } public String getProjectAuthor () { return this .projectAuthor; } public void setProjectAuthor (String projectAuthor) { this .projectAuthor = projectAuthor; } public Date getProjectTime () { return this .projectTime; } public void setProjectTime (Date projectTime) { this .projectTime = projectTime; } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 @ConfigurationProperties(prefix = "spring.zero") public class ZeroProperties { private String projectName; private String projectAuthor; private Date projectTime; public String getProjectName () { return projectName; } public void setProjectName (String projectName) { this .projectName = projectName; } public String getProjectAuthor () { return projectAuthor; } public void setProjectAuthor (String projectAuthor) { this .projectAuthor = projectAuthor; } public Date getProjectTime () { return projectTime; } public void setProjectTime (String time) throws ParseException { this .projectTime = new SimpleDateFormat("yyyy-MM-dd" ).parse(time); } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 public class ZeroService { private ZeroProperties properties; public ZeroService () { } public ZeroService (ZeroProperties zeroProperties) { this .properties = zeroProperties; } public String getProjectInfo () { return "This project is " + properties.getProjectName() + " , author is " + properties.getProjectAuthor() + " , creation time is " + properties.getProjectTime().toString(); } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 @Configuration @EnableConfigurationProperties(ZeroProperties.class) @ConditionalOnClass(ZeroService.class) @ConditionalOnProperty(prefix = "spring.zero",value = "enabled",matchIfMissing = true) public class ZeroServiceAutoConfiguration { @Autowired private ZeroProperties properties; @Bean @ConditionalOnMissingBean(ZeroService.class) public ZeroService zeroService () { return new ZeroService(properties); } }
resources下创建目录META-INF,在 META-INF 目录下创建 spring.factories,在SpringBoot启动时会根据该类文件来加载项目的自动化配置类
1 org.springframework.boot.autoconfigure.EnableAutoConfiguration =com.zero.ZeroServiceAutoConfiguration
2.使用自定义Starter
新建SpringBoot项目,在Project Structure检查是否maven版本正确
将jar包加入Maven(Terminal)
1 mvn install:install-file -DgroupId="com.zero" -DartifactId=spring-boot-zero-starter -Dversion="0.0.1-SNAPSHOT" -Dpackaging=jar -Dfile="C:\Users\29921\Desktop\spring-boot-zero-starter-0.0.1-SNAPSHOT.jar"
1 2 3 4 5 <dependency > <groupId > com.zero</groupId > <artifactId > spring-boot-zero-starter</artifactId > <version > 0.0.1-SNAPSHOT</version > </dependency >
1 2 3 4 5 spring: zero: project-name: MyStarter project-author: Zero project-time: 2022-01-23
1 2 3 4 5 6 7 8 9 10 @RestController @RequestMapping("/my") public class TestController { @Resource private ZeroService zeroService; @GetMapping("/starter") public Object starter () { return zeroService.getProjectInfo(); } }
SpringBootApplication 1 2 3 4 5 6 7 @SpringBootApplication public class DemoApplication { public static void main (String[] args) { SpringApplication.run(DemoApplication.class); } }
yaml
概述
1.YAML是一个可读性高,用来表达资料序列化的格式。YAML参考了其他多种语言,包括:C语言、Python、Perl,并从XML、电子邮件的数据格式(RFC 2822)中获得灵感。Clark Evans在2001年首次发表了这种语言。
2.YAML是YAML Ain't a Markup Language
(YAML不是一种标记语言)的递归缩写。开发该语言时YAML其实是Yet Another Markup Language
(仍是一种标记语言),但为了强调这种语言以数据为中心,而不是以标记语言为重点,而用反向缩略语重命名。
3.YAML的语法和其他高级语言类似,并且可以简单表达清单、散列表,标量等资料形态。它使用空白符号缩进和大量依赖外观的特色,特别适合用来表达或编辑数据结构、各种配置文件、倾印调试内容、文件大纲(例如:许多电子邮件标题格式和YAML非常接近)。尽管它比较适合用来表达层次结构式(hierarchical model)的数据结构,不过也有精致的语法可以表示关系性(relational model)的资料。巧妙避开各种封闭符号使得yaml易于上手,如:引号、各种括号等,这些符号在嵌套结构时会变得复杂而难以辨认。
4.YAML 的配置文件后缀为 .yml 。
基本语法
小写敏感
使用缩进表示层级关系
缩进不允许使用tab,只允许空格
缩进的空格数不重要,只要相同层级的元素左对齐即可
#
表示注释,从这个字符一直到行尾,都会被解析器忽略
数据类型
对象:键值对的集合,又称为映射(mapping)/ 哈希(hashes) / 字典(dictionary)
数组:一组按次序排列的值,又称为序列(sequence) / 列表(list)
纯量(scalars):单个的、不可再分的值
YAML 对象 对象键值对
冒号结构 key: value
,冒号后面要加一个空格
将所有键值对写成一个行内对象,key: {key1: value1, key2: value2, ...}
。
使用缩进表示层级关系;
1 2 3 key: child-key: value child-key2: value2
对应 JavaScript
1 { key : { key1 : value1, key2 : value2 } }
可以使用问号加一个空格代表一个复杂的 key,配合一个冒号加一个空格代表一个 value:
1 2 3 4 5 6 7 ? - complexkey1 - complexkey2 : - complexvalue1 - complexvalue2
YAML 数组 一组-
开头的行表示构成一个数组:
转换为 JavaScript
YAML 可使用行内表示:
1 key: [value1 , value2 , ... ]
对应 JavaScript
1 { key : [ value1, value2 ] }
数据结构的子成员是一个数组,可在该项下面缩进一个空格。
1 2 3 4 5 6 7 8 9 10 companies: - id: 1 name: company1 price: 200W - id: 2 name: company2 price: 500W
数组可使用流式(flow)的方式表示:
1 companies: [{id: 1 ,name: company1 ,price: 200W },{id: 2 ,name: company2 ,price: 500W }]
复合结构 数组和对象可以构成复合结构,例:
1 2 3 4 5 6 7 8 9 languages: - Ruby - Perl - Python websites: YAML: yaml.org Ruby: ruby-lang.org Python: python.org Perl: use.perl.org
转换为 json 为:
1 2 3 4 5 6 7 8 9 { languages: [ 'Ruby', 'Perl', 'Python'], websites: { YAML: 'yaml.org', Ruby: 'ruby-lang.org', Python: 'python.org', Perl: 'use.perl.org' } }
纯量 纯量是最基本的,不可再分的值,包括:
1.字符串
字符串默认不使用引号表示
字符串包含空格或特殊字符,需要放在引号之中
单引号和双引号都可使用,双引号不会对特殊字符转义
单引号之中如还有单引号,须连续使用两个单引号转义
字符串可写成多行,从第二行开始,必须有一个单空格缩进。换行符会被转为空格
多行字符串可以使用|
保留换行符,也可以使用>
折叠换行
+
表示保留文字块末尾的换行,-
表示删除字符串末尾的换行
字符串可插入 HTML 标记
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 str: 你好世界 str1: 'Hello world' str2: 'labor' 's day' s1: '内容\n字符串' s2: "内容\n字符串" str3: This is String this: | Foo Bar that: > Foo Bar s1: | Foo s2: |+ Foo s3: |- Foo message: | <p style="color: red"> 段落 </p>
部分转换为JavaScript
1 2 3 4 5 { s1 : '内容\\n字符串' , s2 : '内容\n字符串' } { str : 'This ' } { this : 'Foo\nBar\n' , that : 'Foo Bar\n' } { s1 : 'Foo\n' , s2 : 'Foo\n\n\n' , s3 : 'Foo' } { message : '\n<p style="color: red">\n 段落\n</p>\n' }
2.布尔值
true(True)
和false(False)
1 2 isSet: true isNumber: True
3.整数
1 2 num: 123 count: 0b1010_0111_0100_1010_1110
4.浮点数
1 2 num: 3.14 point: 6.8523015e+5
5.Null
使用~
表示null
6.时间
时间使用ISO 8601格式,时间和日期之间使用T连接,最后使用+代表时区
1 datetime: 2018-02-17T15:02:31+08:00
7.日期
日期使用复合ISO 8601格式,即yyyy-MM-dd
YAML允许使用两个感叹号强制转换数据类型
1 2 e: !!str 12 f: !!str true
对应JavaScript
引用 &
锚点和 *
别名,可以用来引用:
1 2 3 4 5 6 7 8 9 10 11 defaults: &defaults adapter: postgres host: localhost development: database: myapp_development <<: *defaults test: database: myapp_test <<: *defaults
相当于
1 2 3 4 5 6 7 8 9 10 11 12 13 defaults: adapter: postgres host: localhost development: database: myapp_development adapter: postgres host: localhost test: database: myapp_test adapter: postgres host: localhost
&
用来建立锚点(defaults),<<
表示合并到当前数据,*
用来引用锚点。
1 2 3 4 5 - &showell Steve - Clark - Brian - Oren - *showell
转为 JavaScript 代码:
1 [ 'Steve' , 'Clark' , 'Brian' , 'Oren' , 'Steve' ]
1 2 3 4 5 6 <dependency > <groupId > org.springframework.boot</groupId > <artifactId > spring-boot-configuration-processor</artifactId > <optional > true</optional > </dependency >
1 2 3 4 5 6 7 8 @Component @Data @NoArgsConstructor @AllArgsConstructor public class Pet { private String name; private Integer age; }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 @Component @Data @NoArgsConstructor @AllArgsConstructor @ConfigurationProperties(prefix = "person") public class Person { private String name; private Integer age; private Boolean isEmployee; private Date birth; private Map<String,Object> hobbies; private Pet pet; }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 server: port: 8081 person: name: Spring age: 34 isEmployee: true birth: 2020 /08/06 hobbies: - read - code pet: name: Coco age: 6
1 2 3 4 5 6 7 8 9 10 @SpringBootTest class DemoApplicationTests { @Autowired private Person person; @Test void contextLoads () { System.out.println(person); } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 @Data @Component @ConfigurationProperties(prefix = "person") public class Person { private String userName; private Boolean boss; private Date birth; private Integer age; private Pet pet; private String[] interests; private List<String> animal; private Map<String, Object> score; private Set<Double> salarys; private Map<String, List<Pet>> allPets; }
1 2 3 4 5 6 @Data @Component public class Pet { private String name; private Double weight; }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 person: user-name: Admin boss: true birth: 2019 /12/1 20 :01:23 age: 34 pet: name: jackson weight: 23.5 interests: [阅读 ,运动 ] animal: - jerry - mario score: english: first: 30 second: 40 third: 50 math: [131 ,140 ,148 ] chinese: {first: 128 ,second: 136 } salarys: [3999 ,4999.98 ,5999.99 ] allPets: sick: - {name: tom } - {name: jerry ,weight: 47 } health: [{name: mario ,weight: 47 }]
yaml文件加载中文数组时java.lang.IllegalStateException: Failed to load ApplicationContext: 将IDEA右下角格式ISO-8859-1改为UTF-8
指定配置文件
1 2 3 4 5 6 7 8 9 10 11 12 13 @Component @Data @NoArgsConstructor @AllArgsConstructor @PropertySource(value = "classpath:application.properties") public class Pet { @Value("${name}") private String name; @Value("${age}") private Integer age; }
1 2 3 4 5 6 7 8 9 @SpringBootTest class DemoApplicationTests { @Autowired private Pet pet; @Test void contextLoads () { System.out.println(pet); } }
1 2 3 4 5 6 7 8 9 10 @Component @Data @NoArgsConstructor @AllArgsConstructor @ConfigurationProperties(prefix = "pet") public class Pet { private String name; private Integer age; private String id; }
1 2 3 4 pet: name: ${person.name:boot}_dog age: ${random.int} id: ${random.uuid}
@ConfigurationProperties
@Value
功能
批量注入配置文件中的属性
单个指定
松散绑定
支持
不支持
SpEl
不支持
支持
JSR303数据校验
支持
不支持
复杂类型封装
支持
不支持
数据校验 JSR-303是 Java EE 6 中的一项子规范(Bean Validation),官方参考实现是hibernate Validator。 JSR 303 用于对 Java Bean 中的字段的值进行验证。 Spring MVC 3.x 之中支持 JSR-303,可以在控制器中对表单提交的数据方便地验证。 1.导入依赖
1 2 3 4 <dependency > <groupId > org.springframework.boot</groupId > <artifactId > spring-boot-starter-validation</artifactId > </dependency >
2.测试
1 2 3 4 5 6 7 8 9 10 11 12 13 14 @Component @Data @NoArgsConstructor @AllArgsConstructor @ConfigurationProperties(prefix = "pet") @Validated public class Pet { @NotEmpty(message = "姓名不能为空") private String firstName; private Integer age; @Email(message = "邮箱格式错误") private String email; }
Bean Validation 中内置的 constraint
Constraint
详细信息
@Null
被注释的元素必须为 null
@NotNull
被注释的元素必须不为 null
@AssertTrue
被注释的元素必须为 true
@AssertFalse
被注释的元素必须为 false
@Min(value)
被注释的元素必须是一个数字,其值必须大于等于指定的最小值
@Max(value)
被注释的元素必须是一个数字,其值必须小于等于指定的最大值
@DecimalMin(value)
被注释的元素必须是一个数字,其值必须大于等于指定的最小值
@DecimalMax(value)
被注释的元素必须是一个数字,其值必须小于等于指定的最大值
@Size(max, min)
被注释的元素的大小必须在指定的范围内
@Digits (integer, fraction)
被注释的元素必须是一个数字,其值必须在可接受的范围内
@Past
被注释的元素必须是一个过去的日期
@Future
被注释的元素必须是一个将来的日期
@Pattern(value)
被注释的元素必须符合指定的正则表达式
Hibernate Validator 附加的 constraint
Constraint
详细信息
@Email
被注释的元素必须是电子邮箱地址
@Length
被注释的字符串的大小必须在指定的范围内
@NotEmpty
被注释的字符串的必须非空
@Range
被注释的元素必须在合适的范围内
Property Files
By default, the configured locations are . The resulting search order is the following:classpath:/,classpath:/config/,file:./,file:./config/
1.file:./config/
2.file:./
3.classpath:/config/
4.classpath:/
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 │ application.yml │ pom.xml │ ├─.idea ├─.mvn ├─config │ application.yml │ ├─src │ ├─main │ │ ├─java │ │ │ └─com │ │ │ └─zero │ │ │ └─demo │ │ │ │ DemoApplication.java │ │ └─resources │ │ │ application.yml │ │ │ │ │ └─config │ │ application.yml │ │ │ └─test │ └─java │ └─com │ └─zero │ └─demo │ DemoApplicationTests.java │ └─target
1.file:项目次级目录(src包同级) classpath:resources路径
同一路径下优先级:properties > yml > yaml
1 2 3 4 server.port =8080 spring.profiles.active =dev
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 server: port: 8081 spring: profiles: active: test debug: true --- server: port: 8082 spring: config: activate: on-profile: dev --- server: port: 8083 spring: config: activate: on-profile: test
Web开发 静态资源导入 1.WebJars :WebJars are client-side web libraries (e.g. jQuery & Bootstrap) packaged into JAR (Java Archive) files.
Explicitly and easily manage the client-side dependencies in JVM-based web applications
Use JVM-based build tools (e.g. Maven, Gradle, sbt, …) to download your client-side dependencies
Know which client-side dependencies you are using
Transitive dependencies are automatically resolved and optionally loaded via RequireJS
Deployed on Maven Central
Public CDN
1.导入资源
1 2 3 4 5 <dependency > <groupId > org.webjars</groupId > <artifactId > jquery</artifactId > <version > 3.6.0</version > </dependency >
2.访问资源(注意浏览器缓存)
1 2 3 private static final String[] CLASSPATH_RESOURCE_LOCATIONS = new String[]{"classpath:/META-INF/resources/" , "classpath:/resources/" , "classpath:/static/" , "classpath:/public/" };
1 2 3 4 5 6 resources │ application.yml ├─public ├─resources ├─static └─templates
http://localhost:8080/webjars/jquery/3.6.0/jquery.js
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 private Resource getIndexHtml (String location) { return this .getIndexHtml(this .resourceLoader.getResource(location)); } private Resource getIndexHtml (Resource location) { try { Resource resource = location.createRelative("index.html" ); if (resource.exists() && resource.getURL() != null ) { return resource; } } catch (Exception var3) { } return null ; }
SpringMVC
The Spring Web MVC framework (Spring MVC) is a rich “model view controller” web framework. Spring MVC lets you create special @Controller
or @RestController
beans to handle incoming HTTP requests. Methods in your controller are mapped to HTTP by using @RequestMapping
annotations.
Spring Boot provides auto-configuration for Spring MVC that works well with most applications:
Inclusion of ContentNegotiatingViewResolver
and BeanNameViewResolver
beans.
Support for serving static resources, including support for WebJars.
Automatic registration of Converter
, GenericConverter
, and Formatter
beans.
Support for HttpMessageConverters
.
Automatic registration of MessageCodesResolver
.
Static index.html
support.
Custom Favicon
support.
Automatic use of a ConfigurableWebBindingInitializer
bean.
If you want to keep Spring Boot MVC features and you want to add additional MVC configuration (interceptors, formatters, view controllers, and other features), you can add your own @Configuration
class of type WebMvcConfigurer
but without @EnableWebMvc
. If you wish to provide custom instances of RequestMappingHandlerMapping
, RequestMappingHandlerAdapter
, or ExceptionHandlerExceptionResolver
, you can declare a WebMvcRegistrationsAdapter
instance to provide such components.If you want to take complete control of Spring MVC, you can add your own @Configuration
annotated with @EnableWebMvc
.
1 2 3 4 5 6 7 8 @Configuration public class MyMvcConfig implements WebMvcConfigurer { @Override public void addViewControllers (ViewControllerRegistry registry) { registry.addViewController("/hello" ).setViewName("index" ); } }
员工管理系统 1.数据库模拟
1 2 3 4 5 6 7 @Data @AllArgsConstructor @NoArgsConstructor public class Department { private Integer id; private String departmentName; }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 @Data @NoArgsConstructor public class Employee { private Integer id; private String lastName; private String email; private Integer gender; private Department department; private Date birth; public Employee (Integer id, String lastName, String email, Integer gender, Department department) { this .id = id; this .lastName = lastName; this .email = email; this .gender = gender; this .department = department; this .birth = new Date(); } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 @Repository public class DepartmentDao { private static Map<Integer, Department> departments = null ; static { departments = new HashMap<Integer,Department>(); departments.put(101 ,new Department(101 ,"教学部" )); departments.put(102 ,new Department(102 ,"市场部" )); departments.put(103 ,new Department(103 ,"教学部" )); departments.put(104 ,new Department(104 ,"运营部" )); departments.put(105 ,new Department(105 ,"后勤部" )); } public Collection<Department> getDepartments () { return departments.values(); } public Department getDepartmentById (Integer id) { return departments.get(id); } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 @Repository public class EmployeeDao { private static Map<Integer, Employee> employees = null ; @Autowired private DepartmentDao departmentDao; static { employees = new HashMap<Integer,Employee>(); employees.put(1001 ,new Employee(1001 ,"Alice" ,"2329@qq.com" ,1 ,new Department(101 ,"教学部" ))); employees.put(1002 ,new Employee(1002 ,"Bob" ,"232309@qq.com" ,1 ,new Department(102 ,"市场部" ))); employees.put(1003 ,new Employee(1003 ,"Coke" ,"32309@qq.com" ,1 ,new Department(103 ,"教学部" ))); employees.put(1004 ,new Employee(1004 ,"Dice" ,"22309@qq.com" ,1 ,new Department(104 ,"运营部" ))); employees.put(1005 ,new Employee(1005 ,"Eric" ,"23239@qq.com" ,1 ,new Department(105 ,"后勤部" ))); } public static Integer initId = 1006 ; public void addEmployee (Employee employee) { if (employee.getId()==null ){ employee.setId(initId++); } employee.setDepartment(departmentDao.getDepartmentById(employee.getDepartment().getId())); employees.put(employee.getId(),employee); } public Collection<Employee> getAll () { return employees.values(); } public Employee getEmployeeById (Integer id) { return employees.get(id); } public void deleteEmployeeById (Integer id) { employees.remove(id); } }
2.首页访问
1 2 3 4 5 6 7 8 @Configuration public class MyMvcConfig implements WebMvcConfigurer { @Override public void addViewControllers (ViewControllerRegistry registry) { registry.addViewController("/" ).setViewName("index" ); registry.addViewController("/index" ).setViewName("index" ); } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 <!DOCTYPE html > <html xmlns:th ="http://www.thymeleaf.org" > <head > <meta http-equiv ="Content-Type" content ="text/html; charset=UTF-8" > <meta name ="viewport" content ="width=device-width, initial-scale=1, shrink-to-fit=no" > <meta name ="description" content ="" > <meta name ="author" content ="" > <title > Signin Template for Bootstrap</title > <link th:href ="@{/css/bootstrap.min.css}" rel ="stylesheet" > <link th:href ="@{/css/signin.css}" rel ="stylesheet" > </head > <body class ="text-center" > <form class ="form-signin" action ="dashboard.html" > <img class ="mb-4" th:src ="@{/img/bootstrap-solid.svg}" alt ="" width ="72" height ="72" > <h1 class ="h3 mb-3 font-weight-normal" > Please sign in</h1 > <label class ="sr-only" > Username</label > <input type ="text" class ="form-control" placeholder ="Username" required ="" autofocus ="" > <label class ="sr-only" > Password</label > <input type ="password" class ="form-control" placeholder ="Password" required ="" > <div class ="checkbox mb-3" > <label > <input type ="checkbox" value ="remember-me" > Remember me </label > </div > <button class ="btn btn-lg btn-primary btn-block" type ="submit" > Sign in</button > <p class ="mt-5 mb-3 text-muted" > © 2017-2018</p > <a class ="btn btn-sm" > 中文</a > <a class ="btn btn-sm" > English</a > </form > </body > </html >
3.国际化
IDEA->Setting->File Encoding(UTF-8)
安装ResourceBundle Editor插件(用于编辑本地化的属性文件(localized properties files),同时管理所有相关联属性文件中的key/value信息 IDEA右下角Resource Bundle)
在Resource文件夹下新建i18n
文件夹,加入配置文件
1 2 3 4 5 6 login.tip =登录 login.password =密码 login.remember =记住 login.username =用户名 login.btn =登录
1 2 3 4 5 6 login.tip =Sign in login.password =password login.remember =Remember login.username =username login.btn =Sign in
1 2 3 4 5 6 login.tip =Sign in login.password =password login.remember =Remember login.username =username login.btn =Sign in
1 2 3 4 5 6 7 8 spring : thymeleaf : cache : false messages : basename : i18n.login
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 <!DOCTYPE html > <html xmlns:th ="http://www.thymeleaf.org" > <head > <meta http-equiv ="Content-Type" content ="text/html; charset=UTF-8" > <meta name ="viewport" content ="width=device-width, initial-scale=1, shrink-to-fit=no" > <meta name ="description" content ="" > <meta name ="author" content ="" > <title > Signin Template for Bootstrap</title > <link th:href ="@{/css/bootstrap.min.css}" rel ="stylesheet" > <link th:href ="@{/css/signin.css}" rel ="stylesheet" > </head > <body class ="text-center" > <form class ="form-signin" action ="dashboard.html" > <img class ="mb-4" th:src ="@{/img/bootstrap-solid.svg}" alt ="" width ="72" height ="72" > <h1 class ="h3 mb-3 font-weight-normal" th:text ="#{login.tip}" > Please sign in</h1 > <label class ="sr-only" th:text ="#{login.username}" > Username</label > <input type ="text" class ="form-control" th:placeholder ="#{login.username}" required ="" autofocus ="" > <label class ="sr-only" th:text ="#{login.password}" > Password</label > <input type ="password" class ="form-control" th:placeholder ="#{login.password}" required ="" > <div class ="checkbox mb-3" > <label > <input type ="checkbox" value ="remember-me" th:text ="#{login.remember}" > </label > </div > <button class ="btn btn-lg btn-primary btn-block" type ="submit" th:text ="#{login.btn}" > Sign in</button > <p class ="mt-5 mb-3 text-muted" > © 2017-2018</p > <a class ="btn btn-sm" th:href ="@{/index(lang='zh_CN')}" > 中文</a > <a class ="btn btn-sm" th:href ="@{/index(lang='en_US')}" > English</a > </form > </body > </html >
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 public class MyLocaleResolver implements LocaleResolver { @Override public Locale resolveLocale (HttpServletRequest request) { String language = request.getParameter("lang" ); Locale locale = Locale.getDefault(); if (!StringUtils.isEmpty(language)){ String[] split = language.split("_" ); locale = new Locale(split[0 ],split[1 ]); } return locale; } @Override public void setLocale (HttpServletRequest request, HttpServletResponse response, Locale locale) { } }
1 2 3 4 5 6 7 8 9 10 11 12 @Configuration public class MyMvcConfig implements WebMvcConfigurer { @Override public void addViewControllers (ViewControllerRegistry registry) { registry.addViewController("/" ).setViewName("index" ); registry.addViewController("/index" ).setViewName("index" ); } @Bean public LocaleResolver localeResolver () { return new MyLocaleResolver(); } }
4.登录
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 <form class ="form-signin" th:action ="@{/user/login}" > <img class ="mb-4" th:src ="@{/img/bootstrap-solid.svg}" alt ="" width ="72" height ="72" > <h1 class ="h3 mb-3 font-weight-normal" th:text ="#{login.tip}" > Please sign in</h1 > <p style ="color: red" th:text ="${msg}" th:if ="${not #strings.isEmpty(msg)}" > </p > <label class ="sr-only" th:text ="#{login.username}" > Username</label > <input type ="text" name ="username" class ="form-control" th:placeholder ="#{login.username}" required ="" autofocus ="" > <label class ="sr-only" th:text ="#{login.password}" > Password</label > <input type ="password" name ="password" class ="form-control" th:placeholder ="#{login.password}" required ="" > <div class ="checkbox mb-3" > <label > <input type ="checkbox" value ="remember-me" th:text ="#{login.remember}" > </label > </div > <button class ="btn btn-lg btn-primary btn-block" type ="submit" th:text ="#{login.btn}" > Sign in</button > <p class ="mt-5 mb-3 text-muted" > © 2017-2018</p > <a class ="btn btn-sm" th:href ="@{/index(lang='zh_CN')}" > 中文</a > <a class ="btn btn-sm" th:href ="@{/index(lang='en_US')}" > English</a > </form >
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 @Controller public class LoginController { @RequestMapping("/user/login") public String login ( @RequestParam("username") String username, @RequestParam("password") String password, Model model ) { if (!StringUtils.isEmpty(username)&&password.equals("root" )){ return "redirect:/main.html" ; }else { model.addAttribute("msg" ,"用户名或者密码错误" ); return "index" ; } } }
1 2 3 4 5 6 7 8 9 10 11 12 13 @Configuration public class MyMvcConfig implements WebMvcConfigurer { @Override public void addViewControllers (ViewControllerRegistry registry) { registry.addViewController("/" ).setViewName("index" ); registry.addViewController("/index" ).setViewName("index" ); registry.addViewController("/main.html" ).setViewName("dashboard" ); } @Bean public LocaleResolver localeResolver () { return new MyLocaleResolver(); } }
5.登录拦截
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 @Controller public class LoginController { @RequestMapping("/user/login") public String login ( @RequestParam("username") String username, @RequestParam("password") String password, Model model, HttpSession session) { if (!StringUtils.isEmpty(username)&&password.equals("root" )){ session.setAttribute("loginUser" ,username); return "redirect:/main.html" ; }else { model.addAttribute("msg" ,"用户名或者密码错误" ); return "index" ; } } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 public class LoginHandlerIntercept implements HandlerInterceptor { @Override public boolean preHandle (HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { Object loginUser = request.getSession().getAttribute("loginUser" ); if (loginUser==null ){ request.setAttribute("msg" ,"请先登录" ); request.getRequestDispatcher("/index" ).forward(request,response); return false ; }else { return true ; } } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 @Configuration public class MyMvcConfig implements WebMvcConfigurer { @Override public void addViewControllers (ViewControllerRegistry registry) { registry.addViewController("/" ).setViewName("index" ); registry.addViewController("/index" ).setViewName("index" ); registry.addViewController("/main.html" ).setViewName("dashboard" ); } @Bean public LocaleResolver localeResolver () { return new MyLocaleResolver(); } @Override public void addInterceptors (InterceptorRegistry registry) { registry.addInterceptor(new LoginHandlerIntercept()) .addPathPatterns("/**" ) .excludePathPatterns("/index" ,"/" ,"/user/login" ,"/static/**" ); } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 <!DOCTYPE html > <html lang ="en" > <head > <meta http-equiv ="Content-Type" content ="text/html; charset=UTF-8" > <meta name ="viewport" content ="width=device-width, initial-scale=1, shrink-to-fit=no" > <meta name ="description" content ="" > <meta name ="author" content ="" > <title > Dashboard Template for Bootstrap</title > <link href ="/css/bootstrap.min.css" rel ="stylesheet" > <link href ="/css/dashboard.css" rel ="stylesheet" > <style type ="text/css" > @-webkit-keyframes chartjs-render-animation { from { opacity : 0.99 } to { opacity : 1 } } @keyframes chartjs-render-animation { from { opacity : 0.99 } to { opacity : 1 } } .chartjs-render-monitor { -webkit-animation : chartjs-render-animation 0.001s ; animation : chartjs-render-animation 0.001s ; } </style > </head > <body > <nav class ="navbar navbar-dark sticky-top bg-dark flex-md-nowrap p-0" > <a class ="navbar-brand col-sm-3 col-md-2 mr-0" href ="http://getbootstrap.com/docs/4.0/examples/dashboard/#" > [[${session.loginUser}]]</a > <input class ="form-control form-control-dark w-100" type ="text" placeholder ="Search" aria-label ="Search" > <ul class ="navbar-nav px-3" > <li class ="nav-item text-nowrap" > <a class ="nav-link" href ="http://getbootstrap.com/docs/4.0/examples/dashboard/#" > Sign out</a > </li > </ul > </nav > <div class ="container-fluid" > <div class ="row" > <nav class ="col-md-2 d-none d-md-block bg-light sidebar" > <div class ="sidebar-sticky" > <ul class ="nav flex-column" > <li class ="nav-item" > <a class ="nav-link active" href ="http://getbootstrap.com/docs/4.0/examples/dashboard/#" > <svg xmlns ="http://www.w3.org/2000/svg" width ="24" height ="24" viewBox ="0 0 24 24" fill ="none" stroke ="currentColor" stroke-width ="2" stroke-linecap ="round" stroke-linejoin ="round" class ="feather feather-home" > <path d ="M3 9l9-7 9 7v11a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z" > </path > <polyline points ="9 22 9 12 15 12 15 22" > </polyline > </svg > Dashboard <span class ="sr-only" > (current)</span > </a > </li > <li class ="nav-item" > <a class ="nav-link" href ="http://getbootstrap.com/docs/4.0/examples/dashboard/#" > <svg xmlns ="http://www.w3.org/2000/svg" width ="24" height ="24" viewBox ="0 0 24 24" fill ="none" stroke ="currentColor" stroke-width ="2" stroke-linecap ="round" stroke-linejoin ="round" class ="feather feather-file" > <path d ="M13 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V9z" > </path > <polyline points ="13 2 13 9 20 9" > </polyline > </svg > Orders </a > </li > <li class ="nav-item" > <a class ="nav-link" href ="http://getbootstrap.com/docs/4.0/examples/dashboard/#" > <svg xmlns ="http://www.w3.org/2000/svg" width ="24" height ="24" viewBox ="0 0 24 24" fill ="none" stroke ="currentColor" stroke-width ="2" stroke-linecap ="round" stroke-linejoin ="round" class ="feather feather-shopping-cart" > <circle cx ="9" cy ="21" r ="1" > </circle > <circle cx ="20" cy ="21" r ="1" > </circle > <path d ="M1 1h4l2.68 13.39a2 2 0 0 0 2 1.61h9.72a2 2 0 0 0 2-1.61L23 6H6" > </path > </svg > Products </a > </li > <li class ="nav-item" > <a class ="nav-link" href ="http://getbootstrap.com/docs/4.0/examples/dashboard/#" > <svg xmlns ="http://www.w3.org/2000/svg" width ="24" height ="24" viewBox ="0 0 24 24" fill ="none" stroke ="currentColor" stroke-width ="2" stroke-linecap ="round" stroke-linejoin ="round" class ="feather feather-users" > <path d ="M17 21v-2a4 4 0 0 0-4-4H5a4 4 0 0 0-4 4v2" > </path > <circle cx ="9" cy ="7" r ="4" > </circle > <path d ="M23 21v-2a4 4 0 0 0-3-3.87" > </path > <path d ="M16 3.13a4 4 0 0 1 0 7.75" > </path > </svg > Customers </a > </li > <li class ="nav-item" > <a class ="nav-link" href ="http://getbootstrap.com/docs/4.0/examples/dashboard/#" > <svg xmlns ="http://www.w3.org/2000/svg" width ="24" height ="24" viewBox ="0 0 24 24" fill ="none" stroke ="currentColor" stroke-width ="2" stroke-linecap ="round" stroke-linejoin ="round" class ="feather feather-bar-chart-2" > <line x1 ="18" y1 ="20" x2 ="18" y2 ="10" > </line > <line x1 ="12" y1 ="20" x2 ="12" y2 ="4" > </line > <line x1 ="6" y1 ="20" x2 ="6" y2 ="14" > </line > </svg > Reports </a > </li > <li class ="nav-item" > <a class ="nav-link" href ="http://getbootstrap.com/docs/4.0/examples/dashboard/#" > <svg xmlns ="http://www.w3.org/2000/svg" width ="24" height ="24" viewBox ="0 0 24 24" fill ="none" stroke ="currentColor" stroke-width ="2" stroke-linecap ="round" stroke-linejoin ="round" class ="feather feather-layers" > <polygon points ="12 2 2 7 12 12 22 7 12 2" > </polygon > <polyline points ="2 17 12 22 22 17" > </polyline > <polyline points ="2 12 12 17 22 12" > </polyline > </svg > Integrations </a > </li > </ul > <h6 class ="sidebar-heading d-flex justify-content-between align-items-center px-3 mt-4 mb-1 text-muted" > <span > Saved reports</span > <a class ="d-flex align-items-center text-muted" href ="http://getbootstrap.com/docs/4.0/examples/dashboard/#" > <svg xmlns ="http://www.w3.org/2000/svg" width ="24" height ="24" viewBox ="0 0 24 24" fill ="none" stroke ="currentColor" stroke-width ="2" stroke-linecap ="round" stroke-linejoin ="round" class ="feather feather-plus-circle" > <circle cx ="12" cy ="12" r ="10" > </circle > <line x1 ="12" y1 ="8" x2 ="12" y2 ="16" > </line > <line x1 ="8" y1 ="12" x2 ="16" y2 ="12" > </line > </svg > </a > </h6 > <ul class ="nav flex-column mb-2" > <li class ="nav-item" > <a class ="nav-link" href ="http://getbootstrap.com/docs/4.0/examples/dashboard/#" > <svg xmlns ="http://www.w3.org/2000/svg" width ="24" height ="24" viewBox ="0 0 24 24" fill ="none" stroke ="currentColor" stroke-width ="2" stroke-linecap ="round" stroke-linejoin ="round" class ="feather feather-file-text" > <path d ="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z" > </path > <polyline points ="14 2 14 8 20 8" > </polyline > <line x1 ="16" y1 ="13" x2 ="8" y2 ="13" > </line > <line x1 ="16" y1 ="17" x2 ="8" y2 ="17" > </line > <polyline points ="10 9 9 9 8 9" > </polyline > </svg > Current month </a > </li > <li class ="nav-item" > <a class ="nav-link" href ="http://getbootstrap.com/docs/4.0/examples/dashboard/#" > <svg xmlns ="http://www.w3.org/2000/svg" width ="24" height ="24" viewBox ="0 0 24 24" fill ="none" stroke ="currentColor" stroke-width ="2" stroke-linecap ="round" stroke-linejoin ="round" class ="feather feather-file-text" > <path d ="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z" > </path > <polyline points ="14 2 14 8 20 8" > </polyline > <line x1 ="16" y1 ="13" x2 ="8" y2 ="13" > </line > <line x1 ="16" y1 ="17" x2 ="8" y2 ="17" > </line > <polyline points ="10 9 9 9 8 9" > </polyline > </svg > Last quarter </a > </li > <li class ="nav-item" > <a class ="nav-link" href ="http://getbootstrap.com/docs/4.0/examples/dashboard/#" > <svg xmlns ="http://www.w3.org/2000/svg" width ="24" height ="24" viewBox ="0 0 24 24" fill ="none" stroke ="currentColor" stroke-width ="2" stroke-linecap ="round" stroke-linejoin ="round" class ="feather feather-file-text" > <path d ="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z" > </path > <polyline points ="14 2 14 8 20 8" > </polyline > <line x1 ="16" y1 ="13" x2 ="8" y2 ="13" > </line > <line x1 ="16" y1 ="17" x2 ="8" y2 ="17" > </line > <polyline points ="10 9 9 9 8 9" > </polyline > </svg > Social engagement </a > </li > <li class ="nav-item" > <a class ="nav-link" href ="http://getbootstrap.com/docs/4.0/examples/dashboard/#" > <svg xmlns ="http://www.w3.org/2000/svg" width ="24" height ="24" viewBox ="0 0 24 24" fill ="none" stroke ="currentColor" stroke-width ="2" stroke-linecap ="round" stroke-linejoin ="round" class ="feather feather-file-text" > <path d ="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z" > </path > <polyline points ="14 2 14 8 20 8" > </polyline > <line x1 ="16" y1 ="13" x2 ="8" y2 ="13" > </line > <line x1 ="16" y1 ="17" x2 ="8" y2 ="17" > </line > <polyline points ="10 9 9 9 8 9" > </polyline > </svg > Year-end sale </a > </li > </ul > </div > </nav > <main role ="main" class ="col-md-9 ml-sm-auto col-lg-10 pt-3 px-4" > <div class ="chartjs-size-monitor" style ="position: absolute; left: 0px; top: 0px; right: 0px; bottom: 0px; overflow: hidden; pointer-events: none; visibility: hidden; z-index: -1;" > <div class ="chartjs-size-monitor-expand" style ="position:absolute;left:0;top:0;right:0;bottom:0;overflow:hidden;pointer-events:none;visibility:hidden;z-index:-1;" > <div style ="position:absolute;width:1000000px;height:1000000px;left:0;top:0" > </div > </div > <div class ="chartjs-size-monitor-shrink" style ="position:absolute;left:0;top:0;right:0;bottom:0;overflow:hidden;pointer-events:none;visibility:hidden;z-index:-1;" > <div style ="position:absolute;width:200%;height:200%;left:0; top:0" > </div > </div > </div > <div class ="d-flex justify-content-between flex-wrap flex-md-nowrap align-items-center pb-2 mb-3 border-bottom" > <h1 class ="h2" > Dashboard</h1 > <div class ="btn-toolbar mb-2 mb-md-0" > <div class ="btn-group mr-2" > <button class ="btn btn-sm btn-outline-secondary" > Share</button > <button class ="btn btn-sm btn-outline-secondary" > Export</button > </div > <button class ="btn btn-sm btn-outline-secondary dropdown-toggle" > <svg xmlns ="http://www.w3.org/2000/svg" width ="24" height ="24" viewBox ="0 0 24 24" fill ="none" stroke ="currentColor" stroke-width ="2" stroke-linecap ="round" stroke-linejoin ="round" class ="feather feather-calendar" > <rect x ="3" y ="4" width ="18" height ="18" rx ="2" ry ="2" > </rect > <line x1 ="16" y1 ="2" x2 ="16" y2 ="6" > </line > <line x1 ="8" y1 ="2" x2 ="8" y2 ="6" > </line > <line x1 ="3" y1 ="10" x2 ="21" y2 ="10" > </line > </svg > This week </button > </div > </div > <canvas class ="my-4 chartjs-render-monitor" id ="myChart" width ="1076" height ="454" style ="display: block; width: 1076px; height: 454px;" > </canvas > </main > </div > </div > <script type ="text/javascript" src ="/js/jquery-3.2.1.slim.min.js" > </script > <script type ="text/javascript" src ="/js/popper.min.js" > </script > <script type ="text/javascript" src ="/js/bootstrap.min.js" > </script > <script type ="text/javascript" src ="/js/feather.min.js" > </script > <script > feather.replace() </script > <script type ="text/javascript" src ="/js/Chart.min.js" > </script > <script > var ctx = document .getElementById("myChart" ); var myChart = new Chart(ctx, { type : 'line' , data : { labels : ["Sunday" , "Monday" , "Tuesday" , "Wednesday" , "Thursday" , "Friday" , "Saturday" ], datasets : [{ data : [15339 , 21345 , 18483 , 24003 , 23489 , 24092 , 12034 ], lineTension : 0 , backgroundColor : 'transparent' , borderColor : '#007bff' , borderWidth : 4 , pointBackgroundColor : '#007bff' }] }, options : { scales : { yAxes : [{ ticks : { beginAtZero : false } }] }, legend : { display : false , } } }); </script > </body > </html >
注解
@Autowired
:byType方式实现依赖注入
@component
:可将pojo实例化到spring容器中,相当于配置文件中的<bean id="" class=""/>
,可代表各种组件,当类不属于各种归类(如@Controller、@Services等),可以使用@Component来标注这个类。
@ConfigurationProperties
:用于外部化配置,如果要绑定和验证某些外部属性(如 .properties),可将其添加到类定义或类中的方法。绑定通过调用带注释的类上的 setter 实现。如果使用@ConstructorBinding,则通过绑定到构造函数参数来执行。可将配置文件中配置属性的值,映射到该组件中,即该类中的属性和配置文件中相关配置进行绑定。The prefix of the properties that are valid to bind to this object.
@Resource
:byName方式实现依赖注入