SpringBoot
1、第一个项目
2、spring彩蛋 banner
3、初探原理
自动配置:
pom.xml
-
spring-boot-dependencies:核心依赖在父工程中!
-
我们在写或者引入一些Springboot依赖的时候,不用指定版本,因为有这版本仓库
4、springboot配置
配置 文件 有两种格式
- application,properties
- 语法结构: key=value
- application.yml
- 语法结构: key:
- 语法结构: key:
作用修改springboot 的默认配置
官方推荐使用yaml
标记语言
yaml配置:
server:
port: 8081
path: /hello
xml配置:
<server>
<port>8081</port>
</server>
yaml语法
对空格的要求很严格
对象的值可以注入到对象
对象
# 对象
student:
name: lmq
age: 21
# 行类写法
student:{name: lmq,age: 21}
数组
pets:
- cat
- dog
- pig
# 行内写法
pets:[cat,dog,ping]
赋值的操作
原生
package com.lmq.pojo;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;;
/**
* @author 羡鱼
* @version 1.0
* @date 2023/7/25 13:37
*/
@Component
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Dog {
@Value("旺柴")
private String name;
@Value("6")
private Integer age;
}
yaml文件配置 @ConfigurationProperties(prefix = "person")
绑定yaml数据
支持松散绑定 如 lastName
和 last-name
package com.lmq.pojo;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
import java.util.Date;
import java.util.List;
import java.util.Map;
/**
* @author 羡鱼
* @version 1.0
* @date 2023/7/25 13:37
*/
@Component
@ConfigurationProperties(prefix = "person")
@Data
@AllArgsConstructor
@NoArgsConstructor
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;
}
person:
name: lmq
age: 22
happy: false
birth: 2023/7/25
maps: { k1:v1,k2:v2 }
lists:
- code
- music
- girl
高级玩法
server:
port: 8081
person:
name: lmq_${random.uuid}
age:
happy: false
birth: 2023/7/25
maps: { k1:v1,k2:v2 }
lists:
- code
- music
- girl
dog:
name: ${person.ages:hello}_旺柴 # 前面有就输出前面的 没有就输出:后面的
age: ${random.int} # 随机数
properties文件绑定 优先读取application.properties文件
name="lmq"
package com.lmq.pojo;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.PropertySource;
import org.springframework.stereotype.Component;
import java.util.Date;
import java.util.List;
import java.util.Map;
/**
* @author 羡鱼
* @version 1.0
* @date 2023/7/25 13:37
*/
@Component
//@ConfigurationProperties(prefix = "person")
@PropertySource(value = "classpath:lmq.properties")
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Person {
@Value("${name}")
private String name;
private Integer age;
private Boolean happy;
private Date birth;
private Map<String,Object> maps;
private List<Object> lists;
private Dog dog;
}
jsr303 校验
@validated // 数据校验
注解 | 说明 |
---|---|
@Null |
限制只能为null |
@NotNull |
限制必须不为null |
@AssertFalse |
限制必须为false |
@AssertTrue |
限制必须为true |
@DecimalMax(value) |
限制必须为一个不大于指定值的数字 |
@DecimalMin(value) |
限制必须为一个不小于指定值的数字 |
@Digits(integer,fraction) |
限制必须为一个小数,且整数部分的位数不能超过integer,小数部分的位数不能超过fraction |
@Future |
限制必须是一个将来的日期 |
@Max(value) |
限制必须为一个不大于指定值的数字 |
@Min(value) |
限制必须为一个不小于指定值的数字 |
@Past |
限制必须是一个过去的日期 |
@Pattern(value) |
限制必须符合指定的正则表达式 |
@Size(max,min) |
限制字符长度必须在min到max之间 |
@Past |
验证注解的元素值(日期类型)比当前时间早 |
@NotEmpty |
验证注解的元素值不为null且不为空(字符串长度不为0、集合大小不为0) |
@NotBlank |
验证注解的元素值不为空(不为null、去除首位空格后长度为0),只应用于字符串且在比较时会去除字符串的空格 |
@Email |
验证注解的元素值是Email,也可以通过正则表达式和flag指定自定义的email格式 |
配置文件的优先级
优先级由高到底
file:./config/
file:./
classpath:/config/
classpath:/
多个配置文件的选择
指定配置文件
#多环境配置
spring.profiles.active=dev
文件前缀默扔 application
yaml 优势 多文档模块
server:
port: 8081
spring:
profiles:
active: dev
--- # 分割文档
server:
port: 8082
spring:
profiles: dev
---
server:
port: 8082
spring:
profiles: dev
配置文件到底可以写什么
5、web 开发
自动装配
springboot 帮我们配置了什么? 我们能不能修改?能修改哪些东西?能不能扩招
- xxxxAutoConfiguraion… 向容器中自动配置组件
- xxxxproperties: 自动配置类,装配配置文件中自定义的一些内容
要解决的问题:
-
导入静态资源
-
首页
-
jsp 模版引擎 thymeleaf
-
装配扩展springmvc
-
-
增删改查
-
拦截器
-
国际化
静态资源
public void addResourceHandlers(ResourceHandlerRegistry registry) {
if (!this.resourceProperties. ()) {
logger.debug("Default resource handling disabled");
} else {
this.addResourceHandler(registry, "/webjars/**", "classpath:/META-INF/resources/webjars/");
this.addResourceHandler(registry, this.mvcProperties.getStaticPathPattern(), (registration) -> {
registration.addResourceLocations(this.resourceProperties.getStaticLocations());
if (this.servletContext != null) {
ServletContextResource resource = new ServletContextResource(this.servletContext, "/");
registration.addResourceLocations(new Resource[]{resource});
}
});
}
}
总结
- 在springboot里面有很多 xxx Configuration 帮助我们进行扩展配置
- 在springboot,我们可以使用以下方法处理静态资源
- webjarslocalhost:8080/webjars
- public static /** resourceslocalhost:8080/
- resources > static(默认) > public
6、模版引擎
结论 只要使用thymeleaf 只需要放入templates
第一步引入模板引擎
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
第二步 引入thymeleaf 在html上面 所有资源由thymeleaf接管
xmlns:th="http://www.thymeleaf.org"
<link th:href="@{/css/bootstrap.min.css}" rel="stylesheet">
- 简单表达式:
- 可变表达式:
${...}
- 选择变量表达式:
*{...}
- 信息表达式:
#{...}
- 链接URL表达式:
@{...}
- 可变表达式:
- 文字的
- 文字文字:
'one text'
,'Another one!'
,… - 字数:
0
,34
,3.0
,12.3
,… - 布尔文字:
true
,false
- 无文字:
null
- 文字令牌:
one
,sometext
,main
,…
- 文字文字:
- 文本操作:
- 弦连接:
+
- 文字替换:
|The name is ${name}|
- 弦连接:
- 算术运算:
- 二进制操作:
+
,-
,*
,/
,%
- 减号符号(一元操作符):
-
- 二进制操作:
- 布尔运算:
- 二进制操作:
and
,or
- 布尔否定(一元算子):
!
,not
- 二进制操作:
- 比较和平等:
- 比较器:
>
,<
,>=
,<=
(gt
,lt
,ge
,le
) - 平等操作人员:
==
,!=
(eq
,ne
)
- 比较器:
- 有条件经营者:
- 然后:
(if) ? (then)
- 如果当时:
(if) ? (then) : (else)
- 违约:
(value) ?: (defaultvalue)
- 然后:
日志格式
日志显示格式
%d{yyyy/MM/dd-HH:mm:ss} [%thread] %-5level %logger- %msg%n
PatternLayout包含的所有有效的格式
%c 输出logger名称
%C 输出类名
%d{HH:mm:ss.SSS} 表示输出到毫秒的时间
%t 输出当前线程名称
%-5level 输出日志级别,-5表示左对齐并且固定输出5个字符,如果不足在右边补0
%logger 输出logger名称,因为Root Logger没有名称,所以没有输出
%msg 日志文本
%n 换行
其他常用的占位符有:
%F 输出所在的类文件名,如Log4j2Test.java
%L 输出行号
%M或%method 输出所在方法名
%l 输出完整的错误位置, 包括类名、方法名、文件名、行数
%p 该条日志的优先级
%replace{pattern}{regex}{substitution} 将pattern的输出结果pattern按照正则表达式regex替换成substitution
版权声明:本文为CSDN博主「兔币难波万」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/ctubinanbowan/article/details/105374279
DATA
spring:bean 底层统一使用springdata jpa jdbc
jdbc 写法
package com.lmq.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;
/**
* @author 羡鱼
* @version 1.0
* @date 2023/7/25 18:57
*/
@RestController // mvc的
public class JDBCController {
@Autowired
JdbcTemplate jdbcTemplate;
// 查询数据库的所有信息并且显示在网页上
// 没有实体类数据库里面的数据这么获取 ? Map
@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 user(id,name,pwd) values (4,'小明','123123')";
jdbcTemplate.update(sql);
return "插入成功";
}
@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] = "zzzzzz";
jdbcTemplate.update(sql,objects);
return "修改成功";
}
@GetMapping("/deletUser/{id}")
public String deleteUser(@PathVariable("id") int id){
String sql = "delete from mybatis.user where id = ?";
jdbcTemplate.update(sql,id);
return "删除成功";
}
}
Druid
简介
Druid为监控而生的数据库连接池,它是阿里巴巴开源平台上的一个项目。Druid是Java语言中最好的数据库连接池,Druid能够提供强大的监控和扩展功能.它可以替换DBCP和C3P0连接池。Druid提供了一个高效、功能强大、可扩展性好的数据库连接池。
配置
name : 配置这个属性的意义在于,如果存在多个数据源,监控的时候可以通过名字来区分开来。如果没有配置,将会生成一个名字,格式是:"DataSource-" + System.identityHashCode(this). 另外配置此属性至少在1.0.5版本中是不起作用的,强行设置name会出错。
url:连接数据库的url,不同数据库不一样。例如:
mysql : jdbc:mysql://10.20.153.104:3306/druid2
oracle : jdbc:oracle:thin:@10.20.149.85:1521:ocnauto
username:连接数据库的用户名
password:连接数据库的密码。如果你不希望密码直接写在配置文件中,可以使用ConfigFilter
driverClassName: 缺省值-根据url自动识别 这一项可配可不配,如果不配置druid会根据url自动识别dbType,然后选择相应的driverClassName
initialSize: 缺省值-0 初始化时建立物理连接的个数。初始化发生在显示调用init方法,或者第一次getConnection时
maxActive: 缺省值- 8 最大连接池数量
maxIdle: 缺省值- 8 已经不再使用,配置了也没有效果的
minIdle: 最小连接池数量
maxWait:获取连接时最大等待时间,单位毫秒。配置了maxWait之后,缺省启用公平锁,并发效率会有所下降,如果需要可以通过配置useUnfairLock属性为true使用非公平锁。
poolPreparedStatements: 缺省值-false 是否缓存preparedStatement,也就是PSCache。PSCache对支持游标的数据库性能提升巨大,比如说oracle。在mysql下建议关闭。
maxPoolPreparedStatementPerConnectionSize: 缺省值- -1 要启用PSCache,必须配置大于0,当大于0时,poolPreparedStatements自动触发修改为true。在Druid中,不会存在Oracle下PSCache占用内存过多的问题,可以把这个数值配置大一些,比如说100
validationQuery:用来检测连接是否有效的sql,要求是一个查询语句,常用select 'x'。如果validationQuery为null,testOnBorrow、testOnReturn、testWhileIdle都不会起作用
validationQueryTimeout:单位:秒,检测连接是否有效的超时时间。底层调用jdbc Statement对象的void setQueryTimeout(int seconds)方法
testOnBorrow: 缺省值-true 申请连接时执行validationQuery检测连接是否有效,做了这个配置会降低性能。
testOnReturn: 缺省值-false 归还连接时执行validationQuery检测连接是否有效,做了这个配置会降低性能。
testWhileIdle:缺省值-false 建议配置为true,不影响性能,并且保证安全性。申请连接的时候检测,如果空闲时间大于timeBetweenEvictionRunsMillis,执行validationQuery检测连接是否有效。
keepAlive:缺省值-false(1.0.28版本)连接池中的minIdle数量以内的连接,空闲时间超过minEvictableIdleTimeMillis,则会执行keepAlive操作。
timeBetweenEvictionRunsMillis: 缺省值- 1分钟(1.0.14) 有两个含义:
- Destroy线程会检测连接的间隔时间,如果连接空闲时间大于等于minEvictableIdleTimeMillis则关闭物理连接。
- testWhileIdle的判断依据,详细看testWhileIdle属性的说明
numTestsPerEvictionRun:缺省值- 30分钟 不再使用,一个DruidDataSource只支持一个EvictionRun
minEvictableIdleTimeMillis: 连接保持空闲而不被驱逐的最小时间
connectionInitSqls: 物理连接初始化的时候执行的sql
exceptionSorter:缺省值-根据dbtype自动识别 当数据库抛出一些不可恢复的异常时,抛弃连接
filters: 属性类型是字符串,通过别名的方式配置扩展插件,常用的插件有:
监控统计用的filter:stat
日志用的filter:log4j
防御sql注入的filter:wall
proxyFilters:类型是List<com.alibaba.druid.filter.Filter>,如果同时配置了filters和proxyFilters,是组合关系,并非替换关系
congfig配置
package com.lmq.config;
import com.alibaba.druid.pool.DruidDataSource;
import com.alibaba.druid.support.http.StatViewServlet;
import org.springframework.boot.context.properties.ConfigurationProperties;
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;
/**
* @author 羡鱼
* @version 1.0
* @date 2023/7/25 20:47
*/
@Configuration
public class DruidConfig {
@ConfigurationProperties(prefix = "spring.datasource")
@Bean
public DataSource druifDataSource() {
return new DruidDataSource();
}
// 后台监控功能 相当于 web.xml
@Bean
public ServletRegistrationBean a() {
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", ""); // 为空都可以放翁
// 禁止ip 访问
// initParameters.put("名字","192.168.137.1");
bean.setInitParameters(initParameters); // 设置初始化参数
return bean;
}
}
yaml配置文件
spring:
datasource:
username: root
password: 123456
url: jdbc:mysql://124.71.168.125:3310/mybatis?userUnicode=true&characterEncoding=utf8&serverTimezone=UTC
driver-class-name: com.mysql.cj.jdbc.Driver
type: com.alibaba.druid.pool.DruidDataSource
#Spring Boot 默认是不注入这些属性值的,需要自己绑定
#druid 数据源专有配置
initialSize: 5
minIdle: 5
maxActive: 20
maxWait: 60000
timeBetweenEvictionRunsMillis: 60000
minEvictableIdleTimeMillis: 300000
validationQuery: SELECT 1 FROM DUAL
testWhileIdle: true
testOnBorrow: false
testOnReturn: false
poolPreparedStatements: 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
整合mybatis
整合包
mybatis-spring-boot-starter
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.3.1</version>
</dependency>
<dependency>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
<scope>runtime</scope>
</dependency>
M:数据模型
V:htnml
C:controller
- 导入包
- 配置文件
- mybatis配置
- 编写sql
- 业务层调用dao层
- controller 调用service层
SpringSecurity(安全)
web开发中 安全第一 过滤器 拦截器
功能性需求:否
做网站:安全应该在什么时候考虑? 设计之初
-
漏洞;隐私泄露
-
框架一旦确定就不会去大修改
-
shiro springSecurity: 很像 除了类不一样名字不一样其他都差不多
-
认证授权(VIP1 vip2 vip3 )
身份认证 授权管理
- 功能权限
- 访问权限
- 菜单权限
AOP 思想 横切 配置类1
简介
使用
导入
Shiro
简而言之,Apache Shiro 是一个强大灵活的开源安全框架,可以完全处理身份验证、授权、加密和会话管理。
Shiro能到底能做些什么呢?
- 验证用户身份
- 用户访问权限控制,比如:1、判断用户是否分配了一定的安全角色。2、判断用户是否被授予完成某个操作的权限
- 在非 Web 或 EJB 容器的环境下可以任意使用Session API
- 可以响应认证、访问控制,或者 Session 生命周期中发生的事件
- 可将一个或以上用户安全数据源数据组合成一个复合的用户 “view”(视图)
- 支持单点登录(SSO)功能
- 支持提供“Remember Me”服务,获取用户关联信息而无需登录
···
为什么是 Shiro?
使用 Shiro 官方给了许多令人信服的原因,因为 Shiro 具有以下几个特点:
- 易于使用——易用性是项目的最终目标。应用程序安全非常令人困惑和沮丧,被认为是“不可避免的灾难”。如果你让它简化到新手都可以使用它,它就将不再是一种痛苦了。
- 全面——没有其他安全框架的宽度范围可以同Apache Shiro一样,它可以成为你的“一站式”为您的安全需求提供保障。
- 灵活——Apache Shiro可以在任何应用程序环境中工作。虽然在网络工作、EJB和IoC环境中可能并不需要它。但Shiro的授权也没有任何规范,甚至没有许多依赖关系。
- Web支持——Apache Shiro拥有令人兴奋的web应用程序支持,允许您基于应用程序的url创建灵活的安全策略和网络协议(例如REST),同时还提供一组JSP库控制页面输出。
- 低耦合——Shiro干净的API和设计模式使它容易与许多其他框架和应用程序集成。你会看到Shiro无缝地集成Spring这样的框架, 以及Grails, Wicket, Tapestry, Mule, Apache Camel, Vaadin…等。
- 被广泛支持——Apache Shiro是Apache软件基金会的一部分。项目开发和用户组都有友好的网民愿意帮助。这样的商业公司如果需要Katasoft还提供专业的支持和服务。
有兴趣的可以去仔细看看官方的文档:【传送门】
Apache Shiro Features 特性
Apache Shiro是一个全面的、蕴含丰富功能的安全框架。下图为描述Shiro功能的框架图:
Authentication(认证), Authorization(授权), Session Management(会话管理), Cryptography(加密)被 Shiro 框架的开发团队称之为应用安全的四大基石。那么就让我们来看看它们吧:
- Authentication(认证):用户身份识别,通常被称为用户“登录”
- Authorization(授权):访问控制。比如某个用户是否具有某个操作的使用权限。
- Session Management(会话管理):特定于用户的会话管理,甚至在非web 或 EJB 应用程序。
- Cryptography(加密):在对数据源使用加密算法加密的同时,保证易于使用。
还有其他的功能来支持和加强这些不同应用环境下安全领域的关注点。特别是对以下的功能支持:
- Web支持:Shiro的Web支持API有助于保护Web应用程序。
- 缓存:缓存是Apache Shiro API中的第一级,以确保安全操作保持快速和高效。
- 并发性:Apache Shiro支持具有并发功能的多线程应用程序。
- 测试:存在测试支持,可帮助您编写单元测试和集成测试,并确保代码按预期得到保障。
- “运行方式”:允许用户承担另一个用户的身份(如果允许)的功能,有时在管理方案中很有用。
- “记住我”:记住用户在会话中的身份,所以用户只需要强制登录即可。
注意: Shiro不会去维护用户、维护权限,这些需要我们自己去设计/提供,然后通过相应的接口注入给Shiro
High-Level Overview 高级概述
在概念层,Shiro 架构包含三个主要的理念:Subject,SecurityManager和 Realm。下面的图展示了这些组件如何相互作用,我们将在下面依次对其进行描述。
- Subject:当前用户,Subject 可以是一个人,但也可以是第三方服务、守护进程帐户、时钟守护任务或者其它–当前和软件交互的任何事件。
- SecurityManager:管理所有Subject,SecurityManager 是 Shiro 架构的核心,配合内部安全组件共同组成安全伞。
- Realms:用于进行权限信息的验证,我们自己实现。Realm 本质上是一个特定的安全 DAO:它封装与数据源连接的细节,得到Shiro 所需的相关的数据。在配置 Shiro 的时候,你必须指定至少一个Realm 来实现认证(authentication)和/或授权(authorization)。
我们需要实现Realms的Authentication 和 Authorization。其中 Authentication 是用来验证用户身份,Authorization 是授权访问控制,用于对用户进行的操作授权,证明该用户是否允许进行当前操作,如访问某个链接,某个资源文件等。
Shiro 认证过程
任务
异步任务
// @Enabl开启注解功能
@EnableAsync
@SpringBootApplication
public class Springboot09TestApplication {
public static void main(String[] args) {
SpringApplication.*run*(Springboot09TestApplication.class, args);
}
}
定时任务
TaskScheduler //任务调度
taskExecutor //任务执行
@EnableScheduling // 开启定时功能的注解
// 秒 分 时 日 月 周几
@Scheduled(cron="0 * * * * 0-7") // 什么时候执行 cron表达式
邮件发送
public void sendMeail(Boolean html,String title,String context,String filePath,String meailPath) throws MessagingException {
// 发送一个复杂邮件
MimeMessage mimeMessage = mailSender.createMimeMessage();
// 组装
MimeMessageHelper helper = new MimeMessageHelper(mimeMessage,html);
// 标题
helper.setSubject(title);
// 正文
helper.setText(context,true);
helper.setText("<p style='color:pink'>ooxx你好冉冉xxoo</p>spring Boot 发送");
//附件
helper.addAttachment("1.jpg",new File(filePath));
helper.setTo(meailPath);
helper.setFrom("1435456124@qq.com");
mailSender.send(mimeMessage);
}
springBoot 整合redis
springboot 操作数据; spring-data jpa jdbc mongodb redis
说明 : 在spring 2.x 之后 原来使用的jedis 被替换为lettuce
jedis: 采用直连,多个线程操作就不安全,如果想要避免不安全,使用jedis pool 连接池 BIO
lettuce: 采用 netty 实例可以在多个线程中进行共享 不存在线程不安全的问题 可以减少线程数据了 更像 Nio
redis 整合 springboot redis
@Bean
@ConditionalOnMissingBean(name = "redisTemplate")
@ConditionalOnSingleCandidate(RedisConnectionFactory.class)
public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
RedisTemplate<Object, Object> template = new RedisTemplate<>();
template.setConnectionFactory(redisConnectionFactory);
return template;
}
@Bean
@ConditionalOnMissingBean
@ConditionalOnSingleCandidate(RedisConnectionFactory.class)
public StringRedisTemplate stringRedisTemplate(RedisConnectionFactory redisConnectionFactory) {
return new StringRedisTemplate(redisConnectionFactory);
}
导入依赖
配置参数
测试
分布式 Dubbo + Zookeeper + springBoot
RPC
Netty: 30天
前台 中台 后台
什么是Dubbo
服务提供者 (Provider): 暴露服务的服务提供方 服务提供者在启动服务时 向注册中心注册自己提供的服务
服务消费者 (Consumer): 调用远程服务的服务消费方 服务消费者在启动时向注册中心订阅自己所需要的服务, 服务消费者,从提供地址列表中,基于软负载均衡算法 选一台提供者进行调用 如果调用失败就调用另外一台
注册中心(Registry): 注册中心返回服务提供者地址列表给消费者 如果有变更 注册中心将基于长连接推送变更数据给消费者
监控中心(Monitor) : 服务消费者和提供者,在内存中累计调用次数和调用时间, 定时每分钟发送一次统计数据到监控中心
dubbo-admin 监控后台 可以不要
打包maven 项目
mvn clean package -Dmaven.test.skip=true
步骤:
前提 zookeeper开启
-
提供者提供服务
-
导入依赖
<!-- 导入dubbo + zookeeper --> <!-- https://mvnrepository.com/artifact/org.apache.dubbo/dubbo-spring-boot-starter --> <dependency> <groupId>org.apache.dubbo</groupId> <artifactId>dubbo-spring-boot-starter</artifactId> <version>2.7.8</version> </dependency> <!-- zkclient --> <!-- https://mvnrepository.com/artifact/com.github.sgroschupf/zkclient --> <dependency> <groupId>com.github.sgroschupf</groupId> <artifactId>zkclient</artifactId> <version>0.1</version> </dependency> <!-- 日志冲突 --> <dependency> <groupId>org.apache.curator</groupId> <artifactId>curator-framework</artifactId> <version>2.12.0</version> </dependency> <dependency> <groupId>org.apache.curator</groupId> <artifactId>curator-recipes</artifactId> <version>2.12.0</version> </dependency> <dependency> <groupId>org.apache.zookeeper</groupId> <artifactId>zookeeper</artifactId> <version>3.7.1</version> <!-- 排除日志log4g --> <exclusions> <exclusion> <groupId>org.slf4j</groupId> <artifactId>slf4j-log4j12</artifactId> </exclusion> </exclusions> </dependency>
-
配置服务中心地址,以及服务发现名,和要扫描的包
-
在想要被注册的服务上加入注解
@DubboService
-
-
消费者如何消费
- 导入依赖
- 配置注册中心地址,配置自己的服务名
- 从远程注入服务 @DubboReference
小结
三层框架 + MVC
框架 ---> 解耦
开发框架
Spring
IOC AOP
IOC: 控制反转
约泡:
泡温泉,泡茶....泡友
附近的人 一个一个打招呼 聊天
浴场(容器 场所): 有温泉,茶社....有很多泡友
可以直接进温泉就有人和你一起了
原来我们都是自己一步步操作 现在都交给容器了 需要什么就去拿什么
AOP :切面(本质 动态代理)
为了解决什么? 不影响业务本来的情况下增加功能 大量用在日志 事务..等等
Spring是一个轻量级的java开源框架,容器
目的 : 解决企业开发的复杂性问题
spring是春天,觉得它是春天,也十分复杂,配置文件!
SpringBoot
SpringBoot 并不是新东西,就是spring的升级版!
新一代javaee的开发标准,开箱即用 -> 拿过来就可以用
它自动帮我们配置了很多东西,我们拿来即用
特点: 约定大于配置!
随着公司体系越来越大,用户越来越多!
微服务---> 新架构
模块化,功能化!
用户,支付,签到,娱乐....
人多了; 一台服务器解决不了 再增加服务器 横向
假设A服务占用98%的资源 B服务器只占用了10%
将原来的整体项目分成模块化 用户就是一个单独的项目 签到也是一个单独的项目, 项目和项目之间需要通讯
用户非常多 签到非常少 给用户多一点服务,签到少一点
微服务架构问题
分布式架构遇到四个核心问题?
1. 这么多服务客户端如何去放翁
2. 这么多服务,服务之间如何进行通讯?
3. 这么多服务如何治理?
4. 服务器挂了怎么办?
解决方案:
SpringCloud 是一套生态,就是用来解决以上分布式架构的问题
向使用SpringCloud,必须掌握SpringBoot,应为SpringCloud是基于SpringBoot
1. SpringCloud netflix 出来了一套解决方案
API网关 zuul 组件
Feign --> HttpClient --> HTTP的通讯方式,同步并阻塞
服务注册与发现 Eureka
熔断机制 Hystrix
2018年年底 宣布无限期停止维护. 生态不再维护 就会脱节. 出现安全问题
2. Apache Dubbo zookeeper
API 没有 要么找第三方组件 要么自己实现
Dubbo : 高性能的基于JAVA实现的 RPC通讯框架
服务注册与发现; zookeeper 动物园管理者
熔断机制: 没有 借用了Hystrix
3. SpringCloud Alibaba 一站式解决方案!
目前又提出了一个方案:
服务网格:下一代微服务标准! ServerMesh
代表解决方案 istio (未来可能需要掌握)
万变不离其宗一通百通
1. API 网关 服务路由
2. HTTP RPC框架 异步调用
3. 服务注册与发现,高可用
4. 熔断机制 服务降级
如果基于这四个问题开发一套解决方案 也叫springCloud解决方案
为什么要解决这些问题? 本质:网络网络不可靠