简介(启动即用)
Spring: 一种框架,是为了企业级应用开发的复杂性而创建的,简化开发。
Spring是如何简化Java开发的?
- 基于POJO的轻量级和最小入侵性编程;
- 通过IOC(控制反转),依赖注入(DI)和面向接口实现松耦合;
- 基于切面(AOP(本质:动态代理))和惯例进行声明式编程;
- 通过切面和模板减少样式代码。
SpringBoot: 一个javaweb的开发框架,和SpringMVC类似,约定大于配置,能快速开发web应用,几行代码开发一个http接口。(Spring配置文件复杂)
SpringBoot基于Spring开发,SpringBoot本身不提供Spring框架的核心特性以及扩展功能,只是用于快速、敏捷地开发新一代基于Spring框架的应用程序。它不是用来替代Spring的解决方案,而是和Spring框架紧密结合用于提升Spring开发者体验的工具。SpringBoot以约定大于配置为核心思想,默认帮我们进行了很多设置,多数SpringBoot应用只需要很少的Spring配置。同时它集成了大量常用的第三方库配置(例如Redis、MonfoDB、Jpa、RabbitMQ、Quartz等等),SpringBoot应用中这些第三方库几乎可以零配置的开箱即用。
就像maven整合了所有的jar包,SpringBoot整合了所有的框架。
SpringBoot主要优点:
- 为所有Spring开发者更快的入门
- 开箱即用,提供各种默认配置来简化项目配置
- 内嵌式容器简化Web项目
- 没有冗余代码生成和XML配置的要求
第一个SpringBoot程序
自动配置
pom.xml
- spring-boot-dependencies:核心依赖在父工程中
- 我们在写或者引入一些Springboot依赖的时候,不需要指定版本,就是因为有这些版本仓库
启动器
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
- 启动器就是Springboot的启动场景;
- 比如spring-boot-starter-web,它会帮我们自动导入web环境所有的依赖;
- springboot会将所有的功能场景,都变成一个个的启动器;
- 要使用某个功能,就找到对应的启动器。
主程序
//这个类是一个springboot的应用
@SpringBootApplication
public class Springboot01HelloworldApplication {
public static void main(String[] args) {
//将springboot应用启动
SpringApplication.run(Springboot01HelloworldApplication.class, args);
}
}
- 注解
@SpringBootConfiguration:springboot的配置
@Configuration:spring配置类
@Component:说明这也是一个spring的组件
@EnableAutoConfiguration:自动配置
@AutoConfigurationPackage:自动配置包
(原理听懵了,先搁置)
结论: springboot所有自动配置都是在启动的时候扫描并加载:spring.factories所有的自动配置类都在这里面,但是不一定生效,要判断条件是否成立,只要导入了对应的start,就有对应的启动器了,有了启动器,我们自动装配就会生效,然后就配置成功!
关于SpringBoot,谈谈你的理解
- 自动装配
- run()
- 推断应用的类型是普通的项目还是Web项目
- 查找并加载所有可用初始化器,设置到initializers属性中
- 找出所有的应用程序监听器,设置到listeners属性中
- 推断并设置main方法的定义类,找到运行的主类
yaml语法讲解
SpringBoot使用一个全局的配置文件,配置文件名称是固定的
- application.properties
- 语法结构:key = value
- application.yml
- 语法结构:key:空格 value
配置文件的作用: 修改SpringBoot自动配置的默认值,因为SpringBoot在底层都给我们自动配置好了。
YAML 是"YAML Ain't a Markup Language"(YAML不是一种标记语言)的递归缩写。
properties只能保存键值对!
使用yaml要注意 空格。
yaml给属性赋值
- pojo编写实体类
package com.example.springboot02config.pojo;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
@Component
public class Dog {
private String name;
private Integer age;
public Dog() {}
public Dog(String name, Integer age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public Integer getAge() {
return age;
}
public void setName(String name) {
this.name = name;
}
public void setAge(Integer age) {
this.age = age;
}
@Override
public String toString() {
return "Dog{" +
"name='" + name + ''' +
", age=" + age +
'}';
}
}
package com.example.springboot02config.pojo;
import com.sun.org.apache.xpath.internal.operations.Bool;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
import java.util.Date;
import java.util.List;
import java.util.Map;
@Component
@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> list;
private Dog dog;
public Person() {
}
public Person(String name, Integer age, Boolean happy, Date birth, Map<String, Object> maps, List<Object> list, Dog dog) {
this.name = name;
this.age = age;
this.happy = happy;
this.birth = birth;
this.maps = maps;
this.list = list;
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 list;
}
public void setList(List<Object> list) {
this.list = list;
}
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 +
", maps=" + maps +
", list=" + list +
", dog=" + dog +
'}';
}
}
- 编写.yaml文件
server:
port: 8080
person:
name: macondo
age: 3
happy: false
birth: 2019/11/02
maps: {k1: v1,k2: v2}
list:
- code
- music
- book
dog:
name: 旺财
age: 3
- 测试
package com.example.springboot02config;
import com.example.springboot02config.pojo.Dog;
import com.example.springboot02config.pojo.Person;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
@SpringBootTest
class Springboot02ConfigApplicationTests {
@Autowired
private Person person;
@Test
void contextLoads() {
System.out.println(person);
}
}
- 遇到报错,导入依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
- 结果
.yaml文件配置位置
- 项目目录下的config优先级最高
- pom.xml上面那个优先级其次
- resources/config下面的第三
- 默认生成的是优先级最低的
多环境配置
.properties
.yaml
自动装配原理再详解
- SpringBoot启动会加载大量的自动配置类;
- 我们看我们需要的功能有没有在SpringBoot默认写好的自动配置类当中;
- 我们再看这个自动配置类中到底配置了哪些组件;(只要我们要用的组件存在其中,我们就不需要再手动配置了)
- 给容器中自动配置类添加组件的时候,会从properties类中获取某些属性。我们只需要在配置文件中指定这些属性的值即可。
xxxAutoConfiguration:自动配置类,给容器中添加组件
xxxProperties:封装配置文件中相关属性
SpringBoot Web开发
导入静态资源
在springboot中,我们可以使用以下方式处理静态资源
优先级:resources > static(默认) > public
Thymeleaf
导入依赖即可使用。
所有的html元素都可以被thymeleaf替换接管:
th : 元素名
整合Druid数据源
- pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.example</groupId>
<artifactId>springboot-03-data</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>springboot-03-data</name>
<description>springboot-03-data</description>
<properties>
<java.version>1.8</java.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<spring-boot.version>2.6.13</spring-boot.version>
</properties>
<dependencies>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<dependency>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.2.16</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>${spring-boot.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
<encoding>UTF-8</encoding>
</configuration>
</plugin>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>${spring-boot.version}</version>
<configuration>
<mainClass>com.example.springboot03data.Springboot03DataApplication</mainClass>
<skip>true</skip>
</configuration>
<executions>
<execution>
<id>repackage</id>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
- application.yaml
spring:
datasource:
username: "root"
password: "12345678"
url: jdbc:mysql://localhost:3306/mybatis?useSSL=false&useUnicode=true&characterEncoding=utf8&serverTimezone=UTC&rewriteBatchedStatements=true
driver-class-name: com.mysql.cj.jdbc.Driver
type: com.alibaba.druid.pool.DruidDataSource
filters: stat
- DruidConfig.java
package com.example.springboot03data.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;
import java.util.Map;
@Configuration
public class DruidConfig {
@ConfigurationProperties(prefix = "spring.datasource")
@Bean
public DataSource druidDataSource() {
return new DruidDataSource();
}
//后台监控
@Bean
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;
}
//filter
@Bean
public FilterRegistrationBean webStatFilter() {
FilterRegistrationBean bean = new FilterRegistrationBean();
bean.setFilter(new WebStatFilter());
//可以过滤的请求
Map<String, String> initParameters = new HashMap<>();
//不进行统计
initParameters.put("exclusions", "*.js, *.css, /druid/*");
bean.setInitParameters(initParameters);
return bean;
}
}
- JDBCController.java
package com.example.springboot03data.controller;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
import java.util.Map;
@RestController
public class JDBCController {
@Autowired
JdbcTemplate jdbcTemplate;
//查询数据库的所有信息
@GetMapping("/userList")
public List<Map<String, Object>> userList() {
String sql = "select * from user";
List<Map<String, Object>> maps = jdbcTemplate.queryForList(sql);
return maps;
}
@GetMapping("/addUser")
public String addUser() {
String sql = "insert into mybatis.user(id, name, pwd) values(5, '小明', '123456')";
jdbcTemplate.update(sql);
return "add-ok";
}
@GetMapping("/updateUser/{id}")
public String updateUser(@PathVariable("id") int id) {
String sql = "update mybatis.user set name = ?, pwd = ? where id =" + id;
//封装
Object[] objects = new Object[2];
objects[0] = "小明2";
objects[1] = "111111";
jdbcTemplate.update(sql, objects);
return "update-ok";
}
@GetMapping("/deleteUser/{id}")
public String deleteUser(@PathVariable("id") int id) {
String sql = "delete from mybatis.user where id = ?";
jdbcTemplate.update(sql, id);
return "delete-ok";
}
}
- Springboot03DataApplicationTests.java
package com.example.springboot03data;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.SQLException;
@SpringBootTest
class Springboot03DataApplicationTests {
@Autowired
DataSource dataSource;
@Test
void contextLoads() throws SQLException {
//查看默认数据源 class com.zaxxer.hikari.HikariDataSource
System.out.println(dataSource.getClass());
//获得数据库连接 HikariProxyConnection@745966298 wrapping com.mysql.cj.jdbc.ConnectionImpl@c1fca2a
Connection connection = dataSource.getConnection();
System.out.println(connection);
//xxxx Template:SpringBoot已经配置好的模板bean 拿来即用 CRUD
//关闭连接
connection.close();
}
}
SpringBoot整合Mybatis
- 导入包
- 配置文件
- mybatis配置
- 编写sql
- 业务层调用dao层
- controller层调用service层
SpringSecurity
简介
SpringSecurity是针对Spring项目的安全框架,也是SpringBoot底层安全模块默认的技术选型,它可以实现强大的Web安全控制,对于安全控制,我们仅需要引入spring-boot-starter-security模块,进行少量的配置,即可实现强大的安全管理。
- WebSecurityConfigurerAdapter:自定义Security策略
- AuthenticationManagerBuilder:自定义认证策略
- @EnableWebSecurity:开启WebSecurity模式
SpringSecurity的两个主要目标是“认证”和“授权”(访问控制)。
- “认证”(Authentication)
- “授权”(Authorization)
shiro
什么是shiro?
- Apache Shiro是一个Java的安全(权限)框架。
- Shiro可以非常容易的开发出足够好的应用后,其不仅可以用在JavaSE环境,也可以用在JavaEE环境。
- Shiro可以完成:认证、授权、加密、会话管理、Web集成、缓存等。
核心三大对象
- Subject 用户
- SecurityManager 管理所有用户
- Realm 连接数据
Swagger:接口文档
Swagger简介
- 一款Api框架;
- Restful Api文档在线自动生成工具-->Api文档与Api定义同步更新;
- 直接运行,可以在线测试Api接口;
- 支持多种语言。
在项目中使用Swagger需要springfox
- swagger2
- ui
Swagger作用
- 可以通过Swagger给一些比较难的属性或接口,增加注释信息
- 接口文档实时更新
- 可以在线测试
任务
异步任务
@Async 告诉Spring这是一个异步的方法
@EnableAsync 在main方法中开启异步注解功能
邮件任务
定时任务
Dubbo+Zookeeper 分布式开发
Dubbo
Dubbo是一个高性能的基于Java实现的RPC通信框架。
Dubbo提供了三大核心能力:
- 面向接口的远程方法调用
- 智能容错和负载均衡
- 服务自动注册和发现
dubbo-admin:是一个监控管理后台,查看我们注册了哪些服务,哪些服务被消费了。
RPC
RPC(Remote Procedure Call)是一种远程过程调用,是一种进程间通信方式,它是一种技术的思想,而不是规范。它允许程序调用另一个地址空间(通常是共享网络的另一台机器上)的过程或函数,而不用程序员显式编码这个远程调用的细节。
RPC两个核心模块:
- 通讯
- 序列化:方便数据传输
zookeeper
服务注册中心。
步骤:
前提:zookeeper服务已开启
1.提供者提供服务
- 导入依赖
- 配置注册中心的地址,以及服务发现名和要扫描的包
- 在想要被注册的服务上面增加一个注解
@Service
2.消费者如何消费
- 导入依赖
- 配置注册中心的地址,配置自己的服务名
- 从远程注入服务
@Reference
总结
- 架构是为了解耦。
- 微服务架构:分布式架构问题会遇到的四个核心问题?
- 众多服务,客户端该如何去访问?(Api网关处理、第三方组件、自己实现)
- 众多服务,服务之间如何进行通信?(Dubbo、RPC框架)
- 众多服务,如何治理呢?(服务注册与发现Zookeeper)
- 服务崩了,怎么办?(熔断机制Hystrix)
而SpringCloud,作为一种生态,就是来解决以上分布式架构的4个问题,但是想使用SpringCloud,必须要掌握SpringBoot。
万变不离其宗,一通百通!
- API网关,服务路由
- HTTP、RPC框架、异步调用
- 服务注册与发现、高可用
- 熔断机制、服务降级
最后
终于简单过了一遍SpringBoot相关,可以开始做项目了。