开发微服务电商项目演示(三)
一,nginx动静分离
第1步:通过SwitchHosts新增二级域名:images.zmall.com

第2步:将本次项目的易买网所有静态资源js/css/images复制到nginx中的html目录下


第3步:在nginx的核心配置文件nginx.conf中新增二级域名images.zmall.com访问映射,用于实现nginx动静分离
注意:修改成功之后,重启nginx服务使其配置生效!!!
当我们访问80端口 或者images.zmall.com时就会自动路由到nginx中html文件中加载静态资源
server{
listen 80;
server_name images.zmall.com;
location / {
root html;
index index.html;
}
}

检测静态资源服务器配置成功
images.zmall.com/css/style.css

第4步:删除zmall-product商品服务和zmall-gateway网关服务下的static静态资源,改用nginx中配置的静态资源
第5步:修改zmall-product商品服务中的templates/common/head.html
<#assign ctx><#--域名,动态请求时需加入该前缀-->http://product.zmall.com
</#assign>
<#--采用H5方式的base标签,在整个页面的url地址前加入,用于访问nginx中的静态资源-->
<base href="http://images.zmall.com/"/>添加二级域名

第6步:分别重启zmall-product、zmall-gateway以及nginx后输入请求地址(启动nacos):
http://zmall.com/product-serv/index.html 走网关的形式
http://product.zmall.com/index.html 走nginx的形式
访问商品服务首页,如下所示:

如果出现IIS7,那么cmd窗口中执行下列指令
net stop w3svc
实现的原理解释:

二,服务调用
创建配置zmall-cart购物车模块
第1步:基于Spring initializr创建zmall-cart购物车模块
第2步:将zmall-order订单模块配置到主模块中
<modules>...<module>zmall-cart</module>...
</modules>第3步:修改pom.xml
<parent><groupId>com.zking.zmall</groupId><artifactId>zmall</artifactId><version>1.0-SNAPSHOT</version>
</parent>
<artifactId>zmall-cart</artifactId><dependencies><dependency><groupId>com.zking.zmall</groupId><artifactId>zmall-common</artifactId><version>1.0-SNAPSHOT</version></dependency>
</dependencies>第4步:配置application.yml(端口:8030)
server:port: 8030
spring:application:name: zmall-cartdatasource:#type连接池类型 DBCP,C3P0,Hikari,Druid,默认为Hikaritype: com.zaxxer.hikari.HikariDataSourcedriver-class-name: com.mysql.jdbc.Driverurl: jdbc:mysql://localhost:3306/zmall?characterEncoding=utf8&useSSL=false&serverTimezone=Asia/Shanghai&rewriteBatchedStatements=trueusername: rootpassword: 1234freemarker:suffix: .htmltemplate-loader-path: classpath:/templates/cloud:nacos:config:server-addr: localhost:8848
#mybatis-plus配置
mybatis-plus:#所对应的 XML 文件位置mapper-locations: classpath*:/mapper/*Mapper.xml#别名包扫描路径type-aliases-package: com.zking.zmall.modelconfiguration:#驼峰命名规则map-underscore-to-camel-case: true
#日志配置
logging:level:com.zking.zmall.mapper: debug第5步:在启动类上加入@EnableDiscoveryClient
第6步:分别将购物车页面和common/head.html导入到templates目录,并修改head.html中的ctx局部变量
<#assign ctx><#--一级域名,动态请求时需加入该前缀-->http://cart.zmall.com
</#assign>
<#--采用H5方式的base标签,在整个页面的url地址前加入,用于访问nginx中的静态资源-->
<base href="http://images.zmall.com/"/>
第7步:在zmall-gateway网关服务中配置购物车的路由转发规则(重启gateway网关服务)
spring:application:name: zmall-gatewaycloud:nacos:discovery:server-addr: localhost:8848gateway:routes:...- id: cart_routeuri: lb://zmall-cart # lb指的是从nacos中按照名称获取微服务,并遵循负载均衡策略predicates:- Path=/cart-serv/**filters:- StripPrefix=1#此过滤器设置路由过滤器检查的请求属性,以确定是否应发送原始主机头,而不是由 HTTP 客户端确定的主机头- PreserveHostHeader注意:这里要配置过滤器PreserveHostHeader,用于处理重定向时依然已原始主机头发送请求。
第8步:创建CartController并定义请求方法
@Controller
public class CartController {@RequestMapping("/cart.html")public String toCart(){return "buyCar";}@RequestMapping("/addCart")public String addCart(Integer pid,Integer num){return "redirect:/cart.html";}
}注意:这里使用redirect重定向方式跳转页面,在SpringCloud gateway路由转发过程中会导致域名跳转变成了http请求方式,所以必须在Gateway网关服务中进行相关的配置。具体请参考第8步的gateway网关路由配置。
<td><a href="http://cart.zmall.com/addCart?pid=${(product.id)!}&num=3" class="b_sure">去购物车结算</a><a href="#" class="b_buy">继续购物</a></td>创建配置zmall-order订单模块
在zmall-user中通过openfeign方式访问order服务接口
定义openfeign接口
@FeignClient("zmall-order")
public interface IOrderFeignService {
@RequestMapping("/orderUserList")List<Order> orderUserList();
}
启动类上设置@EnableDiscoveryClient和@EnableFeignClients

