1. 前言
1.1 为啥要使用spring-cloud:2021.0.x?
原先使用Hoxton.SR8版本的springcloud,由于Netflix公司宣布其核心组件Hystrix、Ribbon、Zuul、Eureka等进入维护状态,不再进行新特性开发,只修 BUG。而spring官方因此做出应对,在新版本中移除了Netflix,顺便学习下新版本cloud,因此使用最新版本的cloud。
2.项目迭代历程
-
引入gateway网关,swagger文档工具
-
待续
3.项目构建
3.1 认证服务器升级
pom.xml引入cloud相关依赖
<!--Spring Cloud Alibaba 相关依赖-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-dependencies</artifactId>
<version>2021.0.1.0</version>
<type>pom</type>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
<version>2021.0.1.0</version>
</dependency>
增加application.yml对nacos的配置
spring:
cloud:
nacos:
discovery:
server-addr: 192.168.1.69:8848
新建controler,提供feign接口
@Slf4j
@RestController
public class ServerController {
@GetMapping("/getServerTest")
public SingleResultBundle<String> getServerTest(){
return SingleResultBundle.success("这是resource的测试方法 getResourceTest()");
}
}
3.2 资源服务器升级
pom.xml引入cloud相关依赖
<!-- 测试的feign模块 -->
<dependency>
<groupId>com.xueliman.iov</groupId>
<artifactId>server-feign</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-dependencies</artifactId>
<version>2021.0.1.0</version>
<type>pom</type>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
<version>2021.0.1.0</version>
</dependency>
增加application.yml对nacos的配置
spring:
cloud:
nacos:
discovery:
server-addr: 192.168.1.69:8848
启动类 ResourceApplication 增加相关注解
// 可以扫描到相关目录下含FeignClient的包
@EnableFeignClients(basePackages = {"com.xxxx.**"})
// 这个好像可以不要
@EnableDiscoveryClient
新增Controller进行feign调用接口测试
@Slf4j
@RestController
public class UserServerController {
@Autowired
private ServerFeign serverFeign;
@GetMapping("/getServerTest")
public SingleResultBundle<String> getServerTest(){
return serverFeign.getServerTest();
}
}
3.3 新建server-feign模块
此模块作为server认证服务器的feign模块,进行测试feign调用,因此需要开启认证服务器server中校验部分
修改server模块中WebSecurityConfig类
@Bean
public SecurityFilterChain httpSecurityFilterChain(HttpSecurity httpSecurity) throws Exception {
httpSecurity
.authorizeRequests(authorizeRequests ->
authorizeRequests.antMatchers("/login").permitAll()
.anyRequest().authenticated()
)
//使用默认登录页面
//.formLogin(withDefaults())
//设置form登录,设置且放开登录页login
.formLogin(fromlogin -> fromlogin.loginPage("/login").permitAll())
// Spring Security CSRF保护
.csrf(csrfToken -> csrfToken.csrfTokenRepository(new CookieCsrfTokenRepository()))
//开启认证服务器的资源服务器相关功能,即需校验token
.oauth2ResourceServer()
.accessDeniedHandler(new SimpleAccessDeniedHandler())
.authenticationEntryPoint(new SimpleAuthenticationEntryPoint())
.jwt()
;
return httpSecurity.build();
}
}
新建Feign的配置类 FeignRequestConfig
/**
* 为解决调用feign接口,需要认证服务
* 因此实现RequestInterceptor,对feign接口进行拦截,使其request中的header头部添加上token参数
* @author zxg
*/
@Slf4j
@Configuration
public class FeignRequestConfig implements RequestInterceptor {
@Override
public void apply(RequestTemplate template) {
HttpServletRequest httpServletRequest = getHttpServletRequest();
if(httpServletRequest!=null){
Map<String, String> headers = getHeaders(httpServletRequest);
// 传递所有请求头,防止部分丢失
//此处也可以只传递认证的header
//requestTemplate.header("Authorization", request.getHeader("Authorization"));
for (Map.Entry<String, String> entry : headers.entrySet()) {
template.header(entry.getKey(), entry.getValue());
}
log.debug("FeignRequestInterceptor:{}", template.toString());
}
}
private HttpServletRequest getHttpServletRequest() {
try {
return ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
} catch (Exception e) {
return null;
}
}
/**
* 获取原请求头
*/
private Map<String, String> getHeaders(HttpServletRequest request) {
Map<String, String> map = new LinkedHashMap<>();
Enumeration<String> enumeration = request.getHeaderNames();
if(enumeration!=null){
while (enumeration.hasMoreElements()) {
String key = enumeration.nextElement();
String value = request.getHeader(key);
map.put(key, value);
}
}
return map;
}
}
新建feign接口 ServerFeign
@FeignClient(name = "server", fallbackFactory = ServerFeign.ServerFallback.class, configuration = FeignRequestConfig.class)
public interface ServerFeign {
@GetMapping(value = "/getServerTest")
SingleResultBundle<String> getServerTest();
@Slf4j
@Component
class ServerFallback implements FallbackFactory<ServerFeign> {
@Override
public ServerFeign create(Throwable cause) {
return new ServerFeign() {
@Override
public SingleResultBundle<String> getServerTest() {
log.warn("远程调用被限流/降级了", cause);
return SingleResultBundle.failed("接口请求异常");
}
};
}
}
}
3.4 测试项目
分别启动server,resource服务。使用postman测试接口,结果返回如下
4.总结
升级为cloud,仅需引入对应cloud依赖,注意cloud版本之间是否兼容。以及使用feign接口调用时,注意要带上token,即上文中我们的配置的FeignRequestConfig文件,会将头部的token带过去。
期间在网上搜寻了很多资料,然后进行整合,因此文中存在与其他网上教程相同代码,如有争议,请联系我删除改正,谢谢。由于不太会写文章,我就直接贴出代码,代码中我有加上注释,所以上述文章中,没有很具体的描述,基本就是个人开发流程,若文中有那里写不对,欢迎指教,不喜勿喷。
后续整合sentinel部分,请关注后续文章