目录:
(1)整合服务网关
(2)前台用户系统-nuxt搭建前端环境
(3)前台用户系统-目录结构和封装axios
(1)整合服务网关
前面的过程使用nginx请求转发
下面使用SpringCloud中的技术Gateway,也能实现跟nginx相同的效果,他比neginx功能更加强大,简洁。在Geatway里面可以直接解决跨域问题不用在Controller中加@CrossOrign注解
1、网关介绍
API网关出现的原因是微服务架构的出现,不同的微服务一般会有不同的网络地址,而外部客户端可能需要调用多个服务的接口才能完成一个业务需求,如果让客户端直接与各个微服务通信,会有以下的问题:
(1)客户端会多次请求不同的微服务,增加了客户端的复杂性。
(2)存在跨域请求,在一定场景下处理相对复杂。
(3)认证复杂,每个服务都需要独立认证。
(4)难以重构,随着项目的迭代,可能需要重新划分微服务。例如,可能将多个服务合并成一个或者将一个服务拆分成多个。如果客户端直接与微服务通信,那么重构将会很难实施。
(5)某些微服务可能使用了防火墙 / 浏览器不友好的协议,直接访问会有一定的困难。
以上这些问题可以借助 API 网关解决。API 网关是介于客户端和服务器端之间的中间层,所有的外部请求都会先经过API 网关这一层。也就是说,API 的实现方面更多的考虑业务逻辑,而安全、性能、监控可以交由 API 网关来做,这样既提高业务灵活性又不缺安全性
2、Spring Cloud Gateway介绍
Spring cloud gateway是spring官方基于Spring 5.0、Spring Boot2.0和Project Reactor等技术开发的网关,Spring Cloud Gateway旨在为微服务架构提供简单、有效和统一的API路由管理方式,Spring Cloud Gateway作为Spring Cloud生态系统中的网关,目标是替代Netflix Zuul,其不仅提供统一的路由方式,并且还基于Filer链的方式提供了网关基本的功能,例如:安全、监控/埋点、限流等
创建一个新的模块:
在pom.xml:中引入依赖:
<dependencies>
<!--Geatway-->
<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>
</dependencies>
创建配置文件:
# 服务端口
server.port=83
# 服务名
spring.application.name=service-gateway
# nacos服务地址
spring.cloud.nacos.discovery.server-addr=127.0.0.1:8848
#使用服务发现路由
spring.cloud.gateway.discovery.locator.enabled=true
#设置路由id
spring.cloud.gateway.routes[0].id=service-hosp
#设置路由的uri
spring.cloud.gateway.routes[0].uri=lb://service-hosp
#设置路由断言,代理servicerId为auth-service的/auth/路径
spring.cloud.gateway.routes[0].predicates= Path=/*/hosp/**
#设置路由id
spring.cloud.gateway.routes[1].id=service-cmn
#设置路由的uri
spring.cloud.gateway.routes[1].uri=lb://service-cmn
#设置路由断言,代理servicerId为auth-service的/auth/路径
spring.cloud.gateway.routes[1].predicates= Path=/*/cmn/**
创建启动类:
package com.atguigu.yygh.gateway;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class ServerGatewayApplication {
public static void main(String[] args) {
SpringApplication.run(ServerGatewayApplication.class, args);
}
}
前端项目原来监听的是9001端口:现在可以把它换成网关的地址:
改为83的网关端口
前端发送请求先到Geatway网关,网关中根据你的请求路径,转发到Nacos中不同的 服务中去
访问前端页面,访问路径发生了改变
前端的端口号是9528,后端的端口号是8201、8202,他们端口号不一样,所以产生跨域,目前的解决方案是在controller中加一个注解@CrossOrigin ,用了网关之后,就不需要在controller上加这个注解了,直接通过一个配置类,把它统一进行解决
3.5 跨域处理
跨域:浏览器对于javascript的同源策略的限制 。
以下情况都属于跨域:
跨域原因说明 | 示例 |
域名不同 | www.jd.com 与 www.taobao.com |
域名相同,端口不同 | www.jd.com:8080 与 www.jd.com:8081 |
二级域名不同 | item.jd.com 与 miaosha.jd.com |
如果域名和端口都相同,但是请求路径不同,不属于跨域,如:
www.jd.com/item
www.jd.com/goods
http和https也属于跨域
而我们刚才是从localhost:1000去访问localhost:8888,这属于端口不同,跨域了。
3.5.1 为什么有跨域问题?
跨域不一定都会有跨域问题。
因为跨域问题是浏览器对于ajax请求的一种安全限制:一个页面发起的ajax请求,只能是与当前页域名相同的路径,这能有效的阻止跨站攻击。
因此:跨域问题 是针对ajax的一种限制。
但是这却给我们的开发带来了不便,而且在实际生产环境中,肯定会有很多台服务器之间交互,地址和端口都可能不同,怎么办?
3.5.2解决跨域问题
全局配置类实现
CorsConfig类
package com.atguigu.yygh.gateway.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.reactive.CorsWebFilter;
import org.springframework.web.cors.reactive.UrlBasedCorsConfigurationSource;
import org.springframework.web.util.pattern.PathPatternParser;
@Configuration
public class CrosConfig {
@Bean
public CorsWebFilter corsFilter() {
CorsConfiguration config = new CorsConfiguration();
config.addAllowedMethod("*");
config.addAllowedOrigin("*");
config.addAllowedHeader("*");
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(new PathPatternParser());
source.registerCorsConfiguration("/**", config);
return new CorsWebFilter(source);
}
}
3.6服务调整
目前我们已经在网关做了跨域处理,那么service服务就不需要再做跨域处理了,将之前在controller类上添加过@CrossOrigin标签的去掉,防止程序异常
当访问的时候,首先到网关,网关里面,已经把跨域问题解决了,已经从跨域位置跳出去了,所以控制器不需要在加这个注解了
去掉所有Controller上的注解:@CrossOrigin
注释掉所有controller上的跨域注解之后,访问
(2)前台用户系统-nuxt搭建前端环境
1、服务端渲染技术NUXT
1.1 什么是服务端渲染
服务端渲染又称SSR (Server Side Render)是在服务端完成页面的内容,而不是在客户端通过AJAX获取数据。
服务器端渲染(SSR)的优势主要在于:更好的 SEO,由于搜索引擎爬虫抓取工具可以直接查看完全渲染的页面。
如果你的应用程序初始展示 loading 菊花图,然后通过 Ajax 获取内容,抓取工具并不会等待异步完成后再进行页面内容的抓取。也就是说,如果 SEO 对你的站点至关重要,而你的页面又是异步获取内容,则你可能需要服务器端渲染(SSR)解决此问题。
另外,使用服务器端渲染,我们可以获得更快的内容到达时间(time-to-content),无需等待所有的 JavaScript 都完成下载并执行,产生更好的用户体验,对于那些内容到达时间(time-to-content)与转化率直接相关的应用程序而言,服务器端渲染(SSR)至关重要。
1.2 什么是NUXT
Nuxt.js 是一个基于 Vue.js 的轻量级应用框架,可用来创建服务端渲染 (SSR) 应用,也可充当静态站点引擎生成静态站点应用,具有优雅的代码结构分层和热加载等特性。
官网网站:
https://zh.nuxtjs.org/
- NUXT环境初始化
2.1 下载压缩包
https://github.com/nuxt-community/starter-template/archive/master.zip
2.2解压
将template中的内容复制到 yygh-site
先创建一个目录:作为前台的目录:
把提供的包进行解压:
复制里面的文件到创建的目录:
修改里面的package.json:
nuxt.config.js:修改
下载package.json里面的依赖完成下载:
在终端输入命令:npm install
还可以安装其他的依赖:element-ui的依赖后面会用到:
1、下载element-ui
npm install element-ui |
2、在plugins文件夹下创建myPlugin.js文件
3、在myPlugin.js文件引入element-ui
import Vue from 'vue' import ElementUI from 'element-ui' //element-ui的全部组件 import 'element-ui/lib/theme-chalk/index.css'//element-ui的css Vue.use(ElementUI) //使用elementUI |
4、在nuxt.config.js文件中使用myPlugin.js
在build下面添加内容:
plugins: [ { src: '~/plugins/myPlugin.js', ssr: false } ] |
2.7 测试运行
npm run dev
访问项目:http://localhost:3000/
(3)前台用户系统-目录结构和封装axios
.nuxt:编译之后的一些文件,不需要动
assets:放一些静态资源文件,如css文件 js文件
components:放一些Vue支持的组件
middleware、static、store放一些静态资源
plugins:放一些插件
layout pages:
首先进入到布局页面,在布局页面引入其他的页面内容,引入pages内容页面
2.8 NUXT目录结构
1、资源目录 assets
用于组织未编译的静态资源如 LESS、SASS 或 JavaScript。
2、组件目录 components
用于组织应用的 Vue.js 组件。Nuxt.js 不会扩展增强该目录下 Vue.js 组件,即这些组件不会像页面组件那样有 asyncData 方法的特性。
3、布局目录 layouts
用于组织应用的布局组件。
4、页面目录 pages
用于组织应用的路由及视图。Nuxt.js 框架读取该目录下所有的 .vue 文件并自动生成对应的路由配置。
5、插件目录 plugins
用于组织那些需要在 根vue.js应用 实例化之前需要运行的 Javascript 插件。
6、nuxt.config.js 文件
nuxt.config.js 文件用于组织Nuxt.js 应用的个性化配置,以便覆盖默认配置。
创建文件夹和request.js用来封装axios,用于ajax请求
import axios from 'axios'
import { MessageBox, Message } from 'element-ui'
// 创建axios实例
const service = axios.create({
baseURL: 'http://localhost',
timeout: 15000 // 请求超时时间
})
// http request 拦截器
service.interceptors.request.use(
config => {
// token 先不处理,后续使用时在完善
return config
},
err => {
return Promise.reject(err)
})
// http response 拦截器
service.interceptors.response.use(
response => {
if (response.data.code !== 200) {
Message({
message: response.data.message,
type: 'error',
duration: 5 * 1000
})
return Promise.reject(response.data)
} else {
return response.data
}
},
error => {
return Promise.reject(error.response)
})
export default service
3、封装axios
3.1 安装axios
执行安装命令 npm install axios |