SpringBoot

微服务架构风格是一种将单个应用程序开发为一组小服务的方法,每个小服务都在自己的进程中运行,并与轻量级机制(通常是 HTTP 资源 API)进行通信。这些服务是围绕业务能力构建的,并且可以通过完全自动化的部署机制独立部署。这些服务的集中管理极少,可以用不同的编程语言编写并使用不同的数据存储技术。

微服务架构风格:将应用程序构建为服务套件。除了服务可独立部署和扩展的事实外,每个服务还提供了一个牢固的模块边界,甚至允许使用不同的编程语言编写不同的服务。它们也可以由不同的团队管理。

参考:https://martinfowler.com/articles/microservices.html

image-20210925140758048

Spring Boot

Spring Boot是用来简化新 Spring 应用的初始搭建以及开发过程。该框架使用了特定的方式来进行配置,从而使开发人员不再需要定义样板化的配置。也就是Spring Boot已经自动给你配置好mybaits、spring、springMVC这些框架所需要的配置了,不再需要你自己手动去配置。

Spring Boot的最大特点就是简单、快速、方便!

1、创建第一个Spring Boot程序

第一种方法:这种方法需要我们在Spring 官网下载jar,然后进行import。

image-20210925141539407

  • 然后再编译器中import。导入一般直接下一步就OK

image-20210925141608943

  • 最后就可以运行了。

image-20210925141655381

注意:项目所需要的包,一般都是建在HelloSpringbootApplication这个程序入口文件的包中。

image-20210925141832386

第二种方法:不需要再spring官网下载,只需要再idel中直接创建就可以。

image-20210925144950186

接着就是配置对应的信息就可以了。这种方法比较简单和方便,建议使用这种方法创建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

需要引入的模块:

image-20211008154339214

在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、创建项目,导入依赖:

image-20211011145425797

<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从左到右(用空格隔开):秒 分 小时 月份中的日期 月份 星期中的日期 年份image-20211014162805389

邮件发送

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);
    }
}
posted @ 2021-11-05 02:50  VXZX  阅读(192)  评论(0编辑  收藏  举报