调用接口并测试接口
@Controller
public class UserController {@Autowiredprivate IOrderFeignService orderFeignService;@RequestMapping("/login.html")public String toLogin(){return "login";}@RequestMapping("/order.html")@ResponseBodypublic List<Order> orderUserList(){return orderFeignService.orderUserList();}
}
测试链路
http://product.zmall.com/index.html
http://product.zmall.com/product.html?pid=733
http://cart.zmall.com/cart.html
界面能够熊 商品微服务 直接跳转到 购物车微服务中
1.

2.

3.

http://localhost:8010/order.html调用 用户微服务接口 ,能访问 订单微服务的数据

三,spring session实践
什么是Spring Session
SpringBoot整合Spring-Session的自动配置可谓是开箱即用,极其简洁和方便。这篇文章即介绍SpringBoot整合Spring-Session,这里只介绍基于RedisSession的实战。
Spring Session 是Spring家族中的一个子项目,Spring Session提供了用于管理用户会话信息的API和实现。它把servlet容器实现的httpSession替换为spring-session,专注于解决 session管理问题,默认Session信息存储在Redis中,可简单快速且无缝的集成到我们的应用中
spring session官网地址:https://spring.io/projects/spring-session
Spring Session的特性:
提供用户session管理的API和实现
提供HttpSession,以中立的方式取代web容器的session,比如tomcat中的session
支持集群的session处理,不必绑定到具体的web容器去解决集群下的session共享问题
为什么要使用Spring Session

SpringCloud微服务将一个完整的单体应用拆解成了一个个独立的子服务,而每一个独立的微服务子模块都将部署到不同的服务器中,而服务与服务之间是独立隔离的,这个时候使用要实现服务与服务之间的session会话共享,则需要借助于spring-session框架来解决分布式session管理与共享问题。
错误案例展示
在用户服务zmall-user中编写登录控制器,登录时创建session,并将当前登录用户存储sesion中。
@Controller
public class UserController {@RequestMapping("/login.html")public String toLogin(HttpSession session){session.setAttribute("username","admin");return "login";}
}在Gateway网关服务中添加用户服务的路由转发规则
spring:application:name: zmall-gatewaycloud:nacos:discovery:server-addr: localhost:8848gateway:routes:...- id: user_routeuri: lb://zmall-user # lb指的是从nacos中按照名称获取微服务,并遵循负载均衡策略predicates:- Path=/user-serv/**filters:- StripPrefix=1- PreserveHostHeader在商品服务zmall-product中编写查询控制器,在登录创建session后,使用将sessionId置于cookie中访问。如果没有session将返回错误。
@Controller
public class ProductController {@RequestMapping("/index.html")public String index(Model model, HttpSession session){Object username = session.getAttribute("username");System.out.println("**********"+username);return "index";}
}测试链路
#1.session信息存储
http://localhost:8010/login.html
#2.session信息获取
http://product.zmall.com/index.html

