标签:interface enc orm pat inf public should 通信 common
微服务的本质是一系列分布式REST API的集合,因此,各服务间最常用的通信协议为HTTP协议。诚然,通过传统的写URL进行调用的方式当然可以,但未免不够优雅。而通过使用Feign,可以做到像调用本地服务一样优雅地调用远程服务。
开发目标是在Zuul中实现一个基础的过滤器,对所有经过Zuul的请求进行过滤,获取其中的Token并校验其合法性。其中,校验Token合法性的动作需要与user-service进行交互,此处通过Feign来实现。
引入依赖:
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-openfeign</artifactId> <version>2.2.2.RELEASE</version> </dependency>
在Zuul工程中定义如下接口:
package com.aac.acoustics.api.platform.zuul.feign; import com.aac.acoustics.api.platform.zuul.fallback.UserServiceFallbackProvider; import org.springframework.cloud.openfeign.FeignClient; import org.springframework.stereotype.Component; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RequestParam; /** * 用户服务请求Feign */ @FeignClient(name = "user-service") @Component public interface UserServiceFeign { @RequestMapping(value = "/token/validate",method = RequestMethod.POST) boolean validate(@RequestParam(value = "username") String username,@RequestParam(value = "token") String token); }
无需实现该接口。@FeignClient注解参数中的“name”填写目标服务的名称,@RequestMapping注解参数中value填写服务的控制器path,即可完成调用。此处在接口上加入了@Component组件将其声明为Spring Bean,这样就可以在其他地方进行注入调用:
package com.aac.acoustics.api.platform.zuul.filter; import com.aac.acoustics.api.platform.common.utils.ExceptionMsg; import com.aac.acoustics.api.platform.common.utils.ResponseData; import com.aac.acoustics.api.platform.zuul.feign.UserServiceFeign; import com.netflix.hystrix.exception.HystrixRuntimeException; import com.netflix.zuul.ZuulFilter; import com.netflix.zuul.context.RequestContext; import com.netflix.zuul.exception.ZuulException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.stereotype.Component; import org.springframework.util.StringUtils; import javax.servlet.http.HttpServletRequest; /** * 身份验证过滤器 */ @Component public class AuthFilter extends ZuulFilter { private static final Logger logger = LoggerFactory.getLogger(AuthFilter.class); private final UserServiceFeign userServiceFeign; public AuthFilter(UserServiceFeign userServiceFeign) { this.userServiceFeign = userServiceFeign; } @Override public String filterType() { return "pre"; } @Override public int filterOrder() { return 3; } @Override public boolean shouldFilter() { return true; } @Override public Object run() throws ZuulException { logger.info("进入身份验证"); RequestContext ctx = RequestContext.getCurrentContext(); HttpServletRequest request = ctx.getRequest(); String path = request.getServletPath(); boolean needValidate = true; boolean validatePass = false; if(path.contains("/token") && request.getMethod().equals("GET")){ logger.info("获取Token动作,放行"); needValidate = false; validatePass = true; } if(needValidate){ String username = request.getParameter("username"); logger.info("username = "+username); String token = request.getParameter("token"); logger.info("token = "+token); if(!StringUtils.isEmpty(username) && !StringUtils.isEmpty(token)) { try { validatePass = userServiceFeign.validate(username, token); if(!validatePass){ logger.info("验证不通过"); ResponseData responseData = new ResponseData(ExceptionMsg.FORBIDDEN); ctx.setSendZuulResponse(false); ctx.setResponseBody(responseData.toJsonString()); }else { ctx.set("logic-is-success", true); } }catch (HystrixRuntimeException e) { logger.info("服务不可用"); ResponseData responseData = new ResponseData(ExceptionMsg.SERVICE_UNAVAILABLE); ctx.setSendZuulResponse(false); ctx.setResponseBody(responseData.toJsonString()); } } } return null; } }
这里通过一个构造器注入的模式将Feign Bean注入到过滤器中,而后就可以像调用本地服务一样调用远程服务。
Feign的降级处理:
当远端服务不可用时,需要在本地执行服务降级操作。此操作只需在上述@Feign注解中指定fallback的降级处理类即可:
package com.aac.acoustics.api.platform.zuul.fallback; import com.aac.acoustics.api.platform.zuul.feign.UserServiceFeign; import org.springframework.stereotype.Component; /** * 接口服务不可用时的降级处理 * @author Rachel */ @Component public class UserServiceFallbackProvider implements UserServiceFeign { @Override public boolean validate(String username, String token) { return false; } }
标签:interface enc orm pat inf public should 通信 common
原文地址:https://www.cnblogs.com/liuxiaopen1995/p/13820589.html