1. Dubbo

1.1 创建接口

1).定义接口
18-Dubbo 重构京淘项目 - 图1
2).定义接口代码
18-Dubbo 重构京淘项目 - 图2

1.2 创建服务生产者

1.2.1 定义生产者的实现类

  1. package com.jt.dubbo.service;
  2. import java.util.List;
  3. import org.springframework.beans.factory.annotation.Autowired;
  4. import com.alibaba.dubbo.config.annotation.Service;
  5. import com.jt.dubbo.mapper.UserMapper;
  6. import com.jt.dubbo.pojo.User;
  7. @Service(timeout=3000) //3秒超时 内部实现了rpc
  8. //@org.springframework.stereotype.Service//将对象交给spring容器管理
  9. public class UserServiceImpl implements UserService {
  10. @Autowired
  11. private UserMapper userMapper;
  12. @Override
  13. public List<User> findAll() {
  14. System.out.println("我是第一个服务的提供者");
  15. return userMapper.selectList(null);
  16. }
  17. @Override
  18. public void saveUser(User user) {
  19. userMapper.insert(user);
  20. }
  21. }

1.2.2 提供者配置文件

  1. server:
  2. port: 9000 #定义端口
  3. spring:
  4. datasource:
  5. #引入druid数据源
  6. type: com.alibaba.druid.pool.DruidDataSource
  7. driver-class-name: com.mysql.jdbc.Driver
  8. url: jdbc:mysql://127.0.0.1:3306/jtdb?serverTimezone=GMT%2B8&useUnicode=true&characterEncoding=utf8&autoReconnect=true&allowMultiQueries=true
  9. username: root
  10. password: root
  11. #关于Dubbo配置
  12. dubbo:
  13. scan:
  14. basePackages: com.jt #指定dubbo的包路径
  15. application: #应用名称
  16. name: provider-user #一个接口对应一个服务名称
  17. registry:
  18. address: zookeeper://192.168.126.129:2181?backup=192.168.126.129:2182,192.168.126.129:2183
  19. protocol: #指定协议
  20. name: dubbo #使用dubbo协议(tcp-ip) web-controller直接调用sso-Service
  21. port: 20880 #每一个服务都有自己特定的端口 不能重复.
  22. mybatis-plus:
  23. type-aliases-package: com.jt.dubbo.pojo #配置别名包路径
  24. mapper-locations: classpath:/mybatis/mappers/*.xml #添加mapper映射文件
  25. configuration:
  26. map-underscore-to-camel-case: true #开启驼峰映射规则

1.3 服务消费者

1.3.1 编辑Controller

  1. package com.jt.dubbo.controller;
  2. import java.util.List;
  3. import org.springframework.beans.factory.annotation.Autowired;
  4. import org.springframework.web.bind.annotation.RequestMapping;
  5. import org.springframework.web.bind.annotation.RestController;
  6. import com.alibaba.dubbo.config.annotation.Reference;
  7. import com.jt.dubbo.pojo.User;
  8. import com.jt.dubbo.service.UserService;
  9. @RestController
  10. public class UserController {
  11. //利用dubbo的方式为接口创建代理对象 利用rpc调用
  12. //调用远程服务就像调用自己的服务一样的简单!!!
  13. @Reference
  14. private UserService userService;
  15. /**
  16. * Dubbo框架调用特点:远程RPC调用就像调用自己本地服务一样简单
  17. * @return
  18. */
  19. @RequestMapping("/findAll")
  20. public List<User> findAll(){
  21. //远程调用时传递的对象数据必须序列化.
  22. return userService.findAll();
  23. }
  24. @RequestMapping("/saveUser/{name}/{age}/{sex}")
  25. public String saveUser(User user) {
  26. userService.saveUser(user);
  27. return "用户入库成功!!!";
  28. }
  29. }

1.3.2 编辑YML配置文件

  1. server:
  2. port: 9001
  3. dubbo:
  4. scan:
  5. basePackages: com.jt
  6. application:
  7. name: consumer-user #定义消费者名称
  8. registry: #注册中心地址
  9. address: zookeeper://192.168.126.129:2181?backup=192.168.126.129:2182,192.168.126.129:2183

