首先得将自己的qq开启qq邮箱的POP3/SMTP服务

说明:

p,e为路由key。

用户系统完成登录的时候,将{手机号-时间-IP}保存到队列Phone-queue中,msg-sys系统获得消息打印到控制台(完成用户登录过程短信服务的异步调用,完成用户系统和短信系统的解耦合)

用户系统完成注册的时候,将{email-时间-IP-账户激活url }保存到队列email-sys中,email-sys将消息打印到控制台,使用控制台打印的账户激活的url,在浏览器向user-sys系统发送请求,修改user表中locked字段的值。(完成用户注册过程邮件服务的异步调用,完成用户系统和邮件系统的解耦合),修改完成后给用户提示账户激活成功

用户登录

用户登录的时候提交用户名和密码,然后给用户短信提示,用户在什么时间,用哪个IP,进行登录。需要将电话-时间-IP格式的数据保存到队列中

用户注册

用户注册,用户注册后,给用户注册信息进行邮箱的激活,点击哪个url进行账户激活。修改数据库中locked字段的值。需要将Email-时间-URL格式的数据保存到队列中

当我们点击注册的时候,会向消息队列发送注册信息,以及向qq邮箱发送文件激活的url

然后看pom文件

<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.1.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.bjsxt</groupId>
<artifactId>spring-boot-jpa-dlzc</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>spring-boot-jpa-dlzc</name>
<description>spring-boot-jpa-dlzc</description> <properties>
<java.version>1.8</java.version>
</properties> <dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency> <dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.47</version>
</dependency> <!--开启QQ邮箱验证-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-mail</artifactId>
</dependency> <dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency> <!-- rabbitmq -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-amqp</artifactId>
</dependency> <dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies> <build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build> </project>

由于此项目用到了消息队列

因此注意项目奖结构

消息的发送者    spring-boot-jpa-dlzc

application.properties配置文件

#Mysql数据源配置
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/sys?characterEncoding=UTF8&useSSL=false
spring.datasource.username=root
spring.datasource.password=root #JPA相关配置
#项目启动生成数据库
spring.jpa.hibernate.ddl-auto=update
spring.jpa.show-sql=true server.port=8081
spring.rabbitmq.host=192.168.181.134
spring.rabbitmq.port=5672
spring.rabbitmq.username=admin
spring.rabbitmq.password=111111 #设置交换器的名称
mq.config.exchange=log.direct #设置短信的路由键
mq.config.queue.message.routing.key=log.message.routing.key #设置邮件的路由键
mq.config.queue.email.routing.key=log.email.routing.key #qq邮箱的规则
spring.mail.host=smtp.qq.com
spring.mail.username=设置申请邮箱的账号
spring.mail.password=邮箱的验证码
spring.mail.properties.mail.smtp.auth=true
spring.mail.properties.mail.smtp.starttls.enable=true
spring.mail.properties.mail.smtp.starttls.required=true

实体类

locked字段是为了激活账号使用的,给予默认值是0,注册成但是未激活的时候,此时locked值是0,点击激活之后locked值修改成1,在我们登录的时候带着uname和pwd以及locked的值为1三个条件去判断,如果有值说明账户激活成功,查询没有则返回用户,账户未激活信息提示

package com.bjsxt.pojo;

import lombok.Data;
import org.hibernate.annotations.ColumnDefault; import javax.persistence.*;
import java.io.Serializable; @Entity
@Table(name = "users")
@Data
public class Users implements Serializable { @Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "uid")
private int uid; @Column(name = "uname")
private String uname; @Column(name = "pwd")
private String pwd; @Column(name = "email")
private String email; @Column(name = "phone")
private String phone; @Column(name = "locked")
@ColumnDefault(value = "0")
private int locked; public Users() {
} public Users(String uname, String pwd, String email, String phone, int locked) {
this.uname = uname;
this.pwd = pwd;
this.email = email;
this.phone = phone;
this.locked = locked;
}
}

消息发送实现类

com.bjsxt.send.LoginSender

package com.bjsxt.send;