配置spring-session
在公共模块zmall-common中引入spring-session的pom配置,由于spring-boot包含spring-session的starter模块,所以pom中依赖:注意:公共模块作为所有微服务子模块的依赖支持,如果不在各服务模块中配置redis支持,会导致启动其他微服务时出现报错情况。
<!--redis-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<!--spring session-->
<dependency>
<groupId>org.springframework.session</groupId>
<artifactId>spring-session-data-redis</artifactId>
</dependency>
<!--commons-pool2-->
<dependency><groupId>org.apache.commons</groupId><artifactId>commons-pool2</artifactId>
</dependency>分别在商品服务zmall-product和用户服务zmall-user中配置application.yml
spring:session:redis:flush-mode: on_savenamespace: session.zmallcleanup-cron: 0 * * * * *store-type: redistimeout: 1800redis:host: localhostport: 6379password: 123456jedis:pool:max-active: 100max-wait: 10max-idle: 10min-idle: 10database: 0重新启动zmall-user和zmall-product服务,先访问:http://zmall.com/user-serv/login.html,然后在访问:http://zmall.com/product-serv/index.html;回到zmall-product模块控制台查看session获取情况。

注意:借助网关微服务内部可以访问,不同二级域名之间不可以访问
四,二级域名问题
测试在用户模块中保存用户信息,然后在产品模块中读取,但是使用二级域名方式访问读取失败



请分别在用户服务和商品服务中该配置类,解决二级域名访问session无效问题。
@Configuration
public class SessionConfig {@Beanpublic CookieSerializer cookieSerializer(){DefaultCookieSerializer cookieSerializer = new DefaultCookieSerializer();cookieSerializer.setDomainName("zmall.com");cookieSerializer.setCookieName("ZMALLSESSION");return cookieSerializer;}@Beanpublic RedisSerializer<Object> springSessionDefaultRedisSerializer(){return new GenericJackson2JsonRedisSerializer();}
}测试链路
#1.先访问
http://user.zmall.com/login.html
#2.后访问
http://product.zmall.com/index.html

