springboot
什么是springboot
springboot简介:
Springboot是基于spring开发的,Springboot本身不提供spring的核心特性和拓展功能,只能用于快速,敏捷的开发新一代基于spring框架的应用程序。也就是说springboot不是用来替代spring的解决方案,而是和spring紧密结合用于提升spring开发者体验的工具。
核心思想:约定大于配置
约定大于配置,集成了大量常用的第三方库配置(如redis,mongodb,jpa,rabbitmq,quartz),springboot中这些配置几乎可以零配置开箱即用
优点:
- 为所有的sping开发者更快的入门spring框架
- 开箱即用,提供各类默认配置来简化项目配置
- 内嵌web容器,简化了web项目
- 没有冗余的代码生成和xml的配置要求
好的程序=数据结构+算法
微服务架构
几种架构模型:
- MVC三次架构
- MVVM(Model,View,ModelAndView)前端架构
- 微服务架构
微服务架构简介:
微服务架构相当于将原来的业务拆分成模块来管理,相对于将原来的all in one将所有的业务都放在一个应用中,如果整个应用的负载能力不行,我们需要对整个项目进行整个水平复制,然后负载均衡,提高整个应用的负载能力。
但是对于微服务来说,打破了之前的all in one 模式,把每个业务都独立出来做成一个服务,然后将这些服务动态的组合起来,如果某个业务的负载不行,可以单独对这个业务进行水平复制,而不是对整个应用。
微服务架构的优点:
- 节约调用资源
- 每一个业务都是单独的服务,一个可替换可升级的模块
构建大型分布式微服务的全套产品
- 在构建一个业务服务时候,可以使用springboot来快速帮我们构建一个模块服务
- 大型分布式网络服务的调用,可以使用springcloud来解决
- 在分布式中间进行流式数据计算和批处理我们用spring cloud data flow来解决
- spring为我们想好了从构建应用到大型分布式应用的整套流程
第一个springboot程序
创建方式:
- 从官网上下载zip包,并解压,然后用idea的import导入项目
- 直接在idea中选择创建springboot项目
- 这两种方式本质上都是一样的
项目结构分析(springboot项目的maven结构分析):
-
项目元数据信息:创建的时候输入的projectmetaclata部分就是maven项目的基本元素,包括groupid,artifactid,version,name,description等等
-
parent:继承spring-boot-starter-parent这个父工程,他可以帮助我们实现依赖管理,版本控制和打包等功能
-
dependencies:项目的具体依赖,如果是web工程,这里包含了spring-boot-starter-web,用于实现http接口,该依赖包含了springmvc,官网对他的描述是:使用springmvc构建web(包括restful)应用程序的入门者,使用tomcat作为默认的嵌入式容器。还包含了spring-boot-starter-test,该包用于编写测试的依赖包
-
build:这里是构建配置部分,默认使用spring-boot-maven-plugin,配合spring-boot-starter-parent就可以把springboot应用打包成jar
springboot应用程序的注意点:
- 所有的包都要和springboot主程序同级
- 在maven中的工具中双击package就可以将项目打包成jar,jar文件放在了项目的target目录下,使用命令java -jar ...jar就可以直接运行springboot程序
- springboot程序所有的配置都在application.properties或者application.yml文件中来配置
springboot自动装配原理
springboot的依赖管理:在pom.xml的父工程有依赖管理项,里面有大部分的依赖,可以进行版本控制
springboot的使用某个依赖:直接在依赖配置中添加依赖,如果是spring集成的,就是spring-boot-starter-xxx,如果是第三方集成的,就是xxx-spring-boot-starter
主程序:使用了@SpringBootApplication注解标注的类就是主程序,也表明这是一个springboot应用。SpringApplication.run(主程序的class对象,args)。通过反射的方式启动该类。
了解主启动类怎么运行的(简单了解)
初始化:
- 推断应用的类型是普通java项目还是web项目
- 将所有可用的初始化器设置到initializers属性中
- 找出所有应用程序的监听器,设置到listeners属性中
- 推断并设置main方法的定义类,找到运行的主类
yaml语法
yaml是一种标记语言,springboot推荐使用application.yml来增加配置
语法:key:空格value
基本的yaml用法:
-
可以存储对象:
-
#写法一 person: name: clt age: 21 #写法二 person: {name: clt,age: 21}
-
-
可以存储数组:
-
#写法一 array: -dog -cat #写法二 array: [dog,cat]
-
- 相对于properties文件来说,yaml可以存储很多数据类型,properties只能存储key-value形式的数据类型
关于yaml中的${}的用法:
-
自动生成uuid和随机数
person: name: ${random.uuid} age: ${random.int}
-
占位符用法:
-
多文档块:
-
#文档块一(默认) server: port: 8081 spring: profiles: active: prod --- #文档块二(开发环境) server: port: 8082 spring: profiles: dev --- #文档块三(生产环境) server: port: 8083 spring: profiles: prod
-
配置文件给属性赋值的几种方式
yaml配置文件给属性赋值:
- 在application.yaml配置文件中定义一些类和值
- 在需要使用applicaton.yaml赋值的类上使用@ConfigurationProperties(prefix="在application.yaml中定义的对象名")
- 这样就可以将application.yaml中对应的值赋值给类上了
- 注意点:如果是类的属性名和application.yaml中的属性名有大小写不对应的话,在application.yaml中的属性名可以映射,last-name中的-可以将后面的n改为大写lastName
properties配置文件给属性赋值:
- 在application.properties配置文件中定义一些键值对
- 在需要使用application.properties赋值的类上使用@PropertySource(value="classpath:application.properties")
- 在需要赋值的属性上面使用@value("${在application.properties中定义的key}")
- 这样就可以将application.properties中的指定的key的值赋值给属性
- 注意点:如果使用application.properties赋值,如果值是中文,可能会出现乱码。可以将FileEncoding中的properties文件的编码方式改为UTF-8
JSR303校验
在springboot中使用jsr303来校验数据
-
@Validated标注在类上就可以开启数据校验功能
-
常见的jsr303校验数据
-
@Email//表示该属性格式必须为email格式 @Length//表示限定字符串长度 @NotEmpty//必须为非空 @Range//表示在合适的范围内 @Null//表示必须为空 @NotNull//表示必须为非空 @AssertFalse//表示必须为false @AssertTrue//表示必须为true @Min(value)//表示必须为数值,且小于等于指定的value @Max(value)//和上面的相反 @Size(max,min)//表示大小在指定的范围内 @Pattern(value)//必须符合指定的正则表达式
-
多环境配置及配置文件位置
配置文件可以放在那些地方?
- 项目路径下的config包下
- 项目路径下
- classpath下自建的config包下
- classpath下
- 优先级:从下到上优先级依次升高
多环境配置:(yaml和properties)
-
yaml:
-
#文档块一(默认) server: port: 8081 spring: profiles: active: prod --- #文档块二(开发环境) server: port: 8082 spring: profiles: dev --- #文档块三(生产环境) server: port: 8083 spring: profiles: prod
-
-
properties:
- 在同一个文件夹下面同时建立不同的properties文件:application.properties,application-test.properties,application-dev.properties
- 默认走application.properties,当然也可以在application.properties中指定该走那个properties文件。spring.profiles.active=test
- 多环境文件的用处:可以用于配置不同的数据库进行测试
springboot自动配置原理
使用springboot开发web应用
需要解决的问题?
- 导入静态资源
- 首页
- 没有jsp,引入模板引擎来解析页面
- 装配扩展springmvc
- 用springboot实现web的CRUD
- 拦截器
- 国际化
sprinboot下的静态资源
位置:
- resources下的resources下
- resources下的static下
- resources下的public下
- 有webapp的放在META-INF下的resources下
- 对于springboot,静态资源的目录的优先级(从高到低):resources>static>public
- 放在这几个位置都可以直接访问到的
设置欢迎页和访问标签的图标
设置欢迎页:
- 在静态资源目录下写一个index.html文件即可
- 注意放在templates目录下的页面是不能直接访问的,要通过Controller来跳转访问。Controller跳转页面需要引入模板引擎,如thymeleaf
thymeleaf模板引擎
使用:导入thymeleaf依赖和引入命名空间(<html lang="en" xmlns:th="http://www.thymeleaf.org")即可启用。即可跳转页面和传数据到html
- thymeleaf用th标签来绑定html元素,用${}来取到后端的ModelAndView中的数据
thymeleaf中的常用指令:
- th:text="${}"
- th:utext="${}"
- th:each="item:${array}"
- 详细的指令查看thymeleaf官网文档:https://www.thymeleaf.org
MVC配置原理
怎么配置?
- 首先springmvc的配置都要放在继承了WebMvcConfigure接口的配置类里面,一般如果想要拓展springmvc中的某个功能,我们直接在这个配置类中新建静态内部类来继承实现那个功能的接口,然后重写里面的方法,并返回这个自定义的类,就可以使它生效。
设置网站的首页
-
除了直接把index.html放在resources,public,static目录下,还有第二种方法实现首页功能
-
直接重写WebMvcConfigurer中的addViewControllers方法
-
@Override public void addViewControllers(ViewControllerRegistry registry) { registry.addViewController("/").setViewName("Login"); registry.addViewController("/Login.html").setViewName("Login"); registry.addViewController("/i18n.html").setViewName("i18n"); }
-
国际化的实现
作用:可以通过一个请求实现一个页面语种的切换
实现:
-
准备包含各种语种的properties,如login.properties,login_en_US.properties,login_en_CN.properties,这些文件全部放在resources的i18n文件夹下面
-
#英文版的 login.username=clt login.password=123 login.login1=login login.submit=submit
-
#中文版的 login.username=陈浪涛 login.password=123 login.login1=登录 login.submit=提交
-
-
在application.properties中配置国际化文件的文件位置:
-
spring.message.basename=i18n.login
-
-
自定义语言解析器(在MVC配置类中配置)
-
// 自定义语言解析器类(用于国际化) public static class MyLocalResolver implements LocaleResolver { @Override public Locale resolveLocale(HttpServletRequest request) { String lang = request.getParameter("l"); System.out.println(lang); Locale locale = Locale.getDefault(); if (lang!=null){ String[] l = lang.split("_"); locale = new Locale(l[0],l[1]); } return locale; } @Override public void setLocale(HttpServletRequest request, HttpServletResponse response, Locale locale) { } }
-
-
在前端显示效果
-
<!DOCTYPE html> <html lang="en" xmlns:th="http://www.thymeleaf.org"> <head> <meta charset="UTF-8"> <title>国际化</title> </head> <body> <!--用#{}可以读取到properties中的文件--> <input type="text" th:placeholder="#{login.username}"> <br> <input type="password" th:placeholder="#{login.password}"> <br> <!--@{}请求到/i18n.html并携带参数l交给语言解析器处理--> <!--/i18n.html控制器可以跳回到此页面,实现语言解析请求提交并返回到原来的页面--> <a th:href="@{/i18n.html(l='zh_CN')}">Chinese</a> <a th:href="@{/i18n.html(l='en_US')}">English</a> </body> </html>
-
-
完整的WebMvc配置和页面
-
package com.chen.springbootstudy.config; import com.sun.corba.se.spi.orbutil.closure.Closure; import com.sun.corba.se.spi.resolver.LocalResolver; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.util.StringUtils; import org.springframework.web.filter.RequestContextFilter; import org.springframework.web.servlet.*; import org.springframework.web.servlet.config.annotation.*; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.util.Locale; import java.util.Set; //自定义mvc视图解析器 @Configuration //@EnableWebMvc //如果要拓展springmvc,不能加上enablewebmvc,因为webmvc自动装配的条件有一个是缺少WebMvcConfigurationSupport类, // 而这个注解里DelegatingWebMvcConfiguration继承了WebMvcConfigurationSupport public class MvcConfig implements WebMvcConfigurer { // @Bean // public RequestContextFilter myviewresolver(){ // return new DiyViewResolver(); // } // // // // public static class DiyViewResolver extends RequestContextFilter { // // public DiyViewResolver() { // return; // } // } // 设置欢迎页 @Override public void addViewControllers(ViewControllerRegistry registry) { registry.addViewController("/").setViewName("Login"); registry.addViewController("/Login.html").setViewName("Login"); registry.addViewController("/i18n.html").setViewName("i18n"); } // 自定义语言解析器类(用于国际化) public static class MyLocalResolver implements LocaleResolver { @Override public Locale resolveLocale(HttpServletRequest request) { //获得请求中的l参数 String lang = request.getParameter("l"); System.out.println(lang); Locale locale = Locale.getDefault(); if (lang!=null){ //以_为分隔符将参数分割成en,CN;en,US String[] l = lang.split("_"); locale = new Locale(l[0],l[1]); } return locale; } @Override public void setLocale(HttpServletRequest request, HttpServletResponse response, Locale locale) { } } @Bean public LocaleResolver localeResolver(){ return new MyLocalResolver(); } // 拦截器 public static class MyInterceptor implements HandlerInterceptor { @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { System.out.println("Interceptor"); if (request.getSession().getAttribute("loginname")!=null){ return true; } request.getRequestDispatcher("/Login.html").forward(request,response); return false; } @Override public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { } @Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { HandlerInterceptor.super.afterCompletion(request, response, handler, ex); } } @Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(new MyInterceptor()).addPathPatterns("/**").excludePathPatterns("/Login.html","/login.html","/imageslogin/**","/csslogin/**"); } }
-
<!DOCTYPE html> <html lang="en" xmlns:th="http://www.thymeleaf.org"> <head> <meta charset="UTF-8"> <title>国际化</title> </head> <body> <!--用#{}可以读取到properties中的文件--> <input type="text" th:placeholder="#{login.username}"> <br> <input type="password" th:placeholder="#{login.password}"> <br> <!--@{}请求到/i18n.html并携带参数l交给语言解析器处理--> <!--/i18n.html控制器可以跳回到此页面,实现语言解析请求提交并返回到原来的页面--> <a th:href="@{/i18n.html(l='zh_CN')}">Chinese</a> <a th:href="@{/i18n.html(l='en_US')}">English</a> </body> </html>
-
登录功能实现
拦截器
配置方法:
-
在webmvc配置类中重写拦截器方法即可,实现HandlerInterceptor接口即可
-
// 拦截器 public static class MyInterceptor implements HandlerInterceptor { @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { System.out.println("Interceptor"); //返回true就可以放行,false就拦截 if (request.getSession().getAttribute("loginname")!=null){ return true; } request.getRequestDispatcher("/Login.html").forward(request,response); return false; } @Override public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { } @Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { HandlerInterceptor.super.afterCompletion(request, response, handler, ex); } }
-
-
在webmvc中重写注册拦截器的方法即可、
-
@Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(new MyInterceptor()).addPathPatterns("/**").excludePathPatterns("/Login.html","/login.html","/imageslogin/**","/csslogin/**"); //表示拦截所有请求,除了Login.html,login.html和静态资源放行 }
-
设置404页面
如何设置:
- 在静态资源目录下新建404.html或者5xx.html就可以实现错误页面了
- /static,/public,/resources
springboot-jdbc
spring-boot-jdbc-starter使用步骤:
-
导入依赖:
-
spring-boot-jdbc-starter mysql-connecter-java
-
-
在application.properties配置文件中配置相关的jdbc的参数
-
spring: datasource: driver-class-name: com.mysql.cj.jdbc.Driver url: jdbc:mysql://localhost:3306/springboot?useUnicode=true&characterEncoding=utf8&useSSL=true&serverTimezone=UTC username: root password: 7536951 type: com.alibaba.druid.pool.DruidDataSource filters: log4j,stat
-
Druid数据源使用步骤:
-
导入依赖
-
spring-boot-druid-starter
-
-
在application.properties中配置druid以使用druid数据源
-
spring: datasource: driver-class-name: com.mysql.cj.jdbc.Driver url: jdbc:mysql://localhost:3306/springboot?useUnicode=true&characterEncoding=utf8&useSSL=true&serverTimezone=UTC username: root password: 7536951 //配置数据源为Druid type: com.alibaba.druid.pool.DruidDataSource filters: log4j,stat
-
常用的druid配置项
-
filters:stat #filters选项中的三个值:stat,log4j,wall。sata表示开启druid监控功能,log4j表示开启日志功能,wall表示防止sql注入 maxActive:20 initialSize:1 maxWait:60000 minIdle:10 #maxIdle:15 timeBetweenEvictionRunsMillis:60000 minEvictableIdleTimeMillis:300000 validationQuery:SELECT 'x' testWhileIdle:true testOnBorrow:false testOnReturn:false #poolPreparedStatements:true maxOpenPreparedStatements:20 #对于建立连接过长的连接强制关闭 removeAbandoned:true #如果连接建立时间超过了30分钟,则强制将其关闭 removeAbandonedTimeout:1800 #将当前关闭动作记录到日志 logAbandoned:true
-
-
-
新建druid配置文件
-
@Configuration public class DruidConfig { // Druid的監控功能配置 @Bean public ServletRegistrationBean servletRegistrationBean(){ ServletRegistrationBean<StatViewServlet> servletRegistrationBean = new ServletRegistrationBean<StatViewServlet>(new StatViewServlet(),"/druid/*"); Map<String,String> map = new HashMap<String,String>(); // 配置登錄用戶loginUsername配置用戶名loginPassword配置密碼 map.put("loginUsername","clt"); map.put("loginPassword","123456"); // 配置誰能訪問如果值為""誰都可以訪問 map.put("allow",""); servletRegistrationBean.setInitParameters(map); return servletRegistrationBean; } //将druid注入到spring容器中,替换掉springboot默认的数据源。并在配置文件application.yaml中使用spring.datasource对象给druid的配置类注入值 @Bean @ConfigurationProperties(prefix = "spring.datasource") public DataSource DruidDataSource(){ return new DruidDataSource(); } }
-
Druid开启监控功能
-
在配置文件中开启监控功能
-
spring.datasource.filters=stat
-
-
在配置类中注册druid的监控页面的访问路径(在springboot中注册servlet必须要使用servletregistrationBean)
-
@Configuration public class DruidConfig { // Druid的監控功能配置 @Bean public ServletRegistrationBean servletRegistrationBean(){ ServletRegistrationBean<StatViewServlet> servletRegistrationBean = new ServletRegistrationBean<StatViewServlet>(new StatViewServlet(),"/druid/*"); //在这里映射路径必须为/druid/*才可以访问到 Map<String,String> map = new HashMap<String,String>(); // 配置登錄用戶loginUsername配置用戶名loginPassword配置密碼 map.put("loginUsername","clt"); map.put("loginPassword","123456"); // 配置誰能訪問如果值為""誰都可以訪問 map.put("allow",""); /** Map<String, String> initParameters = new HashMap<>(); initParameters.put("resetEnable", "false"); //禁用HTML页面上的“Rest All”功能 initParameters.put("allow", "10.8.9.115"); //ip白名单(没有配置或者为空,则允许所有访问) initParameters.put("loginUsername", "admin"); //++监控页面登录用户名 initParameters.put("loginPassword", "123.admin"); //++监控页面登录用户密码 initParameters.put("deny", ""); //ip黑名单 */ servletRegistrationBean.setInitParameters(map); return servletRegistrationBean; } //将druid注入到spring容器中,替换掉springboot默认的数据源。并在配置文件application.yaml中使用spring.datasource对象给druid的配置类注入值 @Bean @ConfigurationProperties(prefix = "spring.datasource") public DataSource DruidDataSource(){ return new DruidDataSource(); } }
-
- 因为springboot内置了servlet容器,所以想要配置servlet只能通过javaconfig的形式来配置。如ServletRegistrationBean,FilterRegistrationBean
- springboot默认的数据源是hikariDataSource数据源,号称javaweb中最快的数据源
springboot整合mybatis
使用步骤:
-
导包
-
在配置文件application.yml中配置mapper的路径和实体类的别名包位置
-
spring: datasource: driver-class-name: com.mysql.cj.jdbc.Driver url: jdbc:mysql://localhost:3306/springboot?useUnicode=true&characterEncoding=utf8&useSSL=true&serveTimezone=UTC username: root password: 7536951 mybatis: mapper-locations: classpath:mybatis/mappers/*.xml type-aliases-package: com.chen.pojo
-
在springboot项目中一般mapper的位置放在resources的下面的位置下面
-
spring-security(可以实现认证和授权)
简介:
-
Spring-Security是针对spring项目的安全框架,也是springboot底层安全模块默认的技术选型,它可以实现强大的安全控制,对于安全控制,我们只需要映入spring-boot-securyit-starter,进行少量的配置,即可以实现强大的安全管理。spring-security主要的目标就是认证和授权
-
需要了解的几个关于spring-security的几个类
-
WebSecurityConfigurerAdapter:自定义security策略 AuthenicationManagerBuilder:自定义认证策略 @EnableWebSecurity:开启WebSecurity模式
-
WebSecurity的配置:(需要在配置类上开启@EnableWebSecurity)
-
@EnableWebSecurity @Configuration public class SeruityConfig { //授权 @Bean public UserDetailsService userDetailsService() throws Exception { // ensure the passwords are encoded properly User.UserBuilder users = User.withDefaultPasswordEncoder(); InMemoryUserDetailsManager manager = new InMemoryUserDetailsManager(); manager.createUser(users.username("xiaohong").password(new BCryptPasswordEncoder().encode("123")).roles("vip1").build()); manager.createUser(users.username("clt").password("123").roles("vip1","vip2","vip3").build()); manager.createUser(users.username("xiaoming").password("123").roles("vip2").build()); manager.createUser(users.username("xiaosan").password("123").roles("vip3").build()); return manager; } //认证 @Bean public SecurityFilterChain apiFilterChain(HttpSecurity http) throws Exception { http .authorizeHttpRequests() .antMatchers("/").permitAll() .and() .authorizeHttpRequests() .antMatchers("/tolevel1/**").hasRole("vip1") .and() .authorizeHttpRequests() .antMatchers("/tolevel2/**").hasRole("vip2") .and() .authorizeHttpRequests() .antMatchers("/tolevel3/**").hasRole("vip3") .and() .formLogin() // .loginPage("/tologin") // .usernameParameter("user") // .passwordParameter("pwd") .loginPage("/tologin") .loginProcessingUrl("/login") .successForwardUrl("/index") .and() .logout()//开启注销功能,前端请求/logout .logoutSuccessUrl("/index") .and() .csrf().disable() .rememberMe() .rememberMeParameter("remember");//开启记住我功能 return http.build(); } }
-
websecurity实现认证授权(配合thymeleaf模板引擎使用)
-
<!DOCTYPE html> <html lang="en" xmlns:th="http://www.thymeleaf.org" xmlns:sec="http://www.thymeleaf.org/extras/spring-security"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <div sec:authorize="isAuthenticated()"> 用户名:<span sec:authentication="name"></span> </div> <div sec:authorize="hasRole('vip1')"> <a th:href="@{/tolevel1}">level1</a> </div> <div sec:authorize="hasRole('vip2')"> <a th:href="@{/tolevel2}">level2</a> </div> <div sec:authorize="hasRole('vip3')"> <a th:href="@{/tolevel3}">level3</a> </div> <div> <a th:href="@{/tologin}">登录</a> </div> <div> <a th:href="@{/logout}">注销</a> </div> </body> </html>
-
spring-secutity和thymeleaf整合
作用:可以实现登录显示用户名称,不同权限显示不同的内容
常用的属性:
- sec:authorize="isAuthenticated()"判断是否登录,如果登录显示包裹的内容
- sec:authentication="name"显示登录的用户名
- sec:authorize="hasRole('vip1')" 判断登录用户的权限,如果是vip1则显示包裹内容
整合的版本问题:
-
springboot版本最新;thymeleaf默认;整合包使用5;html中使用的命名空间
-
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-security</artifactId> </dependency> <dependency> <groupId>org.thymeleaf.extras</groupId> <artifactId>thymeleaf-extras-springsecurity5</artifactId> <version>3.0.4.RELEASE</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-thymeleaf</artifactId> </dependency>
-
命名空间
-
<html lang="en" xmlns:th="http://www.thymeleaf.org" xmlns:sec="http://www.thymeleaf.org/extras/spring-security">
-
Apache-Shiro(和spring-security都是安全框架)
什么是shiro?
- Apache-Shiro是一个Java的安全框架
- Shiro可以非常容易的开发出足够好的应用
- Shiro可以完成,认证,授权,加密,会话管理,web集成,缓存等
swagger(方便前后端沟通)
了解前后端分离
- 前后端分离时代:主流使用springboot和vue
- 以前的前后端时代:前端只用管理静态网页,后端使用jsp作为模板引擎
- 前后端分离时代介绍:
- 后端:分为控制层,服务层,数据调用层
- 前端:前端控制层(如vue框架),视图层(前端一般会使用伪数据来让前端工程独立运行起来)
- 前后端交互靠前端调用后端api接口
- 前后端时代相对独立,松耦合
- 前后端分离甚至可以不用在同一台服务器上
前后端出现的问题
- 前后端集成联调,前后端人员无法做到“及时协商,尽早解决”,最终会导致问题集中爆发
- 早些年的解决方法:
- 制定schema(提纲)实时更新最新的api,降低集成的风险
- 制定word计划文档
- 前后端分离:
- 前端测试后端接口通常用postman
- 后端提供接口,需要实时更新最新消息
- 现在的解决方案:swagger
- 早些年的解决方法:
- 这就是swagger的作用:及时更新后端接口,方便前后端集成测试,降低集成风险
springboot集成swagger:(需要在配置类上加上@EnableSwagger2)
-
导入依赖
-
<!-- 配置swagger2 --> <!-- 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> <dependency> <groupId>io.springfox</groupId> <artifactId>springfox-swagger2</artifactId> <version>3.0.0</version> </dependency> <!-- https://mvnrepository.com/artifact/io.springfox/springfox-boot-starter --> <dependency> <groupId>io.springfox</groupId> <artifactId>springfox-boot-starter</artifactId> <version>3.0.0</version> </dependency>
-
-
配置swagger
-
package com.chen.swaggerconfig; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.core.env.Environment; import org.springframework.core.env.Profiles; import springfox.documentation.builders.PathSelectors; import springfox.documentation.builders.RequestHandlerSelectors; 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; import java.util.function.Predicate; @Configuration @EnableSwagger2 public class SwaggerConfig { // Evironment 可以获取生产环境也就是application中的spring.profiles.active的值 // Environment environment @Bean public Docket docket(Environment environment){ Profiles profiles = Profiles.of("dev","test"); // 如果application中的spring.profiles.active=dev则返回true否则false boolean flag = environment.acceptsProfiles(profiles); return new Docket(DocumentationType.SWAGGER_2).apiInfo(new ApiInfo("陈浪涛的APi", "Api Documentation", "1.0", "urn:tos", new Contact("陈浪涛", "", "[email protected]"), "Apache 2.0", "http://www.apache.org/licenses/LICENSE-2.0", new ArrayList())) // groupName可以实现分组,不同的人写不同的接口可以通过分组来区分,统一管理 .groupName("A") // .enable(flag) // enable决定是否能在浏览器中访问swagger默认为true .select() //select 写select可以用apis,apis可以指定要扫描的controller包 //RequestHandlerSelectors可以指定要扫描的方法 any扫描所有,none不扫描,withClassAnnotation根据类注解来扫描如@RentController //withMethodannotation根据方法上的注解来扫描如@RequestMapping .apis(RequestHandlerSelectors.basePackage("com.chen.controller")) //paths是过滤器,可以指定只扫描那些请求 // .paths(PathSelectors.ant("/chen/**")) .build(); } @Bean public Docket docket2(){ return new Docket(DocumentationType.SWAGGER_2).groupName("b"); } }
-
-
在application.yml中解决版本问题导致springboot启动失败
-
spring: mvc: pathmatch: matching-strategy: ant_path_matcher
-
-
访问/swagger-ui/请求即可访问swagger页面
swagger的接口常用的注解
- 用在Entity上的注解:
- @ApiModel("注释"):放在类上
- @ApiModelProperty(""):放在字段上
- @Api("")
- 只要controller中有返回类型为实体类的,则swagger中就会有实体类的显示
- 用在controller上的注解:
- @ApiOperation(""):给请求方法加上注解
- @ApiParam(""):给请求的方法中的参数加上注解
swagger的作用:
- 可以为比较难理解的属性式接口加上注释
- 接口文档可以实时更新
- 可以在线测试接口
- 需要注意的是swagger在开发中可以使用,在项目上线后要将其关闭!!!
任务(异步任务,定时任务,邮件发送)
异步任务:
- 在启动类上开启异步任务注解@EnableAsync
- 在需要进行异步的的请求方法上加上@Async注解
- 使用场景:
- 请求一个请求的时候,但里面有需要一定时间才能执行完的代码,不能及时返回处理结果,可以开启异步,及时返回结果。
定时任务:
-
在启动类上加上@EnableScheduling注解
-
在需要进行定时任务的方法上加上@Scheduled(cron ="*/6 * * * * ?"),cron的值就是规定的时间
-
关于定时任务的cron的时间:
-
// @Scheduled(cron="0/2 * * * * ?") //每个2秒执行一次 // @Scheduled(cron="0 25 8 * * *") //每天8:25分秒执行一次 @Scheduled(cron="0 0/5 * * * *") //每5分钟执行一次 // @Scheduled(cron="0 5 * * * *") //每小时第5分钟执行
-
邮件发送:
-
导入依赖:
-
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-mail</artifactId> </dependency>
-
-
application.yml配置mail
spring: mail: #这是qq的 host: smtp.qq.com username: [email protected] #从qq邮箱发送的密码 password: gepjaffygmgjdceh
-
发送简单文本和复杂文本邮件
-
package com.chen.controller; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.core.io.FileSystemResource; import org.springframework.mail.SimpleMailMessage; import org.springframework.mail.javamail.JavaMailSender; import org.springframework.mail.javamail.MimeMailMessage; import org.springframework.mail.javamail.MimeMessageHelper; 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; import javax.mail.MessagingException; import javax.mail.internet.MimeMessage; import java.io.File; @Controller public class mailcontroller { @Autowired JavaMailSender javaMailSender; //发送简单文本文件 @ResponseBody @GetMapping("/mail") public String mail(){ SimpleMailMessage message = new SimpleMailMessage(); message.setTo("[email protected]"); message.setSubject("Hello,Mail"); message.setText("nihao"); message.setFrom("[email protected]"); javaMailSender.send(message); return "ok"; } @ResponseBody @GetMapping("/mimemail") public String mimemail(){ MimeMessage mimeMessage = javaMailSender.createMimeMessage(); MimeMessageHelper helper; try { helper = new MimeMessageHelper(mimeMessage,true); //这里也可以用helper来创建MimeMessage helper.getMimeMessage(); helper.setTo("[email protected]"); helper.setFrom("[email protected]"); helper.setSubject("mimemessage"); String rscid = "001"; //通过html发送图片 helper.setText("<img src=\'cid:"+rscid+"\'/>",true);//发送html邮件 FileSystemResource fileSystemResource2 = new FileSystemResource(new File("E:\\多媒体系列\\图片\\3.jpg")); helper.addInline(rscid,fileSystemResource2); FileSystemResource fileSystemResource = new FileSystemResource(new File("E:\\007-陈浪涛.rar")); String filename = fileSystemResource.getFilename(); helper.addAttachment(filename,fileSystemResource); javaMailSender.send(mimeMessage); } catch (MessagingException e) { e.printStackTrace(); } return "ok"; } }
-