1.3.3 消费者测试

18-Dubbo 重构京淘项目 - 图3

1.4 Dubbo高可用测试

1.4.1 测试需求

1).测试当服务器宕机,用户访问是否受影响. 用户访问不受影响. zk心跳检测机制
2).测试当zk集群宕机,用户访问是否受影响. 不受影响 消费者在本地有服务列表数据,自己维护.
3).测试是否有负载均衡的效果 用户访问有负载均衡的效果

1.5 Dubbo负载均衡

1.5.1 负载均衡方式

1.服务端负载均衡(集中式负载均衡)
说明: 用户访问服务器时不清楚真实的服务器到底是谁,由负载均衡服务器动态动态管理.
典型代表: NGINX
一般nginx服务器做反向代理使用,负载均衡只是提供的功能.
2.客户端负载均衡
说明:采用微服务架构时,当消费者访问服务提供者时,由于框架内部已经实现了负载均衡的策略,所以消费者访问提供者时已经完成了负载均衡的机制.所以将所有的压力平衡到了各个消费者中.
18-Dubbo 重构京淘项目 - 图4

1.5.2 负载均衡-随机算法

默认条件下就是随机算法
18-Dubbo 重构京淘项目 - 图5
18-Dubbo 重构京淘项目 - 图6

1.5.2 负载均衡-轮询算法

18-Dubbo 重构京淘项目 - 图7
18-Dubbo 重构京淘项目 - 图8

1.5.3 负载均衡-一致性hash

18-Dubbo 重构京淘项目 - 图9
18-Dubbo 重构京淘项目 - 图10

1.5.3 负载均衡-最少访问

18-Dubbo 重构京淘项目 - 图11
18-Dubbo 重构京淘项目 - 图12

2. 重构京淘项目

2.0 导入jar包

  1. <!--引入dubbo配置 -->
  2. <dependency>
  3. <groupId>com.alibaba.boot</groupId>
  4. <artifactId>dubbo-spring-boot-starter</artifactId>
  5. <version>0.2.0</version>
  6. </dependency>

2.1 重构接口项目

说明:在jt-common中添加接口文件.
18-Dubbo 重构京淘项目 - 图13

2.2 重构JT-SSO(生产者)

2.2.1编辑Service实现类

18-Dubbo 重构京淘项目 - 图14

2.2.2 编辑YML配置文件

  1. server:
  2. port: 8093
  3. servlet:
  4. context-path: / #在根目录中发布 缺省值.
  5. spring:
  6. datasource:
  7. #引入druid数据源
  8. #type: com.alibaba.druid.pool.DruidDataSource
  9. #driver-class-name: com.mysql.jdbc.Driver
  10. url: jdbc:mysql://127.0.0.1:3306/jtdb?serverTimezone=GMT%2B8&useUnicode=true&characterEncoding=utf8&autoReconnect=true&allowMultiQueries=true
  11. username: root
  12. password: root
  13. mvc:
  14. view:
  15. prefix: /WEB-INF/views/
  16. suffix: .jsp
  17. #mybatis-plush配置
  18. mybatis-plus:
  19. type-aliases-package: com.jt.pojo
  20. mapper-locations: classpath:/mybatis/mappers/*.xml
  21. configuration:
  22. map-underscore-to-camel-case: true
  23. logging:
  24. level:
  25. com.jt.mapper: debug
  26. #关于Dubbo配置
  27. dubbo:
  28. scan:
  29. basePackages: com.jt #指定dubbo的包路径
  30. application: #应用名称
  31. name: provider-user #一个接口对应一个服务名称
  32. registry:
  33. address: zookeeper://192.168.126.129:2181?backup=192.168.126.129:2182,192.168.126.129:2183
  34. protocol: #指定协议
  35. name: dubbo #使用dubbo协议(tcp-ip) web-controller直接调用sso-Service
  36. port: 20880 #每一个服务都有自己特定的端口 不能重复.

2.3 重构服务消费者

2.3.1 编辑UserController

18-Dubbo 重构京淘项目 - 图15

2.3.2 编辑YML配置文件

  1. server:
  2. port: 8092
  3. spring: #定义springmvc视图解析器
  4. mvc:
  5. view:
  6. prefix: /WEB-INF/views/
  7. suffix: .jsp
  8. #配置dubbo消费者
  9. dubbo:
  10. scan:
  11. basePackages: com.jt
  12. application:
  13. name: consumer-user #定义消费者名称
  14. registry: #注册中心地址
  15. address: zookeeper://192.168.126.129:2181?backup=192.168.126.129:2182,192.168.126.129:2183

3. 用户模块实现

3.1 用户注册实现

3.1.1 页面分析

1).页面url地址
18-Dubbo 重构京淘项目 - 图16
2.页面提交参数
18-Dubbo 重构京淘项目 - 图17
3.页面JS分析
18-Dubbo 重构京淘项目 - 图18

3.1.2 编辑UserController

  1. /**
  2. * 完成用户的注册操作
  3. * url地址: http://www.jt.com/user/doRegister
  4. * Request Method: POST
  5. * 请求参数:
  6. * password: admin123
  7. * username: admin123123123
  8. * phone: 13111112225
  9. * 返回值类型:
  10. * SysResult对象
  11. */
  12. @RequestMapping("/doRegister")
  13. @ResponseBody
  14. public SysResult saveUser(User user){
  15. //利用dubbo进行RPC调用
  16. dubboUserService.saveUser(user);
  17. return SysResult.success();
  18. }