import org.springframework.amqp.core.AmqpTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component; /***
* 消息的发送者
*/
@Component
public class LoginSender { @Autowired
private AmqpTemplate amqpTemplate; @Value("${mq.config.exchange}")
private String exchange; @Value("${mq.config.queue.message.routing.key}")
private String routingkey; /**
* 发送消息的方法
* @param msg
*/
public void sendMsg(String msg){
/*向消息队列发送消息*/
/*
* 参数一:队列的名称
* 参数二:发送的消息
* */
amqpTemplate.convertAndSend(exchange,routingkey,msg); }
}

com.bjsxt.send.RegSender

package com.bjsxt.send;

import org.springframework.amqp.core.AmqpTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component; /***
* 消息的发送者
*/
@Component
public class RegSender { @Autowired
private AmqpTemplate amqpTemplate; @Value("${mq.config.exchange}")
private String exchange; @Value("${mq.config.queue.email.routing.key}")
private String routingkey; /**
* 发送消息的方法
* @param msg
*/
public void sendMsg(String msg){
/*向消息队列发送消息*/
/*
* 参数一:队列的名称
* 参数二:发送的消息
* */
amqpTemplate.convertAndSend(exchange,routingkey,msg); }
}

dao层

com.bjsxt.dao.UserDao

package com.bjsxt.dao;

import com.bjsxt.pojo.Users;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
import org.springframework.data.jpa.repository.Modifying;
import org.springframework.data.jpa.repository.Query;
import org.springframework.transaction.annotation.Transactional; public interface UserDao extends JpaRepository<Users,Integer>, JpaSpecificationExecutor<Users> { /**
* 登录操作
* @param uname
* @param pwd
* @return
*/
@Query(value = "select * from users where uname=? and pwd =? and locked=1",nativeQuery = true)
Users findUser(String uname,String pwd); /**
* 激活操作
* @param uid
*/
@Modifying
@Transactional
@Query(value = "update users set locked=1 where uid=?",nativeQuery = true)
void updateUser(int uid); /**
* 激活操作
* @param uname
* @param pwd
*/
@Modifying
@Transactional
@Query(value = "update users set locked=1 where uname=? and pwd =?",nativeQuery = true)
void updateUserlocked(String uname,String pwd); }

service层

com.bjsxt.service.UserService(接口)

package com.bjsxt.service;

import com.bjsxt.pojo.Users;

public interface UserService {
/**
* 添加用户
* @param users
*/
void addUser(Users users); /**
* 处理登录请求
* @param uname
* @param pwd
* @return
*/
Users findUser(String uname,String pwd); /***
* 处理用户激活
* @param uid
* @return
*/
void updateUserLock(int uid); /**
* 处理用户激活
* @param uname
* @param pwd
*/
void updateLock(String uname,String pwd);
}

com.bjsxt.service.impl.UserServiceImpl接口实现类

package com.bjsxt.service.impl;

import com.bjsxt.dao.UserDao;
import com.bjsxt.pojo.Users;
import com.bjsxt.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service; @Service
public class UserServiceImpl implements UserService { @Autowired
private UserDao userDao; /**
* 添加用户操作
* @param users
*/
@Override
public void addUser(Users users) {
userDao.save(users);
} /**
* 处理登录操作
* @param uname
* @param pwd
* @return
*/
@Override
public Users findUser(String uname, String pwd) {
return userDao.findUser(uname,pwd);
} /**
* 处理用户激活操作
* @param uid
*/
@Override
public void updateUserLock(int uid) {
userDao.updateUser(uid);
} /**
* 处理用户激活
* @param uname
* @param pwd
*/
@Override
public void updateLock(String uname,String pwd) {
userDao.updateUserlocked(uname,pwd);
}
}

控制层

com.bjsxt.controller.PageController(页面跳转)

package com.bjsxt.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping; @Controller
public class PageController { /***
* 展示页面
* @return
*/
@RequestMapping("/{page}")
public String showPage(@PathVariable String page){
return page;
}
}

com.bjsxt.controller.UserController用户操作处理

package com.bjsxt.controller;

