- 個人主頁:VON
- 文章所屬專欄:黑馬頭條
- 個人唯一微信:微信
有一起學習微服務的小伙伴可以加作者微信:單擊即可添加
目錄
一、前言
二、項目概述
1、技術棧
2、項目引入
三、改造項目
1、創建heima-leadnews-user
2、創建實體類
3、改造heima-leadnews-user
(1)UserApplication引導類
(2)bootstrap.yml配置文件
(3)nacos配置
(4)logback.xml
4、功能實現
(1)controller層
(2)service層
(3)mapper層
(4)接口測試工具
四、網關
1、創建heima-leadnews-app-gateway
2、改造模塊
(1)實體類
(2)bootstrap.yml配置文件
(3)nacos配置
(4)配置過濾器
3、部署前端項目
(1)創建存放conf的目錄
(2)創建APP端conf
(3)改造conf文件
(4)改造原本的conf文件
4、測試
結語
一、前言
歷時2552分鐘將黑馬商城項目拆分完畢,上述是學習時間表,黑馬商城項目的更新先暫停一下,因為后續大都是知識點了,幾乎也沒有代碼部分的東西了。另一方面也是因為快開學了,所以我還是想學點有關代碼的知識,因此從今天開始學習黑馬頭條。
計劃開學前將黑馬頭條完結,昨天其實已經開始了,只不過配置環境有點復雜,我這里大都是用的之前下載好的軟件,并沒有嚴格對標課程。本系列不再講解有關環境配置方面的問題,如果有疑問就去直接看視頻或者是看之前的文章就行。
廢話不多說我就簡單總結回顧一下我感覺有用的一些知識點。
特別聲明:本系列所涉及資料皆為黑馬程序員課程中的資料
二、項目概述
1、技術棧
這里是用到的相關技術,了解一下即可,后續都會有講解
- 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 : 靜態代碼掃描工具,在項目中掃描項目代碼,檢查異常點、優化點、代碼規范等,為開發團隊提供規范統一,提升項目代碼質量
2、項目引入
將資料中的項目拷貝到本地
這里說明一下,我拷貝的時候并沒有log文件,需要自己創建出來,和其他模塊同級別創建即可,下面會有一個地方需要改動,等會再說
這里的版本改成我這樣就不會報錯了
這兩個別忘了啟動,數據庫中表的導入我就不多說了
這里的數據庫也可以換成本地數據庫
jdk全部換成1.8
編碼全部改為utf-8
這里換成資料中的倉庫就不用再下載其他依賴了,特別方便建議改一下,當然不改也沒事
三、改造項目
上述準備工作完成后就開始改造項目了
1、創建heima-leadnews-user
要看好位置再創建,創建完成后按照我的目錄結構創建相應的包結構
一定不要放錯位置
2、創建實體類
一定要看好位置再創建
package com.heima.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;}
3、改造heima-leadnews-user
(1)UserApplication引導類
package com.heima.user;import org.mybatis.spring.annotation.MapperScan;
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) {org.springframework.boot.SpringApplication.run(UserApplication.class, args);}
}
(2)bootstrap.yml配置文件
這里的addr換成自己的nacos地址,也就是運行nacos的虛擬機地址+端口號
server:port: 51801
spring:application:name: leadnews-usercloud:nacos:discovery:server-addr: 192.168.73.134:8848config:server-addr: 192.168.73.134:8848file-extension: yml
(3)nacos配置
為了防止重復配置所以將公共部分抽取到nacos中了,有不會配置的參考下這篇文章👇
重生之我在暑假學習微服務第十一天《配置篇》+網關篇錯誤訂正
spring:datasource:driver-class-name: com.mysql.jdbc.Driverurl: jdbc:mysql://localhost:3306/leadnews_user?useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC&useSSL=falseusername: rootpassword: 123456
# 設置Mapper接口所對應的XML文件位置,如果你在Mapper接口中有自定義方法,需要進行該配置
mybatis-plus:mapper-locations: classpath*:mapper/*.xml# 設置別名包掃描路徑,通過該屬性可以給包中的類注冊別名type-aliases-package: com.heima.model.user.pojos
(4)logback.xml
還記得上文提到的日志嗎,這里改成./logs就行,將日志放在此文件夾下
<?xml version="1.0" encoding="UTF-8"?><configuration><!--定義日志文件的存儲地址,使用絕對路徑--><property name="LOG_HOME" value="./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>
4、功能實現
這里就是一個簡單的登錄功能的實現,就按照123的順序講解了
(1)controller層
這里我畫住的地方先不用寫,這是用來測試的接口工具
這里要引入一個實體類
實體類代碼👇
package com.heima.model.user.dtos;import lombok.Data;@Data
public class LoginDto {//手機號private String phone;//密碼private String password;
}
(2)service層
實現類👇
一定要放好位置,位置千萬不要錯了
package com.heima.model.common.dtos;import com.alibaba.fastjson.JSON;
import com.heima.model.common.enums.AppHttpCodeEnum;import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;/*** 通用的結果返回類* @param <T>*/
public class ResponseResult<T> implements Serializable {private String host;private Integer code;private String errorMessage;private T data;public ResponseResult() {this.code = 200;}public ResponseResult(Integer code, T data) {this.code = code;this.data = data;}public ResponseResult(Integer code, String msg, T data) {this.code = code;this.errorMessage = msg;this.data = data;}public ResponseResult(Integer code, String msg) {this.code = code;this.errorMessage = msg;}public static ResponseResult errorResult(int code, String msg) {ResponseResult result = new ResponseResult();return result.error(code, msg);}public static ResponseResult okResult(int code, String msg) {ResponseResult result = new ResponseResult();return result.ok(code, null, msg);}public static ResponseResult okResult(Object data) {ResponseResult result = setAppHttpCodeEnum(AppHttpCodeEnum.SUCCESS, AppHttpCodeEnum.SUCCESS.getErrorMessage());if(data!=null) {result.setData(data);}return result;}public static ResponseResult errorResult(AppHttpCodeEnum enums){return setAppHttpCodeEnum(enums,enums.getErrorMessage());}public static ResponseResult errorResult(AppHttpCodeEnum enums, String errorMessage){return setAppHttpCodeEnum(enums,errorMessage);}public static ResponseResult setAppHttpCodeEnum(AppHttpCodeEnum enums){return okResult(enums.getCode(),enums.getErrorMessage());}private static ResponseResult setAppHttpCodeEnum(AppHttpCodeEnum enums, String errorMessage){return okResult(enums.getCode(),errorMessage);}public ResponseResult<?> error(Integer code, String msg) {this.code = code;this.errorMessage = msg;return this;}public ResponseResult<?> ok(Integer code, T data) {this.code = code;this.data = data;return this;}public ResponseResult<?> ok(Integer code, T data, String msg) {this.code = code;this.data = data;this.errorMessage = msg;return this;}public ResponseResult<?> ok(T data) {this.data = data;return this;}public Integer getCode() {return code;}public void setCode(Integer code) {this.code = code;}public String getErrorMessage() {return errorMessage;}public void setErrorMessage(String errorMessage) {this.errorMessage = errorMessage;}public T getData() {return data;}public void setData(T data) {this.data = data;}public String getHost() {return host;}public void setHost(String host) {this.host = host;}public static void main(String[] args) {//前置/*AppHttpCodeEnum success = AppHttpCodeEnum.SUCCESS;System.out.println(success.getCode());System.out.println(success.getErrorMessage());*///查詢一個對象/*Map map = new HashMap();map.put("name","zhangsan");map.put("age",18);ResponseResult result = ResponseResult.okResult(map);System.out.println(JSON.toJSONString(result));*///新增,修改,刪除 在項目中統一返回成功即可/* ResponseResult result = ResponseResult.errorResult(AppHttpCodeEnum.SUCCESS);System.out.println(JSON.toJSONString(result));*///根據不用的業務返回不同的提示信息 比如:當前操作需要登錄、參數錯誤/*ResponseResult result = ResponseResult.errorResult(AppHttpCodeEnum.NEED_LOGIN);System.out.println(JSON.toJSONString(result));*///查詢分頁信息
// PageResponseResult responseResult = new PageResponseResult(1,5,50);
// List list = new ArrayList();
// list.add("itcast");
// list.add("itheima");
// responseResult.setData(list);
// System.out.println(JSON.toJSONString(responseResult));}}
這里的邏輯相對來說不是很難理解
這里忘記了,引入項目的時候導入過了
(3)mapper層
mapper層更簡單了,就直接繼承下BaseMapper就行了
(4)接口測試工具
我這里用習慣了apifox所以就還是用apifox就行測試了,如果想用其他的可以去了解下knife4j
四、網關
不了解網關的可以看下這篇文章,簡而言之就是一對多,是微服務中必不可少的
重生之我在暑假學習微服務第十天《網關篇》
1、創建heima-leadnews-app-gateway
引入依賴,在父工程下引入即可,一定要看好位置
<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、改造模塊
(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);}
}
(2)bootstrap.yml配置文件
這里別忘了換ip地址
server:port: 51601
spring:application:name: leadnews-app-gatewaycloud:nacos:discovery:server-addr: 192.168.73.134:8848config:server-addr: 192.168.73.134:8848file-extension: yml
(3)nacos配置
這里直接復制過去就行
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
(4)配置過濾器
這里的主要功能就是進行過濾的,整體邏輯也不復雜
package com.heima.app.gateway.filter;import com.alibaba.cloud.commons.lang.StringUtils;
import com.heima.app.gateway.util.AppJwtUtil;
import io.jsonwebtoken.Claims;
import lombok.extern.slf4j.Slf4j;
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獲取對象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)){//token不存在response.setStatusCode(HttpStatus.UNAUTHORIZED);return response.setComplete();}//5.判斷token是否正確try {Claims claimsBoby = AppJwtUtil.getClaimsBody(token);if (AppJwtUtil.verifyToken(claimsBoby) == 1 || AppJwtUtil.verifyToken(claimsBoby) == 2) {//token錯誤response.setStatusCode(HttpStatus.UNAUTHORIZED);return response.setComplete();}} catch (Exception e) {e.printStackTrace();//token錯誤response.setStatusCode(HttpStatus.UNAUTHORIZED);return response.setComplete();}//6.放行return chain.filter(exchange);}@Overridepublic int getOrder() {return 0;}
}
3、部署前端項目
主要工作就是對nginx的改造
(1)創建存放conf的目錄
因為項目所涉及不同的網關,所以要放在文件夾下統一保存
(2)創建APP端conf
(3)改造conf文件
將所畫的改為自己的信息即可
這是我的文件內容
upstream heima-app-gateway{server localhost:51601;
}server {listen 8801;location / {root D:\AllCode\java_Code\springcloud\qianduan_All\app-web;index index.html;}location ~/app/(.*) {proxy_pass http://heima-app-gateway/$1;proxy_set_header HOST $host; # 不改變源請求頭的值proxy_pass_request_body on; #開啟獲取請求體proxy_pass_request_headers on; #開啟獲取請求頭proxy_set_header X-Real-IP $remote_addr; # 記錄真實發出請求的客戶端IPproxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; #記錄代理信息}
}
(4)改造原本的conf文件
這里記得修改為自己的路徑,不過如果放在一個文件夾下其實不用更改
直接cv即可
#user nobody;
worker_processes 1;events {worker_connections 1024;
}
http {include mime.types;default_type application/octet-stream;sendfile on;keepalive_timeout 65;# 引入自定義配置文件include leadnews.conf/*.conf;
}
4、測試
準備工作完成開始測試
介紹下網關發揮的作用,可以看到這里可以通過網關的端口來訪問登錄功能
前后端聯調測試
訪問:http://localhost:8801/
測試登錄功能
進入這個頁面就測試成功了
結語
本文記錄了從黑馬商城項目轉向黑馬頭條項目的過程。文章詳細介紹了項目技術棧(包括SpringCloud、Nacos、Kafka等)、環境配置、模塊改造(用戶服務、網關服務)的具體步驟,并重點講解了登錄功能的實現和網關過濾器的配置。還分享了前后端聯調測試經驗,展示了如何通過Nginx配置實現前后端對接。該項目采用微服務架構,包含用戶中心、自媒體等多個微服務模塊,通過SpringCloudGateway實現統一API路由和權限控制。文章為開發者提供了完整的項目搭建指南和技術實現細節。