微服务项目收获和总结---第1天(JWT,Docker,Nacos,Gateway)

①异常处理

②集成Swagger

引入依赖:

java 复制代码
        <dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-swagger2</artifactId>
        </dependency>
        <dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-swagger-ui</artifactId>
        </dependency>

配置Swagger信息:

java 复制代码
@Configuration
@EnableSwagger2
public class SwaggerConfiguration {

   @Bean
   public Docket buildDocket() {
      return new Docket(DocumentationType.SWAGGER_2)
              .apiInfo(buildApiInfo())
              .select()
              // 要扫描的API(Controller)基础包
              .apis(RequestHandlerSelectors.basePackage("com.heima"))
              .paths(PathSelectors.any())
              .build();
   }

   private ApiInfo buildApiInfo() {
      Contact contact = new Contact("黑马程序员","","");
      return new ApiInfoBuilder()
              .title("黑马头条-平台管理API文档")
              .description("黑马头条后台api")
              .contact(contact)
              .version("1.0.0").build();
   }
}

③JWT令牌生成Token

java 复制代码
package com.heima.utils.common;

import io.jsonwebtoken.*;

import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import java.util.*;

public class AppJwtUtil {

    // TOKEN的有效期一天(S)
    private static final int TOKEN_TIME_OUT = 3_600;
    // 加密KEY
    private static final String TOKEN_ENCRY_KEY = "MDk4ZjZiY2Q0NjIxZDM3M2NhZGU0ZTgzMjYyN2I0ZjY";
    // 最小刷新间隔(S)
    private static final int REFRESH_TIME = 300;

    // 生产ID
    public static String getToken(Long id){
        Map<String, Object> claimMaps = new HashMap<>();
        claimMaps.put("id",id);
        long currentTime = System.currentTimeMillis();
        return Jwts.builder()
                .setId(UUID.randomUUID().toString())
                .setIssuedAt(new Date(currentTime))  //签发时间
                .setSubject("system")  //说明
                .setIssuer("heima") //签发者信息
                .setAudience("app")  //接收用户
                .compressWith(CompressionCodecs.GZIP)  //数据压缩方式
                .signWith(SignatureAlgorithm.HS512, generalKey()) //加密方式
                .setExpiration(new Date(currentTime + TOKEN_TIME_OUT * 1000))  //过期时间戳
                .addClaims(claimMaps) //cla信息
                .compact();
    }

    /**
     * 获取token中的claims信息
     *
     * @param token
     * @return
     */
    private static Jws<Claims> getJws(String token) {
            return Jwts.parser()
                    .setSigningKey(generalKey())
                    .parseClaimsJws(token);
    }

    /**
     * 获取payload body信息
     *
     * @param token
     * @return
     */
    public static Claims getClaimsBody(String token) {
        try {
            return getJws(token).getBody();
        }catch (ExpiredJwtException e){
            return null;
        }
    }

    /**
     * 获取hearder body信息
     *
     * @param token
     * @return
     */
    public static JwsHeader getHeaderBody(String token) {
        return getJws(token).getHeader();
    }

    /**
     * 是否过期
     *
     * @param claims
     * @return -1:有效,0:有效,1:过期,2:过期
     */
    public static int verifyToken(Claims claims) {
        if(claims==null){
            return 1;
        }
        try {
            claims.getExpiration()
                    .before(new Date());
            // 需要自动刷新TOKEN
            if((claims.getExpiration().getTime()-System.currentTimeMillis())>REFRESH_TIME*1000){
                return -1;
            }else {
                return 0;
            }
        } catch (ExpiredJwtException ex) {
            return 1;
        }catch (Exception e){
            return 2;
        }
    }

    /**
     * 由字符串生成加密key
     *
     * @return
     */
    public static SecretKey generalKey() {
        byte[] encodedKey = Base64.getEncoder().encode(TOKEN_ENCRY_KEY.getBytes());
        SecretKey key = new SecretKeySpec(encodedKey, 0, encodedKey.length, "AES");
        return key;
    }

}

④Docker拉取Nacos

bash 复制代码
docker pull nacos/nacos-server:1.2.0
java 复制代码
docker run --env MODE=standalone --name nacos 
--restart=always  -d -p 8848:8848 nacos/nacos-server:1.2.0

⑤服务注册中心和配置中心(Nacos)

引入依赖:

java 复制代码
        //Nacos服务依赖
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
        </dependency>
        //Nacos配置依赖
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
        </dependency>

bootstrap.yml:

java 复制代码
server:
  port: 51801  #配置端口
spring:
  application:
    name: leadnews-user    #服务名称
  cloud:
    nacos:
      discovery:
        server-addr: 192.168.136.132:8848    #Nacos服务中心地址
      config:
        server-addr: 192.168.136.132:8848    #Nacos配置中心地址
        file-extension: yml