import com.bjsxt.pojo.Users;
import com.bjsxt.send.LoginSender;
import com.bjsxt.send.RegSender;
import com.bjsxt.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.mail.SimpleMailMessage;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping; import javax.servlet.http.HttpServletRequest;
import java.text.SimpleDateFormat;
import java.util.Date; @Controller
public class UserController { @Autowired
private JavaMailSender mailSender; @Autowired
private UserService us; @Autowired
private RegSender regSender; @Autowired
private LoginSender loginSender; @RequestMapping("/save")
public String addUser(Users users){
us.addUser(users); //将Email-时间-URL格式的数据保存到队列中
String email = users.getEmail();
Date now =new Date();
SimpleDateFormat spdf=new SimpleDateFormat("yyyy年MM月dd日 hh:mm:ss");
String date = spdf.format(now);
String url="http://192.168.41.24:8081/locked/"+users.getUid();
regSender.sendMsg("邮箱:"+email+"\t时间:"+date+"\turl:"+url); /**
* 向qq邮箱发送信息
*/
SimpleMailMessage message = new SimpleMailMessage();
message.setFrom("1252639547@qq.com");//信息由谁发送
message.setTo(users.getEmail());//信息发送给谁
message.setSubject("主人主人!!你有新邮件啦~");//设置邮件的主题
message.setText(url);//设置邮件的内容
mailSender.send(message);
return "login"; } @RequestMapping("/loginuser")
public String login(String uname, String pwd, HttpServletRequest request){
Users user = us.findUser(uname, pwd);
if (user!=null){
//电话-时间-IP格式的数据保存到队列中
String phone = user.getPhone();
Date now =new Date();
SimpleDateFormat spdf=new SimpleDateFormat("yyyy年MM月dd日 hh:mm:ss");
String date = spdf.format(now);
String ip = request.getRemoteHost();
loginSender.sendMsg("电话:"+phone+"\t时间:"+date+"\tIP:"+ip);
return "success";
}else {
request.setAttribute("uname",uname);
request.setAttribute("pwd",pwd);
return "cuowu";
} } /**
* 处理用户激活
* @param uid
* @return
*/
@RequestMapping("/locked/{uid}")
public String bindLock(@PathVariable int uid){
us.updateUserLock(uid);
return "success1";
} /**
* 处理用户激活
* @param uname
* @param pwd
* @return
*/
@RequestMapping("/lock/{uname}/{pwd}")
public String Locked(@PathVariable String uname,@PathVariable String pwd){
us.updateLock(uname,pwd);
return "success1";
} }

前端的页面分步

注册界面

templates/reg.html

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.w3.org/1999/xhtml">
<head>
<meta charset="UTF-8"/>
<title>注册</title>
</head>
<body>
<h1 style="align-content: center">用户注册</h1>
<form th:action="@{/save}" method="post" style="align-content: center">
<p>
用户名:<input type="text" name="uname">
</p>
<p>
密码:<input type="password" name="pwd">
</p>
<p>
确认密码:<input type="password">
</p>
<p>
邮箱:<input type="email" name="email">
</p>
<p>
电话号码:<input type="number" name="phone">
</p>
<p>
<input type="submit" value="注册">
</p>
</form>
</body>
</html>

登录界面

templates/login.html

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.w3.org/1999/xhtml">
<head>
<meta charset="UTF-8"/>
<title>Title</title>
</head>
<body>
<form method="post" th:action="@{/loginuser}">
<p>
用户名:<input type="text" name="uname">
</p>
<p>
密码:<input type="password" name="pwd">
</p>
<p>
<input type="submit" value="登录">&nbsp;&nbsp;<a href="reg.html">戳我去注册</a>
</p>
</form>
</body>
</html>

当你注册成功后,但是没有激活直接登录,失败界面

templates/cuowu.html

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.w3.org/1999/xhtml">
<head>
<meta charset="UTF-8">
<title>主页面</title>
</head>
<body>
<h1>亲,你还未激活,请点击激活后登录</h1>
<table border="1">
<tr>
<th>用户名</th>
<th>密码</th>
<th>操作</th>
</tr>
<tr>
<th th:text="${uname}"></th>
<th th:text="${pwd}"></th>
<th><a th:href="@{/lock/}+${uname}+@{/}+${pwd}">激活</a></th>
</tr>
</table>
</body>
</html>