五,用户登录
第1步:在zmall-common公共模块中创建全局异常处理、响应封装类
第2步:在zmall-user模块中定义IUserService及UserServiceImpl
IUserService
public interface IUserService extends IService<User> {JsonResponseBody<?> userLogin(UserVo user, HttpServletRequest req, HttpServletResponse resp);
}UserServiceImpl
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements IUserService {
@Overridepublic JsonResponseBody<?> userLogin(UserVo user,HttpServletRequest req,HttpServletResponse resp) {//1.判断用户账号和密码是否为空if(StringUtils.isEmpty(user.getLoginName())||StringUtils.isEmpty(user.getPassword()))return new JsonResponseBody<>(JsonResponseStatus.USERNAME_OR_PWD_EMPTY);//2.根据用户名查询数据对应的用户信息User us = this.getOne(new QueryWrapper<User>().eq("loginName", user.getLoginName()));//3.判断us用户对象是否为空if(null==us)return new JsonResponseBody<>(JsonResponseStatus.USERNAME_ERROR);try {//MD5加密转换处理String pwd=MD5Utils.md5Hex(user.getPassword().getBytes());//4.判断输入密码与数据库表存储密码是否一致if(!us.getPassword().equals(pwd)){return new JsonResponseBody<>(JsonResponseStatus.PASSWORD_ERROR);}} catch (Exception e) {e.printStackTrace();return new JsonResponseBody<>(JsonResponseStatus.ERROR);}//5.通过UUID生成token令牌并保存到cookie中String token= UUID.randomUUID().toString().replace("-","");//将随机生成的Token令牌保存到Cookie中,并设置1800秒超时时间CookieUtils.setCookie(req,resp,"token",token,7200);//6.将token令牌与spring session进行绑定并存入redis中HttpSession session = req.getSession();session.setAttribute(token,us);return new JsonResponseBody<>(token);}
}
第3步:创建UserVo类
@Data
public class UserVo {private String loginName;private String password;
}
第4步:在UserController中定义用户登录方法
/**
* 用户登陆功能实现
* @return
*/
@RequestMapping("/userLogin")
@ResponseBody
public JsonResponseBody<?> userLogin(UserVo user,HttpServletRequest req,HttpServletResponse resp){return userService.userLogin(user,req,resp);
}第5步:在前端login.html页面中定义登录js方法
<script>$(function(){$('.log_btn').click(function(){let loginName=$('.l_user').val();let password=$('.l_pwd').val();
if(''===loginName){alert('请输入用户名!');return false;}if(''===password){alert('请输入密码!');return false;}console.log({loginName:loginName,password:password});$.post('http://zmall.com/user-serv/userLogin',{loginName:loginName,password:password},function(rs){console.log(rs);if(rs.code===200){location.href='http://zmall.com/product-serv/index.html';}else{alert(rs.msg);}},'json');});});
</script>登录成功后,跳转到商品首页
http://user.zmall.com/login.html
如果用二级域名进行测试,那么需要解决跨域问题;
url: jdbc:mysql://localhost:3306/zmall?useUnicode=true&characterEncoding=UTF-8&useSSL=false&serverTimezone=UTC成功了!




相关文章:
开发微服务电商项目演示(三)
一,nginx动静分离第1步:通过SwitchHosts新增二级域名:images.zmall.com第2步:将本次项目的易买网所有静态资源js/css/images复制到nginx中的html目录下第3步:在nginx的核心配置文件nginx.conf中新增二级域名images.zma…...
C/C++排序算法(二) —— 选择排序和堆排序
文章目录前言1. 直接选择排序🍑 基本思想🍑 具体步骤🍑 具体步骤🍑 动图演示🍑 代码实现🍑 代码升级🍑 特性总结2. 堆排序🍑 向下调整算法🍑 任意树调整为堆的思想&#…...
爬虫笔记之——selenium安装与使用(1)
爬虫笔记之——selenium安装与使用(1)一、安装环境1、下载Chrome浏览器驱动(1)查看Chrome版本(2)下载相匹配的Chrome驱动程序地址:https://chromedriver.storage.googleapis.com/index.html2、学…...
STC15单片机软串口的使用
STC15软串口的使用📖在没有使用定时器资源的情况下,根据波特率位传输时间,利用STC-ISP工具自动计算出位延时函数。 ✨在官方所提供的库函数中位传输时间函数,仅适用于使用波特率为:9600的串口数据传输: void BitTime(…...
Ansible的脚本------playbook剧本
一、剧本的前置知识点1、主机清单ansible默认的主机清单是/etc/ansible/hosts文件主机清单可以手动设置,也可以通过Dynamic Inventory动态生成一般主机名使用FQDNvi /etc/ansible/hosts [webserver] #使用方括号设置组名 www1.example.org #定…...
实验5-计算中值及分治技术
目录 1.寻找中位数(利用快速排序来寻找中位数) 2.分治方法求数组的和 3.合并排序...
dbeaver从excel导入数据笔记
场景 有excel的数据,需要做到数据库里。 方案一: 开发代码来实现。缺点是需要开发成本。 方案二: 数据库导入工具导入。不用开发,相对快速一些。 这里说下数据库工具导入。 操作过程 1、拿到excel数据文件,根据标题…...
PyTorch学习笔记:nn.MarginRankingLoss——排序损失
PyTorch学习笔记:nn.MarginRankingLoss——排序损失 torch.nn.MarginRankingLoss(margin0.0, size_averageNone, reduceNone, reductionmean)功能:创建一个排序损失函数,用于衡量输入x1x_1x1与x2x_2x2之间的排序损失(Ranking Loss)&…...
【JavaScript】34_Date对象 ,日期的格式化
8、Date Date 在JS中所有的和时间相关的数据都由Date对象来表示 对象的方法: getFullYear() 获取4位年份 getMonth() 返当前日期的月份(0-11) getDate() 返回当前是几日 getDay() 返回当前日期是周几(0-6) 0表示周日…...
计算机视觉 对比学习13篇经典论文、解读、代码
为了快速对 机器视觉中的对比学习有一个快速了解,或者后续复习,此处收录了 13篇经典论文、一些讲解地较好的博客和相应的Github代码,用不同颜色标记。 对比学习 13篇经典论文 论文代码和博客http://www.webhub123.com/#/home/detail?p…...
MySQL 选择数据库
在你连接到 MySQL 数据库后,可能有多个可以操作的数据库,所以你需要选择你要操作的数据库。 在 MySQL 中就有很多系统自带的数据库,那么在操作数据库之前就必须要确定是哪一个数据库。 在 MySQL 中,USE 语句用来完成一个数据库到…...
雅思经验(9)
写作:关于趋势的上升和下降在小作文中,真的是非常常见的,所以还是要积累一下。下面给出了很多词,但是在雅思写作中并不是词越丰富,分数就越高的。雅思写作强调的是准确性:在合适的地方用合适的词和句法。不…...
java面试题(二十)中间件redis
1.1 Redis可以用来做什么? 参考答案 Redis最常用来做缓存,是实现分布式缓存的首先中间件;Redis可以作为数据库,实现诸如点赞、关注、排行等对性能要求极高的互联网需求;Redis可以作为计算工具,能用很小的…...
JavaWEB必知必会-Servlet
目录 Servlet简介Servlet快速入门Servlet配置详解ServletContext 1 Servlet简介 Servlet 运行在服务端的Java小程序,是sun公司提供一套规范(接口),用来处理客户端请求、响应给浏览器的动态资源。但servlet的实质就是java代码&a…...
oralce查找返回不同的值,寻找不同的表(原创)
查找返回不同的值,寻找不同的表 select case a_id when 1 then (select b_id|| ||b_desc from b where b.b_ida.a_id) else (select e_id || ||e_desc from e where e.e_ida.a_id) end from a; 以上方法的缺陷是单表,判断。今天来了个挑战&#…...
Python-第四天 Python循环语句
Python-第四天 Python循环语句一、while循环1.while循环的基础语法2.while循环的基础案例3.while循环的嵌套应用4.while循环的嵌套案例二、for循环1.for循环的基础语法1.1基础语法1.2 range语句2.for循环的嵌套应用三、循环中断 : break和continue1.continue2.break四、 综合案…...
spring中bean的生命周期(简单5步)
目录 一、概念 1.生命是bean的生命周期? 2.知道bean生命周期的意义? 3.bean的生命周期按照粗略的五步 二、例子讲解 一、概念 1.生命是bean的生命周期? 答:spring其实就是管理bean对象的工厂,它负责对象的创建&…...
10 个最难理解的 Python 概念
文章目录技术提升面向对象编程 (OOP)装饰器生成器多线程异常处理正则表达式异步/等待函数式编程元编程网络编程大家好,与其他编程语言相比,Python 是一门相对简单的编程语言,如果你想真正学透这门语言,其实可能并不容易。 今天我…...
【linux】线程概念
概念 什么是线程 在一个程序里的一个执行路线就叫做线程(thread)。更准确的定义是:线程是“一个进程内部的控制序列” 一切进程至少都有一个执行线程,线程在进程内部运行,本质是在进程地址空间内运行 在Linux系统中&a…...
Leg转Goh引擎和架设单机+配置登陆器教程
教程准备1、Leg版本一个2、Goh引擎一套3、电脑一台(最好联网)前言:BLUE/LEGS/Gob/Goh/九龍、4K、AspM2第一步:更换引擎1、把版本自带的LEG引擎换成Goh引擎2、删除服务端里面的exe、dll文件(也可以直接更新)3、清理登录和游戏网关里面的配置文件4、更新引…...
变量 varablie 声明- Rust 变量 let mut 声明与 C/C++ 变量声明对比分析
一、变量声明设计:let 与 mut 的哲学解析 Rust 采用 let 声明变量并通过 mut 显式标记可变性,这种设计体现了语言的核心哲学。以下是深度解析: 1.1 设计理念剖析 安全优先原则:默认不可变强制开发者明确声明意图 let x 5; …...
深入剖析AI大模型:大模型时代的 Prompt 工程全解析
今天聊的内容,我认为是AI开发里面非常重要的内容。它在AI开发里无处不在,当你对 AI 助手说 "用李白的风格写一首关于人工智能的诗",或者让翻译模型 "将这段合同翻译成商务日语" 时,输入的这句话就是 Prompt。…...
基于距离变化能量开销动态调整的WSN低功耗拓扑控制开销算法matlab仿真
目录 1.程序功能描述 2.测试软件版本以及运行结果展示 3.核心程序 4.算法仿真参数 5.算法理论概述 6.参考文献 7.完整程序 1.程序功能描述 通过动态调整节点通信的能量开销,平衡网络负载,延长WSN生命周期。具体通过建立基于距离的能量消耗模型&am…...
SCAU期末笔记 - 数据分析与数据挖掘题库解析
这门怎么题库答案不全啊日 来简单学一下子来 一、选择题(可多选) 将原始数据进行集成、变换、维度规约、数值规约是在以下哪个步骤的任务?(C) A. 频繁模式挖掘 B.分类和预测 C.数据预处理 D.数据流挖掘 A. 频繁模式挖掘:专注于发现数据中…...
鸿蒙中用HarmonyOS SDK应用服务 HarmonyOS5开发一个医院挂号小程序
一、开发准备 环境搭建: 安装DevEco Studio 3.0或更高版本配置HarmonyOS SDK申请开发者账号 项目创建: File > New > Create Project > Application (选择"Empty Ability") 二、核心功能实现 1. 医院科室展示 /…...
【Java_EE】Spring MVC
目录 Spring Web MVC 编辑注解 RestController RequestMapping RequestParam RequestParam RequestBody PathVariable RequestPart 参数传递 注意事项 编辑参数重命名 RequestParam 编辑编辑传递集合 RequestParam 传递JSON数据 编辑RequestBody …...
Redis数据倾斜问题解决
Redis 数据倾斜问题解析与解决方案 什么是 Redis 数据倾斜 Redis 数据倾斜指的是在 Redis 集群中,部分节点存储的数据量或访问量远高于其他节点,导致这些节点负载过高,影响整体性能。 数据倾斜的主要表现 部分节点内存使用率远高于其他节…...
2025季度云服务器排行榜
在全球云服务器市场,各厂商的排名和地位并非一成不变,而是由其独特的优势、战略布局和市场适应性共同决定的。以下是根据2025年市场趋势,对主要云服务器厂商在排行榜中占据重要位置的原因和优势进行深度分析: 一、全球“三巨头”…...
#Uniapp篇:chrome调试unapp适配
chrome调试设备----使用Android模拟机开发调试移动端页面 Chrome://inspect/#devices MuMu模拟器Edge浏览器:Android原生APP嵌入的H5页面元素定位 chrome://inspect/#devices uniapp单位适配 根路径下 postcss.config.js 需要装这些插件 “postcss”: “^8.5.…...
在Mathematica中实现Newton-Raphson迭代的收敛时间算法(一般三次多项式)
考察一般的三次多项式,以r为参数: p[z_, r_] : z^3 (r - 1) z - r; roots[r_] : z /. Solve[p[z, r] 0, z]; 此多项式的根为: 尽管看起来这个多项式是特殊的,其实一般的三次多项式都是可以通过线性变换化为这个形式…...
