系统间通信问题

数据同步


性能有影响。有新的系统,代码需要更新,耦合太高。
方案二:引入消息中间件(MQ),可解耦,异步化。

RabbitMQ

1、simple模式:一对一

2、work模式:消息是共享模式


限流:对于消费者说,哪个干的快,哪个就干的多。给1个,处理完后再给下一个。
用限流+手工确认。
3、发布订阅模式


X:交换机,有两个队列,每个消费者都有队列。
生产者面向的是交换机。
4、路由模式:可以指定推送消息给消费者。打标记。
5、通配符模式:

*

采用MQ的场景

邮件服务

redis实战

首页使用redis优化

第一次没有查数据库,第二次就不用查数据库,可以直接查缓存。

  • 配置application.yml
redis:host: 192.168.142.137port: 6379password: java1907
  • 配置类redisConfig
@Configuration
public class RedisConfig {@Bean(name = "myStringRedisTemplate")public RedisTemplate<String,Object> getRedisTemplate(RedisConnectionFactory connectionFactory){RedisTemplate<String,Object> redisTemplate = new RedisTemplate<>();redisTemplate.setConnectionFactory(connectionFactory);redisTemplate.setKeySerializer(new StringRedisSerializer());return redisTemplate;}
}

建一个RedisTemplate的对象

  • service实现
