├── README.md ├── pom.xml ├── subtlechat-api ├── pom.xml └── src │ └── main │ ├── java │ └── top │ │ └── javahai │ │ └── subtlechat │ │ └── api │ │ ├── Test.java │ │ ├── converter │ │ ├── DateConverter.java │ │ ├── MyContentConverter.java │ │ └── MyUrlImageConverter.java │ │ ├── data │ │ └── GroupMsgContentData.java │ │ ├── entity │ │ ├── Admin.java │ │ ├── Feedback.java │ │ ├── GroupMsgContent.java │ │ ├── MailConstants.java │ │ ├── MailSendLog.java │ │ ├── Message.java │ │ ├── RespBean.java │ │ ├── RespPageBean.java │ │ ├── User.java │ │ └── UserState.java │ │ └── utils │ │ ├── FastDFSUtil.java │ │ ├── ImgUtil.java │ │ ├── JsonUtil.java │ │ ├── TuLingUtil.java │ │ └── UserUtil.java │ └── resources │ └── fastdfs-client.properties ├── subtlechat-mail ├── pom.xml └── src │ ├── main │ ├── java │ │ └── top │ │ │ └── javahai │ │ │ └── subtlechat │ │ │ └── mail │ │ │ ├── SubtleChatMailApplication.java │ │ │ ├── config │ │ │ └── RabbitMQConfig.java │ │ │ └── receiver │ │ │ ├── FeedbackReceiver.java │ │ │ └── VerifyCodeReceiver.java │ └── resources │ │ └── application.yml │ └── test │ └── java │ └── top │ └── javahai │ └── subtlechat │ └── mail │ └── SubtleChatMailApplicationTests.java ├── subtlechat-web ├── pom.xml └── src │ ├── main │ ├── java │ │ └── top │ │ │ └── javahai │ │ │ └── subtlechat │ │ │ ├── SubtleChatWebApplication.java │ │ │ ├── config │ │ │ ├── MultiHttpSecurityConfig.java │ │ │ ├── MyAuthenticationFailureHandler.java │ │ │ ├── MyLogoutSuccessHandler.java │ │ │ ├── RabbitMQConfig.java │ │ │ ├── SecurityConfig.java │ │ │ ├── VerificationCode.java │ │ │ ├── VerificationCodeFilter.java │ │ │ └── WebSocketConfig.java │ │ │ ├── controller │ │ │ ├── AdminController.java │ │ │ ├── ChatController.java │ │ │ ├── FileController.java │ │ │ ├── GroupMsgContentController.java │ │ │ ├── LoginController.java │ │ │ ├── MailController.java │ │ │ ├── UserController.java │ │ │ ├── UserStateController.java │ │ │ └── WsController.java │ │ │ ├── dao │ │ │ ├── AdminDao.java │ │ │ ├── FeedbackDao.java │ │ │ ├── GroupMsgContentDao.java │ │ │ ├── MailSendLogDao.java │ │ │ ├── UserDao.java │ │ │ └── UserStateDao.java │ │ │ ├── exception │ │ │ └── GlobalExceptionHandler.java │ │ │ ├── service │ │ │ ├── AdminService.java │ │ │ ├── FeedbackService.java │ │ │ ├── GroupMsgContentService.java │ │ │ ├── MailSendLogService.java │ │ │ ├── UserService.java │ │ │ ├── UserStateService.java │ │ │ ├── VerifyCodeService.java │ │ │ └── impl │ │ │ │ ├── AdminServiceImpl.java │ │ │ │ ├── FeedbackServiceImpl.java │ │ │ │ ├── GroupMsgContentServiceImpl.java │ │ │ │ ├── MailSendLogServiceImpl.java │ │ │ │ ├── UserServiceImpl.java │ │ │ │ ├── UserStateServiceImpl.java │ │ │ │ └── VerifyCodeServiceImpl.java │ │ │ └── task │ │ │ └── MailSendTask.java │ └── resources │ │ ├── application-dev.properties │ │ ├── application.properties │ │ └── mapper │ │ ├── AdminDao.xml │ │ ├── FeedbackDao.xml │ │ ├── GroupMsgContentDao.xml │ │ ├── MailSendLogDao.xml │ │ ├── UserDao.xml │ │ └── UserStateDao.xml │ └── test │ └── java │ └── top │ └── javahai │ └── subtlechat │ └── SubtleChatWebApplicationTests.java └── subtlechat.sql /README.md: -------------------------------------------------------------------------------- 1 | # 项目介绍 2 | 微言聊天室是基于前后端分离,采用SpringBoot+Vue框架开发的网页版聊天室。 3 | 使用了Spring Security安全框架进行密码的加密存储和登录登出等逻辑的处理,以WebSocket+Socket.js+Stomp.js实现消息的发送与接收,监听。搭建FastDFS文件服务器用于保存图片,使用EasyExcel导出数据,使用Vue.js结合Element UI进行显示弹窗和数据表格分页等功能,以及整个系统的界面进行UI设计,并且使用MyBatis结合数据库MySQL进行开发。最后使用了Nginx进行部署前后端分离项目。 4 | 5 | 功能实现:群聊,单聊,邮件发送,emoji表情发送,图片发送,用户管理,群聊记录管理,Excel的导出。 6 | 7 | 项目预览地址:http://www.javahai.top/index.html 8 | 9 | 演示视频:https://www.bilibili.com/video/BV1qa4y1s7sg/ 10 | 11 | 前端工程源码地址:https://github.com/JustCoding-Hai/subtlechat-vue 12 | 13 | 后端工程源码地址:https://github.com/JustCoding-Hai/subtlechat 14 | 15 | 简化版的后端项目地址(不使用RabbitMQ和Redis): https://github.com/JustCoding-Hai/subtlechat-mini 16 | 17 | ## 项目技术栈 18 | ### 后端技术栈 19 | 1. Spring Boot 20 | 2. Spring Security 21 | 3. MyBatis 22 | 4. MySQL 23 | 5. WebSocket 24 | 6. RabbitMQ 25 | 7. Redis 26 | 27 | ### 前端技术栈 28 | 1. Vue 29 | 2. ElementUI 30 | 3. axios 31 | 4. vue-router 32 | 5. Vuex 33 | 6. WebSocket 34 | 7. vue-cli4 35 | ... 36 | 37 | ## 项目预览图 38 | 客户端界面-群聊主界面 39 | ![在这里插入图片描述](https://img-blog.csdnimg.cn/20201108163850583.png) 40 | 41 | 客户端界面-私聊界面 42 | ![在这里插入图片描述](https://img-blog.csdnimg.cn/2020110816390059.png) 43 | 44 | 管理端界面-用户管理 45 | ![在这里插入图片描述](https://img-blog.csdnimg.cn/20201108163906854.png) 46 | 47 | 管理端界面-群聊消息管理 48 | ![在这里插入图片描述](https://img-blog.csdnimg.cn/20201108163912953.png) 49 | 50 | 51 | ## 部署流程 52 | 1. clone 项目到本地 53 | 2. 在本地 MySQL 中创建一个空的数据库 subtlechat,在该数据库中运行提供的数据库脚本subtlechat.sql,完成表的创建和数据的导入。 54 | 3. 提前准备好Redis,在项目中的mail模块的 application.yml 文件中,将 Redis 配置改为自己的。 55 | 4. 提前准备好RabbitMQ,在项目中的mail模块的 application.yml 文件中和web模块中的 application-dev.properties,将 RabbitMQ 的配置改为自己的。 56 | 5. 注册邮箱的授权码,在项目中的mail模块的 application.yml 文件中填入 57 | 58 | ![在这里插入图片描述](https://img-blog.csdnimg.cn/20201108165225396.png) 59 | 60 | 6. 搭建fastdfs服务器,fastdfs-client.properties文件改成自己的。 61 | 62 | 7. 在 IntelliJ IDEA 中打开subtlechat项目,先启动 mail模块,再启动web模块。 63 | 64 | 8. 启动vue项目。 65 | 66 | ## 文档 67 | 请点击这个查看wiki的文档. 68 | [项目文档](https://github.com/JustCoding-Hai/subtlechat/wiki) 69 | 70 | ## 最后 71 | 本人QQ:1912737955,期待与你交流! 72 | 73 | 如果该项目对你有帮助,跪求star!!! 74 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 4.0.0 5 | 6 | org.springframework.boot 7 | spring-boot-starter-parent 8 | 2.3.4.RELEASE 9 | 10 | 11 | top.javahai 12 | subtlechat 13 | 0.0.1-SNAPSHOT 14 | subtlechat 15 | the back-end project for SubleChat application 16 | 17 | 18 | 1.8 19 | 20 | 21 | 22 | subtlechat-mail 23 | subtlechat-web 24 | subtlechat-api 25 | 26 | 27 | 28 | org.springframework.boot 29 | spring-boot-starter 30 | 31 | 32 | 33 | org.springframework.boot 34 | spring-boot-starter-test 35 | test 36 | 37 | 38 | org.junit.vintage 39 | junit-vintage-engine 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | org.springframework.boot 49 | spring-boot-maven-plugin 50 | 51 | 52 | 53 | 54 | 55 | -------------------------------------------------------------------------------- /subtlechat-api/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 4.0.0 5 | 6 | org.springframework.boot 7 | spring-boot-starter-parent 8 | 2.3.4.RELEASE 9 | 10 | 11 | top.javahai 12 | subtlechat-api 13 | 0.0.1-SNAPSHOT 14 | subtlechat-api 15 | the common used api for SubtleChat application 16 | 17 | 18 | 1.8 19 | 20 | 21 | 22 | 23 | org.springframework.boot 24 | spring-boot-starter 25 | 26 | 27 | org.springframework.boot 28 | spring-boot-starter-web 29 | 30 | 31 | net.oschina.zcx7878 32 | fastdfs-client-java 33 | 1.27.0.0 34 | 35 | 36 | org.springframework.boot 37 | spring-boot-starter-security 38 | 39 | 40 | com.alibaba 41 | fastjson 42 | 1.2.73 43 | 44 | 45 | 46 | com.alibaba 47 | easyexcel 48 | 2.2.6 49 | 50 | 51 | 52 | 53 | net.coobird 54 | thumbnailator 55 | 0.4.8 56 | 57 | 58 | 59 | org.springframework.boot 60 | spring-boot-starter-test 61 | test 62 | 63 | 64 | org.junit.vintage 65 | junit-vintage-engine 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | org.springframework.boot 75 | spring-boot-maven-plugin 76 | 77 | 78 | 79 | 80 | 81 | -------------------------------------------------------------------------------- /subtlechat-api/src/main/java/top/javahai/subtlechat/api/Test.java: -------------------------------------------------------------------------------- 1 | package top.javahai.subtlechat.api; 2 | 3 | import com.alibaba.excel.metadata.CellData; 4 | import com.alibaba.excel.util.IoUtils; 5 | import sun.awt.SunHints; 6 | import top.javahai.subtlechat.api.utils.ImgUtil; 7 | 8 | import java.io.FileNotFoundException; 9 | import java.io.IOException; 10 | import java.io.InputStream; 11 | import java.net.*; 12 | import java.util.UUID; 13 | 14 | /** 15 | * @author Hai 16 | * @program: subtlechat 17 | * @description: gg 18 | * @create 2020/10/9 - 23:15 19 | **/ 20 | public class Test { 21 | public static void main(String[] args) throws IOException { 22 | System.out.println(test("http://")); 23 | } 24 | public static String test(String value) throws IOException { 25 | if (value.toLowerCase().startsWith("http")){ 26 | InputStream inputStream = null; 27 | URL imageUrl = new URL(value); 28 | try { 29 | //开启连接 30 | URLConnection uc = imageUrl.openConnection(); 31 | URL url = null; 32 | //获取响应状态 33 | int statusCode = ((HttpURLConnection) uc).getResponseCode(); 34 | switch (statusCode){ 35 | case 200: 36 | inputStream = imageUrl.openStream(); 37 | break; 38 | default : 39 | //直接当成String处理 40 | return value; 41 | } 42 | byte[] bytes = IoUtils.toByteArray(inputStream); 43 | //压缩图片 44 | byte[] compressBytes = ImgUtil.compressPicForScale(bytes,200, UUID.randomUUID().toString()); 45 | return "success"; 46 | }catch (Exception exception) { 47 | //捕获下链接异常 48 | return value; 49 | } 50 | finally { 51 | if (inputStream != null) { 52 | inputStream.close(); 53 | } 54 | } 55 | 56 | } 57 | else{ 58 | return value; 59 | } 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /subtlechat-api/src/main/java/top/javahai/subtlechat/api/converter/DateConverter.java: -------------------------------------------------------------------------------- 1 | package top.javahai.subtlechat.api.converter; 2 | 3 | import org.springframework.core.convert.converter.Converter; 4 | import org.springframework.stereotype.Component; 5 | 6 | import java.text.ParseException; 7 | import java.text.SimpleDateFormat; 8 | import java.util.Date; 9 | 10 | /** 11 | * @author Hai 12 | * @date 2020/6/23 - 16:28 13 | */ 14 | @Component 15 | public class DateConverter implements Converter { 16 | 17 | SimpleDateFormat simpleDateFormat=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); 18 | @Override 19 | public Date convert(String s) { 20 | Date date = null; 21 | if (s!=null&&!"".equals(s)){ 22 | try { 23 | date= simpleDateFormat.parse(s); 24 | } catch (ParseException e) { 25 | e.printStackTrace(); 26 | } 27 | } 28 | return date; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /subtlechat-api/src/main/java/top/javahai/subtlechat/api/converter/MyContentConverter.java: -------------------------------------------------------------------------------- 1 | package top.javahai.subtlechat.api.converter; 2 | 3 | import com.alibaba.excel.converters.Converter; 4 | import com.alibaba.excel.enums.CellDataTypeEnum; 5 | import com.alibaba.excel.metadata.CellData; 6 | import com.alibaba.excel.metadata.GlobalConfiguration; 7 | import com.alibaba.excel.metadata.property.ExcelContentProperty; 8 | import com.alibaba.excel.util.FileUtils; 9 | import com.alibaba.excel.util.IoUtils; 10 | import top.javahai.subtlechat.api.utils.ImgUtil; 11 | 12 | import java.io.FileNotFoundException; 13 | import java.io.IOException; 14 | import java.io.InputStream; 15 | import java.net.HttpURLConnection; 16 | import java.net.URL; 17 | import java.net.URLConnection; 18 | import java.util.UUID; 19 | 20 | /** 21 | * @author Hai 22 | * @program: subtlechat 23 | * @description: 处理聊天记录的内容的导出 24 | * @create 2020/10/8 - 23:59 25 | **/ 26 | public class MyContentConverter implements Converter { 27 | @Override 28 | public Class supportJavaTypeKey() { 29 | return String.class; 30 | } 31 | 32 | @Override 33 | public CellDataTypeEnum supportExcelTypeKey() { 34 | return CellDataTypeEnum.IMAGE; 35 | } 36 | 37 | @Override 38 | public String convertToJavaData(CellData cellData, ExcelContentProperty contentProperty, 39 | GlobalConfiguration globalConfiguration) { 40 | throw new UnsupportedOperationException("Cannot convert images to string"); 41 | } 42 | 43 | @Override 44 | public CellData convertToExcelData(String value, ExcelContentProperty contentProperty, 45 | GlobalConfiguration globalConfiguration) throws IOException { 46 | if (value.toLowerCase().startsWith("http")){ 47 | InputStream inputStream = null; 48 | URL imageUrl = new URL(value); 49 | try { 50 | //开启连接 51 | URLConnection uc = imageUrl.openConnection(); 52 | URL url = null; 53 | //获取响应状态 54 | int statusCode = ((HttpURLConnection) uc).getResponseCode(); 55 | switch (statusCode){ 56 | case 200: 57 | inputStream = imageUrl.openStream(); 58 | break; 59 | default : 60 | //直接当成String处理 61 | return new CellData(value); 62 | } 63 | byte[] bytes = IoUtils.toByteArray(inputStream); 64 | //压缩图片 65 | byte[] compressBytes = ImgUtil.compressPicForScale(bytes,200, UUID.randomUUID().toString()); 66 | return new CellData(compressBytes); 67 | }catch (Exception exception) { 68 | //直接当成String处理 69 | return new CellData(value); 70 | }finally { 71 | if (inputStream != null) { 72 | inputStream.close(); 73 | } 74 | } 75 | 76 | } 77 | 78 | else{ 79 | return new CellData(value); 80 | } 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /subtlechat-api/src/main/java/top/javahai/subtlechat/api/converter/MyUrlImageConverter.java: -------------------------------------------------------------------------------- 1 | package top.javahai.subtlechat.api.converter; 2 | 3 | import com.alibaba.excel.converters.Converter; 4 | import com.alibaba.excel.enums.CellDataTypeEnum; 5 | import com.alibaba.excel.metadata.CellData; 6 | import com.alibaba.excel.metadata.GlobalConfiguration; 7 | import com.alibaba.excel.metadata.property.ExcelContentProperty; 8 | import com.alibaba.excel.util.IoUtils; 9 | import net.coobird.thumbnailator.Thumbnails; 10 | import org.apache.poi.hpsf.Thumbnail; 11 | import top.javahai.subtlechat.api.utils.ImgUtil; 12 | 13 | import java.io.FileNotFoundException; 14 | import java.io.IOException; 15 | import java.io.InputStream; 16 | import java.net.ConnectException; 17 | import java.net.HttpURLConnection; 18 | import java.net.URL; 19 | import java.net.URLConnection; 20 | import java.util.UUID; 21 | 22 | /** 23 | * @author Hai 24 | * @program: subtlechat 25 | * @description: 将URL图片的格式转化器 26 | * @create 2020/10/8 - 12:45 27 | **/ 28 | public class MyUrlImageConverter implements Converter { 29 | @Override 30 | public Class supportJavaTypeKey() { 31 | return URL.class; 32 | } 33 | 34 | @Override 35 | public CellDataTypeEnum supportExcelTypeKey() { 36 | return CellDataTypeEnum.IMAGE; 37 | } 38 | 39 | @Override 40 | public URL convertToJavaData(CellData cellData, ExcelContentProperty contentProperty, 41 | GlobalConfiguration globalConfiguration) { 42 | throw new UnsupportedOperationException("Cannot convert images to url."); 43 | } 44 | 45 | @Override 46 | public CellData convertToExcelData(URL value, ExcelContentProperty contentProperty, 47 | GlobalConfiguration globalConfiguration) throws IOException { 48 | InputStream inputStream = null; 49 | try { 50 | //开启连接 51 | URLConnection uc = value.openConnection(); 52 | URL url = null; 53 | 54 | 55 | 56 | //获取响应状态 57 | int statusCode = ((HttpURLConnection) uc).getResponseCode(); 58 | switch (statusCode){ 59 | case 200: 60 | inputStream = value.openStream(); 61 | break; 62 | case 404: 63 | //默认给一个图片 64 | url = new URL("https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1598096095144&di=9a72ad26e83effb9341c711c9818b85f&imgtype=0&src=http%3A%2F%2Fpic.616pic.com%2Fys_bnew_img%2F00%2F11%2F69%2Fj2AjnHspwT.jpg"); 65 | inputStream = url.openStream(); 66 | break; 67 | default : 68 | url = new URL("https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1598096095144&di=9a72ad26e83effb9341c711c9818b85f&imgtype=0&src=http%3A%2F%2Fpic.616pic.com%2Fys_bnew_img%2F00%2F11%2F69%2Fj2AjnHspwT.jpg"); 69 | inputStream = url.openStream(); 70 | break; 71 | } 72 | byte[] bytes = IoUtils.toByteArray(inputStream); 73 | byte[] compressBytes = ImgUtil.compressPicForScale(bytes,200, UUID.randomUUID().toString()); 74 | return new CellData(compressBytes); 75 | }catch (ConnectException exception){ 76 | //捕获下链接异常 77 | URL url = new URL("https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1598096095144&di=9a72ad26e83effb9341c711c9818b85f&imgtype=0&src=http%3A%2F%2Fpic.616pic.com%2Fys_bnew_img%2F00%2F11%2F69%2Fj2AjnHspwT.jpg"); 78 | inputStream = url.openStream(); 79 | byte[] bytes = IoUtils.toByteArray(inputStream); 80 | return new CellData(bytes); 81 | }catch (FileNotFoundException fileNotFoundException){ 82 | URL url = new URL("https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1598096095144&di=9a72ad26e83effb9341c711c9818b85f&imgtype=0&src=http%3A%2F%2Fpic.616pic.com%2Fys_bnew_img%2F00%2F11%2F69%2Fj2AjnHspwT.jpg"); 83 | inputStream = url.openStream(); 84 | byte[] bytes = IoUtils.toByteArray(inputStream); 85 | return new CellData(bytes); 86 | }finally { 87 | if (inputStream != null) { 88 | inputStream.close(); 89 | } 90 | } 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /subtlechat-api/src/main/java/top/javahai/subtlechat/api/data/GroupMsgContentData.java: -------------------------------------------------------------------------------- 1 | package top.javahai.subtlechat.api.data; 2 | 3 | import com.alibaba.excel.annotation.ExcelIgnore; 4 | import com.alibaba.excel.annotation.ExcelProperty; 5 | import com.alibaba.excel.annotation.write.style.ColumnWidth; 6 | import com.alibaba.excel.annotation.write.style.ContentRowHeight; 7 | import com.alibaba.excel.converters.string.StringImageConverter; 8 | import com.alibaba.excel.converters.url.UrlImageConverter; 9 | import com.fasterxml.jackson.annotation.JsonFormat; 10 | import top.javahai.subtlechat.api.converter.MyUrlImageConverter; 11 | import top.javahai.subtlechat.api.entity.GroupMsgContent; 12 | 13 | import java.net.MalformedURLException; 14 | import java.net.URL; 15 | import java.util.Date; 16 | 17 | /** 18 | * Excel导入导出的数据类 19 | * @author Hai 20 | * @date 2020/10/7 - 23:52 21 | */ 22 | @ColumnWidth(25) 23 | @ContentRowHeight(30) 24 | public class GroupMsgContentData { 25 | 26 | @ExcelProperty("消息内容编号") 27 | private Integer id; 28 | 29 | @ExcelProperty("发送者的编号") 30 | private Integer fromId; 31 | 32 | @ExcelProperty("昵称") 33 | private String fromName; 34 | 35 | //@ExcelProperty(value = "头像",converter = UrlImageConverter.class) 36 | @ExcelIgnore 37 | private URL fromProfile; 38 | 39 | @ExcelProperty("发送时间") 40 | @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8") 41 | private Date createTime; 42 | 43 | @ExcelProperty(value = {"内容","文本"}) 44 | @ColumnWidth(50) 45 | private String textContent; 46 | 47 | @ExcelProperty(value = {"内容","图片"},converter = MyUrlImageConverter.class) 48 | @ColumnWidth(50) 49 | private URL imageContent; 50 | 51 | @ExcelIgnore 52 | private Integer messageTypeId; 53 | 54 | 55 | public Integer getId() { 56 | return id; 57 | } 58 | 59 | public void setId(Integer id) { 60 | this.id = id; 61 | } 62 | 63 | public Integer getFromId() { 64 | return fromId; 65 | } 66 | 67 | public void setFromId(Integer fromId) { 68 | this.fromId = fromId; 69 | } 70 | 71 | public String getFromName() { 72 | return fromName; 73 | } 74 | 75 | public void setFromName(String fromName) { 76 | this.fromName = fromName; 77 | } 78 | 79 | public URL getFromProfile() { 80 | return fromProfile; 81 | } 82 | 83 | public void setFromProfile(URL fromProfile) { 84 | this.fromProfile = fromProfile; 85 | } 86 | 87 | public Date getCreateTime() { 88 | return createTime; 89 | } 90 | 91 | public void setCreateTime(Date createTime) { 92 | this.createTime = createTime; 93 | } 94 | 95 | public String getTextContent() { 96 | return textContent; 97 | } 98 | 99 | public void setTextContent(String textContent) { 100 | this.textContent = textContent; 101 | } 102 | 103 | public URL getImageContent() { 104 | return imageContent; 105 | } 106 | 107 | public void setImageContent(URL imageContent) { 108 | this.imageContent = imageContent; 109 | } 110 | 111 | public Integer getMessageTypeId() { 112 | return messageTypeId; 113 | } 114 | 115 | public void setMessageTypeId(Integer messageTypeId) { 116 | this.messageTypeId = messageTypeId; 117 | } 118 | 119 | 120 | @Override 121 | public String toString() { 122 | return "GroupMsgContentData{" + 123 | "id=" + id + 124 | ", fromId=" + fromId + 125 | ", fromName='" + fromName + '\'' + 126 | ", fromProfile=" + fromProfile + 127 | ", createTime=" + createTime + 128 | ", textContent='" + textContent + '\'' + 129 | ", imageContent=" + imageContent + 130 | ", messageTypeId=" + messageTypeId + 131 | '}'; 132 | } 133 | } 134 | -------------------------------------------------------------------------------- /subtlechat-api/src/main/java/top/javahai/subtlechat/api/entity/Admin.java: -------------------------------------------------------------------------------- 1 | package top.javahai.subtlechat.api.entity; 2 | 3 | import org.springframework.security.core.GrantedAuthority; 4 | import org.springframework.security.core.userdetails.UserDetails; 5 | 6 | import java.io.Serializable; 7 | import java.util.Collection; 8 | 9 | /** 10 | * (Admin)实体类 11 | * 12 | * @author makejava 13 | * @since 2020-06-16 11:35:56 14 | */ 15 | public class Admin implements Serializable, UserDetails { 16 | private static final long serialVersionUID = -75235725571250857L; 17 | 18 | private Integer id; 19 | /** 20 | * 登录账号 21 | */ 22 | private String username; 23 | /** 24 | * 昵称 25 | */ 26 | private String nickname; 27 | /** 28 | * 密码 29 | */ 30 | private String password; 31 | /** 32 | * 管理员头像 33 | */ 34 | private String userProfile; 35 | 36 | 37 | public Integer getId() { 38 | return id; 39 | } 40 | 41 | public void setId(Integer id) { 42 | this.id = id; 43 | } 44 | 45 | public String getUsername() { 46 | return username; 47 | } 48 | 49 | @Override 50 | public boolean isAccountNonExpired() { 51 | return true; 52 | } 53 | 54 | @Override 55 | public boolean isAccountNonLocked() { 56 | return true; 57 | } 58 | 59 | @Override 60 | public boolean isCredentialsNonExpired() { 61 | return true; 62 | } 63 | 64 | @Override 65 | public boolean isEnabled() { 66 | return true; 67 | } 68 | 69 | public void setUsername(String username) { 70 | this.username = username; 71 | } 72 | 73 | public String getNickname() { 74 | return nickname; 75 | } 76 | 77 | public void setNickname(String nickname) { 78 | this.nickname = nickname; 79 | } 80 | 81 | @Override 82 | public Collection getAuthorities() { 83 | return null; 84 | } 85 | 86 | public String getPassword() { 87 | return password; 88 | } 89 | 90 | public void setPassword(String password) { 91 | this.password = password; 92 | } 93 | 94 | public String getUserProfile() { 95 | return userProfile; 96 | } 97 | 98 | public void setUserProfile(String userProfile) { 99 | this.userProfile = userProfile; 100 | } 101 | 102 | } 103 | -------------------------------------------------------------------------------- /subtlechat-api/src/main/java/top/javahai/subtlechat/api/entity/Feedback.java: -------------------------------------------------------------------------------- 1 | package top.javahai.subtlechat.api.entity; 2 | 3 | import java.io.Serializable; 4 | 5 | /** 6 | * (Feedback)实体类 7 | * 8 | * @author makejava 9 | * @since 2020-10-02 12:14:15 10 | */ 11 | public class Feedback implements Serializable { 12 | private static final long serialVersionUID = 550979088670747783L; 13 | 14 | private String id; 15 | 16 | private String userId; 17 | 18 | private String username; 19 | 20 | private String nickname; 21 | 22 | private String content; 23 | 24 | 25 | public String getId() { 26 | return id; 27 | } 28 | 29 | public void setId(String id) { 30 | this.id = id; 31 | } 32 | 33 | public String getUserId() { 34 | return userId; 35 | } 36 | 37 | public void setUserId(String userId) { 38 | this.userId = userId; 39 | } 40 | 41 | public String getUsername() { 42 | return username; 43 | } 44 | 45 | public void setUsername(String username) { 46 | this.username = username; 47 | } 48 | 49 | public String getNickname() { 50 | return nickname; 51 | } 52 | 53 | public void setNickname(String nickname) { 54 | this.nickname = nickname; 55 | } 56 | 57 | public String getContent() { 58 | return content; 59 | } 60 | 61 | public void setContent(String content) { 62 | this.content = content; 63 | } 64 | 65 | } -------------------------------------------------------------------------------- /subtlechat-api/src/main/java/top/javahai/subtlechat/api/entity/GroupMsgContent.java: -------------------------------------------------------------------------------- 1 | package top.javahai.subtlechat.api.entity; 2 | 3 | import com.alibaba.excel.annotation.ExcelIgnore; 4 | import com.alibaba.excel.annotation.ExcelProperty; 5 | import com.alibaba.excel.annotation.write.style.ColumnWidth; 6 | import com.alibaba.excel.annotation.write.style.ContentRowHeight; 7 | import com.alibaba.excel.converters.string.StringImageConverter; 8 | import com.fasterxml.jackson.annotation.JsonFormat; 9 | import jdk.nashorn.internal.ir.annotations.Ignore; 10 | import top.javahai.subtlechat.api.converter.MyContentConverter; 11 | import top.javahai.subtlechat.api.data.GroupMsgContentData; 12 | 13 | import java.io.Serializable; 14 | import java.net.MalformedURLException; 15 | import java.net.URL; 16 | import java.util.Date; 17 | 18 | /** 19 | * (GroupMsgContent)实体类 20 | * 21 | * @author makejava 22 | * @since 2020-06-17 10:46:50 23 | */ 24 | @ColumnWidth(25) 25 | @ContentRowHeight(40) 26 | public class GroupMsgContent implements Serializable { 27 | private static final long serialVersionUID = 980328865610261046L; 28 | /** 29 | * 消息内容编号 30 | */ 31 | @ExcelProperty("消息内容编号") 32 | private Integer id; 33 | /** 34 | * 发送者的编号 35 | */ 36 | @ExcelProperty("发送者的编号") 37 | private Integer fromId; 38 | /** 39 | * 发送者的昵称 40 | */ 41 | @ExcelProperty("昵称") 42 | private String fromName; 43 | /** 44 | * 发送者的头像 45 | */ 46 | @ExcelIgnore 47 | private String fromProfile; 48 | /** 49 | * 消息发送时间 50 | */ 51 | @ExcelProperty("发送时间") 52 | @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8") 53 | private Date createTime; 54 | /** 55 | * 消息内容 56 | */ 57 | @ExcelProperty(value = "内容",converter = MyContentConverter.class) 58 | @ColumnWidth(50) 59 | private String content; 60 | /** 61 | * 消息类型编号 62 | */ 63 | @ExcelIgnore 64 | private Integer messageTypeId; 65 | 66 | 67 | public Integer getId() { 68 | return id; 69 | } 70 | 71 | public void setId(Integer id) { 72 | this.id = id; 73 | } 74 | 75 | public Integer getFromId() { 76 | return fromId; 77 | } 78 | 79 | public void setFromId(Integer fromId) { 80 | this.fromId = fromId; 81 | } 82 | 83 | public String getFromName() { 84 | return fromName; 85 | } 86 | 87 | public void setFromName(String fromName) { 88 | this.fromName = fromName; 89 | } 90 | 91 | public String getFromProfile() { 92 | return fromProfile; 93 | } 94 | 95 | public void setFromProfile(String fromProfile) { 96 | this.fromProfile = fromProfile; 97 | } 98 | 99 | public Date getCreateTime() { 100 | return createTime; 101 | } 102 | 103 | public void setCreateTime(Date createTime) { 104 | this.createTime = createTime; 105 | } 106 | 107 | public String getContent() { 108 | return content; 109 | } 110 | 111 | public void setContent(String content) { 112 | this.content = content; 113 | } 114 | 115 | public Integer getMessageTypeId() { 116 | return messageTypeId; 117 | } 118 | 119 | public void setMessageTypeId(Integer messageTypeId) { 120 | this.messageTypeId = messageTypeId; 121 | } 122 | 123 | @Override 124 | public String toString() { 125 | return "GroupMsgContent{" + 126 | "id=" + id + 127 | ", fromId=" + fromId + 128 | ", fromName='" + fromName + '\'' + 129 | ", fromProfile='" + fromProfile + '\'' + 130 | ", createTime=" + createTime + 131 | ", content='" + content + '\'' + 132 | ", messageTypeId=" + messageTypeId + 133 | '}'; 134 | } 135 | 136 | /** 137 | * 将数据库实体转化为Excel的数据实体 138 | * @param groupMsgContent 139 | * @return 140 | */ 141 | public static GroupMsgContentData convertEntityToData(GroupMsgContent groupMsgContent) throws MalformedURLException { 142 | GroupMsgContentData groupMsgContentData = new GroupMsgContentData(); 143 | groupMsgContentData.setFromId(groupMsgContent.getFromId()); 144 | groupMsgContentData.setId(groupMsgContent.getId()); 145 | groupMsgContentData.setFromName(groupMsgContent.getFromName()); 146 | groupMsgContentData.setCreateTime(groupMsgContent.getCreateTime()); 147 | //转化为URL以Excel导出图片 148 | groupMsgContentData.setFromProfile(new URL(groupMsgContent.getFromProfile())); 149 | //根据消息类型设置内容 150 | if (groupMsgContent.getMessageTypeId()==1){ 151 | groupMsgContentData.setTextContent(groupMsgContent.getContent()); 152 | } 153 | if (groupMsgContent.getMessageTypeId()==2){ 154 | groupMsgContentData.setImageContent(new URL(groupMsgContent.getContent())); 155 | } 156 | 157 | return groupMsgContentData; 158 | } 159 | } 160 | -------------------------------------------------------------------------------- /subtlechat-api/src/main/java/top/javahai/subtlechat/api/entity/MailConstants.java: -------------------------------------------------------------------------------- 1 | package top.javahai.subtlechat.api.entity; 2 | 3 | /** 4 | * @author Hai 5 | * @date 2020/10/2 - 14:52 6 | */ 7 | public class MailConstants { 8 | //消息投递中 9 | public static final Integer DELIVERING=0; 10 | //消息投递成功 11 | public static final Integer SUCCESS=1; 12 | //消息投递失败 13 | public static final Integer FAILURE=2; 14 | //最大重试次数 15 | public static final Integer MAX_TRY_COUNT=3; 16 | //消息超时时间 17 | public static final Integer MEG_TIMEOUT=1; 18 | //消息类型为反馈 19 | public static final Integer FEEDBACK_TYPE=1; 20 | //消息类型为验证码 21 | public static final Integer VERIFY_CODE_TYPE=2; 22 | } 23 | -------------------------------------------------------------------------------- /subtlechat-api/src/main/java/top/javahai/subtlechat/api/entity/MailSendLog.java: -------------------------------------------------------------------------------- 1 | package top.javahai.subtlechat.api.entity; 2 | 3 | import java.util.Date; 4 | import java.io.Serializable; 5 | 6 | /** 7 | * (MailSendLog)实体类 8 | * 9 | * @author makejava 10 | * @since 2020-10-02 15:10:48 11 | */ 12 | public class MailSendLog implements Serializable { 13 | private static final long serialVersionUID = 740872026109078508L; 14 | 15 | private String msgId; 16 | /** 17 | * 0:反馈,1:验证码 18 | */ 19 | private Integer contentType; 20 | 21 | private String content; 22 | 23 | private Integer status; 24 | 25 | private String routeKey; 26 | 27 | private String exchange; 28 | 29 | private Integer count; 30 | 31 | private Date tryTime; 32 | 33 | private Date createTime; 34 | 35 | private Date updateTime; 36 | 37 | 38 | public String getMsgId() { 39 | return msgId; 40 | } 41 | 42 | public void setMsgId(String msgId) { 43 | this.msgId = msgId; 44 | } 45 | 46 | public Integer getContentType() { 47 | return contentType; 48 | } 49 | 50 | public void setContentType(Integer contentType) { 51 | this.contentType = contentType; 52 | } 53 | 54 | public String getContent() { 55 | return content; 56 | } 57 | 58 | public void setContent(String content) { 59 | this.content = content; 60 | } 61 | 62 | public Integer getStatus() { 63 | return status; 64 | } 65 | 66 | public void setStatus(Integer status) { 67 | this.status = status; 68 | } 69 | 70 | public String getRouteKey() { 71 | return routeKey; 72 | } 73 | 74 | public void setRouteKey(String routeKey) { 75 | this.routeKey = routeKey; 76 | } 77 | 78 | public String getExchange() { 79 | return exchange; 80 | } 81 | 82 | public void setExchange(String exchange) { 83 | this.exchange = exchange; 84 | } 85 | 86 | public Integer getCount() { 87 | return count; 88 | } 89 | 90 | public void setCount(Integer count) { 91 | this.count = count; 92 | } 93 | 94 | public Date getTryTime() { 95 | return tryTime; 96 | } 97 | 98 | public void setTryTime(Date tryTime) { 99 | this.tryTime = tryTime; 100 | } 101 | 102 | public Date getCreateTime() { 103 | return createTime; 104 | } 105 | 106 | public void setCreateTime(Date createTime) { 107 | this.createTime = createTime; 108 | } 109 | 110 | public Date getUpdateTime() { 111 | return updateTime; 112 | } 113 | 114 | public void setUpdateTime(Date updateTime) { 115 | this.updateTime = updateTime; 116 | } 117 | 118 | } 119 | -------------------------------------------------------------------------------- /subtlechat-api/src/main/java/top/javahai/subtlechat/api/entity/Message.java: -------------------------------------------------------------------------------- 1 | package top.javahai.subtlechat.api.entity; 2 | 3 | import java.util.Date; 4 | 5 | /** 6 | * 单聊的消息实体 7 | * @author Hai 8 | * @date 2020/6/25 - 19:32 9 | */ 10 | public class Message { 11 | private String from; 12 | private String to; 13 | private String content; 14 | private Date createTime; 15 | private String fromNickname; 16 | private String fromUserProfile; 17 | private Integer messageTypeId; 18 | 19 | public String getFrom() { 20 | return from; 21 | } 22 | 23 | public void setFrom(String from) { 24 | this.from = from; 25 | } 26 | 27 | public String getTo() { 28 | return to; 29 | } 30 | 31 | public void setTo(String to) { 32 | this.to = to; 33 | } 34 | 35 | public String getContent() { 36 | return content; 37 | } 38 | 39 | public void setContent(String content) { 40 | this.content = content; 41 | } 42 | 43 | public Date getCreateTime() { 44 | return createTime; 45 | } 46 | 47 | public void setCreateTime(Date createTime) { 48 | this.createTime = createTime; 49 | } 50 | 51 | public String getFromNickname() { 52 | return fromNickname; 53 | } 54 | 55 | public void setFromNickname(String fromNickname) { 56 | this.fromNickname = fromNickname; 57 | } 58 | 59 | public String getFromUserProfile() { 60 | return fromUserProfile; 61 | } 62 | 63 | public void setFromUserProfile(String fromUserProfile) { 64 | this.fromUserProfile = fromUserProfile; 65 | } 66 | 67 | public Integer getMessageTypeId() { 68 | return messageTypeId; 69 | } 70 | 71 | public void setMessageTypeId(Integer messageTypeId) { 72 | this.messageTypeId = messageTypeId; 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /subtlechat-api/src/main/java/top/javahai/subtlechat/api/entity/RespBean.java: -------------------------------------------------------------------------------- 1 | package top.javahai.subtlechat.api.entity; 2 | 3 | /** 4 | * @author Hai 5 | * @date 2020/4/19 - 23:23 6 | */ 7 | //JSON返回值的实体类 8 | public class RespBean { 9 | private Integer status;//状态码 10 | private String msg;//返回消息 11 | private Object obj;//返回实体 12 | 13 | public static RespBean build(){ 14 | return new RespBean(); 15 | } 16 | 17 | public static RespBean ok(String msg){ 18 | return new RespBean(200,msg,null); 19 | } 20 | public static RespBean ok(String msg,Object obj){ 21 | return new RespBean(200,msg,obj); 22 | } 23 | 24 | public static RespBean error(String msg){ 25 | return new RespBean(500,msg,null); 26 | } 27 | public static RespBean error(String msg,Object obj){ 28 | return new RespBean(500,msg,obj); 29 | } 30 | 31 | private RespBean(){ 32 | 33 | } 34 | 35 | private RespBean(Integer status, String msg, Object obj) { 36 | this.status = status; 37 | this.msg = msg; 38 | this.obj = obj; 39 | } 40 | 41 | public Integer getStatus() { 42 | return status; 43 | } 44 | 45 | public RespBean setStatus(Integer status) { 46 | this.status = status; 47 | return this; 48 | } 49 | 50 | public String getMsg() { 51 | return msg; 52 | } 53 | 54 | public RespBean setMsg(String msg) { 55 | this.msg = msg; 56 | return this; 57 | } 58 | 59 | public Object getObj() { 60 | return obj; 61 | } 62 | 63 | public RespBean setObj(Object obj) { 64 | this.obj = obj; 65 | return this; 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /subtlechat-api/src/main/java/top/javahai/subtlechat/api/entity/RespPageBean.java: -------------------------------------------------------------------------------- 1 | package top.javahai.subtlechat.api.entity; 2 | 3 | import java.util.List; 4 | 5 | /** 6 | * @author luo 7 | * @date 2020/6/22 - 19:18 8 | */ 9 | public class RespPageBean { 10 | private Long total;//数据总数 11 | private List data;//数据实体列表 12 | 13 | public Long getTotal() { 14 | return total; 15 | } 16 | 17 | public void setTotal(Long total) { 18 | this.total = total; 19 | } 20 | 21 | public List getData() { 22 | return data; 23 | } 24 | 25 | public void setData(List data) { 26 | this.data = data; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /subtlechat-api/src/main/java/top/javahai/subtlechat/api/entity/User.java: -------------------------------------------------------------------------------- 1 | package top.javahai.subtlechat.api.entity; 2 | 3 | import org.springframework.security.core.GrantedAuthority; 4 | import org.springframework.security.core.userdetails.UserDetails; 5 | 6 | import java.util.Collection; 7 | 8 | /** 9 | * (User)实体类 10 | * 11 | * @author makejava 12 | * @since 2020-06-16 12:08:01 13 | */ 14 | public class User implements UserDetails { 15 | 16 | private Integer id; 17 | /** 18 | * 登录账号 19 | */ 20 | private String username; 21 | /** 22 | * 昵称 23 | */ 24 | private String nickname; 25 | /** 26 | * 密码 27 | */ 28 | private String password; 29 | /** 30 | * 用户头像 31 | */ 32 | private String userProfile; 33 | /** 34 | * 用户状态id 35 | */ 36 | private Integer userStateId; 37 | /** 38 | * 是否可用 39 | */ 40 | private Boolean isEnabled; 41 | /** 42 | * 是否被锁定 43 | */ 44 | private Boolean isLocked; 45 | 46 | 47 | public Integer getId() { 48 | return id; 49 | } 50 | 51 | public void setId(Integer id) { 52 | this.id = id; 53 | } 54 | 55 | public String getUsername() { 56 | return username; 57 | } 58 | 59 | //账号是否未过期 60 | @Override 61 | public boolean isAccountNonExpired() { 62 | return true; 63 | } 64 | 65 | //账号是否不锁定 66 | @Override 67 | public boolean isAccountNonLocked() { 68 | return !isLocked; 69 | } 70 | 71 | @Override 72 | public boolean isCredentialsNonExpired() { 73 | return true; 74 | } 75 | 76 | @Override 77 | public boolean isEnabled() { 78 | return isEnabled; 79 | } 80 | 81 | public void setUsername(String username) { 82 | this.username = username; 83 | } 84 | 85 | public String getNickname() { 86 | return nickname; 87 | } 88 | 89 | public void setNickname(String nickname) { 90 | this.nickname = nickname; 91 | } 92 | 93 | /** 94 | * 获取用户拥有的所有角色 95 | * @return 96 | */ 97 | @Override 98 | public Collection getAuthorities() { 99 | return null; 100 | } 101 | 102 | public String getPassword() { 103 | return password; 104 | } 105 | 106 | public void setPassword(String password) { 107 | this.password = password; 108 | } 109 | 110 | public String getUserProfile() { 111 | return userProfile; 112 | } 113 | 114 | public void setUserProfile(String userProfile) { 115 | this.userProfile = userProfile; 116 | } 117 | 118 | public Integer getUserStateId() { 119 | return userStateId; 120 | } 121 | 122 | public void setUserStateId(Integer userStateId) { 123 | this.userStateId = userStateId; 124 | } 125 | 126 | 127 | public void setEnabled(Boolean enabled) { 128 | isEnabled = enabled; 129 | } 130 | 131 | public void setLocked(Boolean locked) { 132 | isLocked = locked; 133 | } 134 | 135 | @Override 136 | public String toString() { 137 | return "User{" + 138 | "id=" + id + 139 | ", username='" + username + '\'' + 140 | ", nickname='" + nickname + '\'' + 141 | ", password='" + password + '\'' + 142 | ", userProfile='" + userProfile + '\'' + 143 | ", userStateId=" + userStateId + 144 | ", isEnabled=" + isEnabled + 145 | ", isLocked=" + isLocked + 146 | '}'; 147 | } 148 | } 149 | -------------------------------------------------------------------------------- /subtlechat-api/src/main/java/top/javahai/subtlechat/api/entity/UserState.java: -------------------------------------------------------------------------------- 1 | package top.javahai.subtlechat.api.entity; 2 | 3 | import java.io.Serializable; 4 | 5 | /** 6 | * (UserState)实体类 7 | * 8 | * @author makejava 9 | * @since 2020-06-16 11:36:02 10 | */ 11 | public class UserState implements Serializable { 12 | private static final long serialVersionUID = -38130170610280885L; 13 | 14 | private Integer id; 15 | /** 16 | * 状态名 17 | */ 18 | private String name; 19 | 20 | 21 | public Integer getId() { 22 | return id; 23 | } 24 | 25 | public void setId(Integer id) { 26 | this.id = id; 27 | } 28 | 29 | public String getName() { 30 | return name; 31 | } 32 | 33 | public void setName(String name) { 34 | this.name = name; 35 | } 36 | 37 | } 38 | -------------------------------------------------------------------------------- /subtlechat-api/src/main/java/top/javahai/subtlechat/api/utils/FastDFSUtil.java: -------------------------------------------------------------------------------- 1 | package top.javahai.subtlechat.api.utils; 2 | 3 | import org.csource.common.MyException; 4 | import org.csource.fastdfs.ClientGlobal; 5 | import org.csource.fastdfs.StorageClient1; 6 | import org.csource.fastdfs.TrackerClient; 7 | import org.csource.fastdfs.TrackerServer; 8 | import org.springframework.web.multipart.MultipartFile; 9 | 10 | import java.io.IOException; 11 | import java.io.UnsupportedEncodingException; 12 | import java.security.NoSuchAlgorithmException; 13 | 14 | /** 15 | * @author Hai 16 | * @date 2020/6/20 - 23:43 17 | */ 18 | public class FastDFSUtil { 19 | private static StorageClient1 client1; 20 | 21 | static{ 22 | try{ 23 | ClientGlobal.initByProperties("fastdfs-client.properties"); 24 | TrackerClient trackerClient=new TrackerClient(); 25 | TrackerServer trackerServer=trackerClient.getConnection(); 26 | client1=new StorageClient1(trackerServer,null); 27 | } catch (IOException e) { 28 | e.printStackTrace(); 29 | } catch (MyException e) { 30 | e.printStackTrace(); 31 | } 32 | } 33 | 34 | /** 35 | * 上传文件 36 | * @param file 37 | * @return 38 | * @throws IOException 39 | * @throws MyException 40 | */ 41 | public static String upload(MultipartFile file) throws IOException, MyException { 42 | //文件名 43 | String oldName=file.getOriginalFilename(); 44 | //返回上传到服务器的路径 45 | //文件拓展名oldName.substring(oldName.lastIndexOf(".")+1) 46 | return client1.upload_file1(file.getBytes(),oldName.substring(oldName.lastIndexOf(".")+1),null); 47 | } 48 | 49 | /** 50 | *获取访问文件的令牌 51 | * @throws UnsupportedEncodingException 52 | * @throws NoSuchAlgorithmException 53 | * @throws MyException 54 | * @return 55 | */ 56 | // public static StringBuilder getToken(String fileId) throws UnsupportedEncodingException, NoSuchAlgorithmException, MyException { 57 | // int ts = (int) Instant.now().getEpochSecond(); 58 | // fileId=fileId.substring(7); 59 | // String token = ProtoCommon.getToken(fileId, ts, "FastDFS1234567890"); 60 | // StringBuilder sb = new StringBuilder(); 61 | // sb.append("?token=").append(token); 62 | // sb.append("&ts=").append(ts); 63 | // return sb; 64 | // } 65 | } 66 | -------------------------------------------------------------------------------- /subtlechat-api/src/main/java/top/javahai/subtlechat/api/utils/ImgUtil.java: -------------------------------------------------------------------------------- 1 | package top.javahai.subtlechat.api.utils; 2 | 3 | 4 | import net.coobird.thumbnailator.Thumbnails; 5 | import org.slf4j.Logger; 6 | import org.slf4j.LoggerFactory; 7 | 8 | import java.io.ByteArrayInputStream; 9 | import java.io.ByteArrayOutputStream; 10 | 11 | /** 12 | * @author Hai 13 | * @program: subtlechat 14 | * @description: 调用Thumbnails压缩图片 15 | * @create 2020/10/8 - 13:50 16 | **/ 17 | public class ImgUtil { 18 | 19 | 20 | private static Logger logger = LoggerFactory.getLogger(ImgUtil.class); 21 | 22 | // public static void main(String[] args) throws IOException { 23 | // byte[] bytes = FileUtils.readFileToByteArray(new File("D:\\1.jpg")); 24 | // long l = System.currentTimeMillis(); 25 | // bytes = ImgUtil.compressPicForScale(bytes, 300, "x");// 图片小于300kb 26 | // System.out.println(System.currentTimeMillis() - l); 27 | // FileUtils.writeByteArrayToFile(new File("D:\\dd1.jpg"), bytes); 28 | // } 29 | 30 | /** 31 | * 根据指定大小压缩图片 32 | * 33 | * @param imageBytes 源图片字节数组 34 | * @param desFileSize 指定图片大小,单位kb 35 | * @param imageId 影像编号 36 | * @return 压缩质量后的图片字节数组 37 | */ 38 | public static byte[] compressPicForScale(byte[] imageBytes, long desFileSize, String imageId) { 39 | if (imageBytes == null || imageBytes.length <= 0 || imageBytes.length < desFileSize * 1024) { 40 | return imageBytes; 41 | } 42 | long srcSize = imageBytes.length; 43 | //double accuracy = getAccuracy(srcSize / 1024); 44 | double accuracy=0.4; 45 | try { 46 | while (imageBytes.length > desFileSize * 1024) { 47 | ByteArrayInputStream inputStream = new ByteArrayInputStream(imageBytes); 48 | ByteArrayOutputStream outputStream = new ByteArrayOutputStream(imageBytes.length); 49 | Thumbnails.of(inputStream) 50 | .scale(accuracy) 51 | .outputQuality(accuracy) 52 | .toOutputStream(outputStream); 53 | imageBytes = outputStream.toByteArray(); 54 | } 55 | logger.info("【图片压缩】imageId={} | 图片原大小={}kb | 压缩后大小={}kb", 56 | imageId, srcSize / 1024, imageBytes.length / 1024); 57 | } catch (Exception e) { 58 | logger.error("【图片压缩】msg=图片压缩失败!", e); 59 | } 60 | return imageBytes; 61 | } 62 | 63 | /** 64 | * 自动调节精度(经验数值) 65 | * 66 | * @param size 源图片大小 67 | * @return 图片压缩质量比 68 | */ 69 | private static double getAccuracy(long size) { 70 | double accuracy; 71 | if (size < 900) { 72 | accuracy = 0.5; 73 | } else if (size < 2047) { 74 | accuracy = 0.6; 75 | } else if (size < 3275) { 76 | accuracy = 0.44; 77 | } else { 78 | accuracy = 0.4; 79 | } 80 | return accuracy; 81 | } 82 | 83 | } 84 | -------------------------------------------------------------------------------- /subtlechat-api/src/main/java/top/javahai/subtlechat/api/utils/JsonUtil.java: -------------------------------------------------------------------------------- 1 | package top.javahai.subtlechat.api.utils; 2 | 3 | import com.alibaba.fastjson.JSON; 4 | import com.alibaba.fastjson.parser.Feature; 5 | 6 | /** 7 | * 封装fastjson的方法,若需要换Json工具,也不需要到处改 8 | * @author Hai 9 | * @date 2020/10/2 - 22:06 10 | */ 11 | public class JsonUtil extends JSON { 12 | 13 | 14 | public static String parseToString(Object object) { 15 | 16 | return toJSONString(object); 17 | 18 | } 19 | 20 | public static T parseToObject(String text, Class clazz) { 21 | return parseObject(text, clazz); 22 | } 23 | 24 | } 25 | -------------------------------------------------------------------------------- /subtlechat-api/src/main/java/top/javahai/subtlechat/api/utils/TuLingUtil.java: -------------------------------------------------------------------------------- 1 | package top.javahai.subtlechat.api.utils; 2 | 3 | 4 | 5 | import com.fasterxml.jackson.core.JsonProcessingException; 6 | import com.fasterxml.jackson.databind.ObjectMapper; 7 | 8 | import java.io.BufferedReader; 9 | import java.io.IOException; 10 | import java.io.InputStreamReader; 11 | import java.net.HttpURLConnection; 12 | import java.net.URL; 13 | import java.net.URLEncoder; 14 | import java.util.HashMap; 15 | 16 | /** 17 | * 智能回复机器人工具类 18 | * @author Hai 19 | * @date 2020/6/25 - 17:53 20 | */ 21 | public class TuLingUtil { 22 | 23 | private static ObjectMapper MAPPER=new ObjectMapper(); 24 | 25 | /** 26 | * 发送消息,获得图灵机器人回复消息 27 | * @param message 28 | * @return 29 | * @throws IOException 30 | */ 31 | public static String replyMessage(String message) throws IOException { 32 | String APIKEY = "40445cf23e2144828218d7fc95d6f05a"; 33 | String INFO = URLEncoder.encode(message, "utf-8"); 34 | String getURL = "http://www.tuling123.com/openapi/api?key=" + APIKEY + "&info=" + INFO; 35 | URL getUrl = new URL(getURL); 36 | HttpURLConnection connection = (HttpURLConnection) getUrl.openConnection(); 37 | connection.connect(); 38 | // 取得输入流,并使用Reader读取 39 | BufferedReader reader = new BufferedReader(new InputStreamReader( connection.getInputStream(), "utf-8")); 40 | StringBuffer sb = new StringBuffer(); 41 | String line = ""; 42 | while ((line = reader.readLine()) != null) { 43 | sb.append(line); 44 | } 45 | reader.close(); 46 | // 断开连接 47 | connection.disconnect(); 48 | 49 | return parseMess(sb.toString()); 50 | } 51 | 52 | /** 53 | * 解析返回的JSON字符串,获取回复字符串 54 | * @param jsonStr 55 | * @return 56 | * @throws JsonProcessingException 57 | */ 58 | public static String parseMess(String jsonStr) throws JsonProcessingException { 59 | HashMap resultMap = MAPPER.readValue(jsonStr, HashMap.class); 60 | String result = ((String) resultMap.get("text")); 61 | return result; 62 | } 63 | public static void main(String[] args) throws IOException { 64 | String jsonStr = replyMessage("http://39.108.169.57/group1/M00/00/00/J2ypOV7wP0-AEZHOAAILbcn5GEM095.jpg"); 65 | HashMap resultMap = MAPPER.readValue(jsonStr, HashMap.class); 66 | System.out.println(resultMap.get("text")); 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /subtlechat-api/src/main/java/top/javahai/subtlechat/api/utils/UserUtil.java: -------------------------------------------------------------------------------- 1 | package top.javahai.subtlechat.api.utils; 2 | 3 | import org.springframework.security.core.context.SecurityContextHolder; 4 | import top.javahai.subtlechat.api.entity.User; 5 | 6 | /** 7 | * @author Hai 8 | * @date 2020/6/16 - 22:56 9 | * 用户工具类 10 | */ 11 | public class UserUtil { 12 | /** 13 | * 获取当前登录用户实体 14 | * @return 15 | */ 16 | public static User getCurrentUser(){ 17 | return ((User) SecurityContextHolder.getContext().getAuthentication().getPrincipal()); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /subtlechat-api/src/main/resources/fastdfs-client.properties: -------------------------------------------------------------------------------- 1 | ## fastdfs-client.properties 2 | 3 | fastdfs.connect_timeout_in_seconds = 5 4 | fastdfs.network_timeout_in_seconds = 30 5 | 6 | fastdfs.charset = UTF-8 7 | 8 | fastdfs.http_anti_steal_token = false 9 | fastdfs.http_secret_key = FastDFS1234567890 10 | fastdfs.http_tracker_http_port = 80 11 | 12 | fastdfs.tracker_servers = 13 | 14 | ## Whether to open the connection pool, if not, create a new connection every time 15 | fastdfs.connection_pool.enabled = true 16 | 17 | ## max_count_per_entry: max connection count per host:port , 0 is not limit 18 | fastdfs.connection_pool.max_count_per_entry = 500 19 | 20 | ## connections whose the idle time exceeds this time will be closed, unit: second, default value is 3600 21 | fastdfs.connection_pool.max_idle_time = 3600 22 | 23 | ## Maximum waiting time when the maximum number of connections is reached, unit: millisecond, default value is 1000 24 | fastdfs.connection_pool.max_wait_time_in_ms = 1000 25 | -------------------------------------------------------------------------------- /subtlechat-mail/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 4.0.0 5 | 6 | org.springframework.boot 7 | spring-boot-starter-parent 8 | 2.3.4.RELEASE 9 | 10 | 11 | top.javahai 12 | subtlechat-mailserver 13 | 0.0.1-SNAPSHOT 14 | subtlechat-mailserver 15 | the mail server project for SubtleChat application 16 | 17 | 18 | 1.8 19 | 20 | 21 | 22 | 23 | top.javahai 24 | subtlechat-api 25 | 0.0.1-SNAPSHOT 26 | 27 | 28 | org.springframework.boot 29 | spring-boot-starter-amqp 30 | 31 | 32 | org.springframework.boot 33 | spring-boot-starter-data-redis 34 | 35 | 36 | org.springframework.boot 37 | spring-boot-starter-mail 38 | 39 | 40 | org.springframework.boot 41 | spring-boot-starter-thymeleaf 42 | 43 | 44 | org.springframework.boot 45 | spring-boot-starter 46 | 47 | 48 | org.springframework.boot 49 | spring-boot-starter-test 50 | test 51 | 52 | 53 | org.junit.vintage 54 | junit-vintage-engine 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | org.springframework.boot 64 | spring-boot-maven-plugin 65 | 66 | 67 | 68 | 69 | 70 | -------------------------------------------------------------------------------- /subtlechat-mail/src/main/java/top/javahai/subtlechat/mail/SubtleChatMailApplication.java: -------------------------------------------------------------------------------- 1 | package top.javahai.subtlechat.mail; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | 6 | @SpringBootApplication 7 | public class SubtleChatMailApplication { 8 | 9 | public static void main(String[] args) { 10 | SpringApplication.run(SubtleChatMailApplication.class, args); 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /subtlechat-mail/src/main/java/top/javahai/subtlechat/mail/config/RabbitMQConfig.java: -------------------------------------------------------------------------------- 1 | package top.javahai.subtlechat.mail.config; 2 | 3 | 4 | import org.springframework.amqp.core.Binding; 5 | import org.springframework.amqp.core.BindingBuilder; 6 | import org.springframework.amqp.core.DirectExchange; 7 | import org.springframework.amqp.core.Queue; 8 | import org.springframework.beans.factory.annotation.Qualifier; 9 | import org.springframework.beans.factory.annotation.Value; 10 | import org.springframework.context.annotation.Bean; 11 | import org.springframework.context.annotation.Configuration; 12 | 13 | /** 14 | * @author Hai 15 | * @date 2020/10/1 - 18:32 16 | */ 17 | @Configuration 18 | public class RabbitMQConfig { 19 | 20 | @Value("${mail.exchange:mail-exchange}") 21 | private String mailExchange; 22 | 23 | @Value("${mail.queue.verifyCode:mail-queue-verifyCode}") 24 | private String mailQueueVerifyCode; 25 | 26 | @Value("${mail.route.verifyCode:mail-route-verifyCode}") 27 | private String mailRouteVerifyCode; 28 | 29 | @Value("${mail.queue.feedback:mail-queue-feedback}") 30 | private String mailQueueFeedback; 31 | 32 | @Value("${mail.route.feedback:mail-route-feedback}") 33 | private String mailRouteFeedback; 34 | 35 | 36 | @Bean 37 | DirectExchange mailExchange(){ 38 | return new DirectExchange(mailExchange,true,false); 39 | } 40 | 41 | /** 42 | * 验证码消息队列 43 | * @return 44 | */ 45 | @Bean 46 | Queue mailQueueVerifyCode(){ 47 | return new Queue(mailQueueVerifyCode,true); 48 | } 49 | 50 | @Bean 51 | Binding mailQueueVerifyCodeBinding(){ 52 | return BindingBuilder.bind(mailQueueVerifyCode()).to(mailExchange()).with(mailRouteVerifyCode); 53 | } 54 | 55 | /** 56 | * 反馈消息队列 57 | * @return 58 | */ 59 | @Bean 60 | Queue mailQueueFeedback(){ 61 | return new Queue(mailQueueFeedback,true); 62 | } 63 | @Bean 64 | Binding mailQueueFeedbackBinding(){ 65 | return BindingBuilder.bind(mailQueueFeedback()).to(mailExchange()).with(mailRouteFeedback); 66 | } 67 | 68 | } 69 | -------------------------------------------------------------------------------- /subtlechat-mail/src/main/java/top/javahai/subtlechat/mail/receiver/FeedbackReceiver.java: -------------------------------------------------------------------------------- 1 | package top.javahai.subtlechat.mail.receiver; 2 | 3 | import com.rabbitmq.client.Channel; 4 | import org.slf4j.Logger; 5 | import org.slf4j.LoggerFactory; 6 | import org.springframework.amqp.rabbit.annotation.RabbitListener; 7 | import org.springframework.amqp.rabbit.core.RabbitTemplate; 8 | import org.springframework.amqp.support.AmqpHeaders; 9 | import org.springframework.beans.factory.annotation.Autowired; 10 | import org.springframework.data.redis.core.RedisTemplate; 11 | import org.springframework.data.redis.core.StringRedisTemplate; 12 | import org.springframework.mail.SimpleMailMessage; 13 | import org.springframework.mail.javamail.JavaMailSender; 14 | import org.springframework.messaging.Message; 15 | import org.springframework.messaging.MessageHeaders; 16 | import org.springframework.messaging.support.MessageHeaderAccessor; 17 | import org.springframework.stereotype.Component; 18 | import top.javahai.subtlechat.api.entity.Feedback; 19 | import top.javahai.subtlechat.api.utils.JsonUtil; 20 | 21 | import java.beans.FeatureDescriptor; 22 | import java.io.IOException; 23 | import java.util.Date; 24 | 25 | /** 26 | * @author Hai 27 | * @date 2020/10/2 - 13:54 28 | */ 29 | @Component 30 | public class FeedbackReceiver { 31 | 32 | private static final Logger LOGGER= LoggerFactory.getLogger(FeedbackReceiver.class); 33 | 34 | @Autowired 35 | JavaMailSender javaMailSender; 36 | @Autowired 37 | StringRedisTemplate redisTemplate; 38 | 39 | @RabbitListener(queues ="${mail.queue.feedback:mail-queue-feedback}") 40 | public void getFeedbackMessage(Message message, Channel channel) throws IOException { 41 | //获取消息内容 42 | String s = message.getPayload().toString(); 43 | //获取消息的唯一标志 44 | MessageHeaders headers = message.getHeaders(); 45 | Long tag = ((Long) headers.get(AmqpHeaders.DELIVERY_TAG)); 46 | String msgId = headers.get("spring_returned_message_correlation").toString(); 47 | LOGGER.info("【"+msgId+"】-正在处理的消息"); 48 | //是否已消费 49 | if (redisTemplate.opsForHash().entries("mail_log").containsKey(msgId)){ 50 | channel.basicAck(tag,true); 51 | LOGGER.info("【"+msgId+"】消息出现重复消费"); 52 | return; 53 | } 54 | try{ 55 | Feedback feedback = JsonUtil.parseToObject(s, Feedback.class); 56 | System.out.println(feedback.getContent()); 57 | SimpleMailMessage mailMessage = new SimpleMailMessage(); 58 | mailMessage.setSubject("来自用户的意见反馈"); 59 | //读取信息 60 | StringBuilder formatMessage = new StringBuilder(); 61 | formatMessage.append("用户编号:"+feedback.getUserId()+"\n"); 62 | formatMessage.append("用户名:"+feedback.getUsername()+"\n"); 63 | formatMessage.append("用户昵称:"+feedback.getNickname()+"\n"); 64 | formatMessage.append("反馈内容:"+feedback.getContent()); 65 | System.out.println(">>>>>>>>>>>>>>"+formatMessage+"<<<<<<<<<<<<<<<<<<"); 66 | //设置邮件消息 67 | mailMessage.setText(formatMessage.toString()); 68 | mailMessage.setFrom("发送的邮箱地址"); 69 | mailMessage.setTo("接收的邮箱地址"); 70 | mailMessage.setSentDate(new Date()); 71 | javaMailSender.send(mailMessage); 72 | //消息处理完成 73 | // redisTemplate.opsForHash().entries("mail_log").put(msgId,msgId+1); 74 | redisTemplate.opsForHash().put("mail_log",msgId,feedback.getContent()); 75 | //手动确定消息处理完成 76 | channel.basicAck(tag,true); 77 | }catch (Exception e){ 78 | //出现异常就重新放回到队列中 79 | channel.basicNack(tag,false,true); 80 | LOGGER.info("【"+msgId+"】消息重新放回到了队列中"); 81 | e.printStackTrace(); 82 | } 83 | 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /subtlechat-mail/src/main/java/top/javahai/subtlechat/mail/receiver/VerifyCodeReceiver.java: -------------------------------------------------------------------------------- 1 | package top.javahai.subtlechat.mail.receiver; 2 | 3 | import com.rabbitmq.client.AMQP; 4 | import com.rabbitmq.client.Channel; 5 | import com.rabbitmq.client.impl.AMQImpl; 6 | import org.slf4j.Logger; 7 | import org.slf4j.LoggerFactory; 8 | import org.springframework.amqp.rabbit.annotation.RabbitListener; 9 | import org.springframework.amqp.rabbit.core.RabbitTemplate; 10 | import org.springframework.amqp.support.AmqpHeaders; 11 | import org.springframework.beans.factory.annotation.Autowired; 12 | import org.springframework.data.redis.core.RedisTemplate; 13 | import org.springframework.data.redis.core.StringRedisTemplate; 14 | import org.springframework.mail.SimpleMailMessage; 15 | import org.springframework.mail.javamail.JavaMailSender; 16 | import org.springframework.messaging.Message; 17 | import org.springframework.messaging.MessageHeaders; 18 | import org.springframework.stereotype.Component; 19 | 20 | import java.io.IOException; 21 | import java.util.Date; 22 | 23 | /** 24 | * 处理发送验证码的消息,保证消息不会重复消费 25 | * @author Hai 26 | * @date 2020/10/2 - 23:25 27 | */ 28 | @Component 29 | public class VerifyCodeReceiver { 30 | @Autowired 31 | JavaMailSender javaMailSender; 32 | @Autowired 33 | StringRedisTemplate redisTemplate; 34 | 35 | private static final Logger LOGGER= LoggerFactory.getLogger(VerifyCodeReceiver.class); 36 | 37 | @RabbitListener(queues = "${mail.queue.verifyCode:mail-queue-verifyCode}") 38 | public void getMessage(Message message, Channel channel) throws IOException { 39 | //获取消息内容 40 | String code = message.getPayload().toString(); 41 | //获取消息头,消息标志tag 42 | MessageHeaders headers = message.getHeaders(); 43 | Long tag = (Long) headers.get(AmqpHeaders.DELIVERY_TAG); 44 | //获取消息ID 45 | String msgId = (String) headers.get("spring_returned_message_correlation"); 46 | LOGGER.info("【"+msgId+"】-正在处理的消息"); 47 | //查看消息是否已消费 48 | if (redisTemplate.opsForHash().entries("mail_log").containsKey(msgId)){ 49 | //手动确认消息已消费 50 | channel.basicAck(tag,false); 51 | LOGGER.info("【"+msgId+"】消息出现重复消费"); 52 | return; 53 | } 54 | //否则进行消息消费 55 | try{ 56 | SimpleMailMessage msg = new SimpleMailMessage(); 57 | msg.setSubject("微言聊天室管理端-验证码验证"); 58 | //TODO 使用Thymeleaf,改邮件模板,添加内容:请不要泄露自己的邮箱验证码 59 | msg.setText("本次登录的验证码:"+code); 60 | msg.setFrom("发送者的邮箱地址"); 61 | msg.setSentDate(new Date()); 62 | msg.setTo("接受者的邮箱地址"); 63 | javaMailSender.send(msg); 64 | //消息发送成功,将id放到redis中,不能这样put 65 | //redisTemplate.opsForHash().entries("mail_log").put(msgId,code); 66 | redisTemplate.opsForHash().put("mail_log",msgId,code); 67 | //确认消息消费成功 68 | channel.basicAck(tag,false); 69 | }catch (Exception e){ 70 | //不批量处理,将消息重新放回到队列中 71 | channel.basicNack(tag,false,true); 72 | LOGGER.info("【"+msgId+"】消息重新放回到了队列中"); 73 | e.printStackTrace(); 74 | } 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /subtlechat-mail/src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | server: 2 | port: 8084 3 | #邮件相关配置 4 | spring: 5 | application: 6 | name: subtlechat-mailserver 7 | mail: 8 | host: smtp.qq.com 9 | protocol: smtp 10 | default-encoding: UTF-8 11 | #邮箱名 12 | username: 13 | #申请的授权码 14 | password: 15 | port: 587 16 | properties.mail.stmp.socketFactory.class: javax.net.ssl.SSLSocketFactory 17 | properties.mail.debug: true 18 | #RabbitMQ的配置 19 | rabbitmq: 20 | host: 21 | port: 22 | username: 23 | password: 24 | virtual-host: /subtlechat 25 | #开启手动确认是否消息消费成功 26 | listener: 27 | simple: 28 | acknowledge-mode: manual 29 | prefetch: 100 30 | #Redis的配置 31 | redis: 32 | database: 0 33 | password: 34 | host: 35 | port: 36 | -------------------------------------------------------------------------------- /subtlechat-mail/src/test/java/top/javahai/subtlechat/mail/SubtleChatMailApplicationTests.java: -------------------------------------------------------------------------------- 1 | package top.javahai.subtlechat.mail; 2 | 3 | import org.junit.jupiter.api.Test; 4 | import org.springframework.boot.test.context.SpringBootTest; 5 | 6 | @SpringBootTest 7 | class SubtleChatMailApplicationTests { 8 | 9 | @Test 10 | void contextLoads() { 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /subtlechat-web/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 4.0.0 5 | 6 | org.springframework.boot 7 | spring-boot-starter-parent 8 | 2.3.1.RELEASE 9 | 10 | 11 | top.javahai 12 | subtlechat-web 13 | 0.0.1-SNAPSHOT 14 | subtlechat-web 15 | the web server for SubtleChat application 16 | 17 | 18 | 1.8 19 | 20 | 21 | 22 | 23 | top.javahai 24 | subtlechat-api 25 | 0.0.1-SNAPSHOT 26 | 27 | 28 | 29 | org.springframework.boot 30 | spring-boot-starter-amqp 31 | 32 | 33 | org.springframework.boot 34 | spring-boot-starter-security 35 | 36 | 37 | org.springframework.boot 38 | spring-boot-starter-web 39 | 40 | 41 | org.springframework.boot 42 | spring-boot-starter-websocket 43 | 44 | 45 | org.mybatis.spring.boot 46 | mybatis-spring-boot-starter 47 | 2.1.3 48 | 49 | 50 | com.alibaba 51 | druid-spring-boot-starter 52 | 1.1.10 53 | 54 | 55 | mysql 56 | mysql-connector-java 57 | runtime 58 | 59 | 60 | org.springframework.boot 61 | spring-boot-starter-test 62 | test 63 | 64 | 65 | org.junit.vintage 66 | junit-vintage-engine 67 | 68 | 69 | 70 | 71 | org.springframework.security 72 | spring-security-test 73 | test 74 | 75 | 76 | mysql 77 | mysql-connector-java 78 | 5.1.44 79 | 80 | 81 | com.github.binarywang 82 | java-emoji-converter 83 | 0.1.1 84 | 85 | 86 | 87 | 88 | 89 | 90 | src/main/resources 91 | 92 | **/* 93 | 94 | 95 | 96 | 97 | org.springframework.boot 98 | spring-boot-maven-plugin 99 | 100 | 101 | 102 | 103 | 104 | -------------------------------------------------------------------------------- /subtlechat-web/src/main/java/top/javahai/subtlechat/SubtleChatWebApplication.java: -------------------------------------------------------------------------------- 1 | package top.javahai.subtlechat; 2 | 3 | import org.mybatis.spring.annotation.MapperScan; 4 | import org.springframework.boot.SpringApplication; 5 | import org.springframework.boot.autoconfigure.SpringBootApplication; 6 | import org.springframework.scheduling.annotation.EnableScheduling; 7 | 8 | /** 9 | * @author Hai 10 | * @date 2020/6/16 - 12:45 11 | */ 12 | @SpringBootApplication 13 | @MapperScan("top.javahai.subtlechat.dao") 14 | @EnableScheduling 15 | public class SubtleChatWebApplication { 16 | public static void main(String[] args) { 17 | SpringApplication.run(SubtleChatWebApplication.class, args); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /subtlechat-web/src/main/java/top/javahai/subtlechat/config/MultiHttpSecurityConfig.java: -------------------------------------------------------------------------------- 1 | package top.javahai.subtlechat.config; 2 | 3 | import com.fasterxml.jackson.databind.ObjectMapper; 4 | import org.springframework.beans.factory.annotation.Autowired; 5 | import org.springframework.context.annotation.Bean; 6 | import org.springframework.context.annotation.Configuration; 7 | import org.springframework.core.annotation.Order; 8 | import org.springframework.messaging.simp.SimpMessagingTemplate; 9 | import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; 10 | import org.springframework.security.config.annotation.web.builders.HttpSecurity; 11 | import org.springframework.security.config.annotation.web.builders.WebSecurity; 12 | import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; 13 | import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; 14 | import org.springframework.security.core.Authentication; 15 | import org.springframework.security.core.AuthenticationException; 16 | import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; 17 | import org.springframework.security.crypto.password.PasswordEncoder; 18 | import org.springframework.security.web.AuthenticationEntryPoint; 19 | import org.springframework.security.web.authentication.AuthenticationSuccessHandler; 20 | import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; 21 | import org.springframework.security.web.authentication.logout.LogoutSuccessHandler; 22 | import top.javahai.subtlechat.api.entity.Admin; 23 | import top.javahai.subtlechat.api.entity.RespBean; 24 | import top.javahai.subtlechat.api.entity.User; 25 | import top.javahai.subtlechat.service.impl.AdminServiceImpl; 26 | import top.javahai.subtlechat.service.impl.UserServiceImpl; 27 | 28 | import javax.servlet.ServletException; 29 | import javax.servlet.http.HttpServletRequest; 30 | import javax.servlet.http.HttpServletResponse; 31 | import java.io.IOException; 32 | import java.io.PrintWriter; 33 | 34 | /** 35 | * @author Hai 36 | * @date 2020/6/19 - 12:37 37 | */ 38 | @EnableWebSecurity 39 | public class MultiHttpSecurityConfig { 40 | //密码加密方案 41 | @Bean 42 | PasswordEncoder passwordEncoder(){ 43 | return new BCryptPasswordEncoder(); 44 | } 45 | @Configuration 46 | @Order(1) 47 | public static class AdminSecurityConfig extends WebSecurityConfigurerAdapter{ 48 | @Autowired 49 | AdminServiceImpl adminService; 50 | @Autowired 51 | VerificationCodeFilter verificationCodeFilter; 52 | @Autowired 53 | SimpMessagingTemplate simpMessagingTemplate; 54 | @Autowired 55 | MyAuthenticationFailureHandler myAuthenticationFailureHandler; 56 | @Autowired 57 | MyLogoutSuccessHandler myLogoutSuccessHandler; 58 | 59 | //用户名和密码验证服务 60 | @Override 61 | protected void configure(AuthenticationManagerBuilder auth) throws Exception { 62 | auth.userDetailsService(adminService); 63 | } 64 | 65 | //忽略"/login","/verifyCode"请求,该请求不需要进入Security的拦截器 66 | @Override 67 | public void configure(WebSecurity web) throws Exception { 68 | web.ignoring().antMatchers("/css/**","/fonts/**","/img/**","/js/**","/favicon.ico","/index.html","/admin/login","/admin/mailVerifyCode"); 69 | } 70 | //http请求验证和处理规则,响应处理的配置 71 | @Override 72 | protected void configure(HttpSecurity http) throws Exception { 73 | //将验证码过滤器添加在用户名密码过滤器的前面 74 | http.addFilterBefore(verificationCodeFilter, UsernamePasswordAuthenticationFilter.class); 75 | http.antMatcher("/admin/**").authorizeRequests() 76 | .anyRequest().authenticated() 77 | .and() 78 | .formLogin() 79 | .usernameParameter("username") 80 | .passwordParameter("password") 81 | .loginPage("/admin/login") 82 | .loginProcessingUrl("/admin/doLogin") 83 | //成功处理 84 | .successHandler(new AuthenticationSuccessHandler() { 85 | @Override 86 | public void onAuthenticationSuccess(HttpServletRequest req, HttpServletResponse resp, Authentication authentication) throws IOException, ServletException { 87 | resp.setContentType("application/json;charset=utf-8"); 88 | PrintWriter out=resp.getWriter(); 89 | Admin admin=(Admin) authentication.getPrincipal(); 90 | admin.setPassword(null); 91 | RespBean ok = RespBean.ok("登录成功", admin); 92 | String s = new ObjectMapper().writeValueAsString(ok); 93 | out.write(s); 94 | out.flush(); 95 | out.close(); 96 | } 97 | }) 98 | //失败处理 99 | .failureHandler(myAuthenticationFailureHandler) 100 | .permitAll()//返回值直接返回 101 | .and() 102 | //登出处理 103 | .logout() 104 | .logoutUrl("/admin/logout") 105 | .logoutSuccessHandler(myLogoutSuccessHandler) 106 | .permitAll() 107 | .and() 108 | .csrf().disable()//关闭csrf防御方便调试 109 | //没有认证时,在这里处理结果,不进行重定向到login页 110 | .exceptionHandling().authenticationEntryPoint(new AuthenticationEntryPoint() { 111 | @Override 112 | public void commence(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, AuthenticationException e) throws IOException, ServletException { 113 | httpServletResponse.setStatus(401); 114 | } 115 | }); 116 | } 117 | } 118 | @Configuration 119 | @Order(2) 120 | public static class UserSecurityConfig extends WebSecurityConfigurerAdapter { 121 | @Autowired 122 | UserServiceImpl userService; 123 | @Autowired 124 | VerificationCodeFilter verificationCodeFilter; 125 | @Autowired 126 | SimpMessagingTemplate simpMessagingTemplate; 127 | @Autowired 128 | MyAuthenticationFailureHandler myAuthenticationFailureHandler; 129 | 130 | //验证服务 131 | @Override 132 | protected void configure(AuthenticationManagerBuilder auth) throws Exception { 133 | auth.userDetailsService(userService); 134 | } 135 | 136 | // //密码加密 137 | // @Bean 138 | // PasswordEncoder passwordEncoder(){ 139 | // return new BCryptPasswordEncoder(); 140 | // } 141 | 142 | 143 | //忽略"/login","/verifyCode"请求,该请求不需要进入Security的拦截器 144 | @Override 145 | public void configure(WebSecurity web) throws Exception { 146 | web.ignoring().antMatchers("/login","/verifyCode","/file","/user/register","/user/checkUsername","/user/checkNickname"); 147 | } 148 | //登录验证 149 | @Override 150 | protected void configure(HttpSecurity http) throws Exception { 151 | //将验证码过滤器添加在用户名密码过滤器的前面 152 | http.addFilterBefore(verificationCodeFilter, UsernamePasswordAuthenticationFilter.class); 153 | http.authorizeRequests() 154 | .anyRequest().authenticated() 155 | .and() 156 | .formLogin() 157 | .usernameParameter("username") 158 | .passwordParameter("password") 159 | .loginPage("/login") 160 | .loginProcessingUrl("/doLogin") 161 | //成功处理 162 | .successHandler(new AuthenticationSuccessHandler() { 163 | @Override 164 | public void onAuthenticationSuccess(HttpServletRequest req, HttpServletResponse resp, Authentication authentication) throws IOException, ServletException { 165 | resp.setContentType("application/json;charset=utf-8"); 166 | PrintWriter out=resp.getWriter(); 167 | User user=(User) authentication.getPrincipal(); 168 | user.setPassword(null); 169 | //更新用户状态为在线 170 | userService.setUserStateToOn(user.getId()); 171 | user.setUserStateId(1); 172 | //广播系统通知消息 173 | simpMessagingTemplate.convertAndSend("/topic/notification","系统消息:用户【"+user.getNickname()+"】进入了聊天室"); 174 | RespBean ok = RespBean.ok("登录成功", user); 175 | String s = new ObjectMapper().writeValueAsString(ok); 176 | out.write(s); 177 | out.flush(); 178 | out.close(); 179 | } 180 | }) 181 | //失败处理 182 | .failureHandler(myAuthenticationFailureHandler) 183 | .permitAll()//返回值直接返回 184 | .and() 185 | //登出处理 186 | .logout() 187 | .logoutUrl("/logout") 188 | .logoutSuccessHandler(new LogoutSuccessHandler() { 189 | @Override 190 | public void onLogoutSuccess(HttpServletRequest req, HttpServletResponse resp, Authentication authentication) throws IOException, ServletException { 191 | //更新用户状态为离线 192 | User user = (User) authentication.getPrincipal(); 193 | userService.setUserStateToLeave(user.getId()); 194 | //广播系统消息 195 | simpMessagingTemplate.convertAndSend("/topic/notification","系统消息:用户【"+user.getNickname()+"】退出了聊天室"); 196 | resp.setContentType("application/json;charset=utf-8"); 197 | PrintWriter out=resp.getWriter(); 198 | out.write(new ObjectMapper().writeValueAsString(RespBean.ok("成功退出!"))); 199 | out.flush(); 200 | out.close(); 201 | } 202 | }) 203 | .permitAll() 204 | .and() 205 | .csrf().disable()//关闭csrf防御方便调试 206 | //没有认证时,在这里处理结果,不进行重定向到login页 207 | .exceptionHandling().authenticationEntryPoint(new AuthenticationEntryPoint() { 208 | @Override 209 | public void commence(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, AuthenticationException e) throws IOException, ServletException { 210 | httpServletResponse.setStatus(401); 211 | } 212 | }); 213 | } 214 | } 215 | 216 | } 217 | -------------------------------------------------------------------------------- /subtlechat-web/src/main/java/top/javahai/subtlechat/config/MyAuthenticationFailureHandler.java: -------------------------------------------------------------------------------- 1 | package top.javahai.subtlechat.config; 2 | 3 | import com.fasterxml.jackson.databind.ObjectMapper; 4 | import org.springframework.context.annotation.Configuration; 5 | import org.springframework.security.authentication.*; 6 | import org.springframework.security.core.AuthenticationException; 7 | import org.springframework.security.web.authentication.AuthenticationFailureHandler; 8 | import top.javahai.subtlechat.api.entity.RespBean; 9 | 10 | import javax.servlet.ServletException; 11 | import javax.servlet.http.HttpServletRequest; 12 | import javax.servlet.http.HttpServletResponse; 13 | import java.io.IOException; 14 | import java.io.PrintWriter; 15 | 16 | /** 17 | * @author Hai 18 | * @date 2020/6/19 - 13:13 19 | */ 20 | @Configuration 21 | public class MyAuthenticationFailureHandler implements AuthenticationFailureHandler { 22 | @Override 23 | public void onAuthenticationFailure(HttpServletRequest req, HttpServletResponse resp, AuthenticationException exception) throws IOException, ServletException { 24 | resp.setContentType("application/json;charset=utf-8"); 25 | PrintWriter out=resp.getWriter(); 26 | RespBean error = RespBean.error("登录失败!"); 27 | if (exception instanceof LockedException){ 28 | error.setMsg("账户已锁定,请联系管理员!"); 29 | }else if (exception instanceof CredentialsExpiredException){ 30 | error.setMsg("密码已过期,请联系管理员!"); 31 | }else if (exception instanceof AccountExpiredException){ 32 | error.setMsg("账户已过期,请联系管理员!"); 33 | }else if (exception instanceof DisabledException){ 34 | error.setMsg("账户被禁用,请联系管理员!"); 35 | }else if (exception instanceof BadCredentialsException){ 36 | error.setMsg("用户名或密码错误,请重新输入!"); 37 | } 38 | String s = new ObjectMapper().writeValueAsString(error); 39 | out.write(s); 40 | out.flush(); 41 | out.close(); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /subtlechat-web/src/main/java/top/javahai/subtlechat/config/MyLogoutSuccessHandler.java: -------------------------------------------------------------------------------- 1 | package top.javahai.subtlechat.config; 2 | 3 | import com.fasterxml.jackson.databind.ObjectMapper; 4 | import org.springframework.context.annotation.Configuration; 5 | import org.springframework.security.core.Authentication; 6 | import org.springframework.security.web.authentication.logout.LogoutSuccessHandler; 7 | import top.javahai.subtlechat.api.entity.RespBean; 8 | 9 | import javax.servlet.ServletException; 10 | import javax.servlet.http.HttpServletRequest; 11 | import javax.servlet.http.HttpServletResponse; 12 | import java.io.IOException; 13 | import java.io.PrintWriter; 14 | 15 | /** 16 | * @author Hai 17 | * @date 2020/6/19 - 13:18 18 | */ 19 | @Configuration 20 | public class MyLogoutSuccessHandler implements LogoutSuccessHandler { 21 | 22 | @Override 23 | public void onLogoutSuccess(HttpServletRequest req, HttpServletResponse resp, Authentication authentication) throws IOException, ServletException { 24 | resp.setContentType("application/json;charset=utf-8"); 25 | PrintWriter out=resp.getWriter(); 26 | out.write(new ObjectMapper().writeValueAsString(RespBean.ok("成功退出!"))); 27 | out.flush(); 28 | out.close(); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /subtlechat-web/src/main/java/top/javahai/subtlechat/config/RabbitMQConfig.java: -------------------------------------------------------------------------------- 1 | package top.javahai.subtlechat.config; 2 | 3 | import org.slf4j.Logger; 4 | import org.slf4j.LoggerFactory; 5 | import org.springframework.amqp.rabbit.connection.CachingConnectionFactory; 6 | import org.springframework.amqp.rabbit.core.RabbitTemplate; 7 | import org.springframework.beans.factory.annotation.Autowired; 8 | import org.springframework.context.annotation.Bean; 9 | import org.springframework.context.annotation.Configuration; 10 | import top.javahai.subtlechat.api.entity.MailConstants; 11 | import top.javahai.subtlechat.service.MailSendLogService; 12 | 13 | /** 14 | * 自定义消息发送RabbitTemplate 15 | * @author Hai 16 | * @date 2020/10/2 - 14:35 17 | */ 18 | @Configuration 19 | public class RabbitMQConfig { 20 | public static final Logger LOGGER= LoggerFactory.getLogger(RabbitMQConfig.class); 21 | 22 | @Autowired 23 | CachingConnectionFactory cachingConnectionFactory; 24 | @Autowired 25 | MailSendLogService mailSendLogService; 26 | 27 | @Bean 28 | public RabbitTemplate rabbitTemplate(){ 29 | RabbitTemplate rabbitTemplate = new RabbitTemplate(cachingConnectionFactory); 30 | //成功投递消息到Broker交换机站点的回调函数 31 | rabbitTemplate.setConfirmCallback((data,ack,cause)->{ 32 | String msgId = data.getId(); 33 | if(ack){ 34 | LOGGER.info(msgId+"消息发送成功"); 35 | //修改数据库中的记录,消息发送成功,将status设为1 36 | mailSendLogService.updateMailSendLogStatus(msgId, MailConstants.SUCCESS); 37 | }else{ 38 | LOGGER.error(msgId+"消息发送失败!"); 39 | } 40 | }); 41 | //消息投递到Queue队列失败的回调函数 42 | rabbitTemplate.setReturnCallback((msg,repCode,repText,exchange,routingKey)->{ 43 | LOGGER.error(msg.getBody()+"----消息从交换机投递到队列失败!\n错误原因:"+repText); 44 | LOGGER.error("发送错误的交换机:"+exchange+",发生错误的路由key:"+routingKey); 45 | }); 46 | return rabbitTemplate; 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /subtlechat-web/src/main/java/top/javahai/subtlechat/config/SecurityConfig.java: -------------------------------------------------------------------------------- 1 | //package top.javahai.subtlechat.config; 2 | // 3 | //import com.fasterxml.jackson.databind.ObjectMapper; 4 | //import org.springframework.beans.factory.annotation.Autowired; 5 | //import org.springframework.context.annotation.Bean; 6 | //import org.springframework.context.annotation.Configuration; 7 | //import org.springframework.messaging.simp.SimpMessagingTemplate; 8 | //import org.springframework.security.authentication.*; 9 | //import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; 10 | //import org.springframework.security.config.annotation.web.builders.HttpSecurity; 11 | //import org.springframework.security.config.annotation.web.builders.WebSecurity; 12 | //import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; 13 | //import org.springframework.security.core.Authentication; 14 | //import org.springframework.security.core.AuthenticationException; 15 | //import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; 16 | //import org.springframework.security.crypto.password.PasswordEncoder; 17 | //import org.springframework.security.web.AuthenticationEntryPoint; 18 | //import org.springframework.security.web.authentication.AuthenticationFailureHandler; 19 | //import org.springframework.security.web.authentication.AuthenticationSuccessHandler; 20 | //import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; 21 | //import org.springframework.security.web.authentication.logout.LogoutSuccessHandler; 22 | //import RespBean; 23 | //import User; 24 | //import top.javahai.subtlechat.service.impl.UserServiceImpl; 25 | // 26 | //import javax.servlet.ServletException; 27 | //import javax.servlet.http.HttpServletRequest; 28 | //import javax.servlet.http.HttpServletResponse; 29 | //import java.io.IOException; 30 | //import java.io.PrintWriter; 31 | // 32 | ///** 33 | // * @author Hai 34 | // * @date 2020/6/16 - 12:31 35 | // */ 36 | ////@Configuration 37 | //public class SecurityConfig extends WebSecurityConfigurerAdapter { 38 | // @Autowired 39 | // UserServiceImpl userService; 40 | // @Autowired 41 | // VerificationCodeFilter verificationCodeFilter; 42 | // @Autowired 43 | // SimpMessagingTemplate simpMessagingTemplate; 44 | // 45 | // //验证服务 46 | // @Override 47 | // protected void configure(AuthenticationManagerBuilder auth) throws Exception { 48 | // auth.userDetailsService(userService); 49 | // } 50 | // 51 | // //密码加密 52 | // @Bean 53 | // PasswordEncoder passwordEncoder(){ 54 | // return new BCryptPasswordEncoder(); 55 | // } 56 | // 57 | // 58 | // //忽略"/login","/verifyCode"请求,该请求不需要进入Security的拦截器 59 | // @Override 60 | // public void configure(WebSecurity web) throws Exception { 61 | // web.ignoring().antMatchers("/login","/verifyCode"); 62 | // } 63 | // //登录验证 64 | // @Override 65 | // protected void configure(HttpSecurity http) throws Exception { 66 | // //将验证码过滤器添加在用户名密码过滤器的前面 67 | // http.addFilterBefore(verificationCodeFilter, UsernamePasswordAuthenticationFilter.class); 68 | // http.authorizeRequests() 69 | // .anyRequest().authenticated() 70 | // .and() 71 | // .formLogin() 72 | // .usernameParameter("username") 73 | // .passwordParameter("password") 74 | // .loginPage("/login") 75 | // .loginProcessingUrl("/doLogin") 76 | // //成功处理 77 | // .successHandler(new AuthenticationSuccessHandler() { 78 | // @Override 79 | // public void onAuthenticationSuccess(HttpServletRequest req, HttpServletResponse resp, Authentication authentication) throws IOException, ServletException { 80 | // resp.setContentType("application/json;charset=utf-8"); 81 | // PrintWriter out=resp.getWriter(); 82 | // User user=(User) authentication.getPrincipal(); 83 | // user.setPassword(null); 84 | // //更新用户状态为在线 85 | // userService.setUserStateToOn(user.getId()); 86 | // user.setUserStateId(1); 87 | // //广播系统通知消息 88 | // simpMessagingTemplate.convertAndSend("/topic/notification","系统消息:用户【"+user.getNickname()+"】进入了聊天室"); 89 | // RespBean ok = RespBean.ok("登录成功", user); 90 | // String s = new ObjectMapper().writeValueAsString(ok); 91 | // out.write(s); 92 | // out.flush(); 93 | // out.close(); 94 | // } 95 | // }) 96 | // //失败处理 97 | // .failureHandler(new AuthenticationFailureHandler() { 98 | // @Override 99 | // public void onAuthenticationFailure(HttpServletRequest req, HttpServletResponse resp, AuthenticationException exception) throws IOException, ServletException { 100 | // resp.setContentType("application/json;charset=utf-8"); 101 | // PrintWriter out=resp.getWriter(); 102 | // RespBean error = RespBean.error("登录失败!"); 103 | // if (exception instanceof LockedException){ 104 | // error.setMsg("账户已锁定,请联系管理员!"); 105 | // }else if (exception instanceof CredentialsExpiredException){ 106 | // error.setMsg("密码已过期,请联系管理员!"); 107 | // }else if (exception instanceof AccountExpiredException){ 108 | // error.setMsg("账户已过期,请联系管理员!"); 109 | // }else if (exception instanceof DisabledException){ 110 | // error.setMsg("账户被禁用,请联系管理员!"); 111 | // }else if (exception instanceof BadCredentialsException){ 112 | // error.setMsg("用户名或密码错误,请重新输入!"); 113 | // } 114 | // String s = new ObjectMapper().writeValueAsString(error); 115 | // out.write(s); 116 | // out.flush(); 117 | // out.close(); 118 | // } 119 | // }) 120 | // .permitAll()//返回值直接返回 121 | // .and() 122 | // //登出处理 123 | // .logout() 124 | // .logoutUrl("/logout") 125 | // .logoutSuccessHandler(new LogoutSuccessHandler() { 126 | // @Override 127 | // public void onLogoutSuccess(HttpServletRequest req, HttpServletResponse resp, Authentication authentication) throws IOException, ServletException { 128 | // //更新用户状态为离线 129 | // User user = (User) authentication.getPrincipal(); 130 | // userService.setUserStateToLeave(user.getId()); 131 | // //广播系统消息 132 | // simpMessagingTemplate.convertAndSend("/topic/notification","系统消息:用户【"+user.getNickname()+"】退出了聊天室"); 133 | // resp.setContentType("application/json;charset=utf-8"); 134 | // PrintWriter out=resp.getWriter(); 135 | // out.write(new ObjectMapper().writeValueAsString(RespBean.ok("成功退出!"))); 136 | // out.flush(); 137 | // out.close(); 138 | // } 139 | // }) 140 | // .permitAll() 141 | // .and() 142 | // .csrf().disable()//关闭csrf防御方便调试 143 | // //没有认证时,在这里处理结果,不进行重定向到login页 144 | // .exceptionHandling().authenticationEntryPoint(new AuthenticationEntryPoint() { 145 | // @Override 146 | // public void commence(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, AuthenticationException e) throws IOException, ServletException { 147 | // httpServletResponse.setStatus(401); 148 | // } 149 | // }); 150 | // } 151 | //} 152 | -------------------------------------------------------------------------------- /subtlechat-web/src/main/java/top/javahai/subtlechat/config/VerificationCode.java: -------------------------------------------------------------------------------- 1 | package top.javahai.subtlechat.config; 2 | 3 | import javax.imageio.ImageIO; 4 | import java.awt.*; 5 | import java.awt.image.BufferedImage; 6 | import java.io.IOException; 7 | import java.io.OutputStream; 8 | import java.util.Random; 9 | 10 | /** 11 | * @author Hai 12 | * @date 2020/6/16 - 17:24 13 | * 生成验证码的工具类 14 | */ 15 | public class VerificationCode { 16 | 17 | private int width = 100;// 生成验证码图片的宽度 18 | private int height = 30;// 生成验证码图片的高度 19 | private String[] fontNames = { "宋体", "楷体", "隶书", "微软雅黑" }; 20 | private Color bgColor = new Color(255, 255, 255);// 定义验证码图片的背景颜色为白色 21 | private Random random = new Random(); 22 | private String codes = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"; 23 | private String text;// 记录随机字符串 24 | 25 | /** 26 | * 获取一个随意颜色 27 | * 28 | * @return 29 | */ 30 | private Color randomColor() { 31 | int red = random.nextInt(150); 32 | int green = random.nextInt(150); 33 | int blue = random.nextInt(150); 34 | return new Color(red, green, blue); 35 | } 36 | 37 | /** 38 | * 获取一个随机字体 39 | * 40 | * @return 41 | */ 42 | private Font randomFont() { 43 | String name = fontNames[random.nextInt(fontNames.length)]; 44 | int style = random.nextInt(4); 45 | int size = random.nextInt(5) + 24; 46 | return new Font(name, style, size); 47 | } 48 | 49 | /** 50 | * 获取一个随机字符 51 | * 52 | * @return 53 | */ 54 | private char randomChar() { 55 | return codes.charAt(random.nextInt(codes.length())); 56 | } 57 | 58 | /** 59 | * 创建一个空白的BufferedImage对象 60 | * 61 | * @return 62 | */ 63 | private BufferedImage createImage() { 64 | BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); 65 | Graphics2D g2 = (Graphics2D) image.getGraphics(); 66 | g2.setColor(bgColor);// 设置验证码图片的背景颜色 67 | g2.fillRect(0, 0, width, height); 68 | return image; 69 | } 70 | 71 | public BufferedImage getImage() { 72 | BufferedImage image = createImage(); 73 | Graphics2D g2 = (Graphics2D) image.getGraphics(); 74 | StringBuffer sb = new StringBuffer(); 75 | for (int i = 0; i < 4; i++) { 76 | String s = randomChar() + ""; 77 | sb.append(s); 78 | g2.setColor(randomColor()); 79 | g2.setFont(randomFont()); 80 | float x = i * width * 1.0f / 4; 81 | g2.drawString(s, x, height - 8); 82 | } 83 | this.text = sb.toString(); 84 | drawLine(image); 85 | return image; 86 | } 87 | 88 | /** 89 | * 绘制干扰线 90 | * 91 | * @param image 92 | */ 93 | private void drawLine(BufferedImage image) { 94 | Graphics2D g2 = (Graphics2D) image.getGraphics(); 95 | int num = 5; 96 | for (int i = 0; i < num; i++) { 97 | int x1 = random.nextInt(width); 98 | int y1 = random.nextInt(height); 99 | int x2 = random.nextInt(width); 100 | int y2 = random.nextInt(height); 101 | g2.setColor(randomColor()); 102 | g2.setStroke(new BasicStroke(1.5f)); 103 | g2.drawLine(x1, y1, x2, y2); 104 | } 105 | } 106 | 107 | public String getText() { 108 | return text; 109 | } 110 | 111 | public static void output(BufferedImage image, OutputStream out) throws IOException { 112 | ImageIO.write(image, "JPEG", out); 113 | } 114 | } 115 | -------------------------------------------------------------------------------- /subtlechat-web/src/main/java/top/javahai/subtlechat/config/VerificationCodeFilter.java: -------------------------------------------------------------------------------- 1 | package top.javahai.subtlechat.config; 2 | 3 | import com.fasterxml.jackson.databind.ObjectMapper; 4 | import org.springframework.stereotype.Component; 5 | import top.javahai.subtlechat.api.entity.RespBean; 6 | 7 | import javax.servlet.*; 8 | import javax.servlet.http.HttpServletRequest; 9 | import javax.servlet.http.HttpServletResponse; 10 | import java.io.IOException; 11 | import java.io.PrintWriter; 12 | 13 | /** 14 | * 拦截登录请求,验证输入的验证码是否正确 15 | * @author Hai 16 | * @date 2020/5/28 - 17:31 17 | */ 18 | @Component 19 | public class VerificationCodeFilter extends GenericFilter { 20 | 21 | @Override 22 | public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { 23 | HttpServletRequest request = (HttpServletRequest) servletRequest; 24 | HttpServletResponse response = (HttpServletResponse) servletResponse; 25 | //如果是登录请求则拦截 26 | if ("POST".equals(request.getMethod())&&"/doLogin".equals(request.getServletPath())){ 27 | //TODO 不启动验证码 28 | filterChain.doFilter(request,response); 29 | //用户输入的验证码 30 | String code = request.getParameter("code"); 31 | //session中保存的验证码 32 | String verify_code = (String) request.getSession().getAttribute("verify_code"); 33 | response.setContentType("application/json;charset=utf-8"); 34 | PrintWriter writer = response.getWriter(); 35 | //验证session中保存是否存在 36 | try { 37 | //验证是否相同 38 | if (!code.toLowerCase().equals(verify_code.toLowerCase())){ 39 | //输出json 40 | writer.write(new ObjectMapper().writeValueAsString( RespBean.error("验证码错误!"))); 41 | return; 42 | }else { 43 | filterChain.doFilter(request,response); 44 | } 45 | }catch (NullPointerException e){ 46 | writer.write(new ObjectMapper().writeValueAsString(RespBean.error("请求异常,请重新请求!"))); 47 | }finally { 48 | writer.flush(); 49 | writer.close(); 50 | } 51 | } 52 | //管理端登录请求 53 | // else if ("POST".equals(request.getMethod())&&"/admin/doLogin".equals(request.getServletPath())){ 54 | // //获取输入的验证码 55 | // String mailCode = request.getParameter("mailCode"); 56 | // //获取session中保存的验证码 57 | // String verifyCode = ((String) request.getSession().getAttribute("mail_verify_code")); 58 | // //构建响应输出流 59 | // response.setContentType("application/json;charset=utf-8"); 60 | // PrintWriter printWriter =response.getWriter(); 61 | // try { 62 | // if(!mailCode.equals(verifyCode)){ 63 | // printWriter.write(new ObjectMapper().writeValueAsString(RespBean.error("验证码错误!"))); 64 | // }else { 65 | // filterChain.doFilter(request,response); 66 | // } 67 | // }catch (NullPointerException e){ 68 | // printWriter.write(new ObjectMapper().writeValueAsString(RespBean.error("请求异常,请重新请求!"))); 69 | // }finally { 70 | // printWriter.flush(); 71 | // printWriter.close(); 72 | // } 73 | // } 74 | else { 75 | filterChain.doFilter(request,response); 76 | } 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /subtlechat-web/src/main/java/top/javahai/subtlechat/config/WebSocketConfig.java: -------------------------------------------------------------------------------- 1 | package top.javahai.subtlechat.config; 2 | 3 | import org.springframework.context.annotation.Configuration; 4 | import org.springframework.messaging.simp.config.MessageBrokerRegistry; 5 | import org.springframework.web.socket.config.annotation.EnableWebSocketMessageBroker; 6 | import org.springframework.web.socket.config.annotation.StompEndpointRegistry; 7 | import org.springframework.web.socket.config.annotation.WebSocketMessageBrokerConfigurer; 8 | 9 | /** 10 | * @author Hai 11 | * @date 2020/6/16 - 23:31 12 | */ 13 | @Configuration 14 | @EnableWebSocketMessageBroker 15 | public class WebSocketConfig implements WebSocketMessageBrokerConfigurer { 16 | /** 17 | * 注册stomp站点 18 | * @param registry 19 | */ 20 | @Override 21 | public void registerStompEndpoints(StompEndpointRegistry registry) { 22 | 23 | registry.addEndpoint("/ws/ep").setAllowedOrigins("*").withSockJS(); 24 | 25 | } 26 | 27 | /** 28 | * 注册拦截"/topic","/queue"的消息 29 | * @param registry 30 | */ 31 | @Override 32 | public void configureMessageBroker(MessageBrokerRegistry registry) { 33 | registry.enableSimpleBroker("/topic","/queue"); 34 | 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /subtlechat-web/src/main/java/top/javahai/subtlechat/controller/AdminController.java: -------------------------------------------------------------------------------- 1 | package top.javahai.subtlechat.controller; 2 | 3 | import top.javahai.subtlechat.api.entity.Admin; 4 | import top.javahai.subtlechat.service.AdminService; 5 | import org.springframework.web.bind.annotation.*; 6 | 7 | import javax.annotation.Resource; 8 | 9 | /** 10 | * (Admin)表控制层 11 | * 12 | * @author makejava 13 | * @since 2020-06-16 11:35:59 14 | */ 15 | @RestController 16 | @RequestMapping("admin") 17 | public class AdminController { 18 | /** 19 | * 服务对象 20 | */ 21 | @Resource 22 | private AdminService adminService; 23 | 24 | /** 25 | * 通过主键查询单条数据 26 | * 27 | * @param id 主键 28 | * @return 单条数据 29 | */ 30 | @GetMapping("selectOne") 31 | public Admin selectOne(Integer id) { 32 | return this.adminService.queryById(id); 33 | } 34 | 35 | } 36 | -------------------------------------------------------------------------------- /subtlechat-web/src/main/java/top/javahai/subtlechat/controller/ChatController.java: -------------------------------------------------------------------------------- 1 | package top.javahai.subtlechat.controller; 2 | 3 | import org.springframework.beans.factory.annotation.Autowired; 4 | import org.springframework.web.bind.annotation.GetMapping; 5 | import org.springframework.web.bind.annotation.RequestMapping; 6 | import org.springframework.web.bind.annotation.RestController; 7 | import top.javahai.subtlechat.api.entity.User; 8 | import top.javahai.subtlechat.service.UserService; 9 | 10 | import java.util.List; 11 | 12 | /** 13 | * @author Hai 14 | * @date 2020/6/16 - 21:32 15 | */ 16 | @RestController 17 | @RequestMapping("/chat") 18 | public class ChatController { 19 | @Autowired 20 | UserService userService; 21 | 22 | @GetMapping("/users") 23 | public List getUsersWithoutCurrentUser(){ 24 | return userService.getUsersWithoutCurrentUser(); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /subtlechat-web/src/main/java/top/javahai/subtlechat/controller/FileController.java: -------------------------------------------------------------------------------- 1 | package top.javahai.subtlechat.controller; 2 | 3 | import org.csource.common.MyException; 4 | import org.springframework.beans.factory.annotation.Value; 5 | import org.springframework.web.bind.annotation.PostMapping; 6 | import org.springframework.web.bind.annotation.RestController; 7 | import org.springframework.web.multipart.MultipartFile; 8 | import top.javahai.subtlechat.api.utils.FastDFSUtil; 9 | 10 | import java.io.IOException; 11 | 12 | /** 13 | * @author Hai 14 | * @date 2020/6/21 - 16:47 15 | */ 16 | @RestController 17 | public class FileController { 18 | 19 | @Value("${fastdfs.nginx.host}") 20 | String nginxHost; 21 | 22 | @PostMapping("/file") 23 | public String uploadFlie(MultipartFile file) throws IOException, MyException { 24 | String fileId= FastDFSUtil.upload(file); 25 | String url=nginxHost+fileId; 26 | return url; 27 | } 28 | 29 | 30 | 31 | 32 | } 33 | -------------------------------------------------------------------------------- /subtlechat-web/src/main/java/top/javahai/subtlechat/controller/GroupMsgContentController.java: -------------------------------------------------------------------------------- 1 | package top.javahai.subtlechat.controller; 2 | 3 | import com.alibaba.excel.EasyExcel; 4 | import com.alibaba.fastjson.JSON; 5 | import top.javahai.subtlechat.api.data.GroupMsgContentData; 6 | import top.javahai.subtlechat.api.entity.GroupMsgContent; 7 | import top.javahai.subtlechat.api.entity.RespBean; 8 | import top.javahai.subtlechat.api.entity.RespPageBean; 9 | import top.javahai.subtlechat.dao.GroupMsgContentDao; 10 | import top.javahai.subtlechat.service.GroupMsgContentService; 11 | import org.springframework.web.bind.annotation.*; 12 | 13 | import javax.annotation.Resource; 14 | import javax.servlet.http.HttpServletRequest; 15 | import javax.servlet.http.HttpServletResponse; 16 | import java.io.IOException; 17 | import java.io.UnsupportedEncodingException; 18 | import java.net.MalformedURLException; 19 | import java.net.URLEncoder; 20 | import java.util.Date; 21 | import java.util.HashMap; 22 | import java.util.List; 23 | import java.util.Map; 24 | import java.util.stream.Collectors; 25 | 26 | /** 27 | * (GroupMsgContent)表控制层 28 | * 29 | * @author makejava 30 | * @since 2020-06-17 10:51:13 31 | */ 32 | @RestController 33 | @RequestMapping("/groupMsgContent") 34 | public class GroupMsgContentController { 35 | /** 36 | * 服务对象 37 | */ 38 | @Resource 39 | private GroupMsgContentService groupMsgContentService; 40 | 41 | @GetMapping("/") 42 | private List getAllGroupMsgContent(){ 43 | return groupMsgContentService.queryAllByLimit(null,null); 44 | } 45 | 46 | /** 47 | * 通过主键查询单条数据 48 | * 49 | * @param id 主键 50 | * @return 单条数据 51 | */ 52 | @GetMapping("selectOne") 53 | public GroupMsgContent selectOne(Integer id) { 54 | return this.groupMsgContentService.queryById(id); 55 | } 56 | 57 | /** 58 | * 分页返回数据 59 | * @author luo 60 | * @param page 页数 61 | * @param size 单页大小 62 | * @param nickname 发送者昵称 63 | * @param type 消息类型 64 | * @param dateScope 发送时间范围 65 | * @return 66 | */ 67 | @GetMapping("/page") 68 | public RespPageBean getAllGroupMsgContentByPage(@RequestParam(value = "page",defaultValue = "1") Integer page, 69 | @RequestParam(value = "size",defaultValue = "10") Integer size, 70 | String nickname, Integer type, 71 | Date[] dateScope){ 72 | return groupMsgContentService.getAllGroupMsgContentByPage(page,size,nickname,type,dateScope); 73 | } 74 | 75 | /** 76 | * 根据id删除单条记录 77 | * @author luo 78 | * @param id 79 | * @return 80 | */ 81 | @DeleteMapping("/{id}") 82 | public RespBean deleteGroupMsgContentById(@PathVariable Integer id){ 83 | if (groupMsgContentService.deleteById(id)){ 84 | return RespBean.ok("删除成功!"); 85 | }else{ 86 | return RespBean.error("删除失败!"); 87 | } 88 | } 89 | @DeleteMapping("/") 90 | public RespBean deleteGroupMsgContentByIds(Integer[] ids){ 91 | if (groupMsgContentService.deleteGroupMsgContentByIds(ids)==ids.length){ 92 | return RespBean.ok("删除成功!"); 93 | }else { 94 | return RespBean.error("删除失败!"); 95 | } 96 | } 97 | 98 | 99 | @GetMapping("/download") 100 | public void download(HttpServletResponse response) throws IOException { 101 | 102 | groupMsgContentService.handleDownload(response); 103 | 104 | } 105 | } 106 | -------------------------------------------------------------------------------- /subtlechat-web/src/main/java/top/javahai/subtlechat/controller/LoginController.java: -------------------------------------------------------------------------------- 1 | package top.javahai.subtlechat.controller; 2 | 3 | import org.springframework.beans.factory.annotation.Autowired; 4 | import org.springframework.web.bind.annotation.GetMapping; 5 | import org.springframework.web.bind.annotation.RestController; 6 | import top.javahai.subtlechat.config.VerificationCode; 7 | import top.javahai.subtlechat.api.entity.RespBean; 8 | import top.javahai.subtlechat.service.VerifyCodeService; 9 | 10 | import javax.servlet.http.HttpServletResponse; 11 | import javax.servlet.http.HttpSession; 12 | import java.awt.image.BufferedImage; 13 | import java.io.IOException; 14 | import java.util.Date; 15 | import java.util.Random; 16 | 17 | /** 18 | * @author Hai 19 | * @date 2020/6/16 - 17:33 20 | */ 21 | @RestController 22 | public class LoginController { 23 | /** 24 | * 获取验证码图片写到响应的输出流中,保存验证码到session 25 | * @param response 26 | * @param session 27 | * @throws IOException 28 | */ 29 | @GetMapping("/verifyCode") 30 | public void getVerifyCode(HttpServletResponse response, HttpSession session) throws IOException { 31 | VerificationCode code = new VerificationCode(); 32 | BufferedImage image = code.getImage(); 33 | String text = code.getText(); 34 | session.setAttribute("verify_code",text); 35 | VerificationCode.output(image,response.getOutputStream()); 36 | } 37 | 38 | 39 | @Autowired 40 | VerifyCodeService verifyCodeService; 41 | /** 42 | * 获取邮箱验证码,并保存到本次会话 43 | * @param session 44 | */ 45 | @GetMapping("/admin/mailVerifyCode") 46 | public RespBean getMailVerifyCode(HttpSession session){ 47 | String code = verifyCodeService.getVerifyCode(); 48 | //保存验证码到本次会话 49 | session.setAttribute("mail_verify_code",code); 50 | verifyCodeService.sendVerifyCodeMail(code); 51 | return RespBean.ok("验证码已发送到邮箱,请注意查看!"); 52 | 53 | // //获取随机的四个数字 54 | // StringBuilder code=new StringBuilder(); 55 | // for (int i = 0; i <4; i++) { 56 | // code.append(new Random().nextInt(10)); 57 | // } 58 | // //邮件内容 59 | // SimpleMailMessage msg = new SimpleMailMessage(); 60 | // msg.setSubject("微言聊天室管理端验证码验证"); 61 | // msg.setText("本次登录的验证码:"+code); 62 | // msg.setFrom("1258398543@qq.com"); 63 | // msg.setSentDate(new Date()); 64 | // msg.setTo("jinhaihuang824@aliyun.com"); 65 | // //保存验证码到本次会话 66 | // session.setAttribute("mail_verify_code",code.toString()); 67 | // //发送到邮箱 68 | // try { 69 | // javaMailSender.send(msg); 70 | // return RespBean.ok("验证码已发送到邮箱,请注意查看!"); 71 | // }catch (Exception e){ 72 | // e.printStackTrace(); 73 | // return RespBean.error("服务器出错啦!请稍后重试!"); 74 | // } 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /subtlechat-web/src/main/java/top/javahai/subtlechat/controller/MailController.java: -------------------------------------------------------------------------------- 1 | package top.javahai.subtlechat.controller; 2 | 3 | import org.springframework.beans.factory.annotation.Autowired; 4 | import org.springframework.web.bind.annotation.*; 5 | import top.javahai.subtlechat.api.entity.Feedback; 6 | import top.javahai.subtlechat.api.entity.RespBean; 7 | import top.javahai.subtlechat.service.FeedbackService; 8 | 9 | 10 | /** 11 | * 邮箱服务控制器 12 | * @author Hai 13 | * @date 2020/6/29 - 18:42 14 | */ 15 | @RestController 16 | @RequestMapping("/mail") 17 | public class MailController { 18 | 19 | 20 | @Autowired 21 | FeedbackService feedbackService; 22 | /** 23 | * 发送反馈消息给系统管理员 24 | * @param feedback 25 | * @return 26 | */ 27 | @PostMapping("/feedback") 28 | public RespBean sendFeedbackToMail(@RequestBody Feedback feedback){ 29 | try{ 30 | feedbackService.sendMessage(feedback); 31 | }catch (Exception e){ 32 | e.printStackTrace(); 33 | }finally { 34 | return RespBean.ok("邮件发送成功!感谢你的反馈~"); 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /subtlechat-web/src/main/java/top/javahai/subtlechat/controller/UserController.java: -------------------------------------------------------------------------------- 1 | package top.javahai.subtlechat.controller; 2 | 3 | import top.javahai.subtlechat.api.entity.RespBean; 4 | import top.javahai.subtlechat.api.entity.RespPageBean; 5 | import top.javahai.subtlechat.api.entity.User; 6 | import top.javahai.subtlechat.service.UserService; 7 | import org.springframework.web.bind.annotation.*; 8 | 9 | import javax.annotation.Resource; 10 | 11 | /** 12 | * (User)表控制层 13 | * 14 | * @author makejava 15 | * @since 2020-06-16 11:37:09 16 | */ 17 | @RestController 18 | @RequestMapping("/user") 19 | public class UserController { 20 | /** 21 | * 服务对象 22 | */ 23 | @Resource 24 | private UserService userService; 25 | 26 | /** 27 | * 注册操作 28 | */ 29 | @PostMapping("/register") 30 | public RespBean addUser(@RequestBody User user){ 31 | if (userService.insert(user)==1){ 32 | return RespBean.ok("注册成功!"); 33 | }else{ 34 | return RespBean.error("注册失败!"); 35 | } 36 | } 37 | 38 | /** 39 | * 注册操作,检查用户名是否已被注册 40 | * @param username 41 | * @return 42 | */ 43 | @GetMapping("/checkUsername") 44 | public Integer checkUsername(@RequestParam("username")String username){ 45 | return userService.checkUsername(username); 46 | } 47 | 48 | /** 49 | * 注册操作,检查昵称是否已被注册 50 | * @param nickname 51 | * @return 52 | */ 53 | @GetMapping("/checkNickname") 54 | public Integer checkNickname(@RequestParam("nickname") String nickname){ 55 | return userService.checkNickname(nickname); 56 | } 57 | 58 | /** 59 | * 通过主键查询单条数据 60 | * 61 | * @param id 主键 62 | * @return 单条数据 63 | */ 64 | @GetMapping("selectOne") 65 | public User selectOne(Integer id) { 66 | return this.userService.queryById(id); 67 | } 68 | 69 | /** 70 | * @author luo 71 | * @param page 页数,对应数据库查询的起始行数 72 | * @param size 数据量,对应数据库查询的偏移量 73 | * @param keyword 关键词,用于搜索 74 | * @param isLocked 是否锁定,用于搜索 75 | * @return 76 | */ 77 | @GetMapping("/") 78 | public RespPageBean getAllUserByPage(@RequestParam(value = "page",defaultValue = "1") Integer page, 79 | @RequestParam(value = "size",defaultValue = "10") Integer size, 80 | String keyword,Integer isLocked){ 81 | return userService.getAllUserByPage(page,size,keyword,isLocked); 82 | } 83 | 84 | /** 85 | * 更新用户的锁定状态 86 | * @author luo 87 | * @param id 88 | * @param isLocked 89 | * @return 90 | */ 91 | @PutMapping("/") 92 | public RespBean changeLockedStatus(@RequestParam("id") Integer id,@RequestParam("isLocked") Boolean isLocked){ 93 | if (userService.changeLockedStatus(id,isLocked)==1){ 94 | return RespBean.ok("更新成功!"); 95 | }else { 96 | return RespBean.error("更新失败!"); 97 | } 98 | } 99 | 100 | /** 101 | * 删除单一用户 102 | * @author luo 103 | * @param id 104 | * @return 105 | */ 106 | @DeleteMapping("/{id}") 107 | public RespBean deleteUser(@PathVariable Integer id){ 108 | if (userService.deleteById(id)){ 109 | return RespBean.ok("删除成功!"); 110 | } 111 | else{ 112 | return RespBean.error("删除失败!"); 113 | } 114 | } 115 | 116 | /** 117 | * 批量删除用户 118 | * @author luo 119 | * @param ids 120 | * @return 121 | */ 122 | @DeleteMapping("/") 123 | public RespBean deleteUserByIds(Integer[] ids){ 124 | if (userService.deleteByIds(ids)==ids.length){ 125 | return RespBean.ok("删除成功!"); 126 | }else{ 127 | return RespBean.error("删除失败!"); 128 | } 129 | } 130 | } 131 | -------------------------------------------------------------------------------- /subtlechat-web/src/main/java/top/javahai/subtlechat/controller/UserStateController.java: -------------------------------------------------------------------------------- 1 | package top.javahai.subtlechat.controller; 2 | 3 | import top.javahai.subtlechat.api.entity.UserState; 4 | import top.javahai.subtlechat.service.UserStateService; 5 | import org.springframework.web.bind.annotation.*; 6 | 7 | import javax.annotation.Resource; 8 | 9 | /** 10 | * (UserState)表控制层 11 | * 12 | * @author makejava 13 | * @since 2020-06-16 11:36:02 14 | */ 15 | @RestController 16 | @RequestMapping("userState") 17 | public class UserStateController { 18 | /** 19 | * 服务对象 20 | */ 21 | @Resource 22 | private UserStateService userStateService; 23 | 24 | /** 25 | * 通过主键查询单条数据 26 | * 27 | * @param id 主键 28 | * @return 单条数据 29 | */ 30 | @GetMapping("selectOne") 31 | public UserState selectOne(Integer id) { 32 | return this.userStateService.queryById(id); 33 | } 34 | 35 | } 36 | -------------------------------------------------------------------------------- /subtlechat-web/src/main/java/top/javahai/subtlechat/controller/WsController.java: -------------------------------------------------------------------------------- 1 | package top.javahai.subtlechat.controller; 2 | 3 | import com.github.binarywang.java.emoji.EmojiConverter; 4 | import org.springframework.beans.factory.annotation.Autowired; 5 | import org.springframework.messaging.handler.annotation.MessageMapping; 6 | import org.springframework.messaging.simp.SimpMessagingTemplate; 7 | import org.springframework.security.core.Authentication; 8 | import org.springframework.stereotype.Controller; 9 | import top.javahai.subtlechat.api.entity.GroupMsgContent; 10 | import top.javahai.subtlechat.api.entity.Message; 11 | import top.javahai.subtlechat.api.entity.User; 12 | import top.javahai.subtlechat.service.GroupMsgContentService; 13 | import top.javahai.subtlechat.api.utils.TuLingUtil; 14 | 15 | import java.io.IOException; 16 | import java.text.SimpleDateFormat; 17 | import java.util.Date; 18 | 19 | /** 20 | * @author Hai 21 | * @date 2020/6/16 - 23:34 22 | */ 23 | @Controller 24 | public class WsController { 25 | @Autowired 26 | SimpMessagingTemplate simpMessagingTemplate; 27 | 28 | /** 29 | * 单聊的消息的接受与转发 30 | * @param authentication 31 | * @param message 32 | */ 33 | @MessageMapping("/ws/chat") 34 | public void handleMessage(Authentication authentication, Message message){ 35 | User user= ((User) authentication.getPrincipal()); 36 | message.setFromNickname(user.getNickname()); 37 | message.setFrom(user.getUsername()); 38 | message.setCreateTime(new Date()); 39 | simpMessagingTemplate.convertAndSendToUser(message.getTo(),"/queue/chat",message); 40 | } 41 | 42 | @Autowired 43 | GroupMsgContentService groupMsgContentService; 44 | EmojiConverter emojiConverter = EmojiConverter.getInstance(); 45 | 46 | SimpleDateFormat dateFormat=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); 47 | /** 48 | * 群聊的消息接受与转发 49 | * @param authentication 50 | * @param groupMsgContent 51 | */ 52 | @MessageMapping("/ws/groupChat") 53 | public void handleGroupMessage(Authentication authentication, GroupMsgContent groupMsgContent){ 54 | User currentUser= (User) authentication.getPrincipal(); 55 | //处理emoji内容,转换成unicode编码 56 | groupMsgContent.setContent(emojiConverter.toHtml(groupMsgContent.getContent())); 57 | //保证来源正确性,从Security中获取用户信息 58 | groupMsgContent.setFromId(currentUser.getId()); 59 | groupMsgContent.setFromName(currentUser.getNickname()); 60 | groupMsgContent.setFromProfile(currentUser.getUserProfile()); 61 | groupMsgContent.setCreateTime(new Date()); 62 | //保存该条群聊消息记录到数据库中 63 | groupMsgContentService.insert(groupMsgContent); 64 | //转发该条数据 65 | simpMessagingTemplate.convertAndSend("/topic/greetings",groupMsgContent); 66 | } 67 | 68 | /** 69 | * 接受前端发来的消息,获得图灵机器人回复并转发回给发送者 70 | * @param authentication 71 | * @param message 72 | * @throws IOException 73 | */ 74 | @MessageMapping("/ws/robotChat") 75 | public void handleRobotChatMessage(Authentication authentication, Message message) throws IOException { 76 | User user = ((User) authentication.getPrincipal()); 77 | //接收到的消息 78 | message.setFrom(user.getUsername()); 79 | message.setCreateTime(new Date()); 80 | message.setFromNickname(user.getNickname()); 81 | message.setFromUserProfile(user.getUserProfile()); 82 | //发送消息内容给机器人,获得回复 83 | String result = TuLingUtil.replyMessage(message.getContent()); 84 | //构建返回消息JSON字符串 85 | Message resultMessage = new Message(); 86 | resultMessage.setFrom("瓦力"); 87 | resultMessage.setCreateTime(new Date()); 88 | resultMessage.setFromNickname("瓦力"); 89 | resultMessage.setContent(result); 90 | //回送机器人回复的消息给发送者 91 | simpMessagingTemplate.convertAndSendToUser(message.getFrom(),"/queue/robot",resultMessage); 92 | 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /subtlechat-web/src/main/java/top/javahai/subtlechat/dao/AdminDao.java: -------------------------------------------------------------------------------- 1 | package top.javahai.subtlechat.dao; 2 | 3 | import top.javahai.subtlechat.api.entity.Admin; 4 | import org.apache.ibatis.annotations.Param; 5 | import java.util.List; 6 | 7 | /** 8 | * (Admin)表数据库访问层 9 | * 10 | * @author makejava 11 | * @since 2020-06-16 11:35:57 12 | */ 13 | public interface AdminDao { 14 | 15 | 16 | Admin loadUserByUsername(String username); 17 | 18 | /** 19 | * 通过ID查询单条数据 20 | * 21 | * @param id 主键 22 | * @return 实例对象 23 | */ 24 | Admin queryById(Integer id); 25 | 26 | /** 27 | * 查询指定行数据 28 | * 29 | * @param offset 查询起始位置 30 | * @param limit 查询条数 31 | * @return 对象列表 32 | */ 33 | List queryAllByLimit(@Param("offset") int offset, @Param("limit") int limit); 34 | 35 | 36 | /** 37 | * 通过实体作为筛选条件查询 38 | * 39 | * @param admin 实例对象 40 | * @return 对象列表 41 | */ 42 | List queryAll(Admin admin); 43 | 44 | /** 45 | * 新增数据 46 | * 47 | * @param admin 实例对象 48 | * @return 影响行数 49 | */ 50 | int insert(Admin admin); 51 | 52 | /** 53 | * 修改数据 54 | * 55 | * @param admin 实例对象 56 | * @return 影响行数 57 | */ 58 | int update(Admin admin); 59 | 60 | /** 61 | * 通过主键删除数据 62 | * 63 | * @param id 主键 64 | * @return 影响行数 65 | */ 66 | int deleteById(Integer id); 67 | } 68 | -------------------------------------------------------------------------------- /subtlechat-web/src/main/java/top/javahai/subtlechat/dao/FeedbackDao.java: -------------------------------------------------------------------------------- 1 | package top.javahai.subtlechat.dao; 2 | 3 | import org.apache.ibatis.annotations.Param; 4 | import top.javahai.subtlechat.api.entity.Feedback; 5 | 6 | import java.util.List; 7 | 8 | /** 9 | * (Feedback)表数据库访问层 10 | * 11 | * @author makejava 12 | * @since 2020-10-02 12:19:43 13 | */ 14 | public interface FeedbackDao { 15 | 16 | /** 17 | * 通过ID查询单条数据 18 | * 19 | * @param id 主键 20 | * @return 实例对象 21 | */ 22 | Feedback queryById(String id); 23 | 24 | /** 25 | * 查询指定行数据 26 | * 27 | * @param offset 查询起始位置 28 | * @param limit 查询条数 29 | * @return 对象列表 30 | */ 31 | List queryAllByLimit(@Param("offset") int offset, @Param("limit") int limit); 32 | 33 | 34 | /** 35 | * 通过实体作为筛选条件查询 36 | * 37 | * @param feedback 实例对象 38 | * @return 对象列表 39 | */ 40 | List queryAll(Feedback feedback); 41 | 42 | /** 43 | * 新增数据 44 | * 45 | * @param feedback 实例对象 46 | * @return 影响行数 47 | */ 48 | int insert(Feedback feedback); 49 | 50 | /** 51 | * 修改数据 52 | * 53 | * @param feedback 实例对象 54 | * @return 影响行数 55 | */ 56 | int update(Feedback feedback); 57 | 58 | /** 59 | * 通过主键删除数据 60 | * 61 | * @param id 主键 62 | * @return 影响行数 63 | */ 64 | int deleteById(String id); 65 | 66 | } 67 | -------------------------------------------------------------------------------- /subtlechat-web/src/main/java/top/javahai/subtlechat/dao/GroupMsgContentDao.java: -------------------------------------------------------------------------------- 1 | package top.javahai.subtlechat.dao; 2 | 3 | import top.javahai.subtlechat.api.entity.GroupMsgContent; 4 | import org.apache.ibatis.annotations.Param; 5 | 6 | import java.util.Date; 7 | import java.util.List; 8 | 9 | /** 10 | * (GroupMsgContent)表数据库访问层 11 | * 12 | * @author makejava 13 | * @since 2020-06-17 10:51:13 14 | */ 15 | public interface GroupMsgContentDao { 16 | 17 | /** 18 | * 通过ID查询单条数据 19 | * 20 | * @param id 主键 21 | * @return 实例对象 22 | */ 23 | GroupMsgContent queryById(Integer id); 24 | 25 | /** 26 | * 查询指定行数据 27 | * 28 | * @param offset 查询起始位置 29 | * @param limit 查询条数 30 | * @return 对象列表 31 | */ 32 | List queryAllByLimit(@Param("offset") Integer offset, @Param("limit") Integer limit); 33 | 34 | 35 | /** 36 | * 通过实体作为筛选条件查询 37 | * 38 | * @param groupMsgContent 实例对象 39 | * @return 对象列表 40 | */ 41 | List queryAll(GroupMsgContent groupMsgContent); 42 | 43 | /** 44 | * 新增数据 45 | * 46 | * @param groupMsgContent 实例对象 47 | * @return 影响行数 48 | */ 49 | int insert(GroupMsgContent groupMsgContent); 50 | 51 | /** 52 | * 修改数据 53 | * 54 | * @param groupMsgContent 实例对象 55 | * @return 影响行数 56 | */ 57 | int update(GroupMsgContent groupMsgContent); 58 | 59 | /** 60 | * 通过主键删除数据 61 | * 62 | * @param id 主键 63 | * @return 影响行数 64 | */ 65 | int deleteById(Integer id); 66 | 67 | List getAllGroupMsgContentByPage(@Param("page") Integer page, 68 | @Param("size") Integer size, 69 | @Param("nickname") String nickname, 70 | @Param("type") Integer type, 71 | @Param("dateScope") Date[] dateScope); 72 | 73 | Long getTotal(@Param("nickname") String nickname, 74 | @Param("type") Integer type, 75 | @Param("dateScope") Date[] dateScope); 76 | 77 | Integer deleteGroupMsgContentByIds(@Param("ids") Integer[] ids); 78 | } 79 | -------------------------------------------------------------------------------- /subtlechat-web/src/main/java/top/javahai/subtlechat/dao/MailSendLogDao.java: -------------------------------------------------------------------------------- 1 | package top.javahai.subtlechat.dao; 2 | 3 | import org.apache.ibatis.annotations.Param; 4 | import org.springframework.security.core.parameters.P; 5 | import top.javahai.subtlechat.api.entity.MailSendLog; 6 | 7 | import java.util.Date; 8 | import java.util.List; 9 | 10 | /** 11 | * (MailSendLog)表数据库访问层 12 | * 13 | * @author makejava 14 | * @since 2020-10-02 14:40:33 15 | */ 16 | public interface MailSendLogDao { 17 | 18 | /** 19 | * 通过ID查询单条数据 20 | * 21 | * @param msgId 主键 22 | * @return 实例对象 23 | */ 24 | MailSendLog queryById(String msgId); 25 | 26 | /** 27 | * 查询指定行数据 28 | * 29 | * @param offset 查询起始位置 30 | * @param limit 查询条数 31 | * @return 对象列表 32 | */ 33 | List queryAllByLimit(@Param("offset") int offset, @Param("limit") int limit); 34 | 35 | 36 | /** 37 | * 通过实体作为筛选条件查询 38 | * 39 | * @param mailSendLog 实例对象 40 | * @return 对象列表 41 | */ 42 | List queryAll(MailSendLog mailSendLog); 43 | 44 | /** 45 | * 新增数据 46 | * 47 | * @param mailSendLog 实例对象 48 | * @return 影响行数 49 | */ 50 | int insert(MailSendLog mailSendLog); 51 | 52 | /** 53 | * 修改数据 54 | * 55 | * @param mailSendLog 实例对象 56 | * @return 影响行数 57 | */ 58 | int update(MailSendLog mailSendLog); 59 | 60 | /** 61 | * 通过主键删除数据 62 | * 63 | * @param msgId 主键 64 | * @return 影响行数 65 | */ 66 | int deleteById(String msgId); 67 | 68 | void updateMailSendLogStatus(@Param("msgId") String msgId,@Param("status") int i); 69 | 70 | List getMailSendLogsByStatus(@Param("delivering") Integer delivering); 71 | 72 | void updateCount(@Param("msgId") String msgId,@Param("date") Date date); 73 | 74 | String getMsgById(@Param("msgId") String msgId); 75 | } 76 | -------------------------------------------------------------------------------- /subtlechat-web/src/main/java/top/javahai/subtlechat/dao/UserDao.java: -------------------------------------------------------------------------------- 1 | package top.javahai.subtlechat.dao; 2 | 3 | import top.javahai.subtlechat.api.entity.User; 4 | import org.apache.ibatis.annotations.Param; 5 | import java.util.List; 6 | 7 | /** 8 | * (User)表数据库访问层 9 | * 10 | * @author makejava 11 | * @since 2020-06-16 12:06:29 12 | */ 13 | public interface UserDao { 14 | 15 | /** 16 | * 根据用户名查询用户对象 17 | * @param username 18 | * @return 19 | */ 20 | User loadUserByUsername(String username); 21 | 22 | 23 | /** 24 | * 获取除当前用户的所有用户 25 | * @param id 26 | * @return 27 | */ 28 | List getUsersWithoutCurrentUser(Integer id); 29 | 30 | /** 31 | * 通过ID查询单条数据 32 | * 33 | * @param id 主键 34 | * @return 实例对象 35 | */ 36 | User queryById(Integer id); 37 | 38 | /** 39 | * 查询指定行数据 40 | * 41 | * @param offset 查询起始位置 42 | * @param limit 查询条数 43 | * @return 对象列表 44 | */ 45 | List queryAllByLimit(@Param("offset") int offset, @Param("limit") int limit); 46 | 47 | 48 | /** 49 | * 通过实体作为筛选条件查询 50 | * 51 | * @param user 实例对象 52 | * @return 对象列表 53 | */ 54 | List queryAll(User user); 55 | 56 | /** 57 | * 新增数据 58 | * 59 | * @param user 实例对象 60 | * @return 影响行数 61 | */ 62 | int insert(User user); 63 | 64 | /** 65 | * 修改数据 66 | * 67 | * @param user 实例对象 68 | * @return 影响行数 69 | */ 70 | int update(User user); 71 | 72 | /** 73 | * 通过主键删除数据 74 | * 75 | * @param id 主键 76 | * @return 影响行数 77 | */ 78 | int deleteById(Integer id); 79 | 80 | void setUserStateToOn(Integer id); 81 | 82 | void setUserStateToLeave(Integer id); 83 | 84 | Integer checkUsername(String username); 85 | 86 | Integer checkNickname(String nickname); 87 | 88 | List getAllUserByPage(@Param("page") Integer page, @Param("size") Integer size,String keyword,Integer isLocked); 89 | 90 | Long getTotal(@Param("keyword") String keyword,@Param("isLocked") Integer isLocked); 91 | 92 | Integer changeLockedStatus(@Param("id") Integer id, @Param("isLocked") Boolean isLocked); 93 | 94 | Integer deleteByIds(@Param("ids") Integer[] ids); 95 | } 96 | -------------------------------------------------------------------------------- /subtlechat-web/src/main/java/top/javahai/subtlechat/dao/UserStateDao.java: -------------------------------------------------------------------------------- 1 | package top.javahai.subtlechat.dao; 2 | 3 | import top.javahai.subtlechat.api.entity.UserState; 4 | import org.apache.ibatis.annotations.Param; 5 | import java.util.List; 6 | 7 | /** 8 | * (UserState)表数据库访问层 9 | * 10 | * @author makejava 11 | * @since 2020-06-16 11:36:02 12 | */ 13 | public interface UserStateDao { 14 | 15 | /** 16 | * 通过ID查询单条数据 17 | * 18 | * @param id 主键 19 | * @return 实例对象 20 | */ 21 | UserState queryById(Integer id); 22 | 23 | /** 24 | * 查询指定行数据 25 | * 26 | * @param offset 查询起始位置 27 | * @param limit 查询条数 28 | * @return 对象列表 29 | */ 30 | List queryAllByLimit(@Param("offset") int offset, @Param("limit") int limit); 31 | 32 | 33 | /** 34 | * 通过实体作为筛选条件查询 35 | * 36 | * @param userState 实例对象 37 | * @return 对象列表 38 | */ 39 | List queryAll(UserState userState); 40 | 41 | /** 42 | * 新增数据 43 | * 44 | * @param userState 实例对象 45 | * @return 影响行数 46 | */ 47 | int insert(UserState userState); 48 | 49 | /** 50 | * 修改数据 51 | * 52 | * @param userState 实例对象 53 | * @return 影响行数 54 | */ 55 | int update(UserState userState); 56 | 57 | /** 58 | * 通过主键删除数据 59 | * 60 | * @param id 主键 61 | * @return 影响行数 62 | */ 63 | int deleteById(Integer id); 64 | 65 | } 66 | -------------------------------------------------------------------------------- /subtlechat-web/src/main/java/top/javahai/subtlechat/exception/GlobalExceptionHandler.java: -------------------------------------------------------------------------------- 1 | package top.javahai.subtlechat.exception; 2 | 3 | import com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException; 4 | import org.springframework.web.bind.annotation.ExceptionHandler; 5 | import org.springframework.web.bind.annotation.RestControllerAdvice; 6 | import top.javahai.subtlechat.api.entity.RespBean; 7 | 8 | import java.sql.SQLException; 9 | 10 | /** 11 | * @author Hai 12 | * @date 2020/4/27 - 19:49 13 | * 功能:全局异常处理类 14 | */ 15 | @RestControllerAdvice 16 | public class GlobalExceptionHandler { 17 | 18 | /* 19 | 处理SQLException异常 20 | */ 21 | @ExceptionHandler(SQLException.class) 22 | public RespBean sqlExceptionHandler(SQLException e){ 23 | if (e instanceof MySQLIntegrityConstraintViolationException){ 24 | return RespBean.error("该数据与其他数据存在关联,无法删除!"); 25 | } 26 | else { 27 | e.printStackTrace(); 28 | return RespBean.error("数据库异常,操作失败!"); 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /subtlechat-web/src/main/java/top/javahai/subtlechat/service/AdminService.java: -------------------------------------------------------------------------------- 1 | package top.javahai.subtlechat.service; 2 | 3 | import top.javahai.subtlechat.api.entity.Admin; 4 | import java.util.List; 5 | 6 | /** 7 | * (Admin)表服务接口 8 | * 9 | * @author makejava 10 | * @since 2020-06-16 11:35:58 11 | */ 12 | public interface AdminService { 13 | 14 | /** 15 | * 通过ID查询单条数据 16 | * 17 | * @param id 主键 18 | * @return 实例对象 19 | */ 20 | Admin queryById(Integer id); 21 | 22 | /** 23 | * 查询多条数据 24 | * 25 | * @param offset 查询起始位置 26 | * @param limit 查询条数 27 | * @return 对象列表 28 | */ 29 | List queryAllByLimit(int offset, int limit); 30 | 31 | /** 32 | * 新增数据 33 | * 34 | * @param admin 实例对象 35 | * @return 实例对象 36 | */ 37 | Admin insert(Admin admin); 38 | 39 | /** 40 | * 修改数据 41 | * 42 | * @param admin 实例对象 43 | * @return 实例对象 44 | */ 45 | Admin update(Admin admin); 46 | 47 | /** 48 | * 通过主键删除数据 49 | * 50 | * @param id 主键 51 | * @return 是否成功 52 | */ 53 | boolean deleteById(Integer id); 54 | 55 | } 56 | -------------------------------------------------------------------------------- /subtlechat-web/src/main/java/top/javahai/subtlechat/service/FeedbackService.java: -------------------------------------------------------------------------------- 1 | package top.javahai.subtlechat.service; 2 | 3 | import top.javahai.subtlechat.api.entity.Feedback; 4 | import java.util.List; 5 | 6 | /** 7 | * (Feedback)表服务接口 8 | * 9 | * @author makejava 10 | * @since 2020-10-02 12:19:43 11 | */ 12 | public interface FeedbackService { 13 | 14 | /** 15 | * 通过ID查询单条数据 16 | * 17 | * @param id 主键 18 | * @return 实例对象 19 | */ 20 | Feedback queryById(String id); 21 | 22 | /** 23 | * 查询多条数据 24 | * 25 | * @param offset 查询起始位置 26 | * @param limit 查询条数 27 | * @return 对象列表 28 | */ 29 | List queryAllByLimit(int offset, int limit); 30 | 31 | /** 32 | * 新增数据 33 | * 34 | * @param feedback 实例对象 35 | * @return 实例对象 36 | */ 37 | Feedback insert(Feedback feedback); 38 | 39 | /** 40 | * 修改数据 41 | * 42 | * @param feedback 实例对象 43 | * @return 实例对象 44 | */ 45 | Feedback update(Feedback feedback); 46 | 47 | /** 48 | * 通过主键删除数据 49 | * 50 | * @param id 主键 51 | * @return 是否成功 52 | */ 53 | boolean deleteById(String id); 54 | 55 | void sendMessage(Feedback feedback); 56 | } 57 | -------------------------------------------------------------------------------- /subtlechat-web/src/main/java/top/javahai/subtlechat/service/GroupMsgContentService.java: -------------------------------------------------------------------------------- 1 | package top.javahai.subtlechat.service; 2 | 3 | import top.javahai.subtlechat.api.entity.GroupMsgContent; 4 | import top.javahai.subtlechat.api.entity.RespPageBean; 5 | 6 | import javax.servlet.http.HttpServletResponse; 7 | import java.io.IOException; 8 | import java.io.UnsupportedEncodingException; 9 | import java.util.Date; 10 | import java.util.List; 11 | 12 | /** 13 | * (GroupMsgContent)表服务接口 14 | * 15 | * @author makejava 16 | * @since 2020-06-17 10:51:13 17 | */ 18 | public interface GroupMsgContentService { 19 | 20 | /** 21 | * 通过ID查询单条数据 22 | * 23 | * @param id 主键 24 | * @return 实例对象 25 | */ 26 | GroupMsgContent queryById(Integer id); 27 | 28 | /** 29 | * 查询多条数据 30 | * 31 | * @param offset 查询起始位置 32 | * @param limit 查询条数 33 | * @return 对象列表 34 | */ 35 | List queryAllByLimit(Integer offset, Integer limit); 36 | 37 | /** 38 | * 新增数据 39 | * 40 | * @param groupMsgContent 实例对象 41 | * @return 实例对象 42 | */ 43 | GroupMsgContent insert(GroupMsgContent groupMsgContent); 44 | 45 | /** 46 | * 修改数据 47 | * 48 | * @param groupMsgContent 实例对象 49 | * @return 实例对象 50 | */ 51 | GroupMsgContent update(GroupMsgContent groupMsgContent); 52 | 53 | /** 54 | * 通过主键删除数据 55 | * 56 | * @param id 主键 57 | * @return 是否成功 58 | */ 59 | boolean deleteById(Integer id); 60 | 61 | RespPageBean getAllGroupMsgContentByPage(Integer page, Integer size, String nickname, Integer type, Date[] dateScope); 62 | 63 | Integer deleteGroupMsgContentByIds(Integer[] ids); 64 | 65 | void handleDownload(HttpServletResponse response) throws IOException; 66 | } 67 | -------------------------------------------------------------------------------- /subtlechat-web/src/main/java/top/javahai/subtlechat/service/MailSendLogService.java: -------------------------------------------------------------------------------- 1 | package top.javahai.subtlechat.service; 2 | 3 | import top.javahai.subtlechat.api.entity.MailSendLog; 4 | 5 | import java.util.Date; 6 | import java.util.List; 7 | 8 | /** 9 | * (MailSendLog)表服务接口 10 | * 11 | * @author makejava 12 | * @since 2020-10-02 14:40:33 13 | */ 14 | public interface MailSendLogService { 15 | 16 | /** 17 | * 通过ID查询单条数据 18 | * 19 | * @param msgId 主键 20 | * @return 实例对象 21 | */ 22 | MailSendLog queryById(String msgId); 23 | 24 | /** 25 | * 查询多条数据 26 | * 27 | * @param offset 查询起始位置 28 | * @param limit 查询条数 29 | * @return 对象列表 30 | */ 31 | List queryAllByLimit(int offset, int limit); 32 | 33 | /** 34 | * 新增数据 35 | * 36 | * @param mailSendLog 实例对象 37 | * @return 实例对象 38 | */ 39 | MailSendLog insert(MailSendLog mailSendLog); 40 | 41 | /** 42 | * 修改数据 43 | * 44 | * @param mailSendLog 实例对象 45 | * @return 实例对象 46 | */ 47 | MailSendLog update(MailSendLog mailSendLog); 48 | 49 | /** 50 | * 通过主键删除数据 51 | * 52 | * @param msgId 主键 53 | * @return 是否成功 54 | */ 55 | boolean deleteById(String msgId); 56 | 57 | void updateMailSendLogStatus(String msgId, int i); 58 | 59 | List getMailSendLogsByStatus(Integer delivering); 60 | 61 | void updateCount(String msgId, Date date); 62 | 63 | String getMsgById(String msgId); 64 | } 65 | -------------------------------------------------------------------------------- /subtlechat-web/src/main/java/top/javahai/subtlechat/service/UserService.java: -------------------------------------------------------------------------------- 1 | package top.javahai.subtlechat.service; 2 | 3 | import top.javahai.subtlechat.api.entity.RespPageBean; 4 | import top.javahai.subtlechat.api.entity.User; 5 | 6 | import java.util.List; 7 | 8 | /** 9 | * (User)表服务接口 10 | * 11 | * @author makejava 12 | * @since 2020-06-16 11:37:09 13 | */ 14 | public interface UserService { 15 | 16 | 17 | /** 18 | * 获取除了当前登录用户的所有user表的数据 19 | * @return 20 | */ 21 | List getUsersWithoutCurrentUser(); 22 | 23 | /** 24 | * 设置用户当前状态为在线 25 | * @param id 用户id 26 | */ 27 | public void setUserStateToOn(Integer id); 28 | 29 | /** 30 | * 设置用户当前状态为离线 31 | * @param id 32 | */ 33 | public void setUserStateToLeave(Integer id); 34 | 35 | /** 36 | * 通过ID查询单条数据 37 | * 38 | * @param id 主键 39 | * @return 实例对象 40 | */ 41 | User queryById(Integer id); 42 | 43 | /** 44 | * 查询多条数据 45 | * 46 | * @param offset 查询起始位置 47 | * @param limit 查询条数 48 | * @return 对象列表 49 | */ 50 | List queryAllByLimit(int offset, int limit); 51 | 52 | /** 53 | * 新增数据 54 | * 55 | * @param user 实例对象 56 | * @return 实例对象 57 | */ 58 | Integer insert(User user); 59 | 60 | /** 61 | * 修改数据 62 | * 63 | * @param user 实例对象 64 | * @return 实例对象 65 | */ 66 | Integer update(User user); 67 | 68 | /** 69 | * 通过主键删除数据 70 | * 71 | * @param id 主键 72 | * @return 是否成功 73 | */ 74 | boolean deleteById(Integer id); 75 | 76 | /** 77 | * 检查用户名是否已存在 78 | * @param username 79 | * @return 80 | */ 81 | Integer checkUsername(String username); 82 | 83 | /** 84 | * 检查昵称是否存在 85 | * @param nickname 86 | * @return 87 | */ 88 | Integer checkNickname(String nickname); 89 | 90 | RespPageBean getAllUserByPage(Integer page, Integer size, String keyword,Integer isLocked); 91 | 92 | Integer changeLockedStatus(Integer id, Boolean isLocked); 93 | 94 | Integer deleteByIds(Integer[] ids); 95 | } 96 | -------------------------------------------------------------------------------- /subtlechat-web/src/main/java/top/javahai/subtlechat/service/UserStateService.java: -------------------------------------------------------------------------------- 1 | package top.javahai.subtlechat.service; 2 | 3 | import top.javahai.subtlechat.api.entity.UserState; 4 | import java.util.List; 5 | 6 | /** 7 | * (UserState)表服务接口 8 | * 9 | * @author makejava 10 | * @since 2020-06-16 11:36:02 11 | */ 12 | public interface UserStateService { 13 | 14 | /** 15 | * 通过ID查询单条数据 16 | * 17 | * @param id 主键 18 | * @return 实例对象 19 | */ 20 | UserState queryById(Integer id); 21 | 22 | /** 23 | * 查询多条数据 24 | * 25 | * @param offset 查询起始位置 26 | * @param limit 查询条数 27 | * @return 对象列表 28 | */ 29 | List queryAllByLimit(int offset, int limit); 30 | 31 | /** 32 | * 新增数据 33 | * 34 | * @param userState 实例对象 35 | * @return 实例对象 36 | */ 37 | UserState insert(UserState userState); 38 | 39 | /** 40 | * 修改数据 41 | * 42 | * @param userState 实例对象 43 | * @return 实例对象 44 | */ 45 | UserState update(UserState userState); 46 | 47 | /** 48 | * 通过主键删除数据 49 | * 50 | * @param id 主键 51 | * @return 是否成功 52 | */ 53 | boolean deleteById(Integer id); 54 | 55 | } 56 | -------------------------------------------------------------------------------- /subtlechat-web/src/main/java/top/javahai/subtlechat/service/VerifyCodeService.java: -------------------------------------------------------------------------------- 1 | package top.javahai.subtlechat.service; 2 | 3 | /** 4 | * @author Hai 5 | * @date 2020/10/2 - 23:27 6 | */ 7 | public interface VerifyCodeService { 8 | 9 | String getVerifyCode(); 10 | 11 | void sendVerifyCodeMail(String code); 12 | 13 | } 14 | -------------------------------------------------------------------------------- /subtlechat-web/src/main/java/top/javahai/subtlechat/service/impl/AdminServiceImpl.java: -------------------------------------------------------------------------------- 1 | package top.javahai.subtlechat.service.impl; 2 | 3 | import org.springframework.security.core.userdetails.UserDetails; 4 | import org.springframework.security.core.userdetails.UserDetailsService; 5 | import org.springframework.security.core.userdetails.UsernameNotFoundException; 6 | import top.javahai.subtlechat.api.entity.Admin; 7 | import top.javahai.subtlechat.dao.AdminDao; 8 | import top.javahai.subtlechat.service.AdminService; 9 | import org.springframework.stereotype.Service; 10 | 11 | import javax.annotation.Resource; 12 | import java.util.List; 13 | 14 | /** 15 | * (Admin)表服务实现类 16 | * 17 | * @author makejava 18 | * @since 2020-06-16 11:35:58 19 | */ 20 | @Service("adminService") 21 | public class AdminServiceImpl implements AdminService, UserDetailsService { 22 | @Resource 23 | private AdminDao adminDao; 24 | 25 | /** 26 | * 根据用户名进行登录 27 | * @param username 28 | * @return 29 | * @throws UsernameNotFoundException 30 | */ 31 | @Override 32 | public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { 33 | Admin admin=adminDao.loadUserByUsername(username); 34 | if (admin==null){ 35 | throw new UsernameNotFoundException("找不到该管理员"); 36 | } 37 | return admin; 38 | } 39 | /** 40 | * 通过ID查询单条数据 41 | * 42 | * @param id 主键 43 | * @return 实例对象 44 | */ 45 | @Override 46 | public Admin queryById(Integer id) { 47 | return this.adminDao.queryById(id); 48 | } 49 | 50 | /** 51 | * 查询多条数据 52 | * 53 | * @param offset 查询起始位置 54 | * @param limit 查询条数 55 | * @return 对象列表 56 | */ 57 | @Override 58 | public List queryAllByLimit(int offset, int limit) { 59 | return this.adminDao.queryAllByLimit(offset, limit); 60 | } 61 | 62 | /** 63 | * 新增数据 64 | * 65 | * @param admin 实例对象 66 | * @return 实例对象 67 | */ 68 | @Override 69 | public Admin insert(Admin admin) { 70 | this.adminDao.insert(admin); 71 | return admin; 72 | } 73 | 74 | /** 75 | * 修改数据 76 | * 77 | * @param admin 实例对象 78 | * @return 实例对象 79 | */ 80 | @Override 81 | public Admin update(Admin admin) { 82 | this.adminDao.update(admin); 83 | return this.queryById(admin.getId()); 84 | } 85 | 86 | /** 87 | * 通过主键删除数据 88 | * 89 | * @param id 主键 90 | * @return 是否成功 91 | */ 92 | @Override 93 | public boolean deleteById(Integer id) { 94 | return this.adminDao.deleteById(id) > 0; 95 | } 96 | 97 | } 98 | -------------------------------------------------------------------------------- /subtlechat-web/src/main/java/top/javahai/subtlechat/service/impl/FeedbackServiceImpl.java: -------------------------------------------------------------------------------- 1 | package top.javahai.subtlechat.service.impl; 2 | 3 | import com.alibaba.fastjson.JSON; 4 | import org.springframework.amqp.rabbit.connection.CorrelationData; 5 | import org.springframework.amqp.rabbit.core.RabbitTemplate; 6 | import org.springframework.beans.factory.annotation.Autowired; 7 | import org.springframework.beans.factory.annotation.Value; 8 | import top.javahai.subtlechat.api.entity.Feedback; 9 | import top.javahai.subtlechat.api.entity.MailConstants; 10 | import top.javahai.subtlechat.api.entity.MailSendLog; 11 | import top.javahai.subtlechat.api.utils.JsonUtil; 12 | import top.javahai.subtlechat.dao.FeedbackDao; 13 | import top.javahai.subtlechat.service.FeedbackService; 14 | import org.springframework.stereotype.Service; 15 | import top.javahai.subtlechat.service.MailSendLogService; 16 | 17 | import javax.annotation.Resource; 18 | import java.util.Date; 19 | import java.util.List; 20 | import java.util.UUID; 21 | 22 | /** 23 | * (Feedback)表服务实现类 24 | * 25 | * @author makejava 26 | * @since 2020-10-02 12:19:44 27 | */ 28 | @Service("feedbackService") 29 | public class FeedbackServiceImpl implements FeedbackService { 30 | @Resource 31 | private FeedbackDao feedbackDao; 32 | 33 | @Autowired 34 | RabbitTemplate rabbitTemplate; 35 | 36 | @Value("${mail.exchange:mail-exchange}") 37 | private String mailExchange; 38 | 39 | @Value("${mail.queue.feedback:mail-queue-feedback}") 40 | private String mailQueueFeedback; 41 | 42 | @Value("${mail.route.feedback:mail-route-feedback}") 43 | private String mailRouteFeedback; 44 | 45 | @Autowired 46 | private MailSendLogService mailSendLogService; 47 | 48 | /** 49 | * 通过ID查询单条数据 50 | * 51 | * @param id 主键 52 | * @return 实例对象 53 | */ 54 | @Override 55 | public Feedback queryById(String id) { 56 | return this.feedbackDao.queryById(id); 57 | } 58 | 59 | /** 60 | * 查询多条数据 61 | * 62 | * @param offset 查询起始位置 63 | * @param limit 查询条数 64 | * @return 对象列表 65 | */ 66 | @Override 67 | public List queryAllByLimit(int offset, int limit) { 68 | return this.feedbackDao.queryAllByLimit(offset, limit); 69 | } 70 | 71 | /** 72 | * 新增数据 73 | * 74 | * @param feedback 实例对象 75 | * @return 实例对象 76 | */ 77 | @Override 78 | public Feedback insert(Feedback feedback) { 79 | this.feedbackDao.insert(feedback); 80 | return feedback; 81 | } 82 | 83 | /** 84 | * 修改数据 85 | * 86 | * @param feedback 实例对象 87 | * @return 实例对象 88 | */ 89 | @Override 90 | public Feedback update(Feedback feedback) { 91 | this.feedbackDao.update(feedback); 92 | return this.queryById(feedback.getId()); 93 | } 94 | 95 | /** 96 | * 通过主键删除数据 97 | * 98 | * @param id 主键 99 | * @return 是否成功 100 | */ 101 | @Override 102 | public boolean deleteById(String id) { 103 | return this.feedbackDao.deleteById(id) > 0; 104 | } 105 | 106 | @Override 107 | public void sendMessage(Feedback feedback) { 108 | feedback.setId(UUID.randomUUID().toString()); 109 | //插入一条记录 110 | insert(feedback); 111 | //将内容转化为JSON字符串 112 | String record = JsonUtil.parseToString(feedback); 113 | //添加消息发送记录 114 | String msgId=UUID.randomUUID().toString(); 115 | MailSendLog sendLog = new MailSendLog(); 116 | sendLog.setMsgId(msgId); 117 | sendLog.setContent(record); 118 | sendLog.setContentType(MailConstants.FEEDBACK_TYPE); 119 | sendLog.setCount(1); 120 | sendLog.setCreateTime(new Date()); 121 | sendLog.setUpdateTime(new Date()); 122 | //当前超过一分钟后开始重试 123 | sendLog.setTryTime(new Date(System.currentTimeMillis()+1000*60*MailConstants.MEG_TIMEOUT)); 124 | sendLog.setExchange(mailExchange); 125 | sendLog.setRouteKey(mailRouteFeedback); 126 | sendLog.setStatus(MailConstants.DELIVERING); 127 | //新增消息发送记录 128 | mailSendLogService.insert(sendLog); 129 | //投递消息 130 | rabbitTemplate.convertAndSend(mailExchange,mailRouteFeedback,record,new CorrelationData(msgId)); 131 | } 132 | } 133 | -------------------------------------------------------------------------------- /subtlechat-web/src/main/java/top/javahai/subtlechat/service/impl/GroupMsgContentServiceImpl.java: -------------------------------------------------------------------------------- 1 | package top.javahai.subtlechat.service.impl; 2 | 3 | import com.alibaba.excel.EasyExcel; 4 | import top.javahai.subtlechat.api.data.GroupMsgContentData; 5 | import top.javahai.subtlechat.api.entity.GroupMsgContent; 6 | import top.javahai.subtlechat.dao.GroupMsgContentDao; 7 | import top.javahai.subtlechat.api.entity.RespPageBean; 8 | import top.javahai.subtlechat.service.GroupMsgContentService; 9 | import org.springframework.stereotype.Service; 10 | 11 | import javax.annotation.Resource; 12 | import javax.servlet.http.HttpServletResponse; 13 | import java.io.IOException; 14 | import java.io.UnsupportedEncodingException; 15 | import java.net.MalformedURLException; 16 | import java.net.URLEncoder; 17 | import java.util.Date; 18 | import java.util.List; 19 | import java.util.stream.Collectors; 20 | 21 | /** 22 | * (GroupMsgContent)表服务实现类 23 | * 24 | * @author makejava 25 | * @since 2020-06-17 10:51:13 26 | */ 27 | @Service("groupMsgContentService") 28 | public class GroupMsgContentServiceImpl implements GroupMsgContentService { 29 | @Resource 30 | private GroupMsgContentDao groupMsgContentDao; 31 | 32 | /** 33 | * 通过ID查询单条数据 34 | * 35 | * @param id 主键 36 | * @return 实例对象 37 | */ 38 | @Override 39 | public GroupMsgContent queryById(Integer id) { 40 | return this.groupMsgContentDao.queryById(id); 41 | } 42 | 43 | /** 44 | * 查询多条数据 45 | * 46 | * @param offset 查询起始位置 47 | * @param limit 查询条数 48 | * @return 对象列表 49 | */ 50 | @Override 51 | public List queryAllByLimit(Integer offset, Integer limit) { 52 | return this.groupMsgContentDao.queryAllByLimit(offset, limit); 53 | } 54 | 55 | /** 56 | * 新增数据 57 | * 58 | * @param groupMsgContent 实例对象 59 | * @return 实例对象 60 | */ 61 | @Override 62 | public GroupMsgContent insert(GroupMsgContent groupMsgContent) { 63 | this.groupMsgContentDao.insert(groupMsgContent); 64 | return groupMsgContent; 65 | } 66 | 67 | /** 68 | * 修改数据 69 | * 70 | * @param groupMsgContent 实例对象 71 | * @return 实例对象 72 | */ 73 | @Override 74 | public GroupMsgContent update(GroupMsgContent groupMsgContent) { 75 | this.groupMsgContentDao.update(groupMsgContent); 76 | return this.queryById(groupMsgContent.getId()); 77 | } 78 | 79 | /** 80 | * 通过主键删除数据 81 | * 82 | * @param id 主键 83 | * @return 是否成功 84 | */ 85 | @Override 86 | public boolean deleteById(Integer id) { 87 | return this.groupMsgContentDao.deleteById(id) > 0; 88 | } 89 | 90 | @Override 91 | public RespPageBean getAllGroupMsgContentByPage(Integer page, Integer size, String nickname, Integer type, Date[] dateScope) { 92 | if (page!=null&&size!=null){ 93 | page=(page-1)*size; 94 | } 95 | List allGroupMsgContentByPage = groupMsgContentDao.getAllGroupMsgContentByPage(page, size, nickname, type, dateScope); 96 | Long total=groupMsgContentDao.getTotal(nickname, type, dateScope); 97 | RespPageBean respPageBean = new RespPageBean(); 98 | respPageBean.setData(allGroupMsgContentByPage); 99 | respPageBean.setTotal(total); 100 | return respPageBean; 101 | } 102 | 103 | @Override 104 | public Integer deleteGroupMsgContentByIds(Integer[] ids) { 105 | return groupMsgContentDao.deleteGroupMsgContentByIds(ids); 106 | } 107 | 108 | /** 109 | * 处理群聊记录的导出 110 | * @param response 111 | * @throws IOException 112 | */ 113 | @Override 114 | public void handleDownload(HttpServletResponse response) throws IOException { 115 | response.setContentType("application/vnd.ms-excel"); 116 | response.setCharacterEncoding("utf-8"); 117 | //设置文件信息 这里URLEncoder.encode可以防止中文乱码 118 | String fileName = URLEncoder.encode("群聊记录", "UTF-8").replaceAll("\\+", "%20"); 119 | response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileName + ".xlsx"); 120 | RespPageBean allGroupMsgContentByPage = getAllGroupMsgContentByPage(null, null, null, null, null); 121 | List data = (List) allGroupMsgContentByPage.getData(); 122 | //转化数据为用于Excel导出的格式 123 | // List convertedData = data.stream().map(item -> { 124 | // try { 125 | // return GroupMsgContent.convertEntityToData(item); 126 | // } catch (MalformedURLException e) { 127 | // e.printStackTrace(); 128 | // } 129 | // return new GroupMsgContentData(); 130 | // }).collect(Collectors.toList()); 131 | 132 | //写出数据到HttpServletResponse中 133 | //EasyExcel.write(response.getOutputStream(),GroupMsgContentData.class).sheet("sheet1").doWrite(convertedData); 134 | EasyExcel.write(response.getOutputStream(),GroupMsgContent.class).sheet("sheet1").doWrite(data); 135 | 136 | } 137 | 138 | } 139 | -------------------------------------------------------------------------------- /subtlechat-web/src/main/java/top/javahai/subtlechat/service/impl/MailSendLogServiceImpl.java: -------------------------------------------------------------------------------- 1 | package top.javahai.subtlechat.service.impl; 2 | 3 | import top.javahai.subtlechat.api.entity.MailSendLog; 4 | import top.javahai.subtlechat.dao.MailSendLogDao; 5 | import top.javahai.subtlechat.service.MailSendLogService; 6 | import org.springframework.stereotype.Service; 7 | 8 | import javax.annotation.Resource; 9 | import java.util.Date; 10 | import java.util.List; 11 | 12 | /** 13 | * (MailSendLog)表服务实现类 14 | * 15 | * @author makejava 16 | * @since 2020-10-02 14:40:33 17 | */ 18 | @Service("mailSendLogService") 19 | public class MailSendLogServiceImpl implements MailSendLogService { 20 | @Resource 21 | private MailSendLogDao mailSendLogDao; 22 | 23 | /** 24 | * 通过ID查询单条数据 25 | * 26 | * @param msgId 主键 27 | * @return 实例对象 28 | */ 29 | @Override 30 | public MailSendLog queryById(String msgId) { 31 | return this.mailSendLogDao.queryById(msgId); 32 | } 33 | 34 | /** 35 | * 查询多条数据 36 | * 37 | * @param offset 查询起始位置 38 | * @param limit 查询条数 39 | * @return 对象列表 40 | */ 41 | @Override 42 | public List queryAllByLimit(int offset, int limit) { 43 | return this.mailSendLogDao.queryAllByLimit(offset, limit); 44 | } 45 | 46 | /** 47 | * 新增数据 48 | * 49 | * @param mailSendLog 实例对象 50 | * @return 实例对象 51 | */ 52 | @Override 53 | public MailSendLog insert(MailSendLog mailSendLog) { 54 | this.mailSendLogDao.insert(mailSendLog); 55 | return mailSendLog; 56 | } 57 | 58 | /** 59 | * 修改数据 60 | * 61 | * @param mailSendLog 实例对象 62 | * @return 实例对象 63 | */ 64 | @Override 65 | public MailSendLog update(MailSendLog mailSendLog) { 66 | this.mailSendLogDao.update(mailSendLog); 67 | return this.queryById(mailSendLog.getMsgId()); 68 | } 69 | 70 | /** 71 | * 通过主键删除数据 72 | * 73 | * @param msgId 主键 74 | * @return 是否成功 75 | */ 76 | @Override 77 | public boolean deleteById(String msgId) { 78 | return this.mailSendLogDao.deleteById(msgId) > 0; 79 | } 80 | 81 | @Override 82 | public void updateMailSendLogStatus(String msgId, int i) { 83 | this.mailSendLogDao.updateMailSendLogStatus(msgId,i); 84 | } 85 | 86 | @Override 87 | public List getMailSendLogsByStatus(Integer delivering) { 88 | return this.mailSendLogDao.getMailSendLogsByStatus(delivering); 89 | } 90 | 91 | @Override 92 | public void updateCount(String msgId, Date date) { 93 | this.mailSendLogDao.updateCount(msgId,date); 94 | } 95 | 96 | @Override 97 | public String getMsgById(String msgId) { 98 | return this.mailSendLogDao.getMsgById(msgId); 99 | } 100 | 101 | 102 | } 103 | -------------------------------------------------------------------------------- /subtlechat-web/src/main/java/top/javahai/subtlechat/service/impl/UserServiceImpl.java: -------------------------------------------------------------------------------- 1 | package top.javahai.subtlechat.service.impl; 2 | 3 | import org.springframework.security.core.userdetails.UserDetails; 4 | import org.springframework.security.core.userdetails.UserDetailsService; 5 | import org.springframework.security.core.userdetails.UsernameNotFoundException; 6 | import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; 7 | import top.javahai.subtlechat.dao.UserDao; 8 | import top.javahai.subtlechat.api.entity.RespPageBean; 9 | import top.javahai.subtlechat.api.entity.User; 10 | import top.javahai.subtlechat.service.UserService; 11 | import org.springframework.stereotype.Service; 12 | import top.javahai.subtlechat.api.utils.UserUtil; 13 | 14 | import javax.annotation.Resource; 15 | import java.util.List; 16 | 17 | /** 18 | * (User)表服务实现类 19 | * 20 | * @author makejava 21 | * @since 2020-06-16 11:37:09 22 | */ 23 | @Service("userService") 24 | public class UserServiceImpl implements UserService, UserDetailsService { 25 | @Resource 26 | private UserDao userDao; 27 | 28 | /** 29 | * 根据用户名进行登录 30 | * @param username 31 | * @return 32 | * @throws UsernameNotFoundException 33 | */ 34 | @Override 35 | public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { 36 | User user = userDao.loadUserByUsername(username); 37 | if (user==null){ 38 | throw new UsernameNotFoundException("用户不存在"); 39 | } 40 | return user; 41 | } 42 | 43 | /** 44 | * 获取除了当前用户的所有user表的数据 45 | * @return 46 | */ 47 | @Override 48 | public List getUsersWithoutCurrentUser() { 49 | return userDao.getUsersWithoutCurrentUser(UserUtil.getCurrentUser().getId()); 50 | } 51 | /** 52 | * 设置用户当前状态为在线 53 | * @param id 用户id 54 | */ 55 | @Override 56 | public void setUserStateToOn(Integer id) { 57 | userDao.setUserStateToOn(id); 58 | } 59 | /** 60 | * 设置用户当前状态为离线 61 | * @param id 用户id 62 | */ 63 | @Override 64 | public void setUserStateToLeave(Integer id) { 65 | userDao.setUserStateToLeave(id); 66 | } 67 | 68 | /** 69 | * 通过ID查询单条数据 70 | * 71 | * @param id 主键 72 | * @return 实例对象 73 | */ 74 | @Override 75 | public User queryById(Integer id) { 76 | return this.userDao.queryById(id); 77 | } 78 | 79 | /** 80 | * 查询多条数据 81 | * 82 | * @param offset 查询起始位置 83 | * @param limit 查询条数 84 | * @return 对象列表 85 | */ 86 | @Override 87 | public List queryAllByLimit(int offset, int limit) { 88 | return this.userDao.queryAllByLimit(offset, limit); 89 | } 90 | 91 | /** 92 | * 新增数据 93 | * 94 | * @param user 实例对象 95 | * @return 实例对象 96 | */ 97 | @Override 98 | public Integer insert(User user) { 99 | //对密码进行加密 100 | BCryptPasswordEncoder encoder = new BCryptPasswordEncoder(); 101 | String encodePass = encoder.encode(user.getPassword()); 102 | user.setPassword(encodePass); 103 | user.setUserStateId(2); 104 | user.setEnabled(true); 105 | user.setLocked(false); 106 | return this.userDao.insert(user); 107 | } 108 | 109 | /** 110 | * 修改数据 111 | * 112 | * @param user 实例对象 113 | * @return 实例对象 114 | */ 115 | @Override 116 | public Integer update(User user) { 117 | return this.userDao.update(user); 118 | } 119 | 120 | /** 121 | * 通过主键删除数据 122 | * 123 | * @param id 主键 124 | * @return 是否成功 125 | */ 126 | @Override 127 | public boolean deleteById(Integer id) { 128 | return this.userDao.deleteById(id) > 0; 129 | } 130 | 131 | @Override 132 | public Integer checkUsername(String username) { 133 | return userDao.checkUsername(username); 134 | } 135 | 136 | @Override 137 | public Integer checkNickname(String nickname) { 138 | return userDao.checkNickname(nickname); 139 | } 140 | 141 | @Override 142 | public RespPageBean getAllUserByPage(Integer page, Integer size,String keyword,Integer isLocked) { 143 | if (page!=null&&size!=null){ 144 | page=(page-1)*size;//起始下标 145 | } 146 | //获取用户数据 147 | List userList=userDao.getAllUserByPage(page,size,keyword,isLocked); 148 | //获取用户数据的总数 149 | Long total=userDao.getTotal(keyword,isLocked); 150 | RespPageBean respPageBean = new RespPageBean(); 151 | respPageBean.setData(userList); 152 | respPageBean.setTotal(total); 153 | return respPageBean; 154 | } 155 | 156 | @Override 157 | public Integer changeLockedStatus(Integer id, Boolean isLocked) { 158 | return userDao.changeLockedStatus(id,isLocked); 159 | } 160 | 161 | @Override 162 | public Integer deleteByIds(Integer[] ids) { 163 | return userDao.deleteByIds(ids); 164 | } 165 | 166 | } 167 | -------------------------------------------------------------------------------- /subtlechat-web/src/main/java/top/javahai/subtlechat/service/impl/UserStateServiceImpl.java: -------------------------------------------------------------------------------- 1 | package top.javahai.subtlechat.service.impl; 2 | 3 | import top.javahai.subtlechat.api.entity.UserState; 4 | import top.javahai.subtlechat.dao.UserStateDao; 5 | import top.javahai.subtlechat.service.UserStateService; 6 | import org.springframework.stereotype.Service; 7 | 8 | import javax.annotation.Resource; 9 | import java.util.List; 10 | 11 | /** 12 | * (UserState)表服务实现类 13 | * 14 | * @author makejava 15 | * @since 2020-06-16 11:36:02 16 | */ 17 | @Service("userStateService") 18 | public class UserStateServiceImpl implements UserStateService { 19 | @Resource 20 | private UserStateDao userStateDao; 21 | 22 | /** 23 | * 通过ID查询单条数据 24 | * 25 | * @param id 主键 26 | * @return 实例对象 27 | */ 28 | @Override 29 | public UserState queryById(Integer id) { 30 | return this.userStateDao.queryById(id); 31 | } 32 | 33 | /** 34 | * 查询多条数据 35 | * 36 | * @param offset 查询起始位置 37 | * @param limit 查询条数 38 | * @return 对象列表 39 | */ 40 | @Override 41 | public List queryAllByLimit(int offset, int limit) { 42 | return this.userStateDao.queryAllByLimit(offset, limit); 43 | } 44 | 45 | /** 46 | * 新增数据 47 | * 48 | * @param userState 实例对象 49 | * @return 实例对象 50 | */ 51 | @Override 52 | public UserState insert(UserState userState) { 53 | this.userStateDao.insert(userState); 54 | return userState; 55 | } 56 | 57 | /** 58 | * 修改数据 59 | * 60 | * @param userState 实例对象 61 | * @return 实例对象 62 | */ 63 | @Override 64 | public UserState update(UserState userState) { 65 | this.userStateDao.update(userState); 66 | return this.queryById(userState.getId()); 67 | } 68 | 69 | /** 70 | * 通过主键删除数据 71 | * 72 | * @param id 主键 73 | * @return 是否成功 74 | */ 75 | @Override 76 | public boolean deleteById(Integer id) { 77 | return this.userStateDao.deleteById(id) > 0; 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /subtlechat-web/src/main/java/top/javahai/subtlechat/service/impl/VerifyCodeServiceImpl.java: -------------------------------------------------------------------------------- 1 | package top.javahai.subtlechat.service.impl; 2 | 3 | import org.springframework.amqp.rabbit.connection.CorrelationData; 4 | import org.springframework.amqp.rabbit.core.RabbitTemplate; 5 | import org.springframework.beans.factory.annotation.Autowired; 6 | import org.springframework.beans.factory.annotation.Value; 7 | import org.springframework.stereotype.Service; 8 | import top.javahai.subtlechat.api.entity.MailConstants; 9 | import top.javahai.subtlechat.api.entity.MailSendLog; 10 | import top.javahai.subtlechat.api.utils.JsonUtil; 11 | import top.javahai.subtlechat.service.MailSendLogService; 12 | import top.javahai.subtlechat.service.VerifyCodeService; 13 | 14 | import java.util.Date; 15 | import java.util.Random; 16 | import java.util.UUID; 17 | 18 | /** 19 | * @author Hai 20 | * @date 2020/10/2 - 23:27 21 | */ 22 | @Service("verifyCodeService") 23 | public class VerifyCodeServiceImpl implements VerifyCodeService { 24 | @Autowired 25 | RabbitTemplate rabbitTemplate; 26 | 27 | @Autowired 28 | MailSendLogService mailSendLogService; 29 | 30 | @Value("${mail.exchange:mail-exchange}") 31 | private String mailExchange; 32 | 33 | @Value("${mail.route.verifyCode:mail-route-verifyCode}") 34 | private String mailRouteVerifyCode; 35 | 36 | @Override 37 | public String getVerifyCode() { 38 | StringBuilder code=new StringBuilder(); 39 | for (int i = 0; i <4; i++) { 40 | code.append(new Random().nextInt(10)); 41 | } 42 | return code.toString(); 43 | } 44 | 45 | @Override 46 | public void sendVerifyCodeMail(String code) { 47 | //添加消息记录 48 | String msgId = UUID.randomUUID().toString(); 49 | MailSendLog mailSendLog = new MailSendLog(); 50 | mailSendLog.setMsgId(msgId); 51 | mailSendLog.setContent(code); 52 | mailSendLog.setContentType(MailConstants.VERIFY_CODE_TYPE); 53 | mailSendLog.setCount(1); 54 | mailSendLog.setCreateTime(new Date()); 55 | mailSendLog.setTryTime(new Date(System.currentTimeMillis()+1000*10*MailConstants.MEG_TIMEOUT)); 56 | mailSendLog.setUpdateTime(new Date()); 57 | mailSendLog.setExchange(mailExchange); 58 | mailSendLog.setRouteKey(mailRouteVerifyCode); 59 | mailSendLog.setStatus(MailConstants.DELIVERING); 60 | mailSendLogService.insert(mailSendLog); 61 | 62 | rabbitTemplate.convertAndSend(mailExchange,mailRouteVerifyCode,code,new CorrelationData(msgId)); 63 | 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /subtlechat-web/src/main/java/top/javahai/subtlechat/task/MailSendTask.java: -------------------------------------------------------------------------------- 1 | package top.javahai.subtlechat.task; 2 | 3 | import org.springframework.amqp.rabbit.connection.CorrelationData; 4 | import org.springframework.amqp.rabbit.core.RabbitTemplate; 5 | import org.springframework.beans.factory.annotation.Autowired; 6 | import org.springframework.beans.factory.annotation.Value; 7 | import org.springframework.scheduling.annotation.Scheduled; 8 | import org.springframework.stereotype.Component; 9 | import top.javahai.subtlechat.api.entity.MailConstants; 10 | import top.javahai.subtlechat.api.entity.MailSendLog; 11 | import top.javahai.subtlechat.service.MailSendLogService; 12 | 13 | import java.util.Date; 14 | import java.util.List; 15 | 16 | /** 17 | * @author Hai 18 | * @date 2020/10/2 - 15:07 19 | */ 20 | @Component 21 | public class MailSendTask { 22 | @Autowired 23 | MailSendLogService mailSendLogService; 24 | @Autowired 25 | RabbitTemplate rabbitTemplate; 26 | 27 | @Scheduled(cron = "0/10 * * * * ?") 28 | public void mailSendTask() { 29 | //TODO 这里每十秒就查询一次,可以考虑使用视图和索引提高效率 30 | //获取发送失败且到达指定重试时间的消息记录 31 | List mailSendLogList = mailSendLogService.getMailSendLogsByStatus(MailConstants.DELIVERING); 32 | mailSendLogList.forEach(mailSendLog -> { 33 | if (mailSendLog.getCount() > MailConstants.MAX_TRY_COUNT) { 34 | //更新状态为发送失败 35 | mailSendLogService.updateMailSendLogStatus(mailSendLog.getMsgId(), MailConstants.FAILURE); 36 | } else { 37 | //更新消息投递的尝试次数和时间 38 | mailSendLogService.updateCount(mailSendLog.getMsgId(), new Date()); 39 | //获取消息 40 | String message=mailSendLogService.getMsgById(mailSendLog.getMsgId()); 41 | //再次投递消息 42 | rabbitTemplate.convertAndSend(mailSendLog.getExchange(),mailSendLog.getRouteKey(), message, new CorrelationData(mailSendLog.getMsgId())); 43 | 44 | } 45 | }); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /subtlechat-web/src/main/resources/application-dev.properties: -------------------------------------------------------------------------------- 1 | #数据库配置 2 | spring.datasource.url=jdbc:mysql://localhost/subtlechat 3 | spring.datasource.type=com.alibaba.druid.pool.DruidDataSource 4 | spring.datasource.username= 5 | #开发环境密码 6 | spring.datasource.password= 7 | #sql日志显示 8 | mybatis.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl 9 | #mapper文件位置配置 10 | mybatis.mapper-locations=classpath:mapper/*.xml 11 | #端口号配置 12 | server.port=8082 13 | #FastDFS文件服务器的主机名 14 | fastdfs.nginx.host= 15 | 16 | #RabbitMQ的配置 17 | spring.rabbitmq.host= 18 | spring.rabbitmq.port= 19 | spring.rabbitmq.username= 20 | spring.rabbitmq.password= 21 | spring.rabbitmq.virtual-host=/subtlechat 22 | #将消息确认投递到交换机的确认类型改为交互 23 | spring.rabbitmq.publisher-returns=true 24 | spring.rabbitmq.publisher-confirm-type=correlated 25 | 26 | 27 | -------------------------------------------------------------------------------- /subtlechat-web/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | #选择激活的配置文件 2 | spring.profiles.active=dev 3 | 4 | 5 | -------------------------------------------------------------------------------- /subtlechat-web/src/main/resources/mapper/AdminDao.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 17 | 18 | 24 | 25 | 26 | 32 | 33 | 34 | 56 | 57 | 58 | 59 | insert into subtlechat.admin(username, nickname, password, user_profile) 60 | values (#{username}, #{nickname}, #{password}, #{userProfile}) 61 | 62 | 63 | 64 | 65 | update subtlechat.admin 66 | 67 | 68 | username = #{username}, 69 | 70 | 71 | nickname = #{nickname}, 72 | 73 | 74 | password = #{password}, 75 | 76 | 77 | user_profile = #{userProfile}, 78 | 79 | 80 | where id = #{id} 81 | 82 | 83 | 84 | 85 | delete from subtlechat.admin where id = #{id} 86 | 87 | 88 | 89 | -------------------------------------------------------------------------------- /subtlechat-web/src/main/resources/mapper/FeedbackDao.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 20 | 21 | 22 | 28 | 29 | 30 | 52 | 53 | 54 | 55 | insert into subtlechat.feedback(id,user_id, username, nickname, content) 56 | values (#{id},#{userId}, #{username}, #{nickname}, #{content}) 57 | 58 | 59 | 60 | 61 | update subtlechat.feedback 62 | 63 | 64 | user_id = #{userId}, 65 | 66 | 67 | username = #{username}, 68 | 69 | 70 | nickname = #{nickname}, 71 | 72 | 73 | content = #{content}, 74 | 75 | 76 | where id = #{id} 77 | 78 | 79 | 80 | 81 | delete from subtlechat.feedback where id = #{id} 82 | 83 | 84 | 85 | -------------------------------------------------------------------------------- /subtlechat-web/src/main/resources/mapper/GroupMsgContentDao.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 22 | 23 | 24 | 32 | 33 | 34 | 62 | 63 | 64 | 65 | insert into subtlechat.group_msg_content(from_id, from_name, from_profile, create_time, content, message_type_id) 66 | values (#{fromId}, #{fromName}, #{fromProfile}, #{createTime}, #{content}, #{messageTypeId}) 67 | 68 | 69 | 70 | 71 | update subtlechat.group_msg_content 72 | 73 | 74 | from_id = #{fromId}, 75 | 76 | 77 | from_name = #{fromName}, 78 | 79 | 80 | from_profile = #{fromProfile}, 81 | 82 | 83 | create_time = #{createTime}, 84 | 85 | 86 | content = #{content}, 87 | 88 | 89 | message_type_id = #{messageTypeId}, 90 | 91 | 92 | where id = #{id} 93 | 94 | 95 | 96 | 97 | delete from subtlechat.group_msg_content where id = #{id} 98 | 99 | 100 | 115 | 127 | 128 | delete from group_msg_content where id in 129 | 130 | #{id} 131 | 132 | 133 | 134 | -------------------------------------------------------------------------------- /subtlechat-web/src/main/resources/mapper/MailSendLogDao.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 25 | 26 | 27 | 33 | 34 | 35 | 72 | 73 | 74 | 75 | insert into subtlechat.mail_send_log(msg_id,content_type, content, status, route_key, exchange, count, try_time, create_time, update_time) 76 | values (#{msgId},#{contentType}, #{content}, #{status}, #{routeKey}, #{exchange}, #{count}, #{tryTime}, #{createTime}, #{updateTime}) 77 | 78 | 79 | 80 | 81 | update subtlechat.mail_send_log 82 | 83 | 84 | content_type = #{contentType}, 85 | 86 | 87 | content = #{content}, 88 | 89 | 90 | status = #{status}, 91 | 92 | 93 | route_key = #{routeKey}, 94 | 95 | 96 | exchange = #{exchange}, 97 | 98 | 99 | count = #{count}, 100 | 101 | 102 | try_time = #{tryTime}, 103 | 104 | 105 | create_time = #{createTime}, 106 | 107 | 108 | update_time = #{updateTime}, 109 | 110 | 111 | where msg_id = #{msgId} 112 | 113 | 114 | 115 | 116 | delete from subtlechat.mail_send_log where msg_id = #{msgId} 117 | 118 | 119 | 120 | update subtlechat.mail_send_log set status=#{status} where msg_id=#{msgId} 121 | 122 | 123 | 126 | 127 | 128 | update subtlechat.mail_send_log set update_time=#{date},count=count+1 where msg_id=#{msgId} 129 | 130 | 131 | 134 | 135 | -------------------------------------------------------------------------------- /subtlechat-web/src/main/resources/mapper/UserDao.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 19 | 20 | 21 | 24 | 25 | 26 | 32 | 33 | 34 | 40 | 41 | 42 | 73 | 74 | 75 | 76 | insert into subtlechat.user(username, nickname, password, user_profile, user_state_id, is_enabled, is_locked) 77 | values (#{username}, #{nickname}, #{password}, #{userProfile}, #{userStateId}, #{isEnabled}, #{isLocked}) 78 | 79 | 80 | 81 | 82 | update subtlechat.user 83 | 84 | 85 | username = #{username}, 86 | 87 | 88 | nickname = #{nickname}, 89 | 90 | 91 | password = #{password}, 92 | 93 | 94 | user_profile = #{userProfile}, 95 | 96 | 97 | user_state_id = #{userStateId}, 98 | 99 | 100 | is_enabled = #{isEnabled}, 101 | 102 | 103 | is_locked = #{isLocked}, 104 | 105 | 106 | where id = #{id} 107 | 108 | 109 | 110 | 111 | delete from subtlechat.user where id = #{id} 112 | 113 | 114 | 115 | update subtlechat.user set user_state_id=1 where id=#{id} 116 | 117 | 118 | update subtlechat.user set user_state_id=2 where id=#{id} 119 | 120 | 123 | 126 | 127 | 139 | 148 | 149 | update user set is_locked=#{isLocked} where id=#{id} 150 | 151 | 152 | delete from user where id in 153 | 154 | #{id} 155 | 156 | 157 | 158 | -------------------------------------------------------------------------------- /subtlechat-web/src/main/resources/mapper/UserStateDao.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 17 | 18 | 19 | 25 | 26 | 27 | 40 | 41 | 42 | 43 | insert into subtlechat.user_state(name) 44 | values (#{name}) 45 | 46 | 47 | 48 | 49 | update subtlechat.user_state 50 | 51 | 52 | name = #{name}, 53 | 54 | 55 | where id = #{id} 56 | 57 | 58 | 59 | 60 | delete from subtlechat.user_state where id = #{id} 61 | 62 | 63 | 64 | -------------------------------------------------------------------------------- /subtlechat-web/src/test/java/top/javahai/subtlechat/SubtleChatWebApplicationTests.java: -------------------------------------------------------------------------------- 1 | package top.javahai.subtlechat; 2 | 3 | import com.github.binarywang.java.emoji.EmojiConverter; 4 | import org.junit.jupiter.api.Test; 5 | import org.springframework.beans.factory.annotation.Autowired; 6 | import org.springframework.boot.test.context.SpringBootTest; 7 | import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; 8 | 9 | import java.text.SimpleDateFormat; 10 | import java.util.Date; 11 | import java.util.Random; 12 | 13 | @SpringBootTest 14 | class SubtleChatWebApplicationTests { 15 | 16 | //测试密码加密 17 | @Test 18 | void contextLoads() { 19 | BCryptPasswordEncoder encoder=new BCryptPasswordEncoder(); 20 | String encode = encoder.encode("123"); 21 | System.out.println(encode); 22 | } 23 | 24 | @Test 25 | void test01(){ 26 | SimpleDateFormat simpleDateFormat=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); 27 | System.out.println(simpleDateFormat.format(new Date())); 28 | System.out.println(new Date()); 29 | } 30 | //测试emoji的转码 31 | @Test 32 | void test02(){ 33 | EmojiConverter emojiConverter = EmojiConverter.getInstance(); 34 | String str="\uE423 \uE424 \uE425An ??awesome ??string with a few ??emojis!"; 35 | String html = emojiConverter.toHtml(str); 36 | System.out.println(html); 37 | } 38 | } 39 | --------------------------------------------------------------------------------