自学内容网 自学内容网

【项目】黑马头条

目录结构

在这里插入图片描述
在这里插入图片描述

全局异常

在这里插入图片描述

登录手动加密(md5 + 随机字符串)

【问题】md5是不可逆加密,md5相同的密码每次加密都一样,不安全。
【解决】在md5的基础上手动加盐(salt)处理
在这里插入图片描述
校验过程:
在这里插入图片描述

接口测试

1. ApiFox中测试

2. swagger

  1. 引入依赖
<dependency>
    <groupId>io.springfox</groupId>
    <artifactId>springfox-swagger2</artifactId>
</dependency>
<dependency>
    <groupId>io.springfox</groupId>
    <artifactId>springfox-swagger-ui</artifactId>
</dependency>
  1. 在common模块下添加swagger配置类:
@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();
   }
}

由于其他model下的包名和common的包名不一样,为了让其他微服务可以扫描到这个配置类,需要在resources目录中添加该配置类的全类名:在这里插入图片描述

  1. swagger的常用注解
  • @Api:修饰整个类,描述Controller的作用
  • @ApiOperation:描述接口
  • @ApiModelProperty:描述属性

成功后启动项目,浏览器访问:http://localhost:51801/swagger-ui.html

3. knife4j(常用)

knife4j继承了swagger,功能比swagger更强大,也会生成接口文档

  1. 引入依赖
<dependency>
     <groupId>com.github.xiaoymin</groupId>
     <artifactId>knife4j-spring-boot-starter</artifactId>
</dependency>
  1. 在common中添加配置类:
@Configuration
@EnableSwagger2
@EnableKnife4j
@Import(BeanValidatorPluginsConfiguration.class)
public class Swagger2Configuration {

    @Bean(value = "defaultApi2")
    public Docket defaultApi2() {
        Docket docket=new Docket(DocumentationType.SWAGGER_2)
                .apiInfo(apiInfo())
                //分组名称
                .groupName("1.0")
                .select()
                //这里指定Controller扫描包路径
                .apis(RequestHandlerSelectors.basePackage("com.heima"))
                .paths(PathSelectors.any())
                .build();
        return docket;
    }
    private ApiInfo apiInfo() {
        return new ApiInfoBuilder()
                .title("黑马头条API文档")
                .description("黑马头条API文档")
                .version("1.0")
                .build();
    }
}

同样也需要在resources目录中添加该配置类的全类名
成功后启动项目,浏览器访问:http://host:port/doc.html

网关

1. 配置网关

一个父模块(heima-leadnews-gateway)下,放多个子模块(heima-leadnews-app-gateway)。
在这里插入图片描述

  1. 在父模块中引入依赖
<dependencies>
    <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>
    <dependency>
        <groupId>io.jsonwebtoken</groupId>
        <artifactId>jjwt</artifactId>
    </dependency>
</dependencies>
  1. 编写子模块的引导类
package com.heima.app.gateway;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;

@SpringBootApplication
@EnableDiscoveryClient  //开启注册中心
public class AppGatewayApplication {

    public static void main(String[] args) {
        SpringApplication.run(AppGatewayApplication.class,args);
    }
}
  1. 编写子模块的bootstrap.yml
server:
  port: 51601
spring:
  application:
    name: heima-leadnews-gateway
  cloud:
    nacos:
      discovery:
        server-addr: 192.168.140.102:8848
      config:
        server-addr: 192.168.140.102:8848
        file-extension: yml
  1. 在注册中心中引入子模块的配置
    在这里插入图片描述
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

2. 设置认证过滤器

@Component
public class AuthorizeFilter implements GlobalFilter, Ordered {
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        // 1. 获取request、response对象
        ServerHttpResponse response = exchange.getResponse();
        ServerHttpRequest request = exchange.getRequest();
        // 2. 判断是否是登录
        if(request.getURI().getPath().contains("/login")) {
            // 放行
            return chain.filter(exchange);
        }
        // 3. 获取token
        String token = request.getHeaders().getFirst("token");
        // 4. 判断token是否存在
        if(StringUtils.isBlank(token)) {
            // 拦截
            response.setStatusCode(HttpStatus.UNAUTHORIZED); // 返回401未授权
            return response.setComplete();
        }
        // 5. 判断token是否有效
        try {
            if(!AppJwtUtil.isValidToken(token)) {
            // token过期
            response.setStatusCode(HttpStatus.UNAUTHORIZED);
            return response.setComplete();
        }
        return chain.filter(exchange); // 放行
        }catch (Exception e) {
            response.setStatusCode(HttpStatus.UNAUTHORIZED);
            return response.setComplete(); // 抛异常,结束
        }
    }

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

认证过滤器用来拦截前端发过来的请求,写在网关里。

文章列表

表的拆分——垂直分表

在这里插入图片描述
将一个表的字段分散到多个表,每个表存储其中一部分字段

优势

  • 减少IO争抢,减少锁表的几率(查看文章信息与文章内容互不影响)
  • 充分发挥高频数据的操作效率,对文章信息操作的高频率不会被操作文章详情数据的低效率拖累。

拆分规则

  1. 把不常用的字段单独放在一张表
  2. 把text、blob等大字段拆分出来单独放在一张表
  3. 经常组合查询的字段单独放在一张表

文章详情

方案1. 直接查文章内容表

用户某一条文章,根据id去查询文章内容表,返回渲染页面
在这里插入图片描述

方案2. 静态模板展示(效率高)

在这里插入图片描述

把文章的内容变成静态的html文件,把生成之后的文件上传到minio中,并保存生成的html存入文章信息表中(static_url字段),前端渲染的时候,直接获取文章信息表的static_url字段,然后去minIO里获取静态访问页面即可。

Freemaker知识点:Freemarker模板引擎技术

持续更新中…


原文地址:https://blog.csdn.net/qq_57882997/article/details/145242891

免责声明:本站文章内容转载自网络资源,如侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!