当前位置: 首页 > news >正文

厂里资讯之总体架构介绍以及环境搭建

本项目是本人根据黑马程序员的微服务项目黑马头条进行包装改造,作为实习简历上面的项目,为了进一步熟悉深挖这个项目,写了这一系列的博客来加深自己对项目的理解。

概述

项目背景

本项目主要着手于使用户获取学校最新最热的资讯,包括学校官方的相关告示,老师学术发布的相关内容,通过大数据分析用户喜好精准推送相关资讯。基于SpringCloud系列微服务组件,搭建微服务基础架构。项目开发层采用SpringBoot、SpringMVC、Mybatis开源框架实现。持久层采用:MySQL、Elasticsearch、 MongoDB进行存储。涉及到的中间件:Redis、RabbitMQ、并且搭建基于ELK日志分析平台。前端采用 uniapp,后台管理系统采用vue+ElementUI.

业务说明

系统架构

  • Spring-Cloud-Gateway : 微服务之前架设的网关服务,实现服务注册中的API请求路由,以及控制流速控制和熔断处理都是常用的架构手段,而这些功能Gateway天然支持

  • 运用Spring Boot快速开发框架,构建项目工程;并结合Spring Cloud全家桶技术,实现后端个人中心、自媒体、管理中心等微服务。

  • 运用Spring Cloud Alibaba Nacos作为项目中的注册中心和配置中心

  • 运用mybatis-plus作为持久层提升开发效率

  • 运用Kafka完成内部系统消息通知;与客户端系统消息通知;以及实时数据计算

  • 运用Redis缓存技术,实现热数据的计算,提升系统性能指标

  • 使用Mysql存储用户数据,以保证上层数据查询的高性能

  • 使用Mongo存储用户热数据,以保证用户热数据高扩展和高性能指标

  • 使用FastDFS作为静态资源存储器,在其上实现热静态资源缓存、淘汰等功能

  • 运用Hbase技术,存储系统中的冷数据,保证系统数据的可靠性

  • 运用ES搜索技术,对冷数据、文章数据建立索引,以保证冷数据、文章查询性能

  • 运用AI技术,来完成系统自动化功能,以提升效率及节省成本。比如实名认证自动化

  • PMD&P3C : 静态代码扫描工具,在项目中扫描项目代码,检查异常点、优化点、代码规范等,为开发团队提供规范统一,提升项目代码质量

环境搭建

nacos安装

①:docker拉取镜像

docker pull nacos/nacos-server:1.2.0

②:创建容器

docker run --env MODE=standalone --name nacos --restart=always  -d -p 8848:8848 nacos/nacos-server:1.2.0
  • MODE=standalone 单机版

  • --restart=always 开机启动

  • -p 8848:8848 映射端口

  • -d 创建一个守护式容器在后台运行

③:访问地址:http://192.168.200.130:8848/nacos

初始工程搭建

环境准备

①:项目依赖环境(需提前安装好)

  • JDK1.8

  • Intellij Idea

  • maven-3.6.1

  • Git

②:创建如下图所示的初始工程

③:IDEA开发工具配置

④:设置项目编码格式

主体结构

这里我就不专门画图了,结构于黑马头条是一样的。

登录

需求分析

  • 用户点击开始使用

    登录后的用户权限较大,可以查看,也可以操作(点赞,关注,评论)

  • 用户点击不登录,先看看

      ​ 游客只有查看的权限

表结构分析

关于app端用户相关的内容较多,可以单独设置一个库Information_user

表名称说明
ap_userAPP用户信息表
ap_user_fanAPP用户粉丝信息表
ap_user_followAPP用户关注信息表
ap_user_realnameAPP实名认证信息表

登录需要用到的是ap_user表,表结构如下:

项目中的持久层使用的mybatis-plus,一般都使用mybais-plus逆向生成对应的实体类

app_user表对应的实体类如下:

package com.changli.model.user.pojos;import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;import java.io.Serializable;
import java.util.Date;/*** <p>* APP用户信息表* </p>** @author itheima*/
@Data
@TableName("ap_user")
public class ApUser implements Serializable {private static final long serialVersionUID = 1L;/*** 主键*/@TableId(value = "id", type = IdType.AUTO)private Integer id;/*** 密码、通信等加密盐*/@TableField("salt")private String salt;/*** 用户名*/@TableField("name")private String name;/*** 密码,md5加密*/@TableField("password")private String password;/*** 手机号*/@TableField("phone")private String phone;/*** 头像*/@TableField("image")private String image;/*** 0 男1 女2 未知*/@TableField("sex")private Boolean sex;/*** 0 未1 是*/@TableField("is_certification")private Boolean certification;/*** 是否身份认证*/@TableField("is_identity_authentication")private Boolean identityAuthentication;/*** 0正常1锁定*/@TableField("status")private Boolean status;/*** 0 普通用户1 自媒体人2 大V*/@TableField("flag")private Short flag;/*** 注册时间*/@TableField("created_time")private Date createdTime;}

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

