如何理解SpringCloud中常用组件之间的配合使用?
使用SpringCloud Gateway时,无法使用Spring Session
spring cloud gateway是基于webflux,是非阻塞的,zuul是基于servlet的,是阻塞的,所以在gateway中需要将EnableRedisHttpSession注解换成EnableRedisWebSession:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
public class RedisSessionConfig {
public WebSessionIdResolver webSessionIdResolver() {
return new CustomWebSessionIdResolver();
}
}
class CustomWebSessionIdResolver extends CookieWebSessionIdResolver {
// 重写resolve方法 对SESSION进行base64解码
public List<String> resolveSessionIds(ServerWebExchange exchange) {
MultiValueMap<String, HttpCookie> cookieMap = exchange.getRequest().getCookies();
// 获取SESSION
List<HttpCookie> cookies = cookieMap.get(getCookieName());
if (cookies == null) {
return Collections.emptyList();
}
return cookies.stream().map(HttpCookie::getValue).map(this::base64Decode).collect(Collectors.toList());
}
private String base64Decode(String base64Value) {
try {
byte[] decodedCookieBytes = Base64.getDecoder().decode(base64Value);
return new String(decodedCookieBytes);
} catch (Exception ex) {
return null;
}
}
}实现GlobalFilter接口,例如:登录过滤功能
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
public class SCWAccessFilter implements GlobalFilter, Ordered {
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
ServerHttpRequest request = exchange.getRequest();
String path = request.getPath().toString();
if (AccessPassResources.PASS_RES_SET.contains(path)) {
return chain.filter(exchange);
}
if (AccessPassResources.currentServletPathIsStaticResource(path)) {
return chain.filter(exchange);
}
AtomicBoolean loginSuccess = new AtomicBoolean(false);
exchange.getSession().subscribe(webSession -> {
Object loginMember = webSession.getAttribute(SCWConstant.ATTR_NAME_LOGIN_MEMBER);
if(loginMember!=null){
loginSuccess.set(true);
}else {
exchange.getResponse();
webSession.getAttributes().put(SCWConstant.ATTR_NAME_MESSAGE, SCWConstant.MESSAGE_ACCESS_FORBIDDEN);
loginSuccess.set(false);
}
});
try {
Thread.sleep(200);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
if (loginSuccess.get()) {
return chain.filter(exchange);
}
ServerHttpResponse response = exchange.getResponse();
response.setStatusCode(HttpStatus.SEE_OTHER);
response.getHeaders().set(HttpHeaders.LOCATION, "/login.html");
response.getHeaders().add("Content-Type", "text/plain;charset=UTF-8");
return response.setComplete();
}
public int getOrder() {
return -1;
}
}
使用SpringCloud Gateway时,如果对应请求的返回结果是重定向,则会改变主机地址为对应微服务的地址(302)?
解决:修改application.yml
配置文件PreserveHostHeader
,对请求头进行处理
1 | spring: |
邮箱验证码功能
1 | public class ProjectUtils { |
OpenFeign远程调用报错
错误内容:
### Error updating database. Cause: java.sql.SQLSyntaxErrorException: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '' at line 1 ### The error may exist in file [D:-member-parent-member-mysql-.xml] ### The error may involve com.zephon.scw.mapper.MemberPOMapper.insertSelective-Inline ### The error occurred while setting parameters ### SQL: insert into t_member ### Cause: java.sql.SQLSyntaxErrorException: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '' at line 1 ; bad SQL grammar []; nested exception is java.sql.SQLSyntaxErrorException: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '' at line 1
解决:
在使用OpenFeign接口时,服务提供者的请求参数中忘写@RequestBody
注解了,之后开发中最好将服务提供者和OpenFeign接口对应的方法请求参数需要写的都写上@RequestBody
服务提供者:
1 |
|
接口:
1 |
|
MyBatis插入数据后如何获取生成的ID?
配置Mapper的XML,
useGeneratedKeys="true" keyProperty="xxx"
如:1
<insert id="insertSelective" useGeneratedKeys="true" keyProperty="id" ...
插入后通过get方法获取生成的id
异步请求中无法对session中的属性进行更新?暂未找到原因,只能侧面解决
问题:
在请求A中设置了Session
1 |
|
在@ResponseBody
请求中更新Session:
1 |
|
在请求C中获取session中的数据,发现之前设置的值是空的
1 |
|
解决方案:未真正解决
猜测:Gateway的问题
侧面解决,换个名:
在请求B中将要添加的属性单独放到session中
1 |
|
然后在请求C中再去获得并设置对应的属性:
1 |
|
正式解决方案:
之前为了解决Gateway无法通过session判断登录的问题,对Gateway进行了配置:
1 |
|
这就会导致Session无法更新的问题,所以将其注释后就可以解决这个问题,然后只能通过token对登录进行认证
在创建一个微服务去调用Feign接口时,直接从另一个服务复制过来的包和配置文件进行修改的,但调用Feign接口报找不到Bean错误
- 检查Main类上面是否有
@EnableFeignClients
注解 - 个人遇到问题的原因是IDEA复制包时没有复制多级包,导致我的controller在abc目录下,而Feign接口在com.zephon.abc包下,因此,需要再建一个对应的多级包即可