SpringBoot
微服务架构风格是一种将单个应用程序开发为一组小服务的方法,每个小服务都在自己的进程中运行,并与轻量级机制(通常是 HTTP 资源 API)进行通信。这些服务是围绕业务能力构建的,并且可以通过完全自动化的部署机制独立部署。这些服务的集中管理极少,可以用不同的编程语言编写并使用不同的数据存储技术。
微服务架构风格:将应用程序构建为服务套件。除了服务可独立部署和扩展的事实外,每个服务还提供了一个牢固的模块边界,甚至允许使用不同的编程语言编写不同的服务。它们也可以由不同的团队管理。
参考:https://martinfowler.com/articles/microservices.html
Spring Boot
Spring Boot是用来简化新 Spring 应用的初始搭建以及开发过程。该框架使用了特定的方式来进行配置,从而使开发人员不再需要定义样板化的配置。也就是Spring Boot已经自动给你配置好mybaits、spring、springMVC这些框架所需要的配置了,不再需要你自己手动去配置。
Spring Boot的最大特点就是简单、快速、方便!
1、创建第一个Spring Boot程序
第一种方法:这种方法需要我们在Spring 官网下载jar,然后进行import。
- 然后再编译器中import。导入一般直接下一步就OK
- 最后就可以运行了。
注意:项目所需要的包,一般都是建在HelloSpringbootApplication
这个程序入口文件的包中。
第二种方法:不需要再spring官网下载,只需要再idel中直接创建就可以。
接着就是配置对应的信息就可以了。这种方法比较简单和方便,建议使用这种方法创建springboot程序。
2、Spring Boot的原理
在.pom下的spring-boot-starter-parent
下的spring-boot-dependencies
可以看出
- 这个是真正管理SpringBoot应用里面所有依赖版本的地方,SpringBoot的版本控制中心;
- 导入依赖默认是不需要写版本;但是如果导入的包没有在依赖中管理着就需要手动配置版本了;
其中,springboot-boot-starter-xxx:是spring-boot的场景启动器;
spring-boot-starter-web:帮我们导入了web模块正常运行所依赖的组件;
即Spring Boot将所有的功能场景抽取出来,生成一个个starter,当我们在使用时,只需要导入starter就可以了;Spring Boot就会自动帮我们导入对应的依赖。
默认的主启动类
@SpringBootApplication
来标注一个主程序类。
- SpringBoot在启动的时候从类路径下的META-INF/spring.factories中获取EnableAutoConfiguration指定的值
- 将这些值作为自动配置类导入容器 , 自动配置类就生效 , 帮我们进行自动配置工作
- 整个J2EE的整体解决方案和自动配置都在springboot-autoconfigure的jar包中
- 它会给容器中导入非常多的自动配置类 (xxxAutoConfiguration), 就是给容器中导入这个场景需要的所有组件 , 并配置好这些组件
- 有了自动配置类 , 免去了我们手动编写配置注入功能组件等的工作
SpringApplication
- 推断应用的类型是普通的项目还是Web项目
- 查找并加载所有可用初始化器 , 设置到initializers属性中
- 找出所有的应用程序监听器,设置到listeners属性中
- 推断并设置main方法的定义类,找到运行的主类
分析自动配置原理
根据当前不同的条件判断,决定这个配置类是否生效!
- 一但这个配置类生效;这个配置类就会给容器中添加各种组件;
- 这些组件的属性是从对应的properties类中获取的,这些类里面的每一个属性又是和配置文件绑定的;
- 所有在配置文件中能配置的属性都是在xxxxProperties类中封装着;
- 配置文件能配置什么就可以参照某个功能对应的这个属性类;
如果自动装配中吗,没有我们需要的配置,则我们可以自己写一个配置到Spring boot:
-
配置文件能配置什么就可以参照某个功能对应的这个属性类
-
我们看我们需要的功能有没有在SpringBoot默认写好的自动配置类当中
-
我们再来看这个自动配置类中到底配置了哪些组件;(只要我们要用的组件存在在其中,我们就不需要再手动配置了)
-
给容器中自动配置类添加组件的时候,会从properties类中获取某些属性。我们只需要在配置文件中指定这些属性的值即可;
- xxxxAutoConfigurartion:自动配置类;给容器中添加组件
- xxxxProperties:封装配置文件中相关属性;
3、yaml语法
YAML是一个可读性高,用来表达数据序列化的格式。YAML的语法和其他高级语言类似,并且可以简单表达清单、散列表,标量等数据形态。其数据一般都是已缩进的形式进行的,数据前面空一格,对数据的缩进有严格的要求。它可以用来修改Spring Boot自动配置的默认值。
语法结果: key: 空格 value
写法,必须保证数据前面有一个空格;
普通的键值对: key-value
name: vxzx
#对象:
student:
name: vxzx
age: 1
student: {name: vxzx,age: 1}
# 数组:
hobbies:
- basketball
- football
- tennis
hobbies: [baketball,football.tennis]
⭐yaml文件还可以给我们的实体类直接注入匹配值!
具体用法:
pojo层:Person
@Component
/*
@ConfigurationProperties作用:
将配置文件中配置的每一个属性的值,映射到这个组件中;
告诉SpringBoot将本类中的所有属性和配置文件中相关的配置进行绑定
参数 prefix = “person” : 将配置文件中的person下面的所有属性一一对应
*/
@ConfigurationProperties(prefix = "person")
public class Person {
private String name;
private Integer age;
private Boolean happy;
private Date birth;
private Map<String,Object> maps;
private List<Object> lists;
private Dog dog;
public Person() {
}
public Person(String name, Integer age, Boolean happy, Date birth, Map<String, Object> maps, List<Object> lists, Dog dog) {
this.name = name;
this.age = age;
this.happy = happy;
this.birth = birth;
this.maps = maps;
this.lists = lists;
this.dog = dog;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public Boolean getHappy() {
return happy;
}
public void setHappy(Boolean happy) {
this.happy = happy;
}
public Date getBirth() {
return birth;
}
public void setBirth(Date birth) {
this.birth = birth;
}
public Map<String, Object> getMaps() {
return maps;
}
public void setMaps(Map<String, Object> maps) {
this.maps = maps;
}
public List<Object> getList() {
return lists;
}
public void setLists(List<Object> lists) {
this.lists = lists;
}
public Dog getDog() {
return dog;
}
public void setDog(Dog dog) {
this.dog = dog;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
", happy=" + happy +
", birth=" + birth +
", map=" + maps +
", list=" + lists +
", dog=" + dog +
'}';
}
application.yaml:
Person:
name: vxzx
age: 1
happy: true
birth: 2021/09/25
maps: {k1: m2,k2: m2}
lists:
- l1
- l2
- l3
Dog:
name: "大黄"
age: 11
Test:
@Autowired
private Person person;
@Test
void contextLoads() {
System.out.println(person);
}
注意:
-
数据值前面的空格不能省略
-
缩进用来控制层级关系,左边对齐的数据都是同一等级
-
属性和值的大小写都是十分敏感的
-
“” 双引号不会转义特殊字符,‘ ’ 单引号会转义特殊字符。
4、多环境配置的优先级
Spring Boot的配置文件可以存放的位置为:
1、file:./config/
2、file:./
3、classpath:/config/
4、classpath:/
其引用配置文件的顺序优先级也是从1---4开始的。
我们还可以指定我们所需要的开发环境:
在properties环境下配置如下:application.properties、application-test.properties、application-dev.properties
在多个环境下,只需要使用spring.profiles.active
加上 配置文件名中间的单词 就可以指定任一环境。
#指定的环境为application-dev.properties这个配置环境
spring.profiles.active=dev
在yaml下的配置如下:只需要一个文件就可以搞定它。可以用 --- 分隔开每个环境
server:
port: 8080
spring:
profiles:
active: dev
---
server:
port: 8081
spring:
profiles: dev
---
server:
port: 8082
spring:
profiles: test
注意:如果yml和properties同时都配置了端口,并且没有激活其他环境 , 默认会使用properties配置文件的!
5、Thymeleaf
如果是我们以前写项目,一般都是需要使用jsp来写前端页面进行数据的接收的。但是Spring Boot默认是不支持jsp的。所以,我们现在可以使用Thymeleaf,Thymeleaf是一个模板引擎。
其实就是将前端页面和控制层传输到Thymeleaf里面渲染,然后再输出到客户端页面。
※Thymeleaf的使用:
导入Thymeleaf
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
我们在使用的时候,只需要将其放在我们的类路径下的templates 目录就可以自动帮我们渲染了,而且不需要我们配置什么东西,只需要放在指定的位置就可以了;十分简单,方便。
Thymeleaf的具体测试
- 编写Controller:
@Controller
public class TestC {
@RequestMapping("/test")
public String test(){
return "test";
}
}
- 编写测试页面,将其放在templates目录下:
<body>
<h1>首页</h1>
</body>
- 启动进行测试。
可以看到,我们启动项目正常运行了,可以正常跳转。
Thymeleaf的语法
Thymeleaf 官网:https://www.thymeleaf.org/
首先可以进行一个小测试:
- Controller:
@Controller
public class TestC {
@RequestMapping("/test")
public String test(Model model){
model.addAttribute("msg1","helloSpring");
model.addAttribute("msg2", Arrays.asList("vxzx","vx","xxx"));
return "test";
}
}
- 前端页面:首先记得在标签导入
xmlns:th="http://www.w3.org"
<body>
<h1>首页</h1>
<div th:text="${msg1}"></div>
<div th:each="item : ${msg2}" th:text="${item}"></div>
</body>
- 启动测试,结果传值成功。
我们可以看看Thymeleaf的具体的语法:
Thymeleaf | 作用 | 相当于JSP |
---|---|---|
th:inert | 片段包含 | jsp:include |
th:replace | 引入子模块的所有,不保留父模块的tag | |
th:each | 循环遍历 | c:ForEach |
th:if | 条件判断 | C:if |
th:unless | 和th:if判断相反 | |
th:switch | 多路选择配合th:case使用 | |
th:case | ||
th:object | 声明变量,替换对象 | c:set |
th:with | 变量赋值运算 | |
th:attr | 任意属性修改 | prepend、append |
th:attrprepend | ||
th:attrappend | ||
th:value | 修改指定的默认属性值 | |
th:href | 链接地址 | |
th:src | 图片类地址引入 | |
th:text | 修改标签内容,特殊字符转义 | |
th:utext | 修改标签内容,特殊字符不转义 | |
th:fragment | 声明片段 | |
th:remove | 删除模板片段 |
6、Spring MVC扩展
#如果您希望保留Spring Boot MVC功能,并且希望添加其他MVC配置(拦截器、格式化程序、视图控制器和其他功能),#则可以添加自己的@configuration类,类型为webmvcconfiguer,但不添加@EnableWebMvc。如果希望提供
#RequestMappingHandlerMapping、RequestMappingHandlerAdapter或ExceptionHandlerExceptionResolver的#自定义实例,则可以声明WebMVCregistrationAdapter实例来提供此类组件。
在Springboot中,所有配置都是Spring内部自动帮我们配置好的。但是,我们也可以在其中加入自己想要的配置,自定义的配置。
一般来说,我们可以在WebMvcAutoConfiguration.java
中找到许多关于spinrgMVC配置的东西。
例如:自定义拦截器:需要实现HandlerInterceptor
接口的方法
public class MyInterceptor 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.html").forward(request,response);
return false;
}else {
return true;
}
}
}
国际化处理:需要实现LocaleResolver
接口
#ch_CN
login.msg=请登录
login.password=密码
login.rm=记住用户
login.sign=登录
login.username=用户名
#en_US
login.msg=Please sign in
login.password=Password
login.rm=Remember me
login.sign=Sign in
login.username=Username
public class MyLocaleResolver implements LocaleResolver {
@Override
public Locale resolveLocale(HttpServletRequest request) {
//获取前端中的语言数据参数:
String language = request.getParameter("lang");
//如果没有参数就使用默认的:
Locale locale = Locale.getDefault();
//如果请求携带了国际化参数,就需要判断:
if (!StringUtils.isEmpty(language)){
//将前端中数据信息进行分割处理:en_US 分割成: en 地区 和 US 国家
String[] split = language.split("_");
//将分割完成的 en 和 US,进行组合到新的locale中:
locale = new Locale(split[0], split[1]);
}
//将获取的值(可能是默认的也可能的自定义的) 返回:
return locale;
}
}
最后就需要把这些自定义的配置放到实现WebMvcConfigurer
接口的中:
WebMvcConfigurer
该接口下有多个配置实现方法,根据自己所需选择对应的方法。
//扩展springMVC:
@Configuration
public class MyMvcconfig implements WebMvcConfigurer {
// 视图跳转:
@Override
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/").setViewName("index");
registry.addViewController("/index.html").setViewName("index");
registry.addViewController("/main.html").setViewName("dashboard");
}
//将自定义的国际化组件放到spring里:
@Bean
public LocaleResolver localeResolver(){
return new MyLocaleResolver();
}
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new MyInterceptor()).addPathPatterns("/**").excludePathPatterns("/","/index.html","/user/login",
"/css/*","/js/*","/img/*");
}
}
7、整合JDBC
需要引入的模块:
在SpringBoot中使用JDBC再也不用像以前一样去配置那么多东西,因为Spring已经自动帮我们配置好,我们只需要在application.proeprties中配置JDBC所需要的数据连接信息就可以了。
在SpringBoot中的application中配置:
spring:
#使用JDBC数据
datasource:
#数据库用户名
username: root
#数据库密码
password: 123456
#数据库连接:
url: jdbc:mysql://localhost:3306/数据库中表名称?serverTimezone=UTC
&useUnicode=true&characterEncoding=utf-8
#数据库连接池:
driver-class-name: com.mysql.cj.jdbc.Driver
在SpringBoot中,会自动帮我们把JDBC的datasource自动配置好了,我们可以查找DataSourceAutoConfiguration文件,可以使用 spring.datasource.type 指定自定义的数据源类型,值为 要使用的连接池实现的完全限定名。可以去了解一下里面的JdbcTemplate
。
JdbcTemplate
- Spring 本身也对原生的JDBC 做了轻量级的封装,即JdbcTemplate。
- JdbcTemplate中配置了我们日常所需要使用到的CRUD。
- 使用JdbcTemplate时,我们不需要去进行配置,只需要将其注入到类中就可以直接使用了。
- JdbcTemplate 的自动配置是依赖 org.springframework.boot.autoconfigure.jdbc 包下的 JdbcTemplateConfiguration 类
JdbcTemplate中几种常用的方法:
方法函数 | 方法作用 |
---|---|
execute() |
可以执行任何的SQL语句,一般用来执行DDL语句 |
update() 、batchUpdate() |
update用于执行添加、修改、删除等语句;batchUpdate用于执行批处理相关语句 |
query() 、queryForxxx() |
用于执行的相关语句 |
call() |
用于执行存储过程、函数相关的语句 |
- Spring Boot 默认提供了数据源,默认提供了 org.springframework.jdbc.core.JdbcTemplate
- JdbcTemplate 中会自己注入数据源,用于简化 JDBC操作
- 还能避免一些常见的错误,使用起来也不用再自己来关闭数据库连接
接下来,我们就可以进行一波测试:
controller.java:可以直接中controller类中进行CRUD,不必去配置其他东西,直接使用即可:
package com.vxzx.controller;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
import java.util.Map;
@RestController
public class JdbcController {
@Autowired
JdbcTemplate jdbcTemplate;
//查询所有用户信息: 可以使用List---》 List里面存一个Map(key,value)代表数据库的每个信息;
@RequestMapping("/query")
public List<Map<String,Object>> query(){
String sql="select * from user";
List<Map<String, Object>> maps = jdbcTemplate.queryForList(sql);
return maps;
}
//添加用户:
@RequestMapping("/add")
public String add(){
String sql = "insert into mybatis.user(id,name,pwd) values(5,'xxx','123456')";
int update = jdbcTemplate.update(sql);
return "添加成功!";
}
//修改用户:
@RequestMapping("/update/{id}")
public String update(@PathVariable("id") int id){
String sql = "update mybatis.user set name=?, pwd=? where id=" + id;
Object[] objects = new Object[2];
objects[0] = "新添加的";
objects[1] = "新密码";
int update = jdbcTemplate.update(sql,objects);
return "修改成功";
}
//删除用户:
@RequestMapping("/delete/{id}")
public String delete(@PathVariable("id") int id){
String sql = "delete from mybatis.user where id=" + id;
jdbcTemplate.update(sql);
return "删除成功!";
}
}
8、整合Mybatis
官方文档:http://mybatis.org/spring-boot-starter/mybatis-spring-boot-autoconfigure/
需要配置文件的,可以去maven仓库找,然后就可以导入依赖。
1、配置数据库连接信息:
spring:
datasource:
username: root
password: 123456
url: jdbc:mysql://localhost:3306/
mybatis?serverTimezone=UTC&useUnicode=true&characterEncoding=utf-8
driver-class-name: com.mysql.cj.jdbc.Driver
测试数据库是否连接成功:
class Spring05MybatisApplicationTests {
@Autowired
DataSource dataSource;
@Test
void contextLoads() throws SQLException {
System.out.println("输出默认数据源:======》" + dataSource.getClass());
System.out.println("输出连接:======》" + dataSource.getConnection());
}
2、创建实体类:
private Integer id;
private String name;
private String pwd;
3、创建Mapper文件:
//@Mapper:代表这是一个mybaits的mapper类。
@Mapper
@Repository
public interface UserMapper {
List<User> queryList();
User queryUser(int id);
int addUser(User user);
int updateUser(User user);
int deleteUser(int id);
}
//写好接口之后,就需要在resource中写sql查询语句;
4、创建Mapper映射文件,此时可以在resources目录下创建mybatis/mapper/*.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.vxzx.dao.UserMapper">
<select id="queryList" resultType="user">
select * from mybatis.user;
</select>
<select id="queryUser" resultType="user">
select * from mybatis.user where id = #{id};
</select>
<insert id="addUser" parameterType="user">
insert into mybatis.user (id, name, pwd) values (#{id},#{name},#{pwd});
</insert>
<update id="updateUser" parameterType="user">
update mybatis.user set name = #{name},pwd = #{pwd} where id = #{id};
</update>
<delete id="deleteUser" parameterType="int">
delete from mybatis.user where id = #{id}
</delete>
</mapper>
注意:需要在application中配置mybatis中的别名,mapper映射路径等。。。
#整合mybatis:
mybatis:
type-aliases-package: com.vxzx.pojo
mapper-locations: classpath:mybaits/mapper/*.xml
5、测试mybatis是否能够成功!
@RestController
public class UserController {
@Autowired
private UserMapper userMapper;
@GetMapping("/queryList")
public List<User> queryList(){
List<User> list = userMapper.queryList();
return list;
}
@GetMapping("/queryUser/{id}")
public User queryUser(@PathVariable("id") int id){
User queryUser = userMapper.queryUser(id);
return queryUser;
}
@GetMapping("/add")
public String addUser(User user){
userMapper.addUser(new User(5,"xxxx","123456"));
return "添加成功!";
}
@GetMapping("/update")
public String updateUser(User user){
userMapper.updateUser(new User(5,"yyyy","11111"));
return "修改成功!";
}
@GetMapping("/delete/{id}")
public String deleteUser(@PathVariable("id") int id){
userMapper.deleteUser(id);
return "删除成功!";
}
}
测试成功,结束!
9、整合Druid
Druid 是阿里巴巴开源平台上一个数据库连接池实现,结合了 C3P0、DBCP 等 DB 池的优点,同时加入了日志监控。Druid 可以很好的监控 DB 池连接和 SQL 的执行情况,天生就是针对监控而生的 DB 连接池。
Github地址:https://github.com/alibaba/druid/
springBoot使用文档:https://github.com/alibaba/druid/tree/master/druid-spring-boot-starter
基本配置参数如下:
属性 | 说明 | 建议值 |
---|---|---|
url | 数据库的jdbc连接地址。 | |
username | 登录数据库的用户名 | |
password | 登录数据库的密码 | |
initialSize | 启动程序时,在连接池中初始化多少个连接 | 10-50 |
maxActive | 连接池中最多支持多少个活动会话 | |
maxWait | 程序向连接池中请求连接时,超过maxWait的值后,认为本次请求失败,即连接池 | 100 |
minEvictableIdleTimeMillis | 池中某个连接的空闲时长达到 N 毫秒后, 连接池在下次检查空闲连接时,将回收该连接。 | |
maxPoolPrepareStatementPerConnectionSize | 每个连接最多缓存多少个SQL | 20 |
filters | 这里配置的是插件,常用的插件有:- 监控统计: filter:stat-日志监控: filter:log4j 或者 slf4j -防御SQL注入: filter:wall | stat,wall,slf4j |
connectProperties | 连接属性。比如设置一些连接池统计方面的配置:druid.stat.mergeSql=true; druid.stat.slowSqlMillis=5000 |
在使用druid时,我们需要先导入其依赖:
<!-- https://mvnrepository.com/artifact/com.alibaba/druid -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.21</version>
</dependency>
在springboot2.0以上,默认使用数据源为:hikari;我们可以使用spring.datasource.type
指定数据源。
spring:
datasource:
username: root
password: 123456
url: jdbc:mysql://localhost:3306/
mybatis?serverTimezone=UTC&useUnicode=true&characterEncoding=utf-8
driver-class-name: com.mysql.cj.jdbc.Driver
#指定数据源为Druid
type: com.alibaba.druid.pool.DruidDataSource
#druid专有配置:
druid:
initial-size: 5
min-idle: 5
max-active: 20
max-wait: 60000
time-between-eviction-runs-millis: 60000
min-evictable-idle-time-millis: 3000000
validation-query: SELECT 1 FROM DUAL
test-while-idle: true
test-on-borrow: false
test-on-return: false
pool-prepared-statements: 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
测试是否成功:
@SpringBootTest
class Springboot04JdbcApplicationTests {
@Autowired
DataSource dataSource;
@Test
void contextLoads() throws SQLException {
System.out.println("数据库默认连接池:=======》" + dataSource.getClass());
Connection connection = dataSource.getConnection();
System.out.println("获取到的连接:====》" + connection);
connection.close();
}
}
我们还可以配置Druid来进行队数据库操作的监控:
@Configuration
public class DruidConfig {
//将自定义的配置,添加到druid的配置中,让我们可以直接使用:
@ConfigurationProperties(prefix = "spring.datasource")
@Bean
public DataSource druidDatasource(){
return new DruidDataSource();
}
//后台监控:
@Bean
public ServletRegistrationBean srb(){
ServletRegistrationBean<Servlet> bean = new ServletRegistrationBean<>(new StatViewServlet(),"/druid/*");
//后台登录:
HashMap<String, String> initParameters = new HashMap<>();
initParameters.put("loginUsername","root"); //其中的key 是固定的,不能更改的。
initParameters.put("loginPassword","123456");
//设置登录权限:
initParameters.put("allow",""); //设置本机可登录
bean.setInitParameters(initParameters); //设置初始化参数
return bean;
}
//设置filter
@Bean
public FilterRegistrationBean frs(){
FilterRegistrationBean<Filter> bean = new FilterRegistrationBean<>();
bean.setFilter(new WebStatFilter());
Map<String, String> initParameters = new HashMap<>();
//放行这些请求:不拦截
initParameters.put("exclusions","*.js,*.css,/druid/*");
return bean;
}
}
10、Spring Security
Spring Security 是一个专注于为 Java 应用程序提供身份验证和授权的框架。与所有 Spring 项目一样,Spring Security 的真正强大之处在于它可以轻松扩展以满足自定义要求。
- 对身份验证和授权的全面且可扩展的支持
- 防止会话固定、点击劫持、跨站点请求伪造等攻击
- Servlet API 集成
1、创建项目,导入依赖:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
2、使用Spring Security,需要记住以下几个主要的类:
- WebSecurityConfigurerAdapter:自定义Security策略,定义请求规则
- AuthenticationManagerBuilder:自定义认证策略,添加认证规则
- @EnableWebSecurity:开启WebSecurity模式
Spring Security:最主要的就是认证和授权。
3、编写配置类:
//开启WebSecurity模式
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
//定制请求规则:
@Override
protected void configure(HttpSecurity http) throws Exception {
//首页所有人都可以访问:
http.authorizeRequests().antMatchers("/").permitAll()
//接下类,各个页面对应各自的权限:
.antMatchers("/level1/**").hasRole("v1")
.antMatchers("/level2/**").hasRole("v2")
.antMatchers("/level3/**").hasRole("v3");
//开启自动配置的登录功能,权限不够直接跳转到登陆页面(该页面为默认页面):
//自定义登录页面:
http.formLogin().loginPage("/toLogin")
.loginProcessingUrl("/login"); // 登陆表单提交请求,最后显示的url
//关闭csrf功能:跨站请求伪造,默认只能通过post方式提交logout请求
http.csrf().disable();
// 开启用户注销功能,用户登录成功后,实现一键退出注销请求:并指定到主页面。
http.logout().logoutSuccessUrl("/");
// 定义remember:记住用户账号密码信息: ----rememberMeParameter:从前端页面获取数据
http.rememberMe().rememberMeParameter("name");
}
//自定义认证规则:
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
// 数据可以从jdbc中获取,也可以从内容中获取:jdbcAuthentication、inMemoryAuthentication
//开启密码加密,使用bcrypt加密方式。
auth.inMemoryAuthentication().passwordEncoder(new BCryptPasswordEncoder())
.withUser("vxzx").password(new BCryptPasswordEncoder().encode("123456")).roles("v1").and()
.withUser("root").password(new BCryptPasswordEncoder().encode("123456")).roles("v1","v2","v3");
}
}
11、Swagger
Swagger可以在项目中集成Swagger自动生成API文档;
- Restful Api 文档在线自动生成器 => API 文档 与API 定义同步更新
- 直接运行,在线测试API
- 官网:https://swagger.io/
Springboot集成Swagger
第一步需要导入依赖:
<!-- 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>
<!-- https://mvnrepository.com/artifact/io.springfox/springfox-swagger2 -->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>2.9.2</version>
</dependency>
第二步编写swagger配置:
- 开启swagger:
@Configuration //spring配置类
@EnableSwagger2 //开启Swagger2
public class SwaggerConfig {
}
测试,输入http://localhost:8080/swagger-ui.html,即可看到swagger界面。
- 配置swagger信息:
配置swagger的核心是Docket,通过配置Docket实例来实现对swagger 的配置。
@Bean //必须加上bean,将其导入到spring中
public Docket docket(){
//进入DocumentationType.SWAGGER_2 配置具体参数:
return new Docket(DocumentationType.SWAGGER_2);
}
具体配置:
@Bean //必须加上bean,将其导入到spring中
public Docket docket(){ //第四组
//进入DocumentationType.SWAGGER_2 配置具体参数:
return new Docket(DocumentationType.SWAGGER_2)
.apiInfo(apiInfo()) //添加自定义文档的配置
//通过.select()方法,去配置扫描接口,RequestHandlerSelectors配置如何扫描接口
.select()
.apis(RequestHandlerSelectors.basePackage("com.vxzx.swaggerdemo.controller"))
// 配置如何通过path过滤,即这里只扫描请求以/vxzx开头的接口
.paths(PathSelectors.ant("/vxzx/**"))
.build()
//是否开启swagger:
.enable(true)
//自定义组名:
.groupName("vxzx");
}
//自定义文档信息:可以在源码中找到该方法的使用
public ApiInfo apiInfo(){
//作者信息:
Contact DEFAULT_CONTACT = new Contact("vxzx","https://www.cnblogs.com/vxzx/","573114781@qq.com");
return new ApiInfo("VXZX Documentation", //标题
"VXZX Documentation", //描述
"1.0", //版本
"VXZX:tos", //组织链接
DEFAULT_CONTACT, //联系人信息
"Apache 2.0", //许可
"https://www.cnblogs.com/vxzx/", //许可链接
new ArrayList<VendorExtension>()); //扩展
}
配置API分组
实现swagger的API分组,可以使用groupName
来自定义组名,如果想要实现多个组展示,可以实例化多个Docket(),即一个Docket为一个组。
//配置分组信息,每个组对应每个事务开发: 一个四个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");
}
swagger注解的使用
Swagger的所有注解定义在io.swagger.annotations包下,下面几个是常用的注解的解释:
Swagger注解 | 说明 |
---|---|
@Api(tags = "xxx模块说明") | 作用在模块类上 |
@ApiOperation("xxx接口说明") | 作用在接口方法上 |
@ApiModel("xxxPOJO说明") | 作用在模型类上:如VO、BO |
@ApiModelProperty(value = "xxx属性说明",hidden = true) | 作用在类方法和属性上,hidden设置为true可以隐藏该属性 |
@ApiParam("xxx参数说明") | 作用在参数、方法和字段上,类似@ApiModelProperty |
12、扩展ATM
异步操作
在程序中,我们程序一般都是按照前后顺序进行执行的,这样在用户体验上就十分不好了。所以我们就需要使用异步操作来解决这个问题。
异步操作:每个任务都有一个或多个回调函数,任务执行完会执行回调函数,后面的任务不会等待前一个任务结束再去执行,即程序的执行顺序是不一致的、异步的。
在springboot中,我们可以更加简单的使用异步操作,只需要添加注解就可以启动其内置的异步操作。
- 编写异步方法:
Async
代表一个异步操作的方法
@Service
@Async //标志这是一个异步方法,且在启动程序标注@EnableAsync,则可以在前端快速显示页面,不需要等待3秒
public class AsynTest {
public void asyn(){
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("执行数据!");
}
}
- 调用异步方法:
@RestController
public class AsynController {
@Autowired
AsynTest asyn;
@RequestMapping("/hello")
public String hello(){
asyn.asyn();
return "hello";
}
}
- 最后需要在主程序启动类上,加上
@EnableAsync
才可以最终启动异步操作:
@SpringBootApplication
@EnableAsync //开启异步操作
public class Springboot08AsynApplication {
public static void main(String[] args) {
SpringApplication.run(Springboot08AsynApplication.class, args);
}
}
进行测试,前端页面正常跳转,但是后端输出语句会跟原来一样,等待三秒再执行,异步操作成功;
定时操作
在日常开发,我们一般会用到定时任务,在spring中为我们内置了两个定时的接口;
- TaskExecutor接口
- TaskScheduler接口
加上两个常用的注解:
- @EnableScheduling : 启动spring的定时功能
- @Scheduled : 标志为一个定时的任务
编写一个定时的类:
@Service
public class TaskServer {
//{@code "0 * * * * MON-FRI"}
// 对应:秒 分钟 小时 天 月 周
@Scheduled(cron = "30 * * * * *")
public void task(){
System.out.println("定时任务 + TaskExecutor");
}
}
执行实现定时任务:
@GetMapping("/task")
public String task(){
task.task();
return "task";
}
最后,需要在主程序启动类上,加上@EnableScheduling
,开启定时任务;
@SpringBootApplication
@EnableScheduling //开启定时任务
public class Springboot08AsynApplication {
public static void main(String[] args) {
SpringApplication.run(Springboot08AsynApplication.class, args);
}
}
cron表达式详解:
corn从左到右(用空格隔开):秒 分 小时 月份中的日期 月份 星期中的日期 年份
邮件发送
java邮件发送的具体步骤:
导入依赖:
<!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-mail -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-mail</artifactId>
<version>2.5.5</version>
</dependency>
在spring中,使用邮件发送任务时,一般都是用到以下几个函数:
-
JavaMailSenderImpl
:是Spring官⽅提供的集成邮件服务的接⼝和实现类,设置邮箱的主要信息 -
SimpleMailMessage
:发送简单的邮件,例如:文本文件 -
MimeMessage
:发送复杂的文件,例如:图片、文件等...... -
MimeMessageHelper
:将mimemessage放入其中,设置邮件的内容
编写Email发送实现类:
@SpringBootTest
class Springboot09MailApplicationTests {
@Autowired
JavaMailSenderImpl mailSender;
@Test
void contextLoads() {
//简单的邮件:
SimpleMailMessage message = new SimpleMailMessage();
message.setSubject("邮件标题");
message.setText("邮件文本内容");
message.setTo("573114781@qq.com");
message.setFrom("573114781@qq.com");
//发送邮件:
mailSender.send(message);
}
@Test
void contextLoads2() throws MessagingException {
//复杂的邮件:
//创建一个复杂邮件所需的mimemessage:
MimeMessage mimeMessage = mailSender.createMimeMessage();
//将mimemessage放入到hlper中: true开启复杂文本
MimeMessageHelper helper = new MimeMessageHelper(mimeMessage,true);
helper.setSubject("邮件标题");
helper.setText("<p style='color:pink'>这个一个带有html标签的文本</p>",true);
//发送附件:
//helper.addAttachment("文件名",new File("文件路径"));
helper.setTo("573114781@qq.com");
helper.setFrom("573114781@qq.com");
//发送邮件:
mailSender.send(mimeMessage);
}
}