md5是不可逆加密,md5相同的密码每次加密都一样,不太安全。在md5的基础上手动加盐(salt)处理

注册->生成盐

登录->使用盐来配合验证

思路分析

1,用户输入了用户名和密码进行登录,校验成功后返回jwt(基于当前用户的id生成)

2,用户游客登录,生成jwt返回(基于默认值0生成)

用户端微服务搭建

在changli-lnformation-service下创建工程changli-Information-user

引导类

package com.changli.user;
​
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
​
@SpringBootApplication
@EnableDiscoveryClient
@MapperScan("com.heima.user.mapper")
public class UserApplication {
​public static void main(String[] args) {SpringApplication.run(UserApplication.class,args);}
}

bootstrap.yml

server:port: 51801
spring:application:name: leadnews-usercloud:nacos:discovery:server-addr: 192.168.200.130:8848config:server-addr: 192.168.200.130:8848file-extension: yml

在nacos中创建配置文件

spring:datasource:driver-class-name: com.mysql.jdbc.Driverurl: jdbc:mysql://localhost:3306/lnformation_user?useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTCusername: rootpassword: root
# 设置Mapper接口所对应的XML文件位置,如果你在Mapper接口中有自定义方法,需要进行该配置
mybatis-plus:mapper-locations: classpath*:mapper/*.xml# 设置别名包扫描路径,通过该属性可以给包中的类注册别名type-aliases-package: com.changli.model.user.pojos

logback.xml

<?xml version="1.0" encoding="UTF-8"?><configuration><!--定义日志文件的存储地址,使用绝对路径--><property name="LOG_HOME" value="e:/logs"/><!-- Console 输出设置 --><appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender"><encoder><!--格式化输出:%d表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度%msg:日志消息,%n是换行符--><pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern><charset>utf8</charset></encoder></appender><!-- 按照每天生成日志文件 --><appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender"><rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"><!--日志文件输出的文件名--><fileNamePattern>${LOG_HOME}/leadnews.%d{yyyy-MM-dd}.log</fileNamePattern></rollingPolicy><encoder><pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern></encoder></appender><!-- 异步输出 --><appender name="ASYNC" class="ch.qos.logback.classic.AsyncAppender"><!-- 不丢失日志.默认的,如果队列的80%已满,则会丢弃TRACT、DEBUG、INFO级别的日志 --><discardingThreshold>0</discardingThreshold><!-- 更改默认的队列的深度,该值会影响性能.默认值为256 --><queueSize>512</queueSize><!-- 添加附加的appender,最多只能添加一个 --><appender-ref ref="FILE"/></appender><logger name="org.apache.ibatis.cache.decorators.LoggingCache" level="DEBUG" additivity="false"><appender-ref ref="CONSOLE"/></logger><logger name="org.springframework.boot" level="debug"/><root level="info"><!--<appender-ref ref="ASYNC"/>--><appender-ref ref="FILE"/><appender-ref ref="CONSOLE"/></root>
</configuration>

登录功能实现

登录功能具体代码就不展示了,非常简单,太占篇幅了。

网关搭建

(1)在changli-lnformation-gateway导入以下依赖

pom文件

<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>

(2)在changli-Information-gateway下创建changli-lnformation-app-gateway微服务

引导类:

package com.changli.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);}
}

bootstrap.yml

​
server:port: 51601
spring:application:name: leadnews-app-gatewaycloud:nacos:discovery:server-addr: 192.168.200.130:8848config:server-addr: 192.168.200.130:8848file-extension: yml​

在nacos的配置中心创建dataid为lnformation-app-gateway的yml配置

spring:cloud:gateway:globalcors:add-to-simple-url-handler-mapping: truecorsConfigurations:'[/**]':allowedHeaders: "*"allowedOrigins: "*"allowedMethods:- GET- POST- DELETE- PUT- OPTIONroutes:# 平台管理- id: useruri: lb://leadnews-userpredicates:- Path=/user/**filters:- StripPrefix= 1

全局过滤器实现jwt校验

思路分析:

  1. 用户进入网关开始登陆,网关过滤器进行判断,如果是登录,则路由到后台管理微服务进行登录

  2. 用户登录成功,后台管理微服务签发JWT TOKEN信息返回给用户

  3. 用户再次进入网关开始访问,网关过滤器接收用户携带的TOKEN

  4. 网关过滤器解析TOKEN ,判断是否有权限,如果有,则放行,如果没有则返回未认证错误

具体实现:

第一:

​ 在认证过滤器中需要用到jwt的解析,所以需要把工具类拷贝一份到网关微服务

第二:

在网关微服务中新建全局过滤器:

package com.changli.app.gateway.filter;import com.heima.app.gateway.util.AppJwtUtil;
import io.jsonwebtoken.Claims;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.http.HttpStatus;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;@Component
@Slf4j
public class AuthorizeFilter implements Ordered, GlobalFilter {@Overridepublic Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {//1.获取request和response对象ServerHttpRequest request = exchange.getRequest();ServerHttpResponse response = exchange.getResponse();//2.判断是否是登录if(request.getURI().getPath().contains("/login")){//放行return chain.filter(exchange);}//3.获取tokenString 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*/@Overridepublic int getOrder() {return 0;}
}

