Spring是一个开源框架,2003年兴起的一个轻量级的Java开发框架。Spring是为了解决企业级应用开发的复杂性而创建的,简化开发
为了降低Java开发的复杂性,Spring采用了以下4种关键策略:
核心思想:约定大于配置!!!
(程序猿)程序 = 数据结构 + 算法(集合框架)
(码农)程序 = 面向对象 + 框架
微服务是一种架构风格,它要求我们在开发一个应用的时候,这个应用必须构建一系列小服务的组合;可以通过http方式进行互通。要说微服务架构,先得说说过去我们的单体应用架构
单体应用架构:
微服务架构:
高内聚,低耦合!!!
一个大型系统的微服务架构,就像一个复杂交织的神经网络,每一个神经元就是一个功能元素,它们各自完成自己的功能,然后通过http相互请求调用。比如一个电商系统,查缓存、连数据库、浏览页面、结账、支付等服务都是一个个独立的功能服务,都被微化了,它们作为一个个微服务共同构建一个庞大的系统。如果修改其中的一个功能,只需要更新升级其中一个功能服务单元即可。
但是这种庞大的系统架构给部署和运维带来很大的难度。于是,Spring为我们带来了构建大型分布式微服务的全套、全程产品:
官方:提供一个快速生成的网站,IDEA集成了这个网站
官网网址:https://spring.io/projects/spring-boot
进入官网后,点击Spring Initializr
在官网配置好项目后,就可以点击下面的 GENERATE CTRL + 回车
。然后会得到一个项目压缩包,解压后,就可以导入到 idea 中。
如果是在idea工具里面进行配置的话,一定要注意,下载来源不要默认,而要加上阿里云镜像!!!!
后面的过程就和官网配置页面设置一样,选好后,就可以进入到项目中编写了。
package com.blb.demo.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
@Controller
@RequestMapping("/hello")
public class HelloController {
@GetMapping("/hello")
@ResponseBody
public String hello(){
return "hello,world";
}
}
细节讲解:
从命名约定我们可以看到每个注释都是为了处理各自的传入请求方法类型,即@GetMapping
用于处理请求方法的GET类型,@PostMapping
用于处理请求方法的POST类型等。
如果我们想使用传统的@RequestMapping注释实现URL处理程序,那么它应该是这样的:
@RequestMapping(value = "/get/{id}", method = RequestMethod.GET)
新方法可以简化为:
@GetMapping("/get/{id}")
@responseBody注解的作用是:
自动配置:
启动器:
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starterartifactId>
dependency>
主程序:
package com.blb.demo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
// @SpringBootApplication : 标注这个类是一个SpringBoot的应用(启动类下的所有资源被导入)
@SpringBootApplication
public class DemoApplication {
public static void main(String[] args) {
// 将SpringBoot应用启动
SpringApplication.run(DemoApplication.class, args);
}
}
List 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;
}
META-INF/spring.factories:自动配置的核心文件
所有资源加载到配置类中!
Properties properties = PropertiesLoaderUtils.loadProperties(resource);
结论:SpringBoot所有自动配置都是在启动的时候扫描并加载(spring.factories所有的自动配置类都在这里面,但是不一定生效,要判断条件是否成立,只要导入了对应的start,就有对应的启动器了,有了启动器,我们自动装配就会生效,然后就配置成功!)
/META-INF/spring.factories
获取指定的值;spring-boot-autoconfigure-2.2.0.RELEASE.jar
这个包下xxxAutoConfiguration@Bean
的文件,就是这些类给容器中导入了这个场景需要的所有组件;并自动配置。@Configuration,JavaConfig!SpringApplication.run(主程序类)分析:分析该方法主要分为两部分
SpringApplication:这个类主要做了以下四件事情
查看构造器:
public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {
// 设置一些默认参数
this.sources = new LinkedHashSet();
this.bannerMode = Mode.CONSOLE;
this.logStartupInfo = true;
this.addCommandLineProperties = true;
this.addConversionService = true;
this.headless = true;
this.registerShutdownHook = true;
this.additionalProfiles = new HashSet();
this.isCustomEnvironment = false;
this.lazyInitialization = false;
this.resourceLoader = resourceLoader;
Assert.notNull(primarySources, "PrimarySources must not be null");
// 保存主配置类到一个Set集合primarySources中
this.primarySources = new LinkedHashSet(Arrays.asList(primarySources));
// 获取当前的应用类型,判断是不是Web应用
this.webApplicationType = WebApplicationType.deduceFromClasspath();
// 从类路径下找到META-INF/spring.factories配置的所有ApplicationContextInitializer;然后保存起来
this.setInitializers(this.getSpringFactoriesInstances(ApplicationContextInitializer.class));
// 从类路径下找到META‐INF/spring.ApplicationListener;然后保存起来,原理同上
this.setListeners(this.getSpringFactoriesInstances(ApplicationListener.class));
// 从多个配置类中找到有main方法的主配置类。在调run方法的时候是可以传递多个配置类的
this.mainApplicationClass = this.deduceMainApplicationClass();
// 执行完毕,SpringApplication对象就创建出来了,返回到1处,调用SpringApplication对象的run方法,到3
}
配置文件:SpringBoot使用一个全局的配置文件,配置文件名称是固定的
配置文件的作用:修改SpringBoot自动配置的默认值,因为SpringBoot在底层都给我们自动配置好了;
YAML是"YAML Ain’t a Markup Language"(YAML不是一种标记语言)的递归缩写。在开发的这种语言时,YAML 的意思其实是:“Yet Another Markup Language”(仍是一种标记语言),但为了强调这种语言以数据做为中心,而不是以标记语言为重点,而用反向缩略语重命名。(取自百度百科)
标记语言:以前的配置文件,大多数都是使用xml来配置;比如一个简单的端口配置,我们来对比下yaml和xml
yaml配置:
server:
port: 8080
// 普通的key-value
name: huake
// 对象
student:
name: huake
age: 3
// 行内写法
studednt: {name: huake, age: 3}
// 数组
pets:
- cat
- dog
- pig
pets: [cat, dog, pig]
xml配置:
<server>
<port>8080port>
server>
properties只能写键值对
name=huake
student.name = huake
student.age = 3
基本语法:
k:(空格) v
以此来表示一对键值对(空格不能省略);以空格的缩进来控制层级关系,只要是左边对齐的一列数据都是同一个层级的。
注意:属性和值的大小写都是十分敏感的。例如:
server:
port: 8080
path: /hello
值的写法:字面量: 普通的值 [数字, 布尔值, 字符串]
k: v
字面量直接写在后面就可以,字符串默认不用加上双引号或者单引号;"" 双引号,不会转义字符串里面的特殊字符,特殊字符会作为本身想表示的意思;
比如:name: "kuang \n shen"
输出:
kuang
shen
yaml可以直接给实体类赋值:
@ConfigurationProperties作用:
上面采用的方法都是最简单的方式,开发中最常用的;那我们来唠叨一下其他的实现方式,道理都是相通的,写还是那样写;配置文件除了yaml还有我们之前常用的properties,但properties配置文件在写中文的时候,会有乱码,我们需要去IDEA中设置编码格式为UTF-8;
@ConfigurationProperties | @Value | |
---|---|---|
功能 | 批量注入配置文件中的属性 | 一个个指定 |
松散绑定(松散语法) | 支持 | 不支持 |
SpEL | 不支持 | 支持 |
JSR303数据校验 | 支持 | 不支持 |
复杂类型封装 | 支持 | 不支持 |
SpringBoot中可以用@validated来校验数据,如果数据异常则会统一抛出异常,方便异常中心统一处理。
我们这里来写个注解让我们的name只能支持Email格式
空检查
Booelan检查
长度检查
日期检查
数值检查,建议使用在Stirng,Integer类型,不建议使用在int类型上,因为表单值为“”时无法转换为int,但可以转换为Stirng为"",Integer为null
profile是Spring对不同环境提供不同配置功能的支持,可以通过激活不同的环境版本,实现快速切换环境
// 比如在配置文件中指定dev环境,我们可以通过设置不同的端口号进行测试;
// 我们启动SpringBoot,就可以看到已经切换到dev下的配置了
spring.profiles.active=dev
spring.profiles.active=配置文件名
SpringBoot启动会扫描以下位置的application.properties
或者application.yml
文件作为SpringBoot的默认配置文件
优先级由高到低,高优先级的配置会覆盖低优先级的配置;
SpringBoot会从这四个位置全部加载主配置文件,互补配置;我们在最低级的配置文件中设置一个项目访问路径的配置来测试互补问题
// 配置项目的访问路径
server.servlet.context-path=/huake
扩展:指定位置加载配置文件
java -jar spring-boot-config.jar --spring.config.location=F://application.properties
外部加载配置文件的方式十分多,我们选择最常用的即可,在开发的资源文件中进行配置
表示这是一个配置类
@Configuration(proxyBeanMethods = false)
自动配置属性:HttpProperties
@EnableConfigurationProperties(HttpProperties.class)
Spring的底层注解:根据不同的条件,来判断当前配置或者类是否生效
@ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.SERVLET)
在配置文件中能配置的东西,都存在一个固有的规律:xxxProperties
、xxxAutoConfiguration
xxxAutoConfiguration
有默认值(而这些默认值的改变是通过xxxProperties
和配置文件的绑定),所以我们可以使用自定义的配置了
# Initializers
org.springframework.context.ApplicationContextInitializer=\
org.springframework.boot.autoconfigure.SharedMetadataReaderFactoryContextInitializer,\
org.springframework.boot.autoconfigure.logging.ConditionEvaluationReportLoggingListener
# Application Listeners
org.springframework.context.ApplicationListener=\
org.springframework.boot.autoconfigure.BackgroundPreinitializer
# Auto Configuration Import Listeners
org.springframework.boot.autoconfigure.AutoConfigurationImportListener=\
org.springframework.boot.autoconfigure.condition.ConditionEvaluationReportAutoConfigurationImportListener
# Auto Configuration Import Filters
org.springframework.boot.autoconfigure.AutoConfigurationImportFilter=\
org.springframework.boot.autoconfigure.condition.OnBeanCondition,\
org.springframework.boot.autoconfigure.condition.OnClassCondition,\
org.springframework.boot.autoconfigure.condition.OnWebApplicationCondition
# Auto Configure
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.springframework.boot.autoconfigure.admin.SpringApplicationAdminJmxAutoConfiguration,\
org.springframework.boot.autoconfigure.aop.AopAutoConfiguration,\
org.springframework.boot.autoconfigure.amqp.RabbitAutoConfiguration,\
org.springframework.boot.autoconfigure.batch.BatchAutoConfiguration,\
org.springframework.boot.autoconfigure.cache.CacheAutoConfiguration,\
org.springframework.boot.autoconfigure.cassandra.CassandraAutoConfiguration,\
org.springframework.boot.autoconfigure.context.ConfigurationPropertiesAutoConfiguration,\
org.springframework.boot.autoconfigure.context.LifecycleAutoConfiguration,\
org.springframework.boot.autoconfigure.context.MessageSourceAutoConfiguration,\
org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration,\
org.springframework.boot.autoconfigure.couchbase.CouchbaseAutoConfiguration,\
org.springframework.boot.autoconfigure.dao.PersistenceExceptionTranslationAutoConfiguration,\
org.springframework.boot.autoconfigure.data.cassandra.CassandraDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.cassandra.CassandraReactiveDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.cassandra.CassandraReactiveRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.cassandra.CassandraRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.couchbase.CouchbaseDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.couchbase.CouchbaseReactiveDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.couchbase.CouchbaseReactiveRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.couchbase.CouchbaseRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.elasticsearch.ElasticsearchDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.elasticsearch.ElasticsearchRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.elasticsearch.ReactiveElasticsearchRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.elasticsearch.ReactiveElasticsearchRestClientAutoConfiguration,\
org.springframework.boot.autoconfigure.data.jdbc.JdbcRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.jpa.JpaRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.ldap.LdapRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.mongo.MongoDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.mongo.MongoReactiveDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.mongo.MongoReactiveRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.mongo.MongoRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.neo4j.Neo4jDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.neo4j.Neo4jRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.solr.SolrRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.r2dbc.R2dbcDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.r2dbc.R2dbcRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.r2dbc.R2dbcTransactionManagerAutoConfiguration,\
org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration,\
org.springframework.boot.autoconfigure.data.redis.RedisReactiveAutoConfiguration,\
org.springframework.boot.autoconfigure.data.redis.RedisRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.rest.RepositoryRestMvcAutoConfiguration,\
org.springframework.boot.autoconfigure.data.web.SpringDataWebAutoConfiguration,\
org.springframework.boot.autoconfigure.elasticsearch.ElasticsearchRestClientAutoConfiguration,\
org.springframework.boot.autoconfigure.flyway.FlywayAutoConfiguration,\
org.springframework.boot.autoconfigure.freemarker.FreeMarkerAutoConfiguration,\
org.springframework.boot.autoconfigure.groovy.template.GroovyTemplateAutoConfiguration,\
org.springframework.boot.autoconfigure.gson.GsonAutoConfiguration,\
org.springframework.boot.autoconfigure.h2.H2ConsoleAutoConfiguration,\
org.springframework.boot.autoconfigure.hateoas.HypermediaAutoConfiguration,\
org.springframework.boot.autoconfigure.hazelcast.HazelcastAutoConfiguration,\
org.springframework.boot.autoconfigure.hazelcast.HazelcastJpaDependencyAutoConfiguration,\
org.springframework.boot.autoconfigure.http.HttpMessageConvertersAutoConfiguration,\
org.springframework.boot.autoconfigure.http.codec.CodecsAutoConfiguration,\
org.springframework.boot.autoconfigure.influx.InfluxDbAutoConfiguration,\
org.springframework.boot.autoconfigure.info.ProjectInfoAutoConfiguration,\
org.springframework.boot.autoconfigure.integration.IntegrationAutoConfiguration,\
org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration,\
org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration,\
org.springframework.boot.autoconfigure.jdbc.JdbcTemplateAutoConfiguration,\
org.springframework.boot.autoconfigure.jdbc.JndiDataSourceAutoConfiguration,\
org.springframework.boot.autoconfigure.jdbc.XADataSourceAutoConfiguration,\
org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration,\
org.springframework.boot.autoconfigure.jms.JmsAutoConfiguration,\
org.springframework.boot.autoconfigure.jmx.JmxAutoConfiguration,\
org.springframework.boot.autoconfigure.jms.JndiConnectionFactoryAutoConfiguration,\
org.springframework.boot.autoconfigure.jms.activemq.ActiveMQAutoConfiguration,\
org.springframework.boot.autoconfigure.jms.artemis.ArtemisAutoConfiguration,\
org.springframework.boot.autoconfigure.jersey.JerseyAutoConfiguration,\
org.springframework.boot.autoconfigure.jooq.JooqAutoConfiguration,\
org.springframework.boot.autoconfigure.jsonb.JsonbAutoConfiguration,\
org.springframework.boot.autoconfigure.kafka.KafkaAutoConfiguration,\
org.springframework.boot.autoconfigure.availability.ApplicationAvailabilityAutoConfiguration,\
org.springframework.boot.autoconfigure.ldap.embedded.EmbeddedLdapAutoConfiguration,\
org.springframework.boot.autoconfigure.ldap.LdapAutoConfiguration,\
org.springframework.boot.autoconfigure.liquibase.LiquibaseAutoConfiguration,\
org.springframework.boot.autoconfigure.mail.MailSenderAutoConfiguration,\
org.springframework.boot.autoconfigure.mail.MailSenderValidatorAutoConfiguration,\
org.springframework.boot.autoconfigure.mongo.embedded.EmbeddedMongoAutoConfiguration,\
org.springframework.boot.autoconfigure.mongo.MongoAutoConfiguration,\
org.springframework.boot.autoconfigure.mongo.MongoReactiveAutoConfiguration,\
org.springframework.boot.autoconfigure.mustache.MustacheAutoConfiguration,\
org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration,\
org.springframework.boot.autoconfigure.quartz.QuartzAutoConfiguration,\
org.springframework.boot.autoconfigure.r2dbc.R2dbcAutoConfiguration,\
org.springframework.boot.autoconfigure.rsocket.RSocketMessagingAutoConfiguration,\
org.springframework.boot.autoconfigure.rsocket.RSocketRequesterAutoConfiguration,\
org.springframework.boot.autoconfigure.rsocket.RSocketServerAutoConfiguration,\
org.springframework.boot.autoconfigure.rsocket.RSocketStrategiesAutoConfiguration,\
org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration,\
org.springframework.boot.autoconfigure.security.servlet.UserDetailsServiceAutoConfiguration,\
org.springframework.boot.autoconfigure.security.servlet.SecurityFilterAutoConfiguration,\
org.springframework.boot.autoconfigure.security.reactive.ReactiveSecurityAutoConfiguration,\
org.springframework.boot.autoconfigure.security.reactive.ReactiveUserDetailsServiceAutoConfiguration,\
org.springframework.boot.autoconfigure.security.rsocket.RSocketSecurityAutoConfiguration,\
org.springframework.boot.autoconfigure.security.saml2.Saml2RelyingPartyAutoConfiguration,\
org.springframework.boot.autoconfigure.sendgrid.SendGridAutoConfiguration,\
org.springframework.boot.autoconfigure.session.SessionAutoConfiguration,\
org.springframework.boot.autoconfigure.security.oauth2.client.servlet.OAuth2ClientAutoConfiguration,\
org.springframework.boot.autoconfigure.security.oauth2.client.reactive.ReactiveOAuth2ClientAutoConfiguration,\
org.springframework.boot.autoconfigure.security.oauth2.resource.servlet.OAuth2ResourceServerAutoConfiguration,\
org.springframework.boot.autoconfigure.security.oauth2.resource.reactive.ReactiveOAuth2ResourceServerAutoConfiguration,\
org.springframework.boot.autoconfigure.solr.SolrAutoConfiguration,\
org.springframework.boot.autoconfigure.task.TaskExecutionAutoConfiguration,\
org.springframework.boot.autoconfigure.task.TaskSchedulingAutoConfiguration,\
org.springframework.boot.autoconfigure.thymeleaf.ThymeleafAutoConfiguration,\
org.springframework.boot.autoconfigure.transaction.TransactionAutoConfiguration,\
org.springframework.boot.autoconfigure.transaction.jta.JtaAutoConfiguration,\
org.springframework.boot.autoconfigure.validation.ValidationAutoConfiguration,\
org.springframework.boot.autoconfigure.web.client.RestTemplateAutoConfiguration,\
org.springframework.boot.autoconfigure.web.embedded.EmbeddedWebServerFactoryCustomizerAutoConfiguration,\
org.springframework.boot.autoconfigure.web.reactive.HttpHandlerAutoConfiguration,\
org.springframework.boot.autoconfigure.web.reactive.ReactiveWebServerFactoryAutoConfiguration,\
org.springframework.boot.autoconfigure.web.reactive.WebFluxAutoConfiguration,\
org.springframework.boot.autoconfigure.web.reactive.error.ErrorWebFluxAutoConfiguration,\
org.springframework.boot.autoconfigure.web.reactive.function.client.ClientHttpConnectorAutoConfiguration,\
org.springframework.boot.autoconfigure.web.reactive.function.client.WebClientAutoConfiguration,\
org.springframework.boot.autoconfigure.web.servlet.DispatcherServletAutoConfiguration,\
org.springframework.boot.autoconfigure.web.servlet.ServletWebServerFactoryAutoConfiguration,\
org.springframework.boot.autoconfigure.web.servlet.error.ErrorMvcAutoConfiguration,\
org.springframework.boot.autoconfigure.web.servlet.HttpEncodingAutoConfiguration,\
org.springframework.boot.autoconfigure.web.servlet.MultipartAutoConfiguration,\
org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration,\
org.springframework.boot.autoconfigure.websocket.reactive.WebSocketReactiveAutoConfiguration,\
org.springframework.boot.autoconfigure.websocket.servlet.WebSocketServletAutoConfiguration,\
org.springframework.boot.autoconfigure.websocket.servlet.WebSocketMessagingAutoConfiguration,\
org.springframework.boot.autoconfigure.webservices.WebServicesAutoConfiguration,\
org.springframework.boot.autoconfigure.webservices.client.WebServiceTemplateAutoConfiguration
# Failure analyzers
org.springframework.boot.diagnostics.FailureAnalyzer=\
org.springframework.boot.autoconfigure.data.redis.RedisUrlSyntaxFailureAnalyzer,\
org.springframework.boot.autoconfigure.diagnostics.analyzer.NoSuchBeanDefinitionFailureAnalyzer,\
org.springframework.boot.autoconfigure.flyway.FlywayMigrationScriptMissingFailureAnalyzer,\
org.springframework.boot.autoconfigure.jdbc.DataSourceBeanCreationFailureAnalyzer,\
org.springframework.boot.autoconfigure.jdbc.HikariDriverConfigurationFailureAnalyzer,\
org.springframework.boot.autoconfigure.r2dbc.ConnectionFactoryBeanCreationFailureAnalyzer,\
org.springframework.boot.autoconfigure.session.NonUniqueSessionRepositoryFailureAnalyzer
# Template availability providers
org.springframework.boot.autoconfigure.template.TemplateAvailabilityProvider=\
org.springframework.boot.autoconfigure.freemarker.FreeMarkerTemplateAvailabilityProvider,\
org.springframework.boot.autoconfigure.mustache.MustacheTemplateAvailabilityProvider,\
org.springframework.boot.autoconfigure.groovy.template.GroovyTemplateAvailabilityProvider,\
org.springframework.boot.autoconfigure.thymeleaf.ThymeleafTemplateAvailabilityProvider,\
org.springframework.boot.autoconfigure.web.servlet.JspTemplateAvailabilityProvider
每一个这样的xxxAutoConfiguration
类都是容器中的一个组件,最后都加入到容器中;用他们来做自动配置
每一个自动配置类可以进行自动配置功能;
一句话总结:根据当前不同的条件判断,决定这个配置类是否生效!
一但这个配置类生效;这个配置类就会给容器中添加各种组件;这些组件的属性是从对应的properties类中获取的,这些类里面的每一个属性又是和配置文件绑定的;
所有在配置文件中能配置的属性都是在xxxProperties
类中封装着;配置文件能配置什么就可以参照某个功能对应的这个属性类
自动装配的原理:
@Conditional
那么多的自动配置类,必须在一定的条件下才能生效;也就是说,我们加载了这么多的配置类,但不是所有的都生效了
我们可以通过启用 debug=true
属性(默认为false);来让控制台打印自动配置报告,这样我们就可以很方便的知道哪些自动配置类生效
// 开启SpringBoot的调试类
debug=true
jar:webapp!
SpringBoot到底帮我们配置了什么?我们能不能进行修改?能修改哪些东西?能不能扩展?
要解决的问题:
我们任意添加一个jsquery包
依此类推,优先级:resources > static(默认)> public
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
if (!this.resourceProperties.isAddMappings()) {
logger.debug("Default resource handling disabled");
return;
}
Duration cachePeriod = this.resourceProperties.getCache().getPeriod();
CacheControl cacheControl = this.resourceProperties.getCache().getCachecontrol().toHttpCacheControl();
if (!registry.hasMappingForPattern("/webjars/**")) {
customizeResourceHandlerRegistration(registry.addResourceHandler("/webjars/**")
.addResourceLocations("classpath:/META-INF/resources/webjars/")
.setCachePeriod(getSeconds(cachePeriod)).setCacheControl(cacheControl));
}
String staticPathPattern = this.mvcProperties.getStaticPathPattern();
if (!registry.hasMappingForPattern(staticPathPattern)) {
customizeResourceHandlerRegistration(registry.addResourceHandler(staticPathPattern)
.addResourceLocations(getResourceLocations(this.resourceProperties.getStaticLocations()))
.setCachePeriod(getSeconds(cachePeriod)).setCacheControl(cacheControl));
}
}
private static final String[] CLASSPATH_RESOURCE_LOCATIONS = { "classpath:/META-INF/resources/",
"classpath:/resources/", "classpath:/static/", "classpath:/public/" };
总结:
localhost:8080/webjars
)前端交给我们的页面,是HTML页面,如果是我们以前开发,我们需要把他们转成JSP页面,JSP好处就是当我们查出一些数据转发到JSP页面以后,我们可以用jsp轻松实现数据的显示,及交互等。jsp支持非常强大的功能,包括能写Java代码,但是呢,
那不支持jsp,如果我们直接用纯静态页面的方式,那给我们开发会带来非常大的麻烦,那怎么办呢,SpringBoot推荐你可以来使用模板引擎——Thymeleaf
。类似的模板引擎有jsp
、freemarker
等等,那如何去使用?
第一步:引入Thymeleaf,对于SpringBoot来说,什么事情不都是一个start的事情嘛,我们在去项目中引入一下。
https://www.thymeleaf.org/
https://github.com/thymeleaf/thymeleaf
https://docs.spring.io/spring-boot/docs/2.1.6.RELEASE/reference/htmlsingle/#using-boot-starter
,找到我们对应的版本<!-- Thymeleaf 我们都是基于3.x开发的-->
<dependency>
<groupId>org.thymeleaf</groupId>
<artifactId>thymeleaf-spring5</artifactId>
</dependency>
<dependency>
<groupId>org.thymeleaf.extras</groupId>
<artifactId>thymeleaf-extras-java8time</artifactId>
</dependency>
结论:只要需要使用thymeleaf,只需要导入对应的依赖就可以了!我们将html放在我们的templates即可
order | Feature | Attributes |
---|---|---|
1 | Fragment inclusion | th:insert & th:replace |
2 | Fragment iteration | th:each |
3 | Conditional evaluation | th:if & th:unless & th:switch & th:case |
4 | Local variable definition | th:object & th:with |
5 | General attribute modification | th:attr & th:attrprepend & th:attrappend |
6 | Specific attribute modification | th:value & th:href & th:src & … |
7 | Text(tag body modification) | th:text & th:utext |
8 | Fragment specificaiton | th:fragment |
9 | Fragment removal | th:remove |
演示一个小案例:(大致和JSP相似)
package com.blb.controller;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import java.util.Arrays;
@Controller
public class IndexController {
@RequestMapping("/test")
public String test(Model model){
model.addAttribute("msg", "hello SpringBoot
");
model.addAttribute("users", Arrays.asList("huake", "wuli"));
return "test";
}
}
DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>This is Thymeleaftitle>
head>
<body>
<div th:text="${msg}">div>
<div th:utext="${msg}">div>
<hr>
<h3 th:each="user:${users}" th:text="${user}">h3>
<h3 th:each="user:${users}">[[ ${user} ]]h3>
body>
html>
在进行测试前,我们还需要知道一个东西,就是SpringBoot对我们的SpringMVC还做了哪些配置,包括如何扩展,如何定制。
地址:https://docs.spring.io/spring-boot/docs/2.1.6.RELEASE/reference/html/boot-features-developing-web-applications.html
修改SpringBoot的默认配置
对于数据访问层,无论是 SQL(关系型数据库)还是NOSQL(非关系数据库),SpringBoot底层都是采用SpringData的方式进行统一处理
SpringBoot底层都是采用SpringData的方式进行统一处理各种数据库,SpringData也是Spring中与SpringBoot、SpringCloud等齐名的知名项目
在pom.xml配置中
// JDBC
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
// Web
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
// MySQL
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
在创建项目后,我们可以选择application.properties里面配置JDBC属性,但我们之前认识到了yaml语言,所以通过yaml来配置
如果你采用的是阿里云的途径来创建项目,则会报如下错;原因是因为通过阿里云创建的项目,在application.properties里面就默认配置好了JDBC的属性,所以只需要注释掉所有application.properties
的配置信息即可
java.sql.SQLException: Access denied for user '***'@'localhost' (using password: YES)
在我们的测试代码中
package com.zya;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.SQLException;
@SpringBootTest
class DemoApplicationTests {
@Autowired
DataSource dataSource;
@Test
void contextLoads() {
// 查看一下默认的数据源 : dbcp
System.out.println(dataSource.getClass()); // class com.zaxxer.hikari.HikariDataSource
// 获取数据库连接
try {
Connection connection = dataSource.getConnection();
System.out.println(connection);
// xxxx Template : SpringBoot已经配置好模板Bean, 拿来即用 CRUD
// 关闭
connection.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
}
DataSource dataSource的作用:
@Autowired
DataSource dataSource;
接着简单写一下我们JDBC的增删改查(但SpringBoot框架真的很好,基本内容都应经帮忙配置好了)
package com.zya.controller;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
import java.util.Map;
@RestController
public class JDBCController {
@Autowired
JdbcTemplate jdbcTemplate;
// 查询数据库的所有信息
// 没有实体类 数据库中的东西通过 Map 获取
@GetMapping("/userList")
public List<Map<String, Object>> userList(){
String sql = "select * from Springuser";
List<Map<String, Object>> list_maps = jdbcTemplate.queryForList(sql);
return list_maps;
}
// 增加用户
@GetMapping("/addUser")
public String addUser(){
String sql = "insert into Springboot01.springuser(id, name, pwd, perms) values (2, 'huake', '123', 'world')";
jdbcTemplate.update(sql);
return "add-ok";
}
// 更新用户
@GetMapping("/updateUser/{id}")
public String updateUser(@PathVariable("id") int id){
String sql = "update Springboot01.springuser set name=?, pwd=? where id="+id;
// 封装
Object[] objects = new Object[2];
objects[0] = "小明";
objects[1] = "zzzzz";
jdbcTemplate.update(sql, objects);
return "update-ok";
}
// 删除用户
@GetMapping("/deleteUser/{id}")
public String deleteUser(@PathVariable("id") int id){
String sql = "delete from Springboot01.springuser where id=?";
jdbcTemplate.update(sql, id);
return "update-ok";
}
}
@PathVariable()
Druid简介:
com.alibaba.druid.pool.DruidDataSource基本配置参数如下:
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close">
<property name="driverClassName" value="${jdbc.driverClassName}" />
<property name="url" value="${jdbc_url}" />
<property name="username" value="${jdbc_user}" />
<property name="password" value="${jdbc_password}" />
<property name="initialSize" value="1" />
<property name="minIdle" value="1" />
<property name="maxActive" value="20" />
<property name="maxWait" value="60000" />
<property name="timeBetweenEvictionRunsMillis" value="60000" />
<property name="minEvictableIdleTimeMillis" value="300000" />
<property name="validationQuery" value="SELECT 'x'" />
<property name="testWhileIdle" value="true" />
<property name="testOnBorrow" value="false" />
<property name="testOnReturn" value="false" />
<property name="poolPreparedStatements" value="true" />
<property name="maxPoolPreparedStatementPerConnectionSize" value="20" />
<property name="filters" value="stat" />
bean>
application.yml配置
spring:
datasource:
username: root
password: zya11230318
url: jdbc:mysql://localhost:3306/springboot01?characterEncoding=utf-8&serverTimezone=GMT%2B8
driver-class-name: com.mysql.cj.jdbc.Driver
type: com.alibaba.druid.pool.DruidDataSource
# SpringBoot 默认是不注入这些属性值的,需要自己绑定
# druid 数据源专有配置
initialSize: 5
minIdle: 5
maxActive: 20
maxWait: 60000
timeBetweenEvictionRunsMillis: 60000
minEvictableIdleTimeMillis: 300000
validationQuery :SELECT 1 FROM DUAL
testWhileIdle: true
testOnBorrow: false
testOnReturn: false
poolPreparedStatements: true
# 配置监控统计拦截的filters, stat:监控统计、Log4j(日志记录)、wall(防御sql注入)
# 如果允许时报错 java.lang.ClassNotFoundException: org.apache.log4j.Priority
# 则导入 log4j 依赖即可, Maven 地址: https://mvnrepository.com/artifact/log4j/log4j
filters: stat,wall,log4j
maxPoolPreparedStatementPerConnectionSize: 20
useGlobalDataSourceStat: true
connectionProperties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=500
后台监控(阿里巴巴)
package com.zya.config;
import com.alibaba.druid.pool.DruidDataSource;
import com.alibaba.druid.support.http.StatViewServlet;
import com.alibaba.druid.support.http.WebStatFilter;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.boot.web.servlet.ServletRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import javax.servlet.Filter;
import javax.sql.DataSource;
import java.util.HashMap;
@Configuration
public class DruidConfig {
@ConfigurationProperties(prefix = "spring.datasource")
@Bean
public DataSource druidDataSource(){
return new DruidDataSource();
}
// 后台监控 : web.xml, ServletRegistrationBean
// 因为SpringBoot内置了servlet容器,所以没有web.xml, 代替方法: ServletRegistrationBean
@Bean
public ServletRegistrationBean a(){
ServletRegistrationBean<StatViewServlet> bean = new ServletRegistrationBean<>(new StatViewServlet(), "/druid/*");
// 后台需要有人登录, 账号密码配置
HashMap<String, String> initParameters = new HashMap<>();
// 增加配置
initParameters.put("loginUsername", "admin"); // 登录key 是固定的 loginUsername和loginPassword
initParameters.put("loginPassword", "123456");
// 允许谁能访问
initParameters.put("allow", ""); // 为空则谁都能访问
// 禁止谁不能访问 initParameters.put("huake", "192.168.11.123"); // 为空则谁都能访问
bean.setInitParameters(initParameters); // 设置初始化参数
return bean;
}
// filter
@Bean
public FilterRegistrationBean webStatFilter(){
FilterRegistrationBean<Filter> bean = new FilterRegistrationBean();
bean.setFilter(new WebStatFilter());
// 可以过滤哪些请求呢?
HashMap<String, String> initParameters = new HashMap<>();
// 这些东西不进行统计
initParameters.put("exclusions", "*.js, *.css, /druid/*");
bean.setInitParameters(initParameters);
return bean;
}
}
启动我们的项目后,在路径上输入druid,就可以进入登录页面;输入账号密码
进入到后台页面
当我们执行之前写的sql语句时,这个后台就会记录下来,还有好多功能,就不在这一一演示了。
mybatis-spring-boot-starter: 整合
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.1.1</version>
</dependency>
application.properties
# 应用名称
spring.application.name=demo
# 应用服务 WEB 访问端口
server.port=8080
# 数据库驱动:
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
# 数据源名称
spring.datasource.name=defaultDataSource
# 数据库连接地址
spring.datasource.url=jdbc:mysql://localhost:3306/mybatis?serverTimezone=UTC&useUnicode=true&characterEncoding=utf-8
# 数据库用户名&密码:
spring.datasource.username=root
spring.datasource.password=zya11230318
# 整合mybatis
mybatis.type-aliases-package=com.zya.pojo
mybatis.mapper-locations=classpath:mybatis/*.xml
创建一个User类
package com.zya.pojo;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@NoArgsConstructor
@AllArgsConstructor
public class User {
private int id;
private String name;
private String pwd;
}
UserMapper接口
@Mapper和@Repository的区别:
package com.zya.mapper;
import com.zya.pojo.User;
import org.apache.ibatis.annotations.Mapper;
import org.springframework.stereotype.Repository;
import java.util.List;
// 这个注解表示了这是一个 mybatis的mapper类
@Mapper
@Repository
public interface UserMapper {
List<User> queryUserList();
User queryUserById(int id);
int addUser(User user);
int updateUser(User user);
int deleteUser(int id);
}
UserController类
@RestController:
package com.zya.controller;
import com.zya.mapper.UserMapper;
import com.zya.pojo.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
@RestController
public class UserController {
@Autowired
private UserMapper userMapper;
// 查询所有人信息
@GetMapping("/queryUserList")
public List<User> queryUserList(){
List<User> userList = userMapper.queryUserList();
for (User user:userList) {
System.out.println(user);
}
return userList;
}
// 添加一个用户
@GetMapping("/addUser")
public String addUser(){
userMapper.addUser(new User(4, "hello", "123"));
return "ok";
}
// 修改一个用户信息
@GetMapping("/updateUser")
public String updateUser(){
userMapper.updateUser(new User(4, "world", "1233"));
return "ok";
}
// 删除一个用户
@GetMapping("/deleteUser")
public String deleteUser(){
userMapper.deleteUser(4);
return "ok";
}
}
mybatis下的UserMapper.xml配置
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.zya.mapper.UserMapper">
<select id="queryUserList" resultType="User">
select * from userone
</select>
<select id="queryUserById" resultType="User">
select * from userone where id=#{id}
</select>
<insert id="addUser" parameterType="User">
insert into userone (id, name, pwd) values (#{id}, #{name}, #{pwd})
</insert>
<update id="updateUser" parameterType="User">
update userone set name=#{name}, pwd=#{pwd} where id=#{id}
</update>
<delete id="deleteUser" parameterType="int">
delete from userone where id=#{id}
</delete>
</mapper>
简介:
Spring Security是针对Spring项目的安全框架,也是SpringBoot底层安全模块默认的技术选型,他可以实现强大的Web安全控制,我们仅需要引入spring-boot-starter-security模块,进行少量的配置,即可实现强大的安全管理
记住几个类:
Spring Security的两个主要目标是 “认证” 和 “授权”(访问控制)
在web开发中,安全第一位!类似:过滤器、拦截器等等
功能性需求:否
做网站时,安全应该在设计之初考虑
shiro、SpringSecurity:很像,除了类不一样,名字不一样;
认证,授权(vip1、vip2、vip3)
MVC - Spring - SpringBoot - 框架思想
认证和授权:
package com.zya.config;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
// AOP: 拦截器
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
// 授权
// 链式编程
@Override
protected void configure(HttpSecurity http) throws Exception {
// 首页所有人可以访问, 但是功能页只有对应有权限的人才能访问
// 请求授权的规则~
http.authorizeRequests()
.antMatchers("/").permitAll() // 所有人都可以访问
.antMatchers("/level1/**").hasRole("vip1") // 只允许vip1的人访问
.antMatchers("/level2/**").hasRole("vip2") // 只允许vip2的人访问
.antMatchers("/level3/**").hasRole("vip3"); // 只允许vip3的人访问
// 没有权限默认会到登录页面
// login
// 定制登录页
http.formLogin().loginPage("/toLogin");
// 注销(开启了注销功能, 跳到首页)
http.logout().logoutSuccessUrl("/");
// 防止网站工具 get post
http.csrf().disable(); // 关闭csrf功能(登录失败可能存在的原因)
// 开启记住我功能(cookie, 默认保存两周)
http.rememberMe();
}
// 认证, SpringBoot 2.1.X 可以直接使用~
// 密码编码: PasswordEncoder
// 在Spring Security 5.0+ 新增了很多的加密方法
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
// 这些数据正常应该从数据库中读取
auth.inMemoryAuthentication().passwordEncoder(new BCryptPasswordEncoder())
.withUser("huake").password(new BCryptPasswordEncoder().encode("123456")).roles("vip1", "vip2", "vip3")
.and()
.withUser("wuda").password(new BCryptPasswordEncoder().encode("123")).roles("vip1")
.and()
.withUser("root").password(new BCryptPasswordEncoder().encode("123456")).roles("vip1", "vip2", "vip3");
}
}
什么是Shiro:
http://shiro.apache.org/
Shiro有哪些功能:
学习目标:
Swagger简介:
前后端分离:
产生一个问题:
Swagger:
Api文档与API定义同步更新
https://swagger.io/
在项目中使用Swagger需要SpringBox:
新建一个SpringBoot = Web项目
导入相关依赖:
<!-- https://mvnrepository.com/artifact/io.springfox/springfox-swagger2 -->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>3.0.0</version>
</dependency>
<!-- https://mvnrepository.com/artifact/io.springfox/springfox-swagger-ui -->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>3.0.0</version>
</dependency>
Swagger的bean实例Docket:
package com.zya.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.service.Contact;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;
import java.util.ArrayList;
@Configuration
@EnableSwagger2 // 开启Swagger2
public class SwaggerConfig {
// 配置了Swagger的Bean实例
@Bean
public Docket docket(){
return new Docket(DocumentationType.SWAGGER_2)
.apiInfo(apiInfo());
}
// 配置Swagger信息=apiInfo
private ApiInfo apiInfo(){
// 作者信息
Contact contact = new Contact("huake", "http://www.apache.org/licenses/LICENSE-2.0", "111");
return new ApiInfo(
"Api Documentation",
"Api Documentation",
"1.0",
"urn:tos",
contact,
"Apache 2.0",
"http://www.apache.org/licenses/LICENSE-2.0",
new ArrayList<>());
}
}
Docket.select():
// 配置了Swagger的Bean实例
@Bean
public Docket docket(){
return new Docket(DocumentationType.SWAGGER_2)
.apiInfo(apiInfo())
.select()
// RequestHandlerSelectors: 配置要扫描接口的方式
// basePackage: 指定要扫描的包
// any(): 扫描全部
// none(): 都不扫描
// withClassAnnotation: 扫描类上的注解, 参数是以一个注解的反射对象
// withMethodAnnotation: 扫描方法上的注解
.apis(RequestHandlerSelectors.basePackage("com.zya.controller"))
// 过滤路径
.paths(PathSelectors.ant("/kuang/**"))
.build();
}
配置是否启动Swagger
// 配置了Swagger的Bean实例
@Bean
public Docket docket(){
return new Docket(DocumentationType.SWAGGER_2)
.apiInfo(apiInfo())
.enable(false) // enable是否启动, 如果为False, 则Swagger不能在浏览器中访问
.select()
.apis(RequestHandlerSelectors.basePackage("com.zya.controller"))
// 过滤路径
//.paths(PathSelectors.ant("/kuang/**"))
.build();
}
问:我只希望我的Swagger在生产环境中使用,在发布的时候不使用?
配置API文档的分组:
.groupName("hello")
多个Docket实例即可配置多个分组:
@Bean
public Docket docket1(){
return new Docket(DocumentationType.SWAGGER_2).groupName("A");
}
@Bean
public Docket docket2(){
return new Docket(DocumentationType.SWAGGER_2).groupName("B");
}
@Bean
public Docket docket3(){
return new Docket(DocumentationType.SWAGGER_2).groupName("C");
}
实体类配置:
package com.zya.pojo;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
// @Api(注释)
@ApiModel("用户实体类")
public class User {
@ApiModelProperty("用户名")
public String username;
@ApiModelProperty("密码")
public String password;
}
package com.zya.controller;
import com.zya.pojo.User;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
// Operation接口
@ApiOperation("Hello控制类")
@RestController
public class HelloController {
@RequestMapping(value = "/hello")
public String hello(){
return "hello";
}
// 只要我们的接口中, 返回值中存在实体类, 他就会被扫描到Swagger中
@PostMapping(value = "/user")
public User user(){
return new User();
}
// Operation接口, 不是放在类上的, 是方法
@ApiOperation("Hello控制类")
@GetMapping(value = "/hello2")
public String hello2(@ApiParam("用户名") String username){
return "hello"+username;
}
}
总结:
Swagger是一个优秀的工具,几乎所有大公司都有使用它 【注意点:在正式发布的时候,关闭Swagger!!!出于安全考虑。而且节省内存】
如果前端响应3秒中之后才能给出数据,那给用户的体验感就非常差。所以我可以通过告诉Spring,我这个任务是一个异步任务,则就会出现不一样的效果。
AsyncController.java
package com.zya.controller;
import com.zya.service.AsyncService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class AsyncController {
@Autowired
AsyncService asyncService;
@RequestMapping("/hello")
public String hello(){
asyncService.hello(); // 停止3秒
return "ok";
}
}
AsyncService.java
package com.zya.service;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
@Service
public class AsyncService {
// 告诉Spring这是一个异步的方法
@Async
public void hello(){
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("数据正在处理...");
}
}
DemoApplication .java
package com.zya;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.scheduling.annotation.EnableAsync;
// 开启异步注解功能
@EnableAsync
@SpringBootApplication
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}