搭建微服务各项功能所需配置
Eureka 服务端
-
依赖:
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId> </dependency> <dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>${spring-cloud.version}</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement>
-
注解:
@EnableEurekaServer
-
Eureka 客户端
-
依赖:
org.springframework.cloud spring-cloud-starter-netflix-eureka-client -
注解 :
@EnableEurekaClient
Ribbon,Hystrix,Feign 消费者端###
-
依赖:
<!-- TODO 重试机制 --> <dependency> <groupId>org.springframework.retry</groupId> <artifactId>spring-retry</artifactId> </dependency> <!-- TODO Hystrix熔断器 --> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-hystrix</artifactId> </dependency> <!-- TODO Feign服务调用 --> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-openfeign</artifactId> </dependency>
-
添加注解:
@EnableEurekaClient //开启Eureka客户端 @EnableHystrix //开启熔断器 @EnableFeignClients //开启Feign远程调用服务
如果使用 Feign 技术,那么 Hystrix 不需要导包和加注解
Zuul 网关依赖
-
依赖:
<!-- TODO 重试机制 --> <dependency> <groupId>org.springframework.retry</groupId> <artifactId>spring-retry</artifactId> </dependency> <!-- TODO zuul网管依赖 --> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-zuul</artifactId> </dependency> <!-- TODO Eureka的客户端依赖--> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> </dependency>
-
yml 配置文件:
server: port: 10400 spring: application: name: zuul-service eureka: client: registry-fetch-interval-seconds: 5 # 获取服务列表的周期:5s service-url: defaultZone: http://127.0.0.1:10300/eureka instance: prefer-ip-address: true ip-address: 127.0.0.1 zuul: retryable: true # 开启重试机制 # routes: # user-service: # 这里是路由id,随意写 # path: /user-service/** # 这里是映射路径 # service-id: user-service # 指定服务名称 # 不用添加routes,就会自动匹配 映射Eureka注册中的服务 ribbon: ConnectTimeout: 250 # 连接超时时间(ms) ReadTimeout: 2000 # 通信超时时间(ms) OkToRetryOnAllOperations: true # 是否对所有操作重试 MaxAutoRetriesNextServer: 2 # 同一服务不同实例的重试次数 MaxAutoRetries: 1 # 同一实例的重试次数 hystrix: command: default: execution: isolation: thread: timeoutInMillisecond: 6000 # 熔断超时时长:6000ms zuul: # 解决zuulfilter 中header头部信息丢失问题 sensitiveHeaders:
-
如果使用 Zuul,就替换了 consumer 消费者。并且 Zuul 中集成了各种依赖
JWT 配置
单独配置:key 密钥写在 java 代码中
-
JWT 定义在 Zuul 网关中,用来拦截请求,处理请求权限。
-
依赖:
<!-- TODO jwt鉴权依赖 --> <dependency> <groupId>io.jsonwebtoken</groupId> <artifactId>jjwt</artifactId> </dependency> <!-- https://mvnrepository.com/artifact/joda-time/joda-time --> <dependency> <groupId>joda-time</groupId> <artifactId>joda-time</artifactId> </dependency>
-
JWTUtil 工具类:
/** * @ClassName: JwtHelper * @Description: token工具类 * @author: yuanxinqi * @date: 2018/8/17 9:59 * @version: V 2.0.0 * @since: (jdk_1.8) */ public class JWTUtils { /** * 获取token中的参数 * * @param token * @return */ public static Claims parseToken(String token,String key) { if ("".equals(token)) { return null; } try { return Jwts.parser() .setSigningKey(DatatypeConverter.parseBase64Binary(key)) .parseClaimsJws(token).getBody(); } catch (Exception ex) { return null; } } /** * 生成token * * @param userId * @return */ public static String createToken(Integer userId,String username,String key, int expireMinutes) { SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.HS256; //生成签名密钥 byte[] apiKeySecretBytes = DatatypeConverter.parseBase64Binary(key); Key signingKey = new SecretKeySpec(apiKeySecretBytes, signatureAlgorithm.getJcaName()); //添加构成JWT的参数 JwtBuilder builder = Jwts.builder() // .setHeaderParam("type", "JWT") // .setSubject(userId.toString()) .claim("userId", userId) // 设置载荷信息 .claim("username",username) .claim("age",23) .setExpiration(DateTime.now().plusMinutes(expireMinutes).toDate())// 设置超时时间 .signWith(signatureAlgorithm, signingKey); //生成JWT return builder.compact(); } public static void main(String[] args) { String token = JWTUtils.createToken(1, "zhangsan","admin", 30); System.out.println(token); Claims claims = JWTUtils.parseToken(token, "admin"); System.out.println(claims); } }
yml 文件中配置 key 密钥:
-
JWTUtils 工具类:
/** * @ClassName: JwtHelper * @Description: token工具类 * @author: yuanxinqi * @date: 2018/8/17 9:59 * @version: V 2.0.0 * @since: (jdk_1.8) */ @ConfigurationProperties("jwt.config") public class JWTUtils { private String key; public String getKey() { return key; } public void setKey(String key) { this.key = key; } /** * 获取token中的参数 * * @param token * @return */ public Claims parseToken(String token) { if ("".equals(token)) { return null; } try { return Jwts.parser() .setSigningKey(DatatypeConverter.parseBase64Binary(key)) .parseClaimsJws(token).getBody(); } catch (Exception ex) { return null; } } /** * 生成token * * @param id * @return */ public String createToken(String id ,String role , int expireMinutes) { SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.HS256; //生成签名密钥 byte[] apiKeySecretBytes = DatatypeConverter.parseBase64Binary(key); Key signingKey = new SecretKeySpec(apiKeySecretBytes, signatureAlgorithm.getJcaName()); //添加构成JWT的参数 JwtBuilder builder = Jwts.builder() // .setHeaderParam("type", "JWT") // .setSubject(userId.toString()) .claim("id", id) // 设置载荷信息 .claim("role",role) .setExpiration(DateTime.now().plusMinutes(expireMinutes).toDate())// 设置超时时间 .signWith(signatureAlgorithm, signingKey); //生成JWT return builder.compact(); } }
-
在需要调用 JWTUtils 的服务中配置文件 yml:
jwt: config: key: tensquare
-
在 application 启动类中进行注册:
@Bean public JWTUtils jwtUtils(){ return new JWTUtils(); }
-
在 controller 中进行调用时,
@Autowired private JWTUtils jwtUtils;
Zuul 中 token 过滤器配置
- 在 Zuul 服务中,定义 JWTFilter 类,添加 @conponent 注解,继承 ZuulFilter,实现四个方法。
@Component
public class JWTFilter extends ZuulFilter {
@Override
public String filterType() {
//TODO 返回pre 表示请求前进行 过滤
// pre请求前 route路由请求时 post在route和error过滤器之后调用 error处理请求时发生错误时
return "pre";
}
@Override
public int filterOrder() {
//TODO 顺序排名
return 1;
}
@Override
public boolean shouldFilter() {
//TODO 是否执行
return true;
}
@Override
public Object run() throws ZuulException {
RequestContext context = RequestContext.getCurrentContext();
HttpServletRequest request = context.getRequest();
String url = request.getRequestURL().toString();
//发布和查看个人信息等,才进行拦截判断
if (url.contains("/user/findByUsername") || url.contains("/user/uploadImg")
|| url.contains("/user/updatePassword") || url.contains("/user/updatePasswordBefore")){
//进行拦截判断
String token = request.getHeader("authorization");
//解析
Claims claims = JWTUtils.parseToken(token, "user");
if (claims == null){
// 10 拦截
context.setSendZuulResponse(false);
context.setResponseStatusCode(401);
context.setResponseBody("{'msg':'校验失败'}");
context.getResponse().setContentType("text/html;charset=utf-8");// 不设置的话,中文乱码
return null;
}
}
return null;
}
}
zuul 中的熔断返回类
- Zuul 中默认是开启了 熔断机制的。只需配置好 yml 中的重试机制。
- 在 Zuul 服务中,添加熔断返回类,如果 Zuul 中发生熔断,就会返回 FallBack 中的值。
@Component
public class ZuulFallBack implements FallbackProvider {
@Override
public String getRoute() {
return "*";
}
@Override
public ClientHttpResponse fallbackResponse(String route, Throwable cause) {
return new ClientHttpResponse() {
@Override
public HttpStatus getStatusCode() throws IOException {
return HttpStatus.OK;
}
@Override
public int getRawStatusCode() throws IOException {
return this.getStatusCode().value();
}
@Override
public String getStatusText() throws IOException {
return this.getStatusCode().getReasonPhrase();
}
@Override
public void close() {
}
@Override
public InputStream getBody() throws IOException {
//返回的内容,在此中书写
return new ByteArrayInputStream("当前服务暂时不可用,喝杯咖啡冷静一下吧~~~".getBytes());
}
@Override
public HttpHeaders getHeaders() {
HttpHeaders headers = new HttpHeaders();
MediaType mt = new MediaType("application", "json", Charset.forName("UTF-8"));
headers.setContentType(mt);
return headers;
}
};
}
}
欢迎来到这里!
我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。
注册 关于