资讯头条
一个微服务项目,项目分为3个部分,app端,管理端,自媒体端
一.项目构建
略
二.app端网关搭建
网关是访问服务的必须要素,经过网管筛选过的请求才允许访问服务
2.1 app端网关构建
在heima-leadnews项目下heima-leadnews-gateway模块下创建模块heima-leadnews-app-gateway,用于提供app网关
1.导入依赖(实际上是heima-leadnews-gateway模块下已经导入了网关gateway,naocs,jwt相关依赖,而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.创建启动类AppGatewayApplication,并使用EnableDiscoveryClient注解将该服务注册为一个微服务:
@SpringBootApplication
@EnableDiscoveryClient
public class AppGatewayApplication {
public static void main(String[] args) {
SpringApplication.run(AppGatewayApplication.class,args);
}
}
3.编写配置文件bootstrap.yml:
server:
port: 51601
spring:
application:
name: leadnews-app-gateway
cloud:
nacos:
discovery:
server-addr: 192.168.163.136:8848
config:
server-addr: 192.168.163.136:8848
file-extension: yml
4.启动nacos在虚拟机中的docker容器,添加配置文件leadnews-app-gateway.yml,这段文件配置了全局的CORS(跨域资源共享)策略和路由规则.
spring:
cloud:
gateway:
globalcors:
add-to-simple-url-handler-mapping: true
corsConfigurations:
'[/**]':
allowedHeaders: "*"
allowedOrigins: "*"
allowedMethods:
- GET
- POST
- DELETE
- PUT
- OPTION
maxAge: 360000
routes:
# 平台管理
- id: user
uri: lb://leadnews-user
predicates:
- Path=/user/**
filters:
- StripPrefix= 1
gateway跨域资源共享
可以参考视频讲解:网关的cors跨域资源共享.
1.“跨域”是指域名不同或者域名相同,端口不同,跨域问题通常是指浏览器禁止请求的发起者与服务端发生跨域ajax请求,请求被浏览器拦截的问题。而微服务之间的相互调用不经过浏览器,所以也不存在这种跨域问题。
这种问题的解决方案是CORS:浏览器询问服务器“你是否允许该请求跨域?”,如果服务器同意,则允许该请求跨域,否则不允许。
2.而网关处理跨域同样是基于CORS方案,只是网关已经封装好了CORS的底层逻辑,我们只需要在网关中进行配置即可。在spring.cloud.gateway.globalcors(全局跨域资源共享)中 :
- add-to-simple-url-handler-mapping: true解决了options请求被拦截的问题;(网关中特有的,浏览器询问服务器时发送的这个询问请求是使用options的,而这种询问请求是不应该被拦截的,因此该请求表示不拦截询问请求)
- 在配置corsConfigurations中对于请求路径[/**](表示任意的请求路径)的配置
- allowedOrigins:“*” # 允许哪些网站跨域请求,星号表示所有网站
- allowedMethods:… # 允许跨域使用的请求方法
- allowedHeaders: “*” # 允许携带的请求头信息,星号表示所有请求头都允许携带
- allowedCredentials: true # 是否允许携带cookie
- maxAge: 360000 # 这次跨域检测的有效期,由于CORS是每一个请求都要询问一次,这就相当于有了2倍的请求,会造成性能上的损耗,因此设置跨域检测有效期,有效期内,浏览器将不再询问,而是直接发起请求
路由规则配置
网关路由的配置包括:
- 路由ID:路由唯一标识
- uri:路由目的地,支持lb和http两种
- predicates:路由断言,判断请求是否符合要求,符合则转发路由目的地
- filters:路由过滤器,处理请求或响应
对于配置文件中的内容:
- id: user # 路由的唯一标识,可以自定义名称
- uri: lb://leadnews-user #路由目的地,lb/http+微服务名称(即为访问的目的地址)
- predicates:
- Path=/user/** # 路由断言,表示只有符合以"/user"开头的请求才能被转发到目的地址 - filters:
- StripPrefix= 1 # 使用了StripPrefix过滤器,过滤器的权重为1
2.2 认证过滤器
认证过滤器的大体逻辑如下:
- 请求发送到网关
- 网关判断该请求是否需要鉴权
- 需要鉴权,查看那是否有token》查看token是否有效,只有有token并且token有效时,才会路由到对应的微服务,否返回401未认证
- 不需要鉴权(可能是登陆/注册等请求),直接路由到对应的微服务
![](https://i-blog.csdnimg.cn/blog_migrate/349917255a971b4549237495bf92b8d0.png)
配置全局认证过滤器
@Component
@Slf4j
public class AuthorizeFilter implements Ordered, GlobalFilter {
@Override
public 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.获取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;
}
}
2.3 用户登陆微服务搭建
具体参考手册,主要是编写配置文件到nacos注册中心中
spring:
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/leadnews_user?useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC
username: root
password: zhr35276680
# 设置Mapper接口所对应的XML文件位置,如果你在Mapper接口中有自定义方法,需要进行该配置
mybatis-plus:
mapper-locations: classpath*:mapper/*.xml
# 设置别名包扫描路径,通过该属性可以给包中的类注册别名
type-aliases-package: com.heima.model.user.pojos
三.app端前端项目集成
1.前端项目的部署,解压打包好的前端项目app-web,解压nginx包.
2.新建了一个目录leadnews-front专门用于存放前端项目与nginx.
3.进入nginx/conf目录,在该目录下创建leadnews.conf目录,然后再该目录下创建app端配置文件heima-leadnews-app.conf.将如下配置写入conf文件:
关于代理和反向代理
代理服务器位于客户端和目标服务器之间,客户端发送的请求首先被发送到代理服务器。代理服务器根据一定的规则(如过滤、缓存、身份验证等)将请求转发给目标服务器,并将目标服务器的响应返回给客户端。客户端通常需要进行特殊的配置才能使用代理服务器,例如设置浏览器的代理配置。
反向代理服务器位于客户端和目标服务器之间,客户端发送的请求首先被发送到反向代理服务器。
反向代理服务器根据一定的规则(如负载均衡、缓存、SSL终止等)将请求转发给一个或多个目标服务器,并将目标服务器的响应返回给客户端。客户端不需要知道目标服务器的存在,因为它们只需要与反向代理服务器进行通信。
其中,upstream后边跟随了网关的入口,在server中配置了访问静态资源的内容和配置反向代理的内容。
upstream heima-app-gateway{
server localhost:51601;
}
server {
listen 8801;
location / {
root E:/JavaCode/heima-leadnews-front/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; # 记录真实发出请求的客户端IP
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; #记录代理信息
}
}
然后,在nginx.conf中修改配置,修改为引入heima-leadnews-app.conf文件加载
#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.进入对应目录,启动nginx.exe
ngxin.exe
5.重新加载修改后的nginx配置(如果之前已经启动了nginx)
nginx -s reload
使用谷歌浏览器打开,并开启手机模式访问,
在这里插入代码片
上边的显示比例使用填满整个屏幕即可,在此状态下即可对手机端(仿)进行操作