一、环境准备
1、环境搭建,查看Spring Cloud专栏
2、提供服务方准备一个接口供该使用服务方(OpenFeign)使用
二、OpenFeign使用:调用提供方服务的接口就是直接调用提供方服务的Http请求,跟调用本地方法一样。
1、pom依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
2、创建一个接口类,注意类上的注解“@FeignClient”和方法上的注解“@GetMapping”,类上注解“@FeignClient”的value值等于提供方注册到nacos中的名称,方法上的注解“@GetMapping”需要跟提供服务方一致和Url需要一致。
package com.cyun.security.oauth2.feign.server;
import com.cyun.core.vo.LoginUserVO;
import com.cyun.security.oauth2.feign.config.FeignSysUserConfiguration;
import com.cyun.security.oauth2.feign.config.FeignSysUserFallbackFactory;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
/**
* 系统服务 接口
*
* @author He PanFu
* @date 2022-03-12 10:50:02
*/
@FeignClient(value = "sys-server")
public interface IFeignSysUserService {
/**
* 获取登录用户信息
*
* @param username 用户名
* @param clientId 客户端标识
* @return 登录用户信息
*/
@GetMapping(value = "/sys_server/user/get/login/info")
LoginUserVO getLoginUserInfo(@RequestParam String username,
@RequestParam String clientId);
}
3、调用:直接调用IFeignSysUserService 服务的方法
package com.cyun.security.oauth2.service.impl;
import com.cyun.core.vo.LoginUserVO;
import com.cyun.security.oauth2.exception.RetryException;
import com.cyun.security.oauth2.feign.server.IFeignSysUserService;
import com.cyun.security.oauth2.service.AccountUserDetailsService;
import lombok.RequiredArgsConstructor;
import org.springframework.security.authentication.DisabledException;
import org.springframework.security.authentication.InternalAuthenticationServiceException;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
/**
* 账号服务
*
* @author He PanFu
* @date 2021-12-07 20:36:15
*/
@Service("accountDetailsServiceImpl")
@RequiredArgsConstructor
public class AccountDetailsServiceImpl implements AccountUserDetailsService {
private final IFeignSysUserService sysUserService;
/**
* 获取用户信息
*
* @param username 用户名
* @return 用户信息
* @throws UsernameNotFoundException 用户不存在
*/
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
final LoginUserVO loginUserVO = sysUserService.getLoginUserInfo(username, "test");
return new User(loginUserVO.getUsername(), loginUserVO.getPassword(), AuthorityUtils.createAuthorityList(loginUserVO.getAuthorities()));
}
}
三、服务降级处理:当提供方超时或者异常时,调用降级方法。
1、方式一:配置fallback
- 新增FeignSysUserFallback类,实现IFeignSysUserService接口
package com.cyun.security.oauth2.feign.config;
import com.cyun.core.vo.LoginUserVO;
import com.cyun.security.oauth2.feign.server.IFeignSysUserService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
/**
* 系统服务 服务降级
*
* @author He PanFu
* @date 2022-03-12 10:50:02
*/
@Component
@Slf4j
public class FeignSysUserFallback implements IFeignSysUserService {
@Override
public LoginUserVO getLoginUserInfo(String username, String clientId) {
log.error("获取用户登录信息失败,用户名:{},客户端标识:{}", username, clientId);
return null;
}
}
- @FeignClient注解上添加配置: fallback
@FeignClient(value = "sys-server", fallback = FeignSysUserFallback.class)
2、方式二:配置fallbackFactory,可以获取异常报错信息
- 新增FeignSysUserFallbackFactory类,实现FallbackFactory接口
package com.cyun.security.oauth2.feign.config;
import com.cyun.core.vo.LoginUserVO;
import com.cyun.security.oauth2.feign.server.IFeignSysUserService;
import feign.hystrix.FallbackFactory;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
/**
* 系统服务 服务降级(能得到错误信息)
*
* @author He PanFu
* @date 2022-03-12 10:50:02
*/
@Component
@Slf4j
public class FeignSysUserFallbackFactory implements FallbackFactory<IFeignSysUserService> {
@Override
public IFeignSysUserService create(Throwable throwable) {
log.error(throwable.getMessage(), throwable);
return new IFeignSysUserService() {
@Override
public LoginUserVO getLoginUserInfo(String username, String clientId) {
log.error("获取用户登录信息失败,用户名:{},客户端标识:{}", username, clientId);
return LoginUserVO.builder().failedFlag(true).build();
}
};
}
}
- @FeignClient注解上添加配置: fallbackFactory
@FeignClient(value = "sys-server", fallbackFactory = FeignSysUserFallbackFactory.class)
四、OpenFeign请求添加token,在请求头上添加内容
- 创建FeignSysUserConfiguration类实现RequestInterceptor接口
package com.cyun.security.oauth2.feign.config;
import com.cyun.tools.jwt.JwtUtil;
import feign.RequestInterceptor;
import feign.RequestTemplate;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.servlet.http.HttpServletRequest;
/**
* 系统服务 请求添加token
*
* @author He PanFu
* @date 2022-03-12 10:50:02
*/
@Configuration
public class FeignSysUserConfiguration implements RequestInterceptor {
@Override
public void apply(RequestTemplate requestTemplate) {
ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
HttpServletRequest request = attributes.getRequest();
//添加token
requestTemplate.header("Authorization", request.getHeader("Authorization"));
}
}
- @FeignClient注解上添加配置: configuration
@FeignClient(value = "sys-server", fallbackFactory = FeignSysUserFallbackFactory.class, configuration = FeignSysUserConfiguration.class)
五、问题总结
1、配置了(fallback)服务降级之后启动报错
解决方案:接口上不能添加@RequestMapper请求,去掉类上的@RequestMapper注解就能解决问题。参考链接
2、配置了(fallback)服务降级之后不生效
解决方案:查看依赖中是否依赖了Sentinel或Hystrix熔断框架,和是否配置了开启;
Sentinel:feign.sentinel.enabled=true
Hystrix:feign.hystrix.enabled=true