Springboot
##创建springboot项目
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-yacC7LMx-1683693522240)(C:\Users\MU\AppData\Roaming\Typora\typora-user-images\image-20221218235805516.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-FZXU7LGA-1683693522241)(C:\Users\MU\AppData\Roaming\Typora\typora-user-images\image-20221218235859885.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-wdRKQu82-1683693522242)(C:\Users\MU\AppData\Roaming\Typora\typora-user-images\image-20221218235919794.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-jXZF2C9p-1683693522242)(C:\Users\MU\AppData\Roaming\Typora\typora-user-images\image-20221218235938357.png)]
Springboot自动装配原理
springboot所有自动配置都是在启动的时候扫描并加载:spring.factories
所有的自动配置类都在这里面,但不一定生效,要判断条件是否成立,只要导入了对应的start,就有对应的启动器了,有了启动器,我们自动装配就会生效,然后配置成功!
- @SpringBootApplication:springboot应用注解,核心注解
- @Configuration:声明这个类为配置类
- @ConditionOnxxxx:条件满足才会触发成功(即导入了所需要的包)
- @AutoConfigurexxxx:自动装配xx类
- @Enablexxxx:开启某个功能
- springboot在启动的时候,从类路径下/META-INF/spring.factories获取指定的值。
- 将这些自动配置的类导入容器,自动配置就会生效,帮我们进行自动配置。
- 以前我们需要自动配置的东西,现在springboot帮我们做了。
- 整个javaEE,解决方案和自动配置的东西都在spring-boot-autoconfigure-2.7.3.jar这个包下。
- 它会把所有需要导入的组件,以类名的方式返回,这些组件就会被添加到容器。(如同spring中注入bean)
- 容器中也会存在非常多的xxxAutoConfiguration的文件(@Bean),就是这些类给容器中导入了这个场景需要的所有组件,并自动配置,@Configuration,JavaConfig。
- 有了自动配置类,免去了我们手动编写配置文件的工作。
自动装配原理的精髓:
-
springboot启动会加载大量的自动配置类
-
我们看我们需要的功能有没有在springboot默认写好的自动配置类当中
-
我们再来看这个自动配置类中到底配置了哪些组件;(只要我们要用的组件存在其中,我们就不需要在手动配置了)
-
给容器中自动配置类添加组件的时候,会从properties类中获取某些属性。我们只需要在配置文件中指定这些属性的值即可
xxxxAutoConfiguration:自动配置类;给容器中添加组件
xxxxProperties:封装配置文件中相关属性
##SpringBoot Web开发
- 导入静态资源
- 首页
- jsp,模板引擎Thymeleaf
- 装配扩展SpringMVC
- 增删改查
- 拦截器
- 国际化
静态资源
获取静态资源源码(在WebMvcAutoConfiguration.class中:)
public void addResourceHandlers(ResourceHandlerRegistry registry) {
if (!this.resourceProperties.isAddMappings()) {
logger.debug("Default resource handling disabled");
} else {
this.addResourceHandler(registry, "/webjars/**", "classpath:/META-INF/resources/webjars/");
this.addResourceHandler(registry, this.mvcProperties.getStaticPathPattern(), (registration) -> {
registration.addResourceLocations(this.resourceProperties.getStaticLocations());
if (this.servletContext != null) {
ServletContextResource resource = new ServletContextResource(this.servletContext, "/");
registration.addResourceLocations(new Resource[]{resource});
}
});
}
}
在WebMvcAutoConfiguration.class中的getStaticLocations()方法:在static resource public目录下读取静态资源
public static class Resources {
private static final String[] CLASSPATH_RESOURCE_LOCATIONS = new String[]{"classpath:/META-INF/resources/", "classpath:/resources/", "classpath:/static/", "classpath:/public/"};
private String[] staticLocations;
private boolean addMappings;
private boolean customized;
private final WebProperties.Resources.Chain chain;
private final WebProperties.Resources.Cache cache;
总结:
在springboot中,我们可以使用以下处理静态资源,文件建在resources目录下
- webjars localhost:8080/wabjars/目录结构(可以读取静态资源)
- localhost:8080/资源名 也可以获取到static resource public目录下的静态资源
- public, static, /**, resources localhost:8080/访问页面
- resources>static>public
首页定制
源码:在WebMvcAutoConfiguration.class下的方法中:
private Resource getWelcomePage() {
String[] var1 = this.resourceProperties.getStaticLocations();
int var2 = var1.length;
for(int var3 = 0; var3 < var2; ++var3) {
String location = var1[var3];
Resource indexHtml = this.getIndexHtml(location);
if (indexHtml != null) {
return indexHtml;
}
}
ServletContext servletContext = this.getServletContext();
if (servletContext != null) {
return this.getIndexHtml((Resource)(new ServletContextResource(servletContext, "/")));
} else {
return null;
}
}
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;
}
从中我们可以得出我们的首页,名字命名为index.html,放在资源目录(resource下的resource,public,static)下可以被访问到
- 首页配置:注意点,所有页面的静态资源都需要使用thymeleaf接管;@{}
- 页面国际化:
- 我们需要配置i18n文件(国际化简写)
- 我们如果需要在项目中进行按钮自动切换,我们需要自定义一个组件
LocaleResolver
- 记得将自己写的组件配置到springrongqi中
@Bean
- #{}
###thymeleaf模板引擎
导入thymeleaf依赖
<!-- Thymeleaf-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
在html中导入thymeleaf命名空间
xmlns:th="http://www.thymeleaf.org"
ThymeleafProperties.class源码:
@ConfigurationProperties(
prefix = "spring.thymeleaf"
)
public class ThymeleafProperties {
private static final Charset DEFAULT_ENCODING;
public static final String DEFAULT_PREFIX = "classpath:/templates/";
public static final String DEFAULT_SUFFIX = ".html";
private boolean checkTemplate = true;
private boolean checkTemplateLocation = true;
private String prefix = "classpath:/templates/";
private String suffix = ".html";
private String mode = "HTML";
private Charset encoding;
private boolean cache;
private Integer templateResolverOrder;
private String[] viewNames;
private String[] excludedViewNames;
private boolean enableSpringElCompiler;
private boolean renderHiddenMarkersBeforeCheckboxes;
private boolean enabled;
private final ThymeleafProperties.Servlet servlet;
private final ThymeleafProperties.Reactive reactive;
在templates资源文件下的文件,只能通过controller进行页面跳转
在页面传递参数的时候,出现取值爆红的情况:
<!--/*@thymesVar id="msg" type="java.lang.String"*/-->
<div th:text="${msg}"></div>
springmvc配置
springboot的默认配置其实就是以前springmvc的手动配置,你可以通过重新编写配置来更改默认配置,多读源码学习!!!
springboot在自动配置很多组件的时候,先看容器中有没有用户自己配制的,如果有,就使用用户的,反之,就是默认配置;如果有些组件可以存在多个,比如我们的视图解析器,就将用户和自己默认的组合起来。
- 添加视图控制器
@Configuration
public class MyMvcConfig implements WebMvcConfigurer {
@Override
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/hello").setViewName("hello");
}
}
##Data
配置application.yml,使用druid数据源,导入log4j
spring:
datasource:
username: root
password: '123456'
url: jdbc:mysql://localhost:3306/mybatis?useUnicode=true&characterEncoding=utf-8&useSSL=false
driver-class-name: com.mysql.cj.jdbc.Driver
type: com.alibaba.druid.pool.DruidDataSource
#Springboot 默认是不注入这些属性值得,需要自己绑定
#druid 数据源专有配置
initialSize: 5
minIdle: 5
maxActive: 20
maxWait: 60000
timeBetweenEvictionRusMillis: 60000
minEvictableIdleTimeMillis: 300000
validationQuery: SELECT 1 FROM DUAL
testWhileIdle: true
testOnBorrow: false
testOnReturn: false
poolPreparedStatements: true
#配置监控统计的拦截器filter,stat:监控统计、log4j:日志记录、wall:防御sql注入
filters: stat,wall,log4j
maxPoolPreparedStatementPerConnectionSize: 20
useGlobalDataSourceStat: true
connectionProperties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=500
类似web.xml可以配置servlet和filter,举例
package com.heze.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.sql.DataSource;
import java.util.HashMap;
@Configuration
public class DruidConfig {
@Bean
@ConfigurationProperties(prefix = "spring.datasource")
public DataSource druidDataSource(){
return new DruidDataSource();
}
@Bean
//后台监控 :web.xml
//因为SpringBoot 内置了servlet容器,所以没有web.xml,替代方法:ServletRegistrationBean
public ServletRegistrationBean statViewServlet(){
ServletRegistrationBean<StatViewServlet> bean = new ServletRegistrationBean<>(new StatViewServlet(), "/druid/*");
//后台需要有人登录,账号密码配置
HashMap<String, String> initParameters = new HashMap<>();
//增加配置
initParameters.put("loginUsername", "admin");
initParameters.put("loginPassword", "123456");
//允许谁可以访问
initParameters.put("allow", "");
bean.setInitParameters(initParameters); //设置初始化参数
return bean;
}
@Bean
//filter
public FilterRegistrationBean webStatFilter(){
FilterRegistrationBean bean = new FilterRegistrationBean();
bean.setFilter(new WebStatFilter());
//可以过滤哪些请求
HashMap<String, String> initParameters = new HashMap<>();
//这些东西不进行统计
initParameters.put("exclusions", "*.js,*.css,/druid/*");
bean.setInitParameters(initParameters);
return bean;
}
}
结果:可以监听我们方法的使用
##整合Mybatis框架
添加依赖
<!-- https://mvnrepository.com/artifact/org.mybatis.spring.boot/mybatis-spring-boot-starter -->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.2.2</version>
</dependency>
123456
在application.properties中添加mybatis
#整合mybatis
mybatis.type-aliases-package=com.mu.pojo
mybatis.mapper-locations=classpath:mybatis/mapper/*.xml
在资源文件中新建mybatis.mapper,将xxxMapper.xml文件放在下面
- 编写sql
、xxxMapper.java使用@Mapper注解,表示这是一个mybatis的mapper类
##SpringSecurity(安全)
在web开发中,安全第一位! 过滤器,拦截器~
功能性需求:否
做网站:在涉及隐私等时候需要考虑安全
所以
- 安全需要在设计之初考虑
Spring Security is a framework that focuses on providing both authentication and authorization to Java applications.
翻译:Spring安全性是一个专注于为Java应用程序提供身份验证和授权的框架。
即:权限的释放:
- 功能权限
- 访问权限
- 菜单权限
- …拦截器,过滤器:大量的原生代码~冗余
从MVC-spring-springboot—框架思想 — > 逐步简化代码
记住几个类:
- WebSecurityConfigurerAdpter:自定义Security策略 用来继承
- AuthenticationManagerBuilder:自定义认证策略
- @EnableWebSecurity:开启WebSecurity模式, @Enablexxxx开启某个功能
Spring Security的两个主要目标是“认证”和“授权”(访问控制)
“认证”(Authentication)
“授权”(Authorization)
步骤:
-
导入依赖
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-security</artifactId> </dependency> 1234
-
在config下新建SecurityConfig.java
授权:
@EnableWebSecurity public class SecurityConfig extends WebSecurityConfigurerAdapter { //链式编程 @Override protected void configure(HttpSecurity http) throws Exception { //首页所有人可以访问,功能页只有对应有权限的人才能访问 http.authorizeRequests().antMatchers("/").permitAll() .antMatchers("/level1/**").hasRole("vip1") .antMatchers("/level2/**").hasRole("vip2") .antMatchers("/level3/**").hasRole("vip3"); //没有权限就会跳到登录页面 http.formLogin(); } //没有权限就会跳到登录页面 // /login // 定制登录页 loginPage("/toLogin") http.formLogin().loginPage("/toLogin").usernameParameter("user").passwordParameter("pwd").loginProcessingUrl("/login"); //注销,开启了注销功能,跳到首页 // 防止网站工具: get 、 post http.csrf().disable(); //关闭csrf功能,登录失败肯定存在原因 http.logout().logoutSuccessUrl("/"); //开启记住我功能 cookie,默认保存两周,自定义接收前端的参数 http.rememberMe().rememberMeParameter("remember"); }
认证:
//认证 @Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { auth.inMemoryAuthentication().passwordEncoder(new BCryptPasswordEncoder()) .withUser("admin").password(new BCryptPasswordEncoder().encode("123456")).roles("vip2","vip3") .and() .withUser("admin2").password(new BCryptPasswordEncoder().encode("123456")).roles("vip1"); }
##Swagger简介
Swagger
- 号称世界上最流行的Api框架;
- RestFul Api文档在线生成工具=>Api文档与API定义同步更新
- 直接运行,可以在线测试API接口;
- 支持多种语言:(Java,Php…)
SpringBoot集成Swagger
-
新建一个SpringBoot项目=>web项目
-
导入依赖
<dependency> <groupId>io.springfox</groupId> <artifactId>springfox-swagger2</artifactId> <version>2.9.2</version> </dependency> <!-- https://mvnrepository.com/artifact/io.springfox/springfox-swagger-ui --> <dependency> <groupId>io.springfox</groupId> <artifactId>springfox-swagger-ui</artifactId> <version>2.9.2</version> </dependency>
3.编写一个Hello工程
4.配置Swagger===>Config
@Configuration
@EnableSwagger2 //开启Swagger2
public class SwaggerConfig {
}
5.配置swagger信息
package com.mu.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的Docket的bean实例
@Bean
public Docket docket() {
return new Docket(DocumentationType.SWAGGER_2).apiInfo(apiInfo());
}
//配置swagger信息=>apiInfo
private ApiInfo apiInfo() {
Contact contact = new Contact("慕余", "https://blog.csdn.net/qq_51326491?type=blog", "309***97@qq.com");
return new ApiInfo(
"SwaggerAPI文档",
"别回头看",
"v1.0", "urn:tos",
contact,
"Apache 2.0",
"http://www.apache.org/licenses/LICENSE-2.0",
new ArrayList()
);
}
}
启动报错:Failed to start bean ‘documentationPluginsBootstrapper’; nested exception is java.lang.NullPointerException
解决方案:
在配置文件application.properties中加入以下配置
spring.mvc.pathmatch.matching-strategy=ANT_PATH_MATCHER
如果是application.yml就加入
spring:
mvc:
pathmatch:
matching-strategy: ant_path_matcher
Swagger配置扫描接口
//配置了Swagger的Docket的bean实例
@Bean
public Docket docket() {
return new Docket(DocumentationType.SWAGGER_2)
.apiInfo(apiInfo())
//.enable(false) enable是否启动swagger,如果为flase,则swagger不能在浏览器中访问
.select()
//RequestHandlerSelectors,配置要扫描接口的方式
//basePackage:指定要扫描的包
//any():扫描全部
//none():不扫描
//withClassAnnotation:扫描类上的注解,参数是一个注解的反射现象
//withMethodAnnotation:扫描方法上的注解
.apis(RequestHandlerSelectors.basePackage("com.mu.controller"))
//path(),过滤路径
// .paths(PathSelectors.ant("/mu/**"))
.build();
}
选择开发环境中使用swagger
@Bean
public Docket docket(Environment environment) {
//设置要显示的Swagger环境
Profiles profiles = Profiles.of("dev", "test");
//通过environment.acceptsProfiles判断是否处在自己设定的环境当中
boolean flag = environment.acceptsProfiles(profiles);
return new Docket(DocumentationType.SWAGGER_2)
.apiInfo(apiInfo())
.enable(flag) //enable是否启动swagger,如果为flase,则swagger不能在浏览器中访问
.select()
.build();
}
配置API文档分组
return new Docket(DocumentationType.SWAGGER_2)
.apiInfo(apiInfo())
.groupName("yiyi") //分组
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-BYIo54Eg-1683693522243)(C:\Users\MU\Desktop\笔记\springswaggerapi分组.jpg)]
配置多个分组
@Bean
public Docket docket1(){
return new Docket(DocumentationType.SWAGGER_2).groupName("A");
}
@Bean
public Docket docket2(){
return new Docket(DocumentationType.SWAGGER_2).groupName("A");
}
@Bean
public Docket docket3(){
return new Docket(DocumentationType.SWAGGER_2).groupName("A");
}
@Bean
public Docket docket(Environment environment) {
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-7chxvstW-1683693522244)(C:\Users\MU\Desktop\笔记\swagger分组.jpg)]
swagger配置扫描接口
接口的使用:
实体类:
//@Api(注释)
@ApiModel("用户实体类")
public class User {
@ApiModelProperty("用户名")
public String username;
@ApiModelProperty("密码")
public String password;
}
扫描接口
//只要我们的接口中,返回值中存在实体类,他就会被扫描到Swagger中
@PostMapping("/user")
public User user(){
return new User();
}
网站显示
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-kV5np7YF-1683693522245)(C:\Users\MU\Desktop\笔记\swagger接口实现实体类.jpg)]
controller中方法接口扫描
@GetMapping("/hello")
public String hello(){
return "hello";
}
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-WAlGKiLJ-1683693522245)(C:\Users\MU\Desktop\笔记\swagger方法接口实现.jpg)]
还可以在方法中传入参数在线测试
@GetMapping("/hello")
public User hello(@Apiparam("用户") User user){//@Apiparam 是对参数的注释说明,只是为了加入中文说明
return user;
}
总结:
优势:
- 我们可以对一些接口属性添加注释信息
- 接口文档实时更新
- 在线测试
任务
异步任务
异步任务是那些被引擎放在一边,不进入主线程、而进入任务队列的任务。只有引擎认为某个异步任务可以执行了(比如 Ajax 操作从服务器得到了结果),该任务(采用回调函数的形式)才会进入主线程执行。排在异步任务后面的代码,不用等待异步任务结束会马上运行,也就是说,异步任务不具有“堵塞”效应。
(先执行主线程,然后主线程中的异步方法进入任务队列,主线程继续执行,无序等待异步任务完成)
在启动类上添加注释
@EnableAsyns//开启异步注解功能
在service方法上添加注释
@Async //告诉spring这是一个异步方法
邮件任务
1.导入依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-mail</artifactId>
</dependency>
2.得去qq邮箱 账号设置开启SMTP服务
3.配置
spring.profiles.active=dev
spring.mail.username=1795308632@qq.com
spring.mail.password=
spring.mail.host=smtp.qq.com
#开启加密验证(qq邮箱需要)
spring.mail.properties.mail.smtp.sll.enble=true
4.发送邮件
@Autowired
JavaMailSenderImpl mailSender;
@Test
void contextLoads() {
SimpleMailMessage mailMessage=new SimpleMailMessage();
mailMessage.setSubject("yiyi,你好"); //主题
mailMessage.setText("谢谢");//内容
mailMessage.setTo("1795308632@qq.com");//发送到
mailMessage.setFrom("1795308632@qq.com");//来自
mailSender.send(mailMessage);
}
//复杂的邮件
MimeMessage mimeMessage=mailSender.createMimeMessage();
MimeMessageHelper helper=new MimeMessageHelper(mimeMessage,true);
helper.setSubject("yiyi,你好");
helper.setText("");
定时任务
在启动类上添加注释
@EnableScheduling//开启定时功能的注解
在service方法上添加注释
@Scheduling(cron="0 * * * * 0-7")//什么时候执行,里面填入cron表达式// 秒 分 时 日 月 星期几 *d