3.1.2 编辑UserService

  1. package com.jt.service;
  2. import com.alibaba.dubbo.config.annotation.Service;
  3. import com.jt.mapper.UserMapper;
  4. import com.jt.pojo.User;
  5. import org.springframework.beans.factory.annotation.Autowired;
  6. import org.springframework.util.DigestUtils;
  7. @Service(timeout = 3000)
  8. public class DubboUserServiceImpl implements DubboUserService{
  9. @Autowired
  10. private UserMapper userMapper;
  11. @Override
  12. public void saveUser(User user) {
  13. //密码采用md5方式进行加密处理
  14. String password = user.getPassword();
  15. String md5Pass = DigestUtils.md5DigestAsHex(password.getBytes());
  16. user.setEmail(user.getPhone()).setPassword(md5Pass);
  17. userMapper.insert(user);
  18. }
  19. }

3.1.3 页面效果展现

18-Dubbo 重构京淘项目 - 图19

3.2 用户登录

3.2.1 单点登录业务实现

单点登录(SingleSignOn,SSO),就是通过用户的一次性鉴别登录。当用户在身份认证服务器上登录一次以后,即可获得访问单点登录系统中其他关联系统和应用软件的权限,同时这种实现是不需要管理员对用户的登录状态或其他信息进行修改的,这意味着在多个应用系统中,用户只需一次登录就可以访问所有相互信任的应用系统。这种方式减少了由登录产生的时间消耗,辅助了用户管理,是目前比较流行的.
18-Dubbo 重构京淘项目 - 图20
实现步骤:
1.用户输入用户名和密码之后点击登录按钮开始进行登录操作.
2.JT-WEB向JT-SSO发送请求,完成数据校验
3.当JT-SSO获取数据信息之后,完成用户的校验,如果校验通过则将用户信息转化为json.并且动态生成UUID.将数据保存到redis中. 并且返回值uuid.
如果校验不存在时,直接返回”不存在”即可.
4.JT-SSO将数据返回给JT-WEB服务器.
5.如果登录成功,则将用户UUID保存到客户端的cookie中.

3.2.2 页面URL分析

1).url请求
18-Dubbo 重构京淘项目 - 图21
2).url参数
18-Dubbo 重构京淘项目 - 图22
3).页面JS分析
18-Dubbo 重构京淘项目 - 图23