Nacos配置中心文件:

java 复制代码
spring:
  #配置数据库
  datasource:
    driver-class-name: com.mysql.jdbc.Driver
    url: jdbc:mysql://localhost:3306/leadnews_user
    username: root
    password: root
# 设置Mapper接口所对应的XML文件位置,如果你在Mapper接口中有自定义方法,需要进行该配置
mybatis-plus:
  mapper-locations: classpath*:mapper/*.xml
  # 设置别名包扫描路径,通过该属性可以给包中的类注册别名
  type-aliases-package: com.heima.model.user.pojos

⑥Gateway

引入依赖:

java 复制代码
<!--        gateway依赖-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-gateway</artifactId>
        </dependency>
<!--        服务注册和配置中心的依赖-->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
        </dependency>
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
        </dependency>

bootstrap.yml(网关也是服务):

java 复制代码
server:
  port: 51601
spring:
  application:
    name: leadnews-app-gateway
  cloud:
    nacos:
      discovery:
        server-addr: 192.168.136.132:8848
      config:
        server-addr: 192.168.136.132:8848
        file-extension: yml

配置中心:

java 复制代码
spring:
  cloud:
    gateway:
      globalcors:
        add-to-simple-url-handler-mapping: true
        corsConfigurations:
          '[/**]':
            allowedHeaders: "*"
            allowedOrigins: "*"
            allowedMethods:
              - GET
              - POST
              - DELETE
              - PUT
              - OPTION
      routes:
        # 平台管理
        - id: user
          uri: lb://leadnews-user
          predicates:
            - Path=/user/**
          filters:
            - StripPrefix= 1

启动类:

java 复制代码
@SpringBootApplication
@EnableDiscoveryClient
public class AppGatewayApplication {
    public static void main(String[] args) {
        SpringApplication.run(AppGatewayApplication.class);
    }
}

网关路由过滤:

java 复制代码
@Component
@Slf4j
public class AuthorizeFilter implements Ordered , GlobalFilter {

    /**
     *处理请求
     * @param exchange
     * @param chain
     * @return
     */
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {

        //1.获取Request和Respose对象
        ServerHttpRequest request = exchange.getRequest();
        ServerHttpResponse response = exchange.getResponse();

        //2.判断是否是登录
        if(request.getURI().getPath().contains("/login")){
            //放行
            System.out.println("放行");
            return chain.filter(exchange);
        }

        //3.获取Token
        String token = request.getHeaders().getFirst("token");

        //4.判断Token是否存在
        if(StringUtils.isBlank(token)){
            response.setStatusCode(HttpStatus.UNAUTHORIZED);
            return response.setComplete();
        }

        //5.判断Token是否有效
        try {
            Claims claimsBody = AppJwtUtil.getClaimsBody(token);
            int result = AppJwtUtil.verifyToken(claimsBody);
            if(result == 1 || result == 2){
                response.setStatusCode(HttpStatus.UNAUTHORIZED);
                return response.setComplete();
            }
        }catch (Exception e){
            e.printStackTrace();
            response.setStatusCode(HttpStatus.UNAUTHORIZED);
            return response.setComplete();
        }

        //6.放行
        return chain.filter(exchange);
    }

    /**
     * 优先级设置,值越小,优先级越高
     * @return
     */
    @Override
    public int getOrder() {
        return 0;
    }
}

⑦第一天总结:

第一天也是我第一次做微服务的项目,今天真实的把理论知识动手实践了,很兴奋,实现了nacos的服务配置和网关的配置过滤,接下来再接再厉。

相关推荐
草字2 分钟前
uniapp input限制输入负数,以及保留小数点两位.
java·前端·uni-app
李迟3 分钟前
某Linux发行版本无法使用nodejs程序重命名文件问题的研究
java·linux·服务器
MapleLea1f15 分钟前
26届JAVA 学习日记——Day14
java·开发语言·学习·tcp/ip·程序人生·学习方法
没有黑科技21 分钟前
基于web的音乐网站(Java+SpringBoot+Mysql)
java·前端·spring boot
爪哇学长23 分钟前
解锁API的无限潜力:RESTful、SOAP、GraphQL和Webhooks的应用前景
java·开发语言·后端·restful·graphql
xiangshangdemayi31 分钟前
Windows环境GeoServer打包Docker极速入门
windows·docker·容器·geoserver·打包·数据挂载
刘大浪35 分钟前
IDEA 2024安装指南(含安装包以及使用说明 cannot collect jvm options 问题 四)
java
Cod_Next41 分钟前
Mac系统下配置 Tomcat 运行环境
java·macos·tomcat
小白不太白9501 小时前
设计模式之建造者模式
java·设计模式·建造者模式
p-knowledge1 小时前
建造者模式(Builder Pattern)
java·开发语言·建造者模式