@Service
public class ProductTypeServiceImpl extends BaseServiceImpl<TProductType> implements IProductTypeService {@Autowiredprivate TProductTypeMapper productTypeMapper;@Resource(name = "myStringRedisTemplate")private RedisTemplate<String,Object> redisTemplate;@Overridepublic IBaseDao<TProductType> getBaseDao() {return productTypeMapper;}/*** 重写获取列表的方法,加入缓存的逻辑* 硬件* 内存读取速度》磁盘读取速度* @return*/@Overridepublic List<TProductType> list() {//1.查询当前缓存是否存在分类信息List<TProductType> list = (List<TProductType>) redisTemplate.opsForValue().get("productType:list");if (list == null || list.size()==0) {//2.缓存不存在,则查询数据库list = super.list();//3.将查询结果保存到缓存中redisTemplate.opsForValue().set("productType:list",list);}return list;}
}
  • Controller层调用
@Controller
@RequestMapping("index")
public class IndexController {@Referenceprivate IProductTypeService productTypeService;@RequestMapping("show")public String showIndex(Model model) {//1.获取到数据List<TProductType> list = productTypeService.list();//2.传递到前端进行展示model.addAttribute("list", list);//return "index";}@RequestMapping("listType")@ResponseBodypublic ResultBean listType() {//1.获取到数据List<TProductType> list = productTypeService.list();//2.封装返回return new ResultBean("200", list);}
}

首页展示是远程调用了商品服务

注册系统

注册系统是远程调用了用户的服务

通过MQ去异步通知邮件服务进行邮件发送。

Mq应用场景:发送邮件


发送失败怎么处理?

登录系统

表结构设计

表名:t-user

phone和email加唯一索引

统一定义返回:ResultBean

@Data
@AllArgsConstructor
public class ResultBean<T> implements Serializable{private String statusCode;private T data;}

用户类:

public class TUser implements Serializable{private Long id;private String username;private String password;private String phone;private String email;private Boolean flag;private Date createTime;private Date updateTime;}
  • 接口层
    IUserService:
public interface IUserService extends IBaseService<TUser>{public ResultBean checkUserNameIsExists(String username);public ResultBean checkPhoneIsExists(String phone);public ResultBean checkEmailIsExists(String email);public ResultBean generateCode(String identification);ResultBean checkLogin(TUser user);ResultBean checkIsLogin(String uuid);
  • service层:
@Service
public class UserServiceImpl extends BaseServiceImpl<TUser> implements IUserService{@Autowiredprivate TUserMapper userMapper;@Resource(name = "myStringRedisTemplate")private RedisTemplate<String,Object> redisTemplate;@Autowiredprivate BCryptPasswordEncoder passwordEncoder;@Autowiredprivate RabbitTemplate rabbitTemplate;@Overridepublic ResultBean checkUserNameIsExists(String username) {return null;}@Overridepublic ResultBean checkPhoneIsExists(String phone) {return null;}@Overridepublic ResultBean checkEmailIsExists(String email) {return null;}@Overridepublic ResultBean generateCode(String identification) {//1.生成验证码String code = CodeUtils.generateCode(6);//2.往redis保存一个凭证跟验证码的对应关系 key-valueredisTemplate.opsForValue().set(identification,code,2, TimeUnit.MINUTES);//3.发送消息,给手机发送验证码//3.1 调通阿里云提供的短信Demo//3.2 发送短信这个功能,整个体系很多系统都可能会用上,变成一个公共的服务//3.3 发送消息,异步处理发送短信Map<String,String> params = new HashMap<>();params.put("identification",identification);params.put("code",code);rabbitTemplate.convertAndSend("sms-exchange","sms.code",params);//此处是不需要发送任何邮件,仅做测试使用Map<String,String> params2 = new HashMap<>();params2.put("to","2678383176@qq.com");params2.put("username","马老师");rabbitTemplate.convertAndSend("email-exchange","email.birthday",params2);return new ResultBean("200","OK");}@Overridepublic ResultBean checkLogin(TUser user) {//1.根据用户输入的账号(手机/邮箱)信息,去查询TUser currentUser = userMapper.selectByIdentification(user.getUsername());//2.根据查询出来的密码信息,进行比较if(currentUser != null){//if(user.getPassword().equals(currentUser.getPassword())){if(passwordEncoder.matches(user.getPassword(),currentUser.getPassword())){//1.生成uuid//String uuid = UUID.randomUUID().toString();//2.保存到redis中,并设置有效期为30分钟,代替原先的session//redisTemplate.opsForValue().set("user:token:"+uuid,currentUser.getUsername(),30,TimeUnit.MINUTES);//生成令牌JwtUtils jwtUtils = new JwtUtils();jwtUtils.setSecretKey("java1907");jwtUtils.setTtl(30*60*1000);String jwtToken = jwtUtils.createJwtToken(currentUser.getId().toString(), currentUser.getUsername());//TODO 构建一个map,返回令牌和唯一标识Map<String,String> params = new HashMap<>();params.put("jwttoken",jwtToken);params.put("username",currentUser.getUsername());return new ResultBean("200",params);}}return new ResultBean("404",null);}@Overridepublic ResultBean checkIsLogin(String uuid) {//1.拼接key//StringBuilder key = new StringBuilder("user:token:").append(uuid);//2.查询redis//String username = (String) redisTemplate.opsForValue().get(key.toString());//3.返回结果/*if(username != null){//刷新凭证的有效期redisTemplate.expire(key.toString(),30,TimeUnit.MINUTES);//return new ResultBean("200",username);}*/JwtUtils jwtUtils = new JwtUtils();jwtUtils.setSecretKey("java1907");//ExpiredJwtException//RuntimeException//解析令牌try {Claims claims = jwtUtils.parseJwtToken(uuid);String username = claims.getSubject();return new ResultBean("200",username);}catch (RuntimeException ex){//如果针对不同的异常,我们需要区分对待,那么就应该写多个catch,分别处理//如果是一样的处理方式,那么直接统一就行return new ResultBean("404",null);}}@Overridepublic IBaseDao<TUser> getBaseDao() {return userMapper;}
}
  • Controller层
@Controller
@RequestMapping("user")
public class UserController {@Referenceprivate IUserService userService;@GetMapping("checkUserNameIsExists/{username}")@ResponseBodypublic ResultBean checkUserNameIsExists(@PathVariable("username") String username){return userService.checkUserNameIsExists(username);}@GetMapping("checkPhoneIsExists/{phone}")@ResponseBodypublic ResultBean checkPhoneIsExists(@PathVariable("phone") String phone){return userService.checkPhoneIsExists(phone);}@GetMapping("checkEmailIsExists/{email}")@ResponseBodypublic ResultBean checkEmailIsExists(@PathVariable("email") String email){return userService.checkEmailIsExists(email);}@PostMapping("generateCode/{identification}")@ResponseBodypublic ResultBean generateCode(@PathVariable("identification") String identification){return userService.generateCode(identification);}/*** 适合处理异步请求* @return*/@PostMapping("register")@ResponseBodypublic ResultBean register(TUser user){return null;}/*** 适合处理同步请求,跳转到相关页面* @return*/@PostMapping("register4PC")public String register4PC(TUser user){return null;}@GetMapping("activating")public String activating(String token){return null;}

  1. 需要设计的接口


关键点,系统是如何为用户保存登录凭证的?

基于session操作

简单的登录验证:

简单验证用户是否登录:
简单的注销:

问题:微服务架构下还能适用吗?
分布式拆分,集群保证高可用,session不能共享

探讨解决方案:
通过cookie解决

jsessionId:凭证信息
2.是http协议的特性,1.是服务器自动的行为
有状态的解决方案:

代码层面

登录校验

  • 增加redis依赖
    1、登录验证,生成uuid,并保存在redis中

service层

public ResultBean checkLogin(TUser user) {//1.根据用户输入的账号(手机/邮箱)信息,去查询TUser currentUser = userMapper.selectByIdentification(user.getUsername());//2.根据查询出来的密码信息,进行比较if(currentUser != null){//if(user.getPassword().equals(currentUser.getPassword())){if(passwordEncoder.matches(user.getPassword(),currentUser.getPassword())){//1.生成uuidString uuid = UUID.randomUUID().toString();//2.保存到redis中,并设置有效期为30分钟,代替原先的sessionredisTemplate.opsForValue().set("user:token:"+uuid,currentUser.getUsername(),30,TimeUnit.MINUTES);return new ResultBean("200",uuid);}}return new ResultBean("404",null);}

redis的key值:“user:token:”+uuid,保证唯一性
redis的value值:currentUser.getUsername(),当前用户的名字

  • SSOController层
 @PostMapping("checkLogin")@ResponseBodypublic ResultBean checkLogin(TUser user,HttpServletResponse response){ResultBean resultBean = userService.checkLogin(user);//2.如果正确,则在服务端保存凭证信息if("200".equals(resultBean.getStatusCode())){//TODO 写cookie给客户端,保存凭证//1.获取uuidString uuid = (String) resultBean.getData();//2.创建cookie对象Cookie cookie = new Cookie("user_token",uuid);cookie.setPath("/");//设置cookie的域名为父域名,这样所有子域名系统都可以访问该cookie,解决cookie的跨域问题cookie.setDomain("qf.com");cookie.setHttpOnly(true);//3.写cookie到客户端response.addCookie(cookie);}return resultBean;}

resultBean里返回了uuid,并且在userservice服务中这个值,已经被写入了redis。
如何将cookie写入到客户端,使用返回对象,response.addCookie();

校验是否在登录状态
1、获取cookie,获取user_token的值,在请求头里,所以用request去取
2、去redis中查询,是否存在这个凭证
SSOController层

@GetMapping("checkIsLogin")@CrossOrigin(origins = "*",allowCredentials = "true")@ResponseBodypublic ResultBean checkIsLogin(@CookieValue(name = "user_token",required = false) String uuid){//1.获取cookie,获取user_token的值if(uuid != null){//2.去redis中查询,是否存在该凭证信息ResultBean resultBean = userService.checkIsLogin(uuid);return resultBean;}return new ResultBean("404",null);}

service层

@Overridepublic ResultBean checkIsLogin(String uuid) {//1.拼接keyStringBuilder key = new StringBuilder("user:token:").append(uuid);//2.查询redisString username = (String) redisTemplate.opsForValue().get(key.toString());///3.返回结果if(username != null){//刷新凭证的有效期redisTemplate.expire(key.toString(),30,TimeUnit.MINUTES);return new ResultBean("200",username);}}

一旦有操作,要刷新redis凭证的有效期,如果有,那就刷新继续持续30min

redisTemplate.expire(key.toString(),30,TimeUnit.MINUTES)

具体的实现,是远程调用service层下面的userservice服务
回顾梳理:

在service层中通过checkLogin方法,去生成一个cookie凭证,并保存在redis中,设置超时时间30min;
然后Controller层中,将cookie写入到客户端。
当做登录验证时,调用checkLogin,返回一个resultBean,Bean里有redis中存入的凭证,如果验证通过了,将凭证(cookie),通过response.addCookie(cookie),写入到客户端。
**

全文索引的实现

**

搭建solar服务器

安装IK分词解释器

springboot整合solr


与自定义域的索引保持一致。


查询和删除



精确匹配用id;

全量同步数据


dubbo+springboot项目相关推荐

  1. Dubbo的Api+Provider+Customer示例(IDEA+Maven+Springboot+dubbo) 项目结构

    项目结构 dubbo-demo dubbo-api:提供api接口,一般存储实体类和接口服务 dubbo-provider:dubbo生产者提供服务,一般存储接口具体实现 dubbo-customer ...

  2. springboot+dubbo实现项目itrip-search-consumer流程

    准备 把3个solr的工具类(BaseQuery.Param.SolrParam)放到itrip-common中,导如下依赖: <!--solr导这个包,注意版本号为2.1.1-->< ...

  3. SpringBoot学习之zookeeper、dubbo入门项目实战(七)

    项目结构 dubbo-demo dubbo-api:提供api接口,一般存储实体类和接口服务 dubbo-provider:dubbo生产者提供服务,一般存储接口具体实现 dubbo-customer ...

  4. Tekton构建Springboot项目操作手册

    Tekton构建前后端项目操作手册--本地Harbor仓库版本 概述 前端Vue项目,后端Springboot项目,后端项目使用Dubbo+Zookeeper+PostgreSQL框架. 镜像版本,本 ...

  5. 使用IDEA搭建一个简单的SpringBoot项目——详细过程

    一.创建项目 1.File->new->project: 2.选择"Spring Initializr",点击next:(jdk1.8默认即可) 3.完善项目信息,组名 ...

  6. Dubbo SpringBoot 实战

    1.Dubbo是什么 Apache Dubbo 是一款高性能.轻量级的RPC框架 Dubbo官网 1.1Dubbo可以做什么 Apache Dubbo提供了六大核心能力:面向接口代理的高性能RPC调用 ...

  7. SpringBoot项目配置disconf

    说明: SpringBoot项目通过application.yml实现项目的配置, 配置文件如下: server:     port: 9090     context-path: #/daily/ ...

  8. Dockerfile springboot项目拿走即用,将yml配置文件从外部挂入容器

    Dockerfile 将springboot项目jar包打成镜像,并将yml配置文件外挂. # 以一个镜像为基础,在其上进行定制.就像我们之前运行了一个 nginx 镜像的容器,再进行修改一样,基础镜 ...

  9. SpringBoot项目使用nacos,kotlin使用nacos,java项目使用nacos,gradle项目使用nacos,maven项目使用nacos

    SpringBoot项目使用nacos kotlin demo见Gitte 一.引入依赖 提示:这里推荐使用2.2.3版本,springboot与nacos的依赖需要版本相同,否则会报错. maven ...

最新文章

  1. c语言 8155 数码管,基于8155的8LED显示串口通信机设计 编程
  2. UVa11452 Dancing the Cheeky-Cheeky(kmp)
  3. 关于windows注册表重定向和虚拟化分析
  4. JS怎样捕获浏览器关闭时间弹出自定义对话框
  5. 结构体位域及联合体解析
  6. python写算法求最短路径,Python实现迪杰斯特拉算法并生成最短路径的示例代码
  7. Android学习笔记(27):日历视图Calendar
  8. 我看到东边的阳光就这样照进车窗
  9. 女人离婚后不要孩子,你怎么看?
  10. 我经历的IT公司面试及离职感受(转)
  11. 计算机病毒实践汇总三:动态分析基础(分析程序)
  12. webservice 安全性 对外_WebService的安全性讨论【身份识别】
  13. spring源码:扫描bean的原理
  14. excel筛选排序从小到大_用Excel函数实现排序与筛选的方法
  15. 计算机病毒蓝屏,电脑中病毒造成蓝屏怎么解决
  16. r 语言计算欧氏距离_R语言实现46种距离算法
  17. 周爱民:架构的实战过程
  18. 10年研发总结和期许
  19. 【0基础强力推荐】R语言快速入门
  20. PHP采集-数据采集PHP采集器

热门文章

  1. java个人小管家代码_Java程序设计基础—Java小管家系统构建
  2. java 修饰器_修饰java
  3. 全球与中国电动空气净化呼吸器(PAPR)系统市场深度研究分析报告
  4. Python2.7对接科大讯飞的语音合成和语音识别接口
  5. mysql touches_touches - 缘起缘落 - OSCHINA - 中文开源技术交流社区
  6. 迭代法求sinx的近似值
  7. Pytorch学习(五)ReLu激活函数
  8. mysql密码忘了_MySQL忘记密码怎么办 密码重置详细教程
  9. selenium 3 ie java_【Java+selenium3】 Firefox/ IE/ Chrome主流瀏覽器自動化環境搭建(一)
  10. 真正的ChatGPT平替产品:Claude