3.2.3 编辑UserController

  1. /**
  2. * 业务:完成用户登录操作
  3. * url地址: http://www.jt.com/user/doLogin?r=0.35842191622936337
  4. * 参数:
  5. * username: admin123
  6. * password: admin123456
  7. * 返回值: SysResult对象
  8. *
  9. * 业务具体实现:
  10. * 1.校验用户名和密码是否正确
  11. * 2.判断返回值结果是否为null 用户名和密码有误 返回201状态码
  12. * 3.如果返回值结果不为null uuid保存到cookie中即可.
  13. *
  14. * Cookie知识介绍:
  15. * 1.cookie.setPath("/") 根目录有效
  16. * url1: www.jt.com/addUser
  17. * url2: www.jt.com/user/addUser
  18. *
  19. * 2. cookie.setDomain("域名地址"); cookie在哪个域名中共享
  20. * 例子1: cookie.setDomain("www.jt.com");
  21. * 只有在www.jt.com的域名中有效
  22. *
  23. * cookie.setDomain("jt.com");
  24. * 只有在jt.com结尾的域名中有效
  25. *
  26. */
  27. @RequestMapping("/doLogin")
  28. @ResponseBody
  29. public SysResult doLogin(User user, HttpServletResponse response){
  30. String uuid = dubboUserService.doLogin(user);
  31. if(StringUtils.isEmpty(uuid)){
  32. return SysResult.fail();
  33. }
  34. //将uuid保存到Cookie中
  35. Cookie cookie = new Cookie("JT_TICKET",uuid);
  36. cookie.setMaxAge(30*24*60*60); //让cookie 30天有效
  37. cookie.setPath("/"); //cookie在哪个url路径生效
  38. cookie.setDomain("jt.com"); //设定cookie共享
  39. response.addCookie(cookie);
  40. return SysResult.success();
  41. }

3.2.4 编辑UserService

  1. /**
  2. * 1.根据用户名和密码查询后端服务器数据
  3. * 将密码加密处理
  4. * @param user
  5. * @return
  6. */
  7. @Override
  8. public String doLogin(User user) {
  9. String md5Pass = DigestUtils.md5DigestAsHex(user.getPassword().getBytes());
  10. user.setPassword(md5Pass);
  11. QueryWrapper<User> queryWrapper = new QueryWrapper<>(user);//u/p不能
  12. //根据对象中不为空的属性,充当where条件.
  13. User userDB = userMapper.selectOne(queryWrapper);
  14. if(userDB == null){
  15. //根据用户名和密码错误
  16. return null;
  17. }
  18. //开始进行单点登录业务操作
  19. String uuid = UUID.randomUUID()
  20. .toString()
  21. .replace("-", "");
  22. userDB.setPassword("123456你信不?"); //去除有效信息.
  23. String userJSON = ObjectMapperUtil.toJSON(userDB);
  24. jedisCluster.setex(uuid, 30*24*60*60, userJSON);
  25. return uuid;
  26. }

3.2.5 页面效果展现

18-Dubbo 重构京淘项目 - 图24

3.3 用户信息回显

3.3.1 用户信息回显业务需求

思路: 用户通过TICKET信息,利用JSONP的方式动态获取远程的服务器数据信息.之后将数据返回之后 回显数据.

3.3.2 用户URL请求

18-Dubbo 重构京淘项目 - 图25

3.3.3 页面JS分析

18-Dubbo 重构京淘项目 - 图26

3.3.4 编辑JT-SSO的UserController

  1. /**
  2. * 业务说明:
  3. * 通过跨域请求方式,获取用户的JSON数据.
  4. * 1.url地址: http://sso.jt.com/user/query/efd321aec0ca4cd6a319b49bd0bed2db?callback=jsonp1605775149414&_=1605775149460
  5. * 2.请求参数: ticket信息
  6. * 3.返回值: SysResult对象 (userJSON)
  7. * 需求: 通过ticket信息获取user JSON串
  8. */
  9. @RequestMapping("/query/{ticket}")
  10. public JSONPObject findUserByTicket(@PathVariable String ticket,String callback){
  11. String userJSON = jedisCluster.get(ticket);
  12. if(StringUtils.isEmpty(userJSON)){
  13. return new JSONPObject(callback, SysResult.fail());
  14. }else{
  15. return new JSONPObject(callback, SysResult.success(userJSON));
  16. }
  17. }

3.3.5 页面效果展现

18-Dubbo 重构京淘项目 - 图27

3.4 用户登出操作

3.4.1 退出业务逻辑

当用户点击退出操作时,应该重定向到系统首页. 同时删除redis信息/Cookie信息.

3.4.2 编辑UserController

  1. /**
  2. * 完成用户退出操作
  3. * url地址:http://www.jt.com/user/logout.html
  4. * 参数: 没有参数
  5. * 返回值: String 重定向到系统首页
  6. * 业务:
  7. * 1.删除redis K-V 获取ticket信息
  8. * 2.删除cookie
  9. */
  10. @RequestMapping("/logout")
  11. public String logout(HttpServletRequest request,HttpServletResponse response){
  12. //1.获取Cookie中的JT_TICKET值
  13. Cookie[] cookies = request.getCookies();
  14. if(cookies != null && cookies.length>0){
  15. for (Cookie cookie : cookies){
  16. if(cookie.getName().equals("JT_TICKET")){
  17. String ticket = cookie.getValue();
  18. //redis删除ticket信息
  19. jedisCluster.del(ticket);
  20. cookie.setMaxAge(0); //0表示立即删除
  21. //规则cookie如果需要操作,必须严格定义
  22. cookie.setPath("/");
  23. cookie.setDomain("jt.com");
  24. response.addCookie(cookie);
  25. }
  26. }
  27. }
  28. return "redirect:/";
  29. }

4. 商品信息展现

4.1 业务需求说明

当用户点击商品时应该跳转到商品的展现页面,在页面中应该展现2部分数据.item数据/itemDesc数据. item.jsp页面
数据取值方式:
1.获取item信息 ${item.title }
2.获取ItemDesc数据 ${itemDesc.itemDesc}

4.2 重构JT-MANAGE

4.2.1 编辑ItemService

18-Dubbo 重构京淘项目 - 图28

4.2.2 编辑YML配置

  1. server:
  2. port: 8091
  3. servlet:
  4. context-path: / #在根目录中发布 缺省值.
  5. spring:
  6. datasource:
  7. #引入druid数据源
  8. #type: com.alibaba.druid.pool.DruidDataSource
  9. #driver-class-name: com.mysql.jdbc.Driver
  10. url: jdbc:mysql://127.0.0.1:3306/jtdb?serverTimezone=GMT%2B8&useUnicode=true&characterEncoding=utf8&autoReconnect=true&allowMultiQueries=true
  11. username: root
  12. password: root
  13. mvc:
  14. view:
  15. prefix: /WEB-INF/views/
  16. suffix: .jsp
  17. #mybatis-plush配置
  18. mybatis-plus:
  19. type-aliases-package: com.jt.pojo
  20. mapper-locations: classpath:/mybatis/mappers/*.xml
  21. configuration:
  22. map-underscore-to-camel-case: true
  23. logging:
  24. level:
  25. com.jt.mapper: debug
  26. #配置manage Dubbo服务
  27. dubbo:
  28. scan:
  29. basePackages: com.jt #指定dubbo的包路径
  30. application: #应用名称
  31. name: provider-item #一个接口对应一个服务名称
  32. registry:
  33. address: zookeeper://192.168.126.129:2181?backup=192.168.126.129:2182,192.168.126.129:2183
  34. protocol: #指定协议
  35. name: dubbo #使用dubbo协议(tcp-ip) web-controller直接调用sso-Service
  36. port: 20881 #每一个服务都有自己特定的端口 不能重复.

4.3 实现页面跳转

4.3.1 页面URL分析

18-Dubbo 重构京淘项目 - 图29

4.3.2 编辑ItemController

  1. package com.jt.controller;
  2. import com.alibaba.dubbo.config.annotation.Reference;
  3. import com.jt.pojo.Item;
  4. import com.jt.pojo.ItemDesc;
  5. import com.jt.service.DubboItemService;
  6. import org.springframework.stereotype.Controller;
  7. import org.springframework.ui.Model;
  8. import org.springframework.web.bind.annotation.PathVariable;
  9. import org.springframework.web.bind.annotation.RequestMapping;
  10. import javax.xml.ws.RequestWrapper;
  11. @Controller
  12. public class ItemController {
  13. @Reference(check = false)
  14. private DubboItemService itemService;
  15. /**
  16. * 实现商品的展现
  17. * url: http://www.jt.com/items/562379.html
  18. * 参数: 562379商品ID号
  19. * 返回值: item.jsp
  20. * 页面取值: item对象/itemDesc对象
  21. * {item.id/title}
  22. */
  23. @RequestMapping("/items/{itemId}")
  24. public String findItemById(@PathVariable Long itemId, Model model){
  25. Item item = itemService.findItemById(itemId);
  26. ItemDesc itemDesc = itemService.findItemDescById(itemId);
  27. model.addAttribute("item",item);
  28. model.addAttribute("itemDesc",itemDesc);
  29. return "item";
  30. }
  31. }

4.3.3 编辑ItemService

  1. package com.jt.web.service;
  2. import com.alibaba.dubbo.config.annotation.Service;
  3. import com.jt.mapper.ItemDescMapper;
  4. import com.jt.mapper.ItemMapper;
  5. import com.jt.pojo.Item;
  6. import com.jt.pojo.ItemDesc;
  7. import com.jt.service.DubboItemService;
  8. import org.springframework.beans.factory.annotation.Autowired;
  9. @Service(timeout = 3000)
  10. public class DubboItemServiceImpl implements DubboItemService {
  11. @Autowired
  12. private ItemMapper itemMapper;
  13. @Autowired
  14. private ItemDescMapper itemDescMapper;
  15. @Override
  16. public Item findItemById(Long itemId) {
  17. return itemMapper.selectById(itemId);
  18. }
  19. @Override
  20. public ItemDesc findItemDescById(Long itemId) {
  21. return itemDescMapper.selectById(itemId);
  22. }
  23. }

4.3.4 页面效果展现

18-Dubbo 重构京淘项目 - 图30

5 购物车操作

5.1 业务分析

说明:当用户点击购物车按钮时,应该跳转到购物车列表页面.
18-Dubbo 重构京淘项目 - 图31
页面名称: cart.jsp
页面数据: ${cartList}

5.2 创建购物Cart POJO

  1. package com.jt.pojo;
  2. import com.baomidou.mybatisplus.annotation.IdType;
  3. import com.baomidou.mybatisplus.annotation.TableId;
  4. import com.baomidou.mybatisplus.annotation.TableName;
  5. import lombok.Data;
  6. import lombok.experimental.Accessors;
  7. @TableName("tb_cart")
  8. @Data
  9. @Accessors(chain = true)
  10. public class Cart extends BasePojo{
  11. @TableId(type = IdType.AUTO) //主键自增
  12. private Long id; //购物车Id号
  13. private Long userId; //用户Id号
  14. private Long itemId; //商品id号
  15. private String itemTitle; //商品标题
  16. private String itemImage; //商品图片信息
  17. private Long itemPrice;
  18. private Integer num;
  19. }

5.3 创建JT-CART项目

5.3.1 创建项目

18-Dubbo 重构京淘项目 - 图32

5.3.2 添加继承依赖插件

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <project xmlns="http://maven.apache.org/POM/4.0.0"
  3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4. xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  5. <modelVersion>4.0.0</modelVersion>
  6. <artifactId>jt-cart</artifactId>
  7. <parent>
  8. <artifactId>jt2007</artifactId>
  9. <groupId>com.jt</groupId>
  10. <version>1.0-SNAPSHOT</version>
  11. </parent>
  12. <!--3.依赖工具API-->
  13. <dependencies>
  14. <dependency>
  15. <groupId>com.jt</groupId>
  16. <artifactId>jt-common</artifactId>
  17. <version>1.0-SNAPSHOT</version>
  18. </dependency>
  19. </dependencies>
  20. <!--4.添加maven插件-->
  21. <build>
  22. <plugins>
  23. <plugin>
  24. <groupId>org.springframework.boot</groupId>
  25. <artifactId>spring-boot-maven-plugin</artifactId>
  26. </plugin>
  27. </plugins>
  28. </build>
  29. </project>

5.3.3 购物车项目结构

18-Dubbo 重构京淘项目 - 图33

6.总结

本节重点在于了解Dubbo服务在项目中的应用,熟悉器基本应用流程,重构京淘项目的业务实现架构。