相关文章:

  • PostgreSQL基础(十四):PostgreSQL的数据迁移
  • IT入门知识博客文章大纲(0/10)
  • Windows 11部署FunASR离线语音识别系统
  • iOS接入Flutter
  • 带侧边栏布局:带导航的网页
  • Cask ‘oraclexxx‘ is unavailable: No Cask with this name exists.
  • 如何完美解决升级 IntelliJ IDEA 最新版之后遇到 Git 记住密码功能失效的问题
  • Python语言例题集(015)
  • 【Go语言】Go语言中的接口类型
  • C++ 进制转换
  • Android11 后台启动Activity
  • 组合和外观模式
  • 「C系列」C 结构体
  • ZYNQ7 Processing System IP核中PS侧Uart的用法
  • Java课程设计:基于swing的贪吃蛇小游戏
  • Apache Zeppelin在Apache Trafodion上的可视化
  • CentOS从零开始部署Nodejs项目
  • CSS相对定位
  • Django 博客开发教程 16 - 统计文章阅读量
  • EventListener原理
  • IDEA 插件开发入门教程
  • JavaScript学习总结——原型
  • k8s 面向应用开发者的基础命令
  • k个最大的数及变种小结
  • Meteor的表单提交:Form
  • overflow: hidden IE7无效
  • Python爬虫--- 1.3 BS4库的解析器
  • react-native 安卓真机环境搭建
  • Yii源码解读-服务定位器(Service Locator)
  • 从零开始在ubuntu上搭建node开发环境
  • 官方新出的 Kotlin 扩展库 KTX,到底帮你干了什么?
  • 快速体验 Sentinel 集群限流功能,只需简单几步
  • 理清楚Vue的结构
  • 区块链将重新定义世界
  • 让你的分享飞起来——极光推出社会化分享组件
  • 算法-插入排序
  • 推荐一个React的管理后台框架
  • 一加3T解锁OEM、刷入TWRP、第三方ROM以及ROOT
  • 直播平台建设千万不要忘记流媒体服务器的存在 ...
  • ​ 无限可能性的探索:Amazon Lightsail轻量应用服务器引领数字化时代创新发展
  • ​​​【收录 Hello 算法】10.4 哈希优化策略
  • ​LeetCode解法汇总1276. 不浪费原料的汉堡制作方案
  • ​LeetCode解法汇总2696. 删除子串后的字符串最小长度
  • ​软考-高级-系统架构设计师教程(清华第2版)【第12章 信息系统架构设计理论与实践(P420~465)-思维导图】​
  • ​无人机石油管道巡检方案新亮点:灵活准确又高效
  • #{} 和 ${}区别
  • #mysql 8.0 踩坑日记
  • $.ajax()方法详解
  • (3)nginx 配置(nginx.conf)
  • (C#)一个最简单的链表类
  • (ctrl.obj) : error LNK2038: 检测到“RuntimeLibrary”的不匹配项: 值“MDd_DynamicDebug”不匹配值“
  • (STM32笔记)九、RCC时钟树与时钟 第二部分
  • (undone) MIT6.824 Lecture1 笔记
  • (WSI分类)WSI分类文献小综述 2024
  • (第30天)二叉树阶段总结