用户激活成功页面

templates/success1.html

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.w3.org/1999/xhtml">
<head>
<meta charset="UTF-8">
<title>激活页面</title>
</head>
<body>
<h1><a th:href="@{/login.html}">用户激活成功,戳我去登录</a></h1>
</body>
</html>

登录成功页面

templates/success.html

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.w3.org/1999/xhtml">
<head>
<meta charset="UTF-8">
<title>主页面</title>
</head>
<body>
<h1>登录成功</h1>
</body>
</html>

消息接受者  spring-boot-jpa-zcdl-consumer

pom文件

<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.1.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.bjsxt</groupId>
<artifactId>spring-boot-jpa-zcdl-consumer</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>spring-boot-jpa-zcdl-consumer</name>
<description>spring-boot-jpa-zcdl-consumer</description> <properties>
<java.version>1.8</java.version>
</properties> <dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-amqp</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency> <dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.amqp</groupId>
<artifactId>spring-rabbit-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies> <build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build> </project>

application.properties配置文件

server.port=8082
spring.rabbitmq.host=192.168.181.134
spring.rabbitmq.port=5672
spring.rabbitmq.username=admin
spring.rabbitmq.password=111111 #设置交换器的名称
mq.config.exchange=log.direct #设置短信队列名称
mq.config.queue.message=log.message #设置短信的路由键
mq.config.queue.message.routing.key=log.message.routing.key #设置邮件队列名称
mq.config.queue.email=log.email #设置邮件的路由键
mq.config.queue.email.routing.key=log.email.routing.key

接收消息

com.bjsxt.receiver.EmailReceiver

package com.bjsxt.receiver;

import org.springframework.amqp.core.ExchangeTypes;
import org.springframework.amqp.rabbit.annotation.*;
import org.springframework.stereotype.Component; @Component
@RabbitListener(
bindings = @QueueBinding(
value =@Queue(value = "${mq.config.queue.email}",autoDelete = "true"),
exchange = @Exchange(value = "${mq.config.exchange}",type = ExchangeTypes.DIRECT),
key = "${mq.config.queue.email.routing.key}"
) )
public class EmailReceiver {
/**
* 接收消息的方法
* 采用消息队列监听机制
* @param msg
*/
@RabbitHandler
public void process(String msg){
System.out.println("邮件消息:"+msg);
}
}

com.bjsxt.receiver.MessageReceiver

package com.bjsxt.receiver;

import org.springframework.amqp.core.ExchangeTypes;
import org.springframework.amqp.rabbit.annotation.*;
import org.springframework.stereotype.Component; @Component
@RabbitListener(
bindings = @QueueBinding(
value =@Queue(value = "${mq.config.queue.message}",autoDelete = "true"),
exchange = @Exchange(value = "${mq.config.exchange}",type = ExchangeTypes.DIRECT),
key = "${mq.config.queue.message.routing.key}"
) )
public class MessageReceiver {
/**
* 接收消息的方法
* 采用消息队列监听机制
* @param msg
*/
@RabbitHandler
public void process(String msg){
System.out.println("短信消息:"+msg);
}
}

Spring Boot 整合Spring Data以及rabbitmq,thymeleaf,向qq邮箱发送信息的更多相关文章

  1. Spring Boot 整合Spring Data JPA

    Spring Boot整合Spring Data JPA 1)加入依赖 <dependency> <groupId>org.springframework.boot</g ...

  2. Spring boot 整合spring Data JPA+Spring Security+Thymeleaf框架(上)

    近期上班太忙所以耽搁了给大家分享实战springboot 框架的使用. 以下是spring boot 整合多个框架的使用. 首先是准备工作要做好. 第一  导入框架所需的包,我们用的事maven 进行 ...

  3. Spring Boot整合Spring Security自定义登录实战

    本文主要介绍在Spring Boot中整合Spring Security,对于Spring Boot配置及使用不做过多介绍,还不了解的同学可以先学习下Spring Boot. 本demo所用Sprin ...

  4. Spring Boot整合Spring Security总结

    一.创建Spring Boot项目 引入Thymeleaf和Web模块以及Spring Security模块方便进行测试,先在pom文件中将 spring-boot-starter-security ...

  5. Spring Boot整合Spring Security

    Spring Boot对于该家族的框架支持良好,但是当中本人作为小白配置还是有一点点的小问题,这里分享一下.这个项目是使用之前发布的Spring Boot会员管理系统重新改装,将之前filter登录验 ...

  6. Spring Boot整合Spring Batch

    引言 Spring Batch是处理大量数据操作的一个框架,主要用来读取大量数据,然后进行一定的处理后输出指定的形式.比如我们可以将csv文件中的数据(数据量几百万甚至几千万都是没问题的)批处理插入保 ...

  7. Spring Boot整合Spring Session实战

    传统java web应用session都是由应用服务器(如tomcat)保存在内存中,这对应但节点应用来说没问题:但对于应用集群来说会造成各节点之间的session无法共享,一个节点挂掉后,其他节点接 ...

  8. Spring Boot 整合 Spring Security,用户登录慢

    场景 Spring Boot + Spring Security搭建一个Web项目. 临时用了inMemoryAuthentication. @EnableWebSecurity public cla ...

  9. spring boot整合spring Data JPA和freemarker

    1.spring Data JPA简介 是一个替代hibernate的一个作用于数据库的框架. 2.整合 1.导入依赖 <dependency> <groupId>org.sp ...

随机推荐

  1. day6-作业(不完整)

    # 1.用代码实现:利用下划线将列表的'每一个元素'拼接成字符串 li=['ndfj','dlfj',12434]# 注意是将元素与元素转换为字符串之间用_拼接,而不是将每个字符串进行拼接 li=[' ...

  2. Havok Physics 2012(2)

    目录 Havok Physics 2012 Chapter 2. Creating a Simulation 创建一个模拟世界 1. Creating Physics 2012 Objects Hav ...

  3. 深入理解计算机系统 第八章 异常控制流 Part2 第二遍

    第二遍读这本书,每周花两到三小时时间,能读多少读多少(这次看了第 508~530 页,共 23 页) 第一遍对应笔记链接 https://www.cnblogs.com/stone94/p/10206 ...

  4. 领扣(LeetCode)二叉树的右视图 个人题解

    给定一棵二叉树,想象自己站在它的右侧,按照从顶部到底部的顺序,返回从右侧所能看到的节点值. 示例: 输入: [1,2,3,null,5,null,4] 输出: [1, 3, 4] 解释: 1 < ...

  5. 《JAVA 程序员面试宝典(第四版)》之传递与引用篇

    废话开场白         这个周末突然很想创业,为什么呢?原因很简单,我周围的同学或者说玩的比较好的朋友都发达了,前一个月和一个两年前还睡在一张床上的朋友,他现在已经在深圳买房买车了,没错是在深圳买 ...

  6. template screen

    从全局搜索主机可看到此screen

  7. react 组件间通信,父子间通信

    一.父组件传值给子组件 父组件向下传值是使用了props属性,在父组件定义的子组件上定义传给子组件的名字和值,然后在子组件通过this.props.xxx调用就可以了. 二.子组件传值给父组件 子组件 ...

  8. 2019-11-24:postgresql数据库安装,最后报错failed to load SQLModule 问题的解决方案

    安装环境:Windows 10 问题描述:Failed to load sql modules into the database cluster 原因在于 Postgresql 没有安装完全. 解决 ...

  9. 【Luogu P3834】可持久化线段树(主席树)

    Luogu P3834 可持久化数据结构就是支持在历史版本上进行查询和修改操作的数据结构. 主席树就是对线段树的改进,使之可持久化. 前置知识:动态开点线段树 我们利用权值(值域)线段树统计区间内的数 ...

  10. MySQL8.0 新特性 Hash Join

    概述&背景 MySQL一直被人诟病没有实现HashJoin,最新发布的8.0.18已经带上了这个功能,令人欣喜.有时候在想,MySQL为什么一直不支持HashJoin呢?我想可能是因为MySQ ...