nacos
第一步,引入依赖
<dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId></dependency>
第二步,增加配置
spring:application:name: ordercloud:nacos:discovery:server-addr: localhost:8848
调用(手写一个负载均衡)
@RequestMapping("/hello")public String hello(){List<ServiceInstance> instances = discoveryClient.getInstances("user-service");ServiceInstance serviceInstance = instances.get(RandomUtil.randomInt(instances.size()));URI uri = serviceInstance.getUri();String url = uri + "/user-service/user/hello";log.info("调用地址:" + url);ResponseEntity<String> result = restTemplate.exchange(url, HttpMethod.GET, null,new ParameterizedTypeReference<String>() {},String.class);String msg = result.getBody();log.info("接口返回:" + msg);return msg;}
openfeign
1、引入依赖
<dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-openfeign</artifactId></dependency><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-loadbalancer</artifactId></dependency>
2、启动类上添加@EnableFeignClients
3、编写FeignClient
package com.niuniu.product.feignclient;import com.niuniu.product.model.Order;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;import java.util.List;@FeignClient(value = "order-service")
public interface OrderClient {@GetMapping(value = "/order-service/order/queryOrderByIds")List<Order> queryOrderByIds(@RequestParam("ids") List<String> ids);
}
4、调用
package com.niuniu.product.controller;import com.google.common.collect.Lists;
import com.niuniu.product.feignclient.OrderClient;
import com.niuniu.product.model.Order;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;import java.util.List;@RestController
@RequestMapping(value = "/product")
public class ProductController {@Autowiredprivate OrderClient orderClient;/*** 调用user-service* @return*/@RequestMapping("/testFeign")public List<Order> testFeign(){List<Order> orders = orderClient.queryOrderByIds(Lists.newArrayList("1", "2"));return orders;}
}
openfeign连接池
1、引入依赖
<!-- openfeign连接池 --><dependency><groupId>io.github.openfeign</groupId><artifactId>feign-okhttp</artifactId></dependency>
2、application.yml中开启
#openfeign连接池
feign:okhttp:enabled: true
3、debug查看效果
openfeign日志
openfeign有自己的日志级别
网关
1、引入依赖
<!-- 负载均衡 --><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-loadbalancer</artifactId></dependency><!--用于被nacos发现该服务 被gateway发现--><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId></dependency><!-- 网关 --><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-gateway</artifactId></dependency>
2、application.yaml配置
spring:application:name: gateway-servicecloud:nacos:discovery:server-addr: localhost:8848gateway:routes:- id: order-serviceuri: lb://order-servicepredicates:- Path=/order-service/**- id: product-serviceuri: lb://product-servicepredicates:- Path=/product-service/**- id: user-serviceuri: lb://user-servicepredicates:- Path=/user-service/**
server:port: 8080servlet:context-path: /gateway-service
注意:
如果直接访问product微服务的地址是http://localhost:8086/product-service/product/testFeign,
- Path=/product-service/**。
如果 直接访问product微服务的地址是http://localhost:8086/product/testFeign,(省略掉了微服务名称)
- Path=/product/**。
实现登录校验
配置管理
jwt登录功能
1、引入依赖
<dependency><groupId>io.jsonwebtoken</groupId><artifactId>jjwt</artifactId><version>0.9.1</version></dependency>
2、Jwt工具类
package com.niuniu.gateway.util;import io.jsonwebtoken.Jwt;
import io.jsonwebtoken.JwtBuilder;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;import java.util.Date;
import java.util.HashMap;
import java.util.Map;public class JWTUtil {/*** 密钥*/private static final String jwtToken = "niuniu";public static String createToken(Long userId) {Map<String, Object> claims = new HashMap<>();claims.put("userId", userId);JwtBuilder jwtBuilder = Jwts.builder().signWith(SignatureAlgorithm.HS256, jwtToken) // 签发算法,密钥为jwtToken.setClaims(claims) // body数据,要唯一,自行设置.setIssuedAt(new Date()) // 设置签发时间.setExpiration(new Date(System.currentTimeMillis() + 24 * 60 * 60 * 60 * 1000)); // 一天的有效时间String token = jwtBuilder.compact();return token;}public static Map<String, Object> checkToken(String token) {try {Jwt parse = Jwts.parser().setSigningKey(jwtToken).parse(token);return (Map<String, Object>) parse.getBody();} catch (Exception e) {e.printStackTrace();}return null;}/*** main方法验证一下工具类* @param args*/public static void main(String[] args) {String token = JWTUtil.createToken(1000L);System.out.println("生成的token" + token);System.out.println("解析token" + JWTUtil.checkToken(token));}}
3、登录,成功,返回token
@GetMapping("/login")public ResponseEntity login(@RequestParam(name = "name") String name, @RequestParam(name = "password") String password){// 1、参数是否合法if (StringUtil.isEmpty(name) || StringUtil.isEmpty(password)) {return ResponseEntity.ok("用户名或密码不能为空");}// 2、用户是否存在User user = userMapper.login(name, password);// 3、用户不存在,登录失败if (user == null) {return ResponseEntity.ok("用户不存在");}// 4、用户存在,使用jwt生成token返给前端String token = JWTUtil.createToken(user.getId());// 5、将token放入redisredisTemplate.opsForValue().set("token_" + user.getId(), token);return ResponseEntity.ok(token);}
jwt登录
1、用户登录,根据用户id生成token并返回给前端;
2、登录后的所有请求,都将token传递给后端;
3、后端拿到token,判断是否登录(把token转成用户id),登录是否失效(使用redis缓存)。
将登录的用户信息传递到微服务
1、登录生成token;
2、在gateway微服务里写一个过滤器,校验token。
校验通过,保存用户信息到请求头(将token转成用户id);
校验不通过,终止请求。
3、写拦截器从请求头中取出用户信息保存到ThreadLocal。(拦截器放到common模块,供所有需要的微服务引用)
4、在业务处理过程中就可以从ThreadLocal中取到用户信息。