SpringCloudはFeignによるサービス間呼び出しスレッド変数転送を実現
18550 ワード
前言
プロジェクトを開発する過程で、登録された情報を一つのサービスから別のサービスに伝達するなど、サービスにまたがっていくつかのデータを伝送する必要があることが多い.この場合、既存のコードをできるだけ少なく動かす必要があり、プログラミングのパッケージ思想をより体現している. SpringCloudはdubboのようにサービス間呼び出しの際に自身のスレッド変数で転送されるわけではないが、SpringCloudはそれ自体のメカニズムで実現をサポートできるに違いないという考えから、このブログがあった.
実現構想.スレッド間で を共有するためのThreadLoad変数を準備する各サービスは、すべてのFeign呼び出しをフィルタリングし、要求ヘッダからユーザ情報を取得し、ThreadLocal変数の が存在する.各サービスは、FeignClientを使用して他のサービスを呼び出す際に、まずThreadLocal変数からユーザ情報を取り出し、Feginのrequest要求ヘッダに を置く.は1つの注釈をカプセル化し、起動クラスに をマークすることができる.
キーコード
1、ThreadLocalツール類
2、ユーザー情報エンティティクラス
3、FeignClientブロッキング
4、Filterフィルタ
5、カスタム注釈
6、カスタム注釈実装クラス
7、起動クラスにカスタム注釈をマークする
プロジェクトを開発する過程で、登録された情報を一つのサービスから別のサービスに伝達するなど、サービスにまたがっていくつかのデータを伝送する必要があることが多い.この場合、既存のコードをできるだけ少なく動かす必要があり、プログラミングのパッケージ思想をより体現している. SpringCloudはdubboのようにサービス間呼び出しの際に自身のスレッド変数で転送されるわけではないが、SpringCloudはそれ自体のメカニズムで実現をサポートできるに違いないという考えから、このブログがあった.
実現構想.
キーコード
1、ThreadLocalツール類
public class UserContext {
// , ,
private static ThreadLocal<User> userInfo = new ThreadLocal<User>();
// request
public static String KEY_USER_IN_HTTP_HEADER = "X-AUTO-FP-USER";
public UserContext() {
}
public static User getUser(){
return (User)user.get();
}
public static void setUser(User user){
user.set(user);
}
}
2、ユーザー情報エンティティクラス
/**
* @author
* @DESCRIPTION
* @create 2019/3/28
*/
@Data
public class User {
/**
* id
*/
private String id;
/**
*
*/
private String userCode;
/**
*
*/
private String userName;
/**
* id
*/
private String companyId;
/**
* token
*/
private String token;
/**
* id
*/
private String roleId;
/**
*
* qq
*/
private String qqOpenId;
/**
*
*
*/
private String weChatOpenId;
/**
*
*
*/
private String wxPlantForm;
}
3、FeignClientブロッキング
public class TransmitUserFeighClientIntercepter implements RequestInterceptor {
private static final Logger log = LoggerFactory.getLogger(TransmitUserFeighClientIntercepter.class);
public TransmitUserFeighClientIntercepter() {
}
@Override
public void apply(RequestTemplate requestTemplate) {
// user , Feign
User user = UserContext.getUser();
if (user != null) {
try {
String userJson = JSON.toJSONString(user);
requestTemplate.header("KEY_USER_IN_HTTP_HEADER",new String[]{URLDecoder.decode(userJson,"UTF-8")});
} catch (UnsupportedEncodingException e) {
log.error(" ",e);
}
}
}
}
4、Filterフィルタ
public class TransmitUserFilter implements Filter {
private static final Logger log = LoggerFactory.getLogger(TransmitUserFeighClientIntercepter.class);
public TransmitUserFilter() {
}
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
this.initUserInfo((HttpServletRequest)request);
chain.doFilter(request,response);
}
private void initUserInfo(HttpServletRequest request){
String userJson = request.getHeader("KEY_USER_IN_HTTP_HEADER");
if (StringUtils.isNotBlank(userJson)) {
try {
userJson = URLDecoder.decode(userJson,"UTF-8");
User userInfo = (User) JSON.parseObject(userJson,UserInfo.class);
//
UserContext.setUser(user);
} catch (UnsupportedEncodingException e) {
log.error("init userInfo error",e);
}
}
}
@Override
public void destroy() {
}
}
5、カスタム注釈
@Documented
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Import({EnableUserTransmitterAutoConfiguration.class})
public @interface EnableUserTransmitter {
}
6、カスタム注釈実装クラス
@Configuration
public class EnableUserTransmitterAutoConfiguration {
public EnableUserTransmitterAutoConfiguration() {
}
@Bean
public TransmitUserFeighClientIntercepter transmitUser2FeighHttpHeader(){
return new TransmitUserFeighClientIntercepter();
}
@Bean
public TransmitUserFilter transmitUserFromHttpHeader(){
return new TransmitUserFilter();
}
}
7、起動クラスにカスタム注釈をマークする