-
在sca-provider工程中使用sca-common工程中的一些公共类(例如StringUtils.java)
-
检查自己电脑环境是否配置了JAVA_HOME环境变量?(set JAVA_HOME)
-
检查自己电脑环境中的JVM虚拟机是否为64位的?(java -version)
-
检查自己电脑环境中mysql的版本是否为5.7以上?(假如是MariaDB ,建议10.5以上)
-
预习Nacos服务注册中心相关内容.
- sca-common 工程创建,例如:
- sca-provider 工程引入sca-common工程依赖
com.jt
sca-common
1.0-SNAPSHOT
- sca-provider工程中使用sca-common工程公共类StringUtils.java
第一步:在sca-common工程中创建StringUtil.java工具类,例如:
package com.jt.common.util;
/**
- 自己定义一个操作字符串的工具类
*/
public class StringUtils {
/**
-
判断字符串的值是否为空
-
@param str 这个参数就是你要验证的字符串
-
@return true表示空
*/
public static boolean isEmpty(String str){
return str==null||“”.equals(str);
}
}
第二步:在sca-provider工程中添加spring-boot-start依赖,例如:
org.springframework.boot
spring-boot-starter
第三步:在sca-provider工程中的test目录下定义单元测试类,并进行测试,例如:
package com.example;
import com.jt.common.util.StringUtils;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringBootConfiguration;
import org.springframework.boot.test.context.SpringBootTest;
/**
- @SpringBootTest 注解描述的类为Spring工程的单元测试类
*/
@SpringBootConfiguration //(假如工程中有启动类,注解就不需要加了)
@SpringBootTest
public class StringTests {
/**
- 在当前测试类方法中,使用了sca-common项目中的StringUtils工具类
*/
@Test
void testStringEmpty(){
String content=“helloworld”;
boolean flag= StringUtils.isEmpty(content);
System.out.println(flag);
}
}
- 检查自己电脑的JAVA_HOME环境变量?
方式1:打开电脑的命令行窗口,输入set JAVA_HOME 指令,例如:
方式2:假如是window平台还可以通过,如下方式进行检查,例如:
- 检查自己电脑环境中的JVM虚拟机是否为64位的,例如:
- 登录mysq,检查mysql或maridb的版本,例如:
============================================================================
-
注册中心诞生的背景? (所有公司需要在工商局进行备案)
-
注册中心的选型?(社区活跃度,稳定性,功能,性能,学习成本)
-
Nacos下载,安装,配置,启动,访问(http://ip:port/nacos)
-
服务向Nacos的注册?(添加依赖,服务配置,启动服务并检查)
-
Nacos进行服务监控的方式?(心跳包)
-
服务(进程)之间的调用?(借助RestTemplate.思考Spring中的JdbcTemplate,SqlSessionTemplate等对象的作用)
-
注册中心诞生的背景? (服务多了,需要对服务进行更好管理)
-
市场上常用的注册中心?(Zookeeper,Eureka,Nacos,Consul)
-
如何对注册中心进行选型?(社区活跃度,稳定性,功能,性能,学习成本)
-
Nacos 是什么?(是Alibaba公司基于SpringBoo技术t实现的一个注册中心,本质上也是一个服务)
-
Nacos 的基本架构?(Client/Server架构)
-
Nacos 主要提供了什么核心功能?(服务的注册,发现,配置)
-
Nacos 服务启动需要什么前置条件?(配置JDK的JAVA_HOME目录,安装MySQL5.7以上版本,配置连接的数据库)
-
Nacos 服务单机模式,window平台下启动时的指令是什么?(startup.cmd -m standalone)
-
实现Nacos服务注册需要添加什么依赖?(两个)
-
实现Nacos服务注册时,必须做哪些配置?(服务名,假如是本机服务注册可以省略服务地址)
-
Nacos如何检查服务状态?(通过心跳包实现)
-
服务之间进行服务调用时,使用了什么API?(RestTemplate)
- JAVA_HOME环境变量定义错误,例如:
说明,这里一定要注意JAVA_HOME单词的拼写,JAVA_HOME中定义的JDK是存在的.
- MySQL版本比较低,例如:
当执行nacos-mysql.sql文件时,出现如下错误:
- SQL文件应用错误,例如:
- Nacos的application.properties配置文件中,连接数据库的配置错误.
- 服务注册时,服务名不正确,例如:
- Nacos 服务注册失败,例如
- 客户端500异常,例如
- 服务调用时,连接异常,例如:
- 服务调用时底层404问题,例如:
-
重新创建新的聚合项目(例如10-sca)
-
重新实现服务的注册和调用(ca-consumer调用ca-provider)
-
尝试完成负载均衡方式的服务调用(参考博客文档)
=======================================================================
-
基于LoadBalancerClient 实现服务发现和负载均衡
-
@Loadbalanced注解的作用以及应用分析
-
Feign方式的服务调用实践
-
何为服务发现?(从nacos获取服务实例)
-
LoadBalancerClient的作用?(从nacos获取服务实例列表,然后本地基于负载均衡算法获取服务实例)
-
@Loadbalanced作用?(描述RestTemplate对象,让系统底层为RestTemplate对象赋能)
-
Feign是什么?(Spring Cloud微服务规范中的一组远程调用API)
-
为什么使用Feign?(优化服务调用结构)
-
如何使用Feign实现服务调用?(依赖,@EnableFeignClients,@FeignClient)
-
Feign方式的服务调用原理是怎样的?(底层基于代理对象实现)
- 服务启动时端口被占用,例如:
- RestTemplate对象应用错误,例如:
- @Autowired描述的属性有红色下划波浪线,例如:
- 依赖注入(DI)问题,例如
- 服务名应用问题,例如:
- Feign 接口方法中@PathVariable注解应用问题.
-
总结微服务中的服务发现及调用方式.
-
构建一个简易的Browser/Tomcat对象,实现两个对象的网络通讯(了解).
-
预习@FeignClient中fallbackFactory注解的应用.
-
预习Nacos配置中心.
- 服务调用方式总结,例如:
- 简易Browser/Tomcat对象实现?(Java中的网络通讯需要借助Socket/ServerSocket对象)
第一步:构建Tomcat对象,例如:
package com.jt.common.net;
import java.io.IOException;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
/**
-
模拟一个简易的tomcat(服务)
-
基于Java中的网络编程实现(java.net)
-
1)网络服务端(ServerSocket)
-
2)网络客户端(Socket)
*/
public class Tomcat {//企业规范
public static void main(String[] args) throws IOException {
//1.创建服务(例如:启动nacos,启动…),并在9999端口进行监听
//网络中计算机的唯一标识是什么?ip
//计算机中应用程序的唯一标识是什么?port
ServerSocket server=new ServerSocket(9999);
System.out.println(“server start …”);
//2.启动服务监听
while(true){
//监听客户端的链接(这里的socket代码客户端对象)
Socket socket=server.accept();//阻塞方法
//在这里可以将socket对象的信息记录一下.(服务注册)
//创建输出流对象,向客户端输出hello client
OutputStream out =
socket.getOutputStream();
//byte[] responseContent=“hello client”.getBytes();
byte[] responseContent=(“HTTP/1.1 200 ok \r\n” +
“Content-Type: text/html;charset=utf-8 \r\n” +
“\r\n” +
“
hello client
”).getBytes();out.write(responseContent);
out.flush();
}
}
}
第二步:构建Browser对象,例如:
package com.jt.common.net;
import java.io.IOException;
import java.io.InputStream;
import java.net.Socket;
/**
- 模拟一个简易浏览器(Client)
*/
public class Browser {
public static void main(String[] args) throws IOException {
//1.创建网络编程中的客户端对象(Socket)
//构建Socket对象时要执行连接个计算机(ip),访问计算机中的哪个应用(port)
Socket socket=new Socket(“127.0.0.1”,9999);//TCP
//2.创建一个输入流对象,读取服务端写到客户端的数据
InputStream in = socket.getInputStream();
byte[] buf=new byte[1024];
int len=in.read(buf);
String content=new String(buf,0,len);
System.out.println(content);
//3.释放资源
socket.close();
}
}
第三步:运行tomcat和Browser,检测Browser输出.
也可以打开,浏览器直接访问http://localhost:9999
============================================================================
-
配置中心诞生的背景(分布式架构下如何动态发布和更新配置)
-
市场上主流的配置中心(Nacos,…)
-
Nacos配置中心的基本应用(添加依赖,修改配置文件名以及内容,新建配置,应用配置)
*@RefreshScope注解的应用(描述类,实现类中属性值@Value与配置中心中内容的同步)
-
为什么要使用配置中心?(项目上线后实现配置的动态发布和更新)
-
你知道哪些主流配置中心?
-
Nacos配置中心如何应用?
-
Java项目中你用的日志API是什么?(org.slf4j.Logger)
-
你项目中为什么使用org.slf4j.Logger对象记录日志?此对象是日志规范,是对外面的门面,可以更好降低耦合
-
@Slf4j注解的作用是什么?(此注解属于lombok,用于描述类,在类中创建org.slf4j.Logger对象)
-
你知道Java中有哪些常用日志级别?(debug<info<warn<error)
-
Java日志在设计时为什么要设计日志级别?(方便根据级别调整日志输出)
-
Java中日志级别的配置通常要写到哪里?(配置中心)
-
你觉得Nacos配置中心通常会配置哪些内容?(可能经常变化的数据)
-
Nacos配置中心依赖对项目中配置文件的名字有要求吗?(bootstrap.yml)
-
Nacos中@RefreshScope注解的应用场景以及作用.
-
如何在初始化对象属性时从配置中心读取配置内容?(@Value注解对属性进行描述)
- idea连接database,例如mysql.(可以baidu,然后输入idea database进行复合查询)
- 配置文件或配置文件格式不正确,例如:
- @Value注解包引入错误,例如:
*@Value配置读取不到,例如:
-
总结课上知识点,并尝试重新构建项目进行配置实践.
-
将Nacos配置入门章节的小节节面试仔细读一遍.
-
预习Nacos的配置模型.
===========================================================================
-
配置管理模型存在的意义
-
配置管理模型三要素及其要素关系
-
Nacos中读取指定命名空间和分组下的配置
-
Naocs中的共享配置的设计(对很多配置文件中的共性的一种提取方式)
-
如何理解配置的命名空间(Namesapce)?(定义一些配置的作用域,做配置的分类管理,不同环境不同配置)
-
为什么要进行配置分组?(一个命名空间可以有多个分组,同一个生产环境下的不同活动会有不同配置)
-
配置中心运行有共享配置吗,如何引用?(可以,基于shared-configs元素进行引用)
-
Java程序中读取不到配置?(依赖,配置文件,命名空间,分组,data-id,空格,缩进,重启,放大招)
-
@Value(“${logging.level.com.jt}”) 读取不到值?(先检查你是否有这个配置,假如没有可以给定一个默认值)
-
线程(Thread)安全问题?(多个线程,共享数据集,原子操作)
-
如何理解线程并发中的双重校验?(既要保证安全,又要保证效率)
-
如何理解定时任务?(让线程对象在规定的时间范围内自动去执行任务,例如配置信息的定时刷新)
-
总结课上内容(命名空间,分组,共享配置)
-
基于Timer对象实现定时任务调度(单线程有顺序的任务调度)
-
基于ScheduledExecutorService实现一个任务调度(课后拓展,Nacos中的定时心跳,配置长轮询都是基于这个对象)
-
在ProviderCacheController类中添加一个本地Cache(基于CopyOnWriteArrayList对象实现)
-
基于双重校验机制,实现类的单实例设计(拓展,自己尝试实现).
-
预习Sentinel章节的限流操作(北京市为什么要限号)
- 基于Timer对象实现定时任务调度,例如:
package com.jt.common.util;
import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.ScheduledExecutorService;
/**
- 单线程定义任务工具类
*/
public class TimerUtils {
public static void main(String[] args) {
//1.构建执行任务的对象(这里选择java中的Timer对象)
//Timer对象创建时会创建一个线程,并且为线程分配一个任务队列
Timer timer=new Timer();
//2.构建任务对象
TimerTask task1=new TimerTask() {
@Override
public void run() {
System.out.println(System.currentTimeMillis());
//timer.cancel(); 结束任务调度
}
};
//3.定时执行任务
timer.schedule(task1,//要执行的任务
1000,//1秒以后开始执行
1000);//每隔1秒执行1次
//基于Timer类执行定时任务时,最大的缺陷是多个任务不能并发执行.
}
}
- 基于ScheduledExecutorService实现一个任务调度,例如:
package com.jt.common.util;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
/**
- 测试多线程任务调度
*/
public class ScheduledExecutorServiceTests {
public static void main(String[] args) {
//构建一个负责任务调度的线程池对象,池中最多有三个核心线程
ScheduledExecutorService ses=
Executors.newScheduledThreadPool(3);
//构建任务对象
Runnable task=new Runnable() {
@Override
public void run() {
String tName=Thread.currentThread().getName();
System.out.println(tName+“->”+System.currentTimeMillis());
}
};
//执行任务对象(定时任务调度):1秒以后开始执行,每隔1秒执行1次
ses.scheduleAtFixedRate(task,
1,//初始延迟
5,//每隔1秒启动1次(与任务是否执行结束无关)
TimeUnit.SECONDS);//时间单位
}
}
- 在ProviderCacheController类中添加一个本地Cache对象,在保证其线程安全的前提下,提高其性能.
//构建一个本地(Local)缓存对象(基于jvm中的一个对象存储从数据库获取的数据).
private List cache=new CopyOnWriteArrayList<>();
@RequestMapping(“/provider/cache02”)
public List doUseLocalCache02(){
if(!useLocalCache){//假如没有打开本地Cache,则直接访问数据库
System.out.println(“Get data from database”);
return Arrays.asList(“Category-A”, “Category-B”, “Category-C”);
}
if(cache.isEmpty()) {
synchronized (cache) {
if (cache.isEmpty()) {//Thread-A,Thread-B,…
System.out.println(“Get data from database”);
//假设这部分分类信息是从数据库获取的,但是,我不希望每次获取分类信息都要从数据库查
List cates = Arrays.asList(“Category-A”, “Category-B”, “Category-C”);
cache.addAll(cates);
}
}
}
return cache;
}//生产层面
- 基于双重校验机制,实现类的单实例设计,例如:
package com.jt.common.thread;
/**
- 如何保证如下类的设计在外界能获取一个实例~单例设计
*/
class Singleton{
private Singleton(){}
private static Singleton instance;
public static Singleton getInstance(){
if(instance==null) {
synchronized (Singleton.class) {
if (instance == null) {//双重
校验
instance = new Singleton();
}
}
}
return instance;
}
}
public class SingleTests {
public static void main(String[] args) {
Thread t1=new Thread(){
@Override
public void run() {
System.out.println(Singleton.getInstance());
}
};
Thread t2=new Thread(){
@Override
public void run() {
System.out.println(Singleton.getInstance());
}
};
Thread t3=new Thread(){
@Override
public void run() {
System.out.println(Singleton.getInstance());
}
};
t1.start();
t2.start();
t3.start();
}
}
============================================================================
-
限流的背景
-
Sentinel限流入门(控制台8180-定义规则,客户端服务应用规则:依赖,配置)
-
Sentinel常用限流模式(直接,关联,链路)
-
Sentinel降级入门实现(暂停对服务的访问)
-
为什么要进行限流? (系统处理能力有限,可以通过限流方式,保证系统可靠运行)
-
Sentinel限流的基本原理?(底层对请求进行拦截,然后通过流控规则限定对资源访问)
-
Sentinel限流有哪些算法? (计数器,令牌桶,漏桶,滑动窗口算法~sentinel默认)
-
Sentinel常用限流效果有哪些?(快速失败,预热,排队)
-
sentinel 服务启动不起来?(要使用JDK8)
-
sentinel 面板不显示我们的服务?(依赖,配置,访问,大招)
-
总结课上知识点.
-
了解常用限流算法.
-
尝试基于@SentinelResource注解描述的方法进行限流结果的定义?
-
预习sentinel降级异常处理,Sentinel热点规则设计,授权设计.
- 基于@SentinelResource注解描述的方法进行限流结果的定义.
第一步:定义blockHandlerClass,例如:
package com.jt.provider.service;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
@Slf4j
@Component
public class ResourceBlockHandler {
/**
-
注意此方法中的异常类型必须为BlockException (
-
它是所有限流,降级等异常的父类类型),方法的返回
-
值类型为@SentinelResource注解描述的返回值类型,
-
方法的其他参数为@SentinelResource注解描述的方法参数,
-
并且此方法必须为静态方法
-
@param ex
-
@return
*/
public static String call(BlockException ex){
log.error(“block exception {}”, ex.getMessage());
return “访问太频繁了,稍等片刻再访问”;
}
}
第二步:修改@SentinelResource注解中的属性定义,例如:
@SentinelResource(value=“doGetResource”,
blockHandlerClass = ResourceBlockHandler.class,
blockHandler = “call”)
public String doGetResource(){
return “do get resource”;
}
第三步:在controller方法中,调用@Sentinel注解描述的方法,例如:
/**
-
演示链路限流
-
@return
*/
@GetMapping(“/sentinel03”)
public String doSentinel03(){
return resourceService.doGetResource();
//return “sentinel 03 test”;
}
============================================================================
-
Sentinel 异常处理
-
Sentinel 热点数据限流
-
Sentinel 系统规则应用实践
-
Sentinel 授权规则应用实践
-
Sentinel 拦截器应用原理分析
-
为什么要进行异常处理?(提高用户体验)
-
Sentinel中限流,降级的父类异常类型是什么?(BlockException)
-
Sentinel中默认的BlockException处理对象是谁?(DefaultBlockException)
-
如何自己定义Sentinel的异常处理对象?(直接或间接继承BlockExceptionHandler)
-
如何理解热点数据以及限流的方式是什么?(经常访问的数据,基于参数或参数值进行限流)
-
如何理解sentinel中的系统规则?(全局限流规则,基于QPS,CPU,…)
-
如何理解Sentinel中的授权规则?(黑白名单)
-
请求被限流时出现500异常?
-
异常处理对象没有交给Spring管理(例如类使用@Common修饰)
-
总结课上sentinel应用规则
-
实践Spring MVC中的拦截器应用(重点)
-
思考客户端向tomcat发起一个请求时,tomcat处理这个请求的过程?
-
手写一个简易的框架执行链(了解)
-
手写一个简易的过滤链(了解)
-
预习微服务中的Gateway组件.
- tomcat 处理客户端的请求时的一个简易流程分析,例如:
- 基于Spring MVC中的拦截器实现对控制方法进行时间访问控制?
package com.jt.provider.interceptor;
import org.springframework.web.servlet.HandlerInterceptor;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.time.LocalTime;
/**
-
Spring MVC 中的拦截器对象,
-
此对象可以在你执行目标Controller方法之前执行
*/
public class TimeInterceptor implements HandlerInterceptor {
/**
-
此方法在你执行的目标Controller方法之前执行
-
@return 返回值true表示放行,可以继续执行request的后续业务
*/
@Override
public boolean preHandle(HttpServletRequest request,
HttpServletResponse response,
Object handler) throws Exception {
System.out.println(“=preHandle=”);
//业务:允许在8点之后,晚9点之前可访问
LocalTime now = LocalTime.now();//获取当前时间,
int hour = now.getHour();//获取当前时间的小时单位
if(hour<8||hour>=21)
throw new RuntimeException(“请在规定时间访问8~21”);
return true;
}
}
第二步:配置拦截器,例如:
package com.jt;
import com.jt.provider.interceptor.TimeInterceptor;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class SpringWebConfig implements WebMvcConfigurer {
//注册拦截器
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new TimeInterceptor())
.addPathPatterns(“/provider/sentinel01”);
}
}
第三步:对/provider/sentinel01路径按时间段进行访问,检测拦截器的执行.
- 手写一个简易的框架执行链(了解),模拟框架中执行链的设计,例如:
package com.jt.common.interceptor;
import javax.xml.transform.Source;
import java.time.LocalTime;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
/**
-
如何理解框架?设计好的一个半成品?(类似简历模板)
-
框架设计时会有一些对象的定义以及这些对象的执行流程,类似一个执行链.
-
在当前案例中,我们模拟一个框架中执行链的设计.
*/
//拦截器接口
interface HandlerInterceptor{
default void before(){}//定义在目标handler方法执行之前执行
default void after(){}//定义在目标handler方法之后执行
}
//处理器接口
interface Handler{
void processed();//处理业务的方法
}
//定义一个执行链
class ExecutionChain{//我是执行链的设计者
//一些拦截器
private List interceptors=
new CopyOnWriteArrayList<>();
//业务处理器
private Handler handler;
public ExecutionChain(List interceptors,Handler handler){
this.handler=handler;
this.interceptors.addAll(interceptors);
}
public void execute(){//负责执行业务的方法(例如处理请求)
//1.before
for(int i=0;i<interceptors.size();i++){
interceptors.get(i).before();
}
//2.processed
handler.processed();
//3.after
for(int i=interceptors.size()-1;i>=0;i–){
interceptors.get(i).after();
}
}
}
public class FrameworkTests {//框架应用者
public static void main(String[] args) {
//应用执行链
//1.创建拦截器
List interceptors=new CopyOnWriteArrayList<>();
HandlerInterceptor interceptor=new HandlerInterceptor() {
@Override
public void before() {
System.out.println(“记录考试开始时间:”+ LocalTime.now());
}
@Override
public void after() {
System.out.println(“记录考试结束时间:”+ LocalTime.now());
}
};
interceptors.add(interceptor);
//2.创建处理
Handler handler=new Handler() {
@Override
public void processed() {
System.out.println(“同学们开始考试”);
}
};
//3.创建执行链
ExecutionChain chain=
new ExecutionChain(interceptors,handler);
//4.执行执行链
chain.execute();
}
}
- 基于JAVA技术实现一个简易的过滤链?(了解)
在我们的web服务处理请求时,系统底层有一个过滤链,用于对请求做一个预处理,这里做一个简易设计分析,例如:
package com.jt.common.filter;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
//过滤器(特殊拦截器)
interface Filter{
boolean invoke();
}
//控制器(负责请求分发)
interface Servlet{
void dispatch();
}
//过滤链
class FilterChain{
private List filters=new CopyOnWriteArrayList<>();//过滤器(请求数据过滤)
private Servlet servlet;//控制器(请求控制逻辑)
public FilterChain(List filters, Servlet servlet) {
this.filters.addAll(filters);
this.servlet = servlet;
}
public void doFilter(){//执行过滤链
//请求过滤
for(int i=0;i<filters.size();i++){
if(!filters.get(i).invoke())return;
}
//请求分发
servlet.dispatch();
}
}
public class FilterChainTests {
public static void main(String[] args) {
//1.构建过滤器对象
Filter filter1=new Filter() {
@Override
public boolean invoke() {
System.out.println(“filter 01”);
return true;
}
};
Filter filter2=new Filter() {
@Override
public boolean invoke() {
System.out.println(“filter 02”);
return true;
}
};
List filters=new CopyOnWriteArrayList<>();
filters.add(filter1);
filters.add(filter2);
//2.构建控制器对象
Servlet servlet=new Servlet() {
@Override
public void dispatch() {
System.out.println(“将请求分发给具体对象去执行”);
}
};
//3.执行请求过滤及处理
FilterChain fc=new FilterChain(filters,servlet);
fc.doFilter();
}
}
===============================================================================
-
API 网关诞生背景
-
市场主流微服务网关.
-
Gateway实现服务的保护和转发(重点)
-
Gateway层面的负载均衡实现(重点)
-
Gateway请求处理原理分析(重点)
-
Gateway中的常用谓词对象(了解)
-
Gateway中的常用过滤器(了解)
-
Gateway中基于sentinel实现限流操作(重点)
-
网关入门实践的步骤? (依赖,配置,启动,服务访问)
-
网关项目中的负载均衡是如何实现?(基于Ribbon实现,可以在RibbonLoadBalancerClient中加断点分析)
-
网关项目中过滤器的类型?(GlobalFilter,GatewayFilter)
-
网关项目中如何基于sentinel实现服务的限流?(路由id,API分组限流)
-
Idea中如何使用HttpClient客户端工具?(发送post,put等请求,传递请求头参数)
-
Idea中Maven helper插件的安装和应用?
- 网关项目中的请求处理逻辑是如何实现的?(XxxHandlerMapping–谓词逻辑->XxxWebhandler-Filters–>…)
- idea中httpclient工具的应用,例如:
假如,idea中没有Tools,可以在键盘上按ctrl+shift+a进行查找.
- 配置文件格式不正确,例如
- 服务访问被拒绝,例如
- 服务注册失败(nacos没启动),例如:
-
了解过滤链的设计(自己参考课堂代码反复实现)
-
总结网关的基本应用(服务Netty,请求处理WebFlux,…)
-
课后了解单点登录系统诞生(SSO)的背景,有什么设计方案?
-
课后了解一下Spring Security技术(认证,授权),JWT技术?
=============================================================================
-
单点登录系统诞生的背景
-
Java中单点登录系统解决方案.
-
单点登录系统(SSO)中的服务划分及关系设计
-
单点登录系统中父工程的创建及初始化
-
系统基础服务(sso-system)工程的创建及基本业务实现
-
认证服务(sso-auth)工程的创建及初始化
-
为什么要做单点登录设计?(业务简化,代码复用,不需要每个服务都登录一次)
-
你知道哪些SSO系统解决方案?(基于用户登录状态信息的存储进行方案设计)
-
单点登录系统中你的服务是如何设计的,工程结构是怎样的?
-
用户登录时,需要从数据库查询哪些信息?(用户信息以及用户的权限信息)
-
如何基于用户id查询用户权限,你有什么方案?
-
基于idea的为类自动生成序列化id?
- 基于idea中的httpclient进行服务访问测试?
- 如何将链接数据库的信息写到配置中心?
- 连接数据库的url中时区定义有问题,例如:
-
NullPointerExeption 异常分析?
-
-
MyBatis 绑定异常(BindException)
-
总结课上内容
-
尝试自己构建单点登录系统(12-sso)
-
尝试完成认证服务中的用户业务对象以及Security配置类的定义.
===============================================================================
-
定义用户信息远程调用接口(RemoteUserService~基于此接口调用sso-system服务中的用户信息)
-
定义用户业务逻辑服务对象(UserDetailsServiceImpl~调用RemoteUserService完成用户信息的获取和封装)
-
定义用户认证基本配置类(SecurityConfig~配置密码加密对象以及登录成功或失败的处理方案)
-
实现自定义登录逻辑测试(校验登录正确账号和错误账户下服务端的响应结果)
-
熟悉SpringSecurity的认证流程?
-
为什么定义RemoteUserService 接口?
-
sso-auth服务中用户业务数据的获取在哪里?
-
为什么要构建SecurityConfig对象?
-
为什么要让SecurityConfig类要继承WebSecurityConfigurerAdapter类型?
-
认证过程中使用的密码加密对象是谁?
-
单体架构中的用户的状态的存储是如何实现的?
- 没有PasswordEncoder对象,例如:
- 远程调用服务404异常,例如:
- 远程调用服务没启动或服务名不正确,例如
- 服务名的定义和使用不规范,例如:
- 依赖注入异常,例如: