1. Dubbo
1.1 创立接口
1).定义接口
2).定义接口代码
1.2 创立服务生产者
1.2.1 定义生产者的实现类
package com.jt.dubbo.service;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import com.alibaba.dubbo.config.annotation.Service;
import com.jt.dubbo.mapper.UserMapper;
import com.jt.dubbo.pojo.User;
@Service(timeout=3000) //3秒超时 外部实现了rpc
//@org.springframework.stereotype.Service//将对象交给spring容器治理
public class UserServiceImpl implements UserService {
@Autowired
private UserMapper userMapper;
@Override
public List<User> findAll() {
System.out.println("我是第一个服务的提供者");
return userMapper.selectList(null);
}
@Override
public void saveUser(User user) {
userMapper.insert(user);
}
}
1.2.2 提供者配置文件
server:
port: 9000 #定义端口
spring:
datasource:
#引入druid数据源
type: com.alibaba.druid.pool.DruidDataSource
driver-class-name: com.mysql.jdbc.Driver
url: jdbc:mysql://127.0.0.1:3306/jtdb?serverTimezone=GMT%2B8&useUnicode=true&characterEncoding=utf8&autoReconnect=true&allowMultiQueries=true
username: root
password: root
#对于Dubbo配置
dubbo:
scan:
basePackages: com.jt #指定dubbo的包门路
application: #利用名称
name: provider-user #一个接口对应一个服务名称
registry:
address: zookeeper://192.168.126.129:2181?backup=192.168.126.129:2182,192.168.126.129:2183
protocol: #指定协定
name: dubbo #应用dubbo协定(tcp-ip) web-controller间接调用sso-Service
port: 20880 #每一个服务都有本人特定的端口 不能反复.
mybatis-plus:
type-aliases-package: com.jt.dubbo.pojo #配置别名包门路
mapper-locations: classpath:/mybatis/mappers/*.xml #增加mapper映射文件
configuration:
map-underscore-to-camel-case: true #开启驼峰映射规定
1.3 服务消费者
1.3.1 编辑Controller
package com.jt.dubbo.controller;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.alibaba.dubbo.config.annotation.Reference;
import com.jt.dubbo.pojo.User;
import com.jt.dubbo.service.UserService;
@RestController
public class UserController {
//利用dubbo的形式为接口创立代理对象 利用rpc调用
//调用近程服务就像调用本人的服务一样的简略!!!
@Reference
private UserService userService;
/**
* Dubbo框架调用特点:近程RPC调用就像调用本人本地服务一样简略
* @return
*/
@RequestMapping("/findAll")
public List<User> findAll(){
//近程调用时传递的对象数据必须序列化.
return userService.findAll();
}
@RequestMapping("/saveUser/{name}/{age}/{sex}")
public String saveUser(User user) {
userService.saveUser(user);
return "用户入库胜利!!!";
}
}
1.3.2 编辑YML配置文件
server:
port: 9001
dubbo:
scan:
basePackages: com.jt
application:
name: consumer-user #定义消费者名称
registry: #注册核心地址
address: zookeeper://192.168.126.129:2181?backup=192.168.126.129:2182,192.168.126.129:2183
1.3.3 消费者测试
1.4 Dubbo高可用测试
1.4.1 测试需要
1).测试当服务器宕机,用户拜访是否受影响. 用户拜访不受影响. zk心跳检测机制
2).测试当zk集群宕机,用户拜访是否受影响. 消费者在本地有服务列表数据,本人保护.
3).测试是否由负载平衡的成果 用户拜访有负载平衡的成果
1.5 Dubbo负载平衡
1.5.1 负载平衡形式
1.服务端负载平衡(集中式负载平衡)
阐明:用户拜访服务器时不分明实在的服务器到底是谁,由负载平衡服务器动静治理
典型代表:NGINX
个别nginx服务器做反向代理应用,负载平衡只是提供服务
2.客户端负载平衡
阐明:采纳微服务架构时,当消费者拜访服务提供者时,因为框架外部曾经实现了负载平衡的策略,所以消费者拜访提供者时曾经实现了负载平衡的机制.所以将所有的压力均衡到了各个消费者中.
1.5.2 负载平衡-随机算法
默认条件下就是随机算法
1.5.2 负载平衡-轮询算法
1.5.3 负载平衡-一致性hash
1.5.3 负载平衡-起码拜访
2. 重构京淘我的项目
2.0 导入jar包
<!--引入dubbo配置 -->
<dependency>
<groupId>com.alibaba.boot</groupId>
<artifactId>dubbo-spring-boot-starter</artifactId>
<version>0.2.0</version>
</dependency>
2.1 重构接口我的项目
阐明:在jt-common中增加接口文件
重构JT-SSO(生产者)
2.2.1 编辑Servicec实现类
2.2.2 编辑YML配置文件
server:
port: 8093
servlet:
context-path: / #在根目录中公布 缺省值.
spring:
datasource:
#引入druid数据源
#type: com.alibaba.druid.pool.DruidDataSource
#driver-class-name: com.mysql.jdbc.Driver
url: jdbc:mysql://127.0.0.1:3306/jtdb?serverTimezone=GMT%2B8&useUnicode=true&characterEncoding=utf8&autoReconnect=true&allowMultiQueries=true
username: root
password: root
mvc:
view:
prefix: /WEB-INF/views/
suffix: .jsp
#mybatis-plush配置
mybatis-plus:
type-aliases-package: com.jt.pojo
mapper-locations: classpath:/mybatis/mappers/*.xml
configuration:
map-underscore-to-camel-case: true
logging:
level:
com.jt.mapper: debug
#对于Dubbo配置
dubbo:
scan:
basePackages: com.jt #指定dubbo的包门路
application: #利用名称
name: provider-user #一个接口对应一个服务名称
registry:
address: zookeeper://192.168.126.129:2181?backup=192.168.126.129:2182,192.168.126.129:2183
protocol: #指定协定
name: dubbo #应用dubbo协定(tcp-ip) web-controller间接调用sso-Service
port: 20880 #每一个服务都有本人特定的端口 不能反复.
2.3 重构服务消费者
2.3.1 编辑UserController
2.3.2 编辑YML配置文件
server:
port: 8092
spring: #定义springmvc视图解析器
mvc:
view:
prefix: /WEB-INF/views/
suffix: .jsp
#配置dubbo消费者
dubbo:
scan:
basePackages: com.jt
application:
name: consumer-user #定义消费者名称
registry: #注册核心地址
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地址
2.页面提交参数
3.页面JS剖析
3.1.2 编辑UserController
/**
* 实现用户的注册操作
* url地址: http://www.jt.com/user/doRegister
* Request Method: POST
* 申请参数:
* password: admin123
* username: admin123123123
* phone: 13111112225
* 返回值类型:
* SysResult对象
*/
@RequestMapping("/doRegister")
@ResponseBody
public SysResult saveUser(User user){
//利用dubbo进行RPC调用
dubboUserService.saveUser(user);
return SysResult.success();
}
3.1.2 编辑UserService
package com.jt.service;
import com.alibaba.dubbo.config.annotation.Service;
import com.jt.mapper.UserMapper;
import com.jt.pojo.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.DigestUtils;
@Service(timeout = 3000)
public class DubboUserServiceImpl implements DubboUserService{
@Autowired
private UserMapper userMapper;
@Override
public void saveUser(User user) {
//明码采纳md5形式进行加密解决
String password = user.getPassword();
String md5Pass = DigestUtils.md5DigestAsHex(password.getBytes());
user.setEmail(user.getPhone()).setPassword(md5Pass);
userMapper.insert(user);
}
}
3.1.3 页面成果展示
3.2 用户登录
3.2.1 单点登录业务实现
单点登录(SingleSignOn,SSO),就是通过用户的一次性甄别登录。当用户在身份认证服务器上登录一次当前,即可取得拜访单点登录零碎中其余关联系统和应用软件的权限,同时这种实现是不须要管理员对用户的登录状态或其余信息进行批改的,这意味着在多个利用零碎中,用户只需一次登录就能够拜访所有相互信任的利用零碎。这种形式缩小了由登录产生的工夫耗费,辅助了用户治理,是目前比拟风行的
实现步骤:
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申请
2).url参数
3).页面JS剖析
3.2.2 编辑UserController
/**
* 业务:实现用户登录操作
* url地址: http://www.jt.com/user/doLogin?r=0.35842191622936337
* 参数:
* username: admin123
* password: admin123456
* 返回值: SysResult对象
*
* 业务具体实现:
* 1.校验用户名和明码是否正确
* 2.判断返回值后果是否为null 用户名和明码有误 返回201状态码
* 3.如果返回值后果不为null uuid保留到cookie中即可.
*
* Cookie常识介绍:
* 1.cookie.setPath("/") 根目录无效
* url1: www.jt.com/addUser
* url2: www.jt.com/user/addUser
*
* 2. cookie.setDomain("域名地址"); cookie在哪个域名中共享
* 例子1: cookie.setDomain("www.jt.com");
* 只有在www.jt.com的域名中无效
*
* cookie.setDomain("jt.com");
* 只有在jt.com结尾的域名中无效
*
*/
@RequestMapping("/doLogin")
@ResponseBody
public SysResult doLogin(User user, HttpServletResponse response){
String uuid = dubboUserService.doLogin(user);
if(StringUtils.isEmpty(uuid)){
return SysResult.fail();
}
//将uuid保留到Cookie中
Cookie cookie = new Cookie("JT_TICKET",uuid);
cookie.setMaxAge(30*24*60*60); //让cookie 30天无效
cookie.setPath("/"); //cookie在哪个url门路失效
cookie.setDomain("jt.com"); //设定cookie共享
response.addCookie(cookie);
return SysResult.success();
}
3.2.4 编辑UserService
/**
* 1.依据用户名和明码查问后端服务器数据
* 将明码加密解决
* @param user
* @return
*/
@Override
public String doLogin(User user) {
String md5Pass = DigestUtils.md5DigestAsHex(user.getPassword().getBytes());
user.setPassword(md5Pass);
QueryWrapper<User> queryWrapper = new QueryWrapper<>(user);//u/p不能
//依据对象中不为空的属性,充当where条件.
User userDB = userMapper.selectOne(queryWrapper);
if(userDB == null){
//依据用户名和明码谬误
return null;
}
//开始进行单点登录业务操作
String uuid = UUID.randomUUID()
.toString()
.replace("-", "");
userDB.setPassword("123456你信不?"); //去除无效信息.
String userJSON = ObjectMapperUtil.toJSON(userDB);
jedisCluster.setex(uuid, 30*24*60*60, userJSON);
return uuid;
}
3.2.5 页面成果展示
3.3 用户信息回显
3.3.1 用户信息回显业务需要
思路: 用户通过TICKET信息,利用JSONP的形式动静获取近程的服务器数据信息.之后将数据返回之后 回显数据.
3.3.2 用户URL申请
3.3.3 页面JS剖析
3.3.4 编辑JT-SSO的UserController
/**
* 业务阐明:
* 通过跨域申请形式,获取用户的JSON数据.
* 1.url地址: http://sso.jt.com/user/query/efd321aec0ca4cd6a319b49bd0bed2db?callback=jsonp1605775149414&_=1605775149460
* 2.申请参数: ticket信息
* 3.返回值: SysResult对象 (userJSON)
* 需要: 通过ticket信息获取user JSON串
*/
@RequestMapping("/query/{ticket}")
public JSONPObject findUserByTicket(@PathVariable String ticket,String callback){
String userJSON = jedisCluster.get(ticket);
if(StringUtils.isEmpty(userJSON)){
return new JSONPObject(callback, SysResult.fail());
}else{
return new JSONPObject(callback, SysResult.success(userJSON));
}
}
3.3.5 页面成果展示
3.4 用户登出操作
3.4.1 退出业务逻辑
当用户点击退出操作时,应该重定向到零碎首页.同时删除redis信息/Cookie信息.
3.4.1 编辑UserController
/**
* 实现用户退出操作
* url地址:http://www.jt.com/user/logout.html
* 参数: 没有参数
* 返回值: String 重定向到零碎首页
* 业务:
* 1.删除redis K-V 获取ticket信息
* 2.删除cookie
*/
@RequestMapping("/logout")
public String logout(HttpServletRequest request,HttpServletResponse response){
//1.获取Cookie中的JT_TICKET值
Cookie[] cookies = request.getCookies();
if(cookies != null && cookies.length>0){
for (Cookie cookie : cookies){
if(cookie.getName().equals("JT_TICKET")){
String ticket = cookie.getValue();
//redis删除ticket信息
jedisCluster.del(ticket);
cookie.setMaxAge(0); //0示意立刻删除
//规定cookie如果须要操作,必须严格定义
cookie.setPath("/");
cookie.setDomain("jt.com");
response.addCookie(cookie);
}
}
}
return "redirect:/";
}
4. 商品信息展示
4.1 业务需要阐明
当用户点击商品时应该跳转到商品的展示页面,在页面中应该展示2局部数据.item数据/itemDesc数据. item.jsp页面
数据取值形式:
1.获取item信息 ${item.title }
2.获取ItemDesc数据 ${itemDesc.itemDesc}
4.2 重构JT-MANAGE
4.2.1 编辑ItemService
4.2.2 编辑YML配置
server:
port: 8091
servlet:
context-path: / #在根目录中公布 缺省值.
spring:
datasource:
#引入druid数据源
#type: com.alibaba.druid.pool.DruidDataSource
#driver-class-name: com.mysql.jdbc.Driver
url: jdbc:mysql://127.0.0.1:3306/jtdb?serverTimezone=GMT%2B8&useUnicode=true&characterEncoding=utf8&autoReconnect=true&allowMultiQueries=true
username: root
password: root
mvc:
view:
prefix: /WEB-INF/views/
suffix: .jsp
#mybatis-plush配置
mybatis-plus:
type-aliases-package: com.jt.pojo
mapper-locations: classpath:/mybatis/mappers/*.xml
configuration:
map-underscore-to-camel-case: true
logging:
level:
com.jt.mapper: debug
#配置manage Dubbo服务
dubbo:
scan:
basePackages: com.jt #指定dubbo的包门路
application: #利用名称
name: provider-item #一个接口对应一个服务名称
registry:
address: zookeeper://192.168.126.129:2181?backup=192.168.126.129:2182,192.168.126.129:2183
protocol: #指定协定
name: dubbo #应用dubbo协定(tcp-ip) web-controller间接调用sso-Service
port: 20881 #每一个服务都有本人特定的端口 不能反复.
4.3 实现页面跳转
4.3.1 页面URL剖析
4.3.2 编辑ItemController
package com.jt.controller;
import com.alibaba.dubbo.config.annotation.Reference;
import com.jt.pojo.Item;
import com.jt.pojo.ItemDesc;
import com.jt.service.DubboItemService;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import javax.xml.ws.RequestWrapper;
@Controller
public class ItemController {
@Reference(check = false)
private DubboItemService itemService;
/**
* 实现商品的展示
* url: http://www.jt.com/items/562379.html
* 参数: 562379商品ID号
* 返回值: item.jsp
* 页面取值: item对象/itemDesc对象
* {item.id/title}
*/
@RequestMapping("/items/{itemId}")
public String findItemById(@PathVariable Long itemId, Model model){
Item item = itemService.findItemById(itemId);
ItemDesc itemDesc = itemService.findItemDescById(itemId);
model.addAttribute("item",item);
model.addAttribute("itemDesc",itemDesc);
return "item";
}
}
4.3.3 编辑ItemService
package com.jt.web.service;
import com.alibaba.dubbo.config.annotation.Service;
import com.jt.mapper.ItemDescMapper;
import com.jt.mapper.ItemMapper;
import com.jt.pojo.Item;
import com.jt.pojo.ItemDesc;
import com.jt.service.DubboItemService;
import org.springframework.beans.factory.annotation.Autowired;
@Service(timeout = 3000)
public class DubboItemServiceImpl implements DubboItemService {
@Autowired
private ItemMapper itemMapper;
@Autowired
private ItemDescMapper itemDescMapper;
@Override
public Item findItemById(Long itemId) {
return itemMapper.selectById(itemId);
}
@Override
public ItemDesc findItemDescById(Long itemId) {
return itemDescMapper.selectById(itemId);
}
}
4.3.4 页面成果展示
5 购物车操作
5.1 业务剖析
阐明:当影虎点击购物车按钮时,应该跳转到购物车页面
页面名称: cart.jsp
页面数据: ${cartList}
5.2 创立购物Cart POJO
package com.jt.pojo;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import lombok.experimental.Accessors;
@TableName("tb_cart")
@Data
@Accessors(chain = true)
public class Cart extends BasePojo{
@TableId(type = IdType.AUTO) //主键自增
private Long id; //购物车Id号
private Long userId; //用户Id号
private Long itemId; //商品id号
private String itemTitle; //商品题目
private String itemImage; //商品图片信息
private Long itemPrice;
private Integer num;
}
5.3 创立JT-CART我的项目
5.3.1 创立我的项目
5.3.2 增加继承依赖插件
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<artifactId>jt-cart</artifactId>
<parent>
<artifactId>jt2007</artifactId>
<groupId>com.jt</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<!--3.依赖工具API-->
<dependencies>
<dependency>
<groupId>com.jt</groupId>
<artifactId>jt-common</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
</dependencies>
<!--4.增加maven插件-->
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
5.3.3 购物车我的项目构造
发表回复