1500字范文,内容丰富有趣,写作好帮手!
1500字范文 > 【项目实战】- 基于SpringBoot+WebScoket+Vue+ElementUI实现一个网页版地球聊天软件

【项目实战】- 基于SpringBoot+WebScoket+Vue+ElementUI实现一个网页版地球聊天软件

时间:2019-02-16 22:46:12

相关推荐

【项目实战】- 基于SpringBoot+WebScoket+Vue+ElementUI实现一个网页版地球聊天软件

项目介绍

项目已开源gitee:

/gdones/gd-webchart

技术选型

后端:SpringBoot(WEB)+ JWT + MyBatis-plus +MySql5.7 + Redis + SpringFileStroage

前端:Vue2.0 + ElementUI

技术难点

多端聊天(长链接的实现)- WebSocket文件存储、消息的存储 - IO\Reids\Mysql登录权限的验证(完整版登录功能)- JWT\行为验证码\拦截器、过滤器(SpringBoot)

后端框架的搭建

1. SpringBoot框架构建

1.下载工具

使用idea工具(企业版)

下载地址:/idea/download/#section=windows

找破解工具破解

2.配置maven工具

下载地址:/download.cgi

1.下载解压好配置环境变量:

配置mavne-》bin目录添加到path环境变量中

2. 修改maven的配置:

<?xml version="1.0" encoding="UTF-8"?><settings xmlns="/SETTINGS/1.0.0"xmlns:xsi="/2001/XMLSchema-instance"xsi:schemaLocation="/SETTINGS/1.0.0 /xsd/settings-1.0.0.xsd"><!-- jar包下载的位置 --> <localRepository>F:\GjbSVN\maven仓库</localRepository><pluginGroups></pluginGroups><proxies></proxies><servers></servers><mirrors><!-- 修改mavn仓库的镜像资源位置 --><mirror><id>nexus-aliyun</id><mirrorOf>*,!jeecg,!jeecg-snapshots,!getui-nexus</mirrorOf><name>Nexus aliyun</name><url>/nexus/content/groups/public</url></mirror> </mirrors><profiles></profiles></settings>

3.idea构建springBoot项目

此时会打开项目窗口,然后要进行idea的maven配置修改

完成后项目会从新下载相关的jar包,稍等片刻

接下来启动程序:

2. 网络接口的编写测试

controller类编写

/*** 模块名称:测试控制器类* 模块类型:Controller* 编码人:高靖博* 创建时间:/4/13* 联系电话:18587388612*/// 协议名称:// 服务器ip地址:服务端口号/资源地址// http://localhost:9010/test/test1@RestController@RequestMapping("/test")public class TestController {// 只允许GET类型请求// 查询:GET 提交或加密: POST 修改:PUT 删除:DELETE@GetMapping("/test1")public String test1(){return "<h1>只因你太美!</h1>";}// 返回值类型只要不是String,都会将对象转换为json数据返回到前端@GetMapping("/test2")public MyResult test2(){return new MyResult();}}

3.SpringBoot集成MyBatis-plus

1.打开pom.xml引入依赖

<!-- 新:版本升级 mybatis-plus --><dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-boot-starter</artifactId><version>3.5.1</version></dependency><!-- freemarker-模板引擎 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-freemarker</artifactId></dependency><!-- mp代码生成器 --><dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-generator</artifactId><version>3.5.1</version></dependency><!-- mysql驱动 --><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>8.0.21</version></dependency><!-- 阿里fastjson --><dependency><groupId>com.alibaba</groupId><artifactId>fastjson</artifactId><version>1.2.80</version></dependency>

2. 配置mybatis-plus

在resources目录下,将application.properties文件删除改为application.yml文件

# 修改springBoot端口号server:port: 9010# mybatis-plus相关内容mybatis-plus:#dto别名映射 !!!!!!!需要修改type-aliases-package: com.webchartserver#xml文件路径映射(xml文件要和接口文件同名)!!!!!!!需要修改mapper-locations: com/webchartserver/**/dao/mapper/**.xmlconfiguration:log-impl: org.apache.ibatis.logging.stdout.StdOutImpl #开启日志(需要引入log4j日志框架)map-underscore-to-camel-case: false# 全局变量配置# 逻辑删除-如:每个表中都有一个通用的字段isDelete描述当前数据是否被删除,1:已删除 0:未删除global-config:db-config:# 当逻辑删除应该设置什么值:1logic-delete-value: 1logic-not-delete-value: 0logic-delete-field: isDelete # 所有表中都要有一个isDelete字段且字段类型是int类型

3.编写一个代码生成工具

package com.webchartserver.core.mpganer;import com.baomidou.mybatisplus.annotation.FieldFill;import com.baomidou.mybatisplus.annotation.IdType;import com.baomidou.mybatisplus.generator.FastAutoGenerator;import com.baomidou.mybatisplus.generator.config.rules.DateType;import com.baomidou.mybatisplus.generator.engine.FreemarkerTemplateEngine;import com.baomidou.mybatisplus.generator.fill.Column;/*** 模块名称:* 模块类型:* 编码人:高靖博* 创建时间:/4/13* 联系电话:18587388612*/public class MyBatisGer {// 数据库的连接 !!!需要修改private final static String URL = "jdbc:mysql://localhost:3306/webchart?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=Asia/Shanghai";// 数据库用户名private final static String USER_NAME = "root";// 数据库密码private final static String PWD = "cxk666";// 每个类作者的名字private final static String AUTHOR = "GaoJingBo";// 生成的代码输出的目录private final static String OUT_PUT_DIR = "D://mybatis";// 修改根包路径private final static String PARENT_PACKAGE_NAME = "com.webchartserver";// 业务模块名private final static String PARENT_MODEL_NAME = "user";// 要生成的业务表private final static String TABLE_NAME = "t_user";// 如果表名有前缀可以去除前缀private final static String PREFIX = "t_";public static void main(String[] args) {FastAutoGenerator.create(URL, USER_NAME, PWD).globalConfig(builder -> {builder.author(AUTHOR) // 设置作者.fileOverride() // 覆盖已生成文件.dateType(DateType.ONLY_DATE)// 日期类型.commentDate("yyyy-MM-dd") //公共默认日期格式.outputDir(OUT_PUT_DIR); // 指定输出目录}).packageConfig(builder -> {builder.parent(PARENT_PACKAGE_NAME) //设置父路径根包.moduleName(PARENT_MODEL_NAME) //设置模块名称.entity("dto") //dto实体.service("service") //业务接口.serviceImpl("service.impl") //业务实现.mapper("mapper") //mybatis-plus-mapper接口.xml("mapper.xml") mybatis-plus-mapper接口映射xml.controller("controller") //控制器.other("other");}).strategyConfig(builder -> {builder.controllerBuilder().enableHyphenStyle().enableRestStyle();builder.mapperBuilder().enableMapperAnnotation();builder.entityBuilder().enableLombok().logicDeleteColumnName("isDelete")// 逻辑删除表字段名.logicDeletePropertyName("isDelete")// 逻辑删除实体属性名// 添加填充规则.addTableFills(new Column("insertTime", FieldFill.INSERT)).addTableFills(new Column("updateTime", FieldFill.INSERT_UPDATE)).idType(IdType.NONE);builder.addInclude(TABLE_NAME) // 设置需要生成的表名.enableSkipView()//跳过视图.addTablePrefix(PREFIX); // 设置过滤表前缀}).templateEngine(new FreemarkerTemplateEngine()) // 使用Freemarker引擎模板,默认的是Velocity引擎模板.execute();}}

4. 准备一个数据表,进行代码生成

用户信息表

用户信息表-ER图

CREATE TABLE `t_user` (`userID` varchar(80) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '用户id',`insertID` varchar(30) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '记录插入者帐号',`insertIP` varchar(80) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '记录插入者IP',`updateTime` datetime(0) NULL DEFAULT NULL COMMENT '记录更新时间',`updateID` varchar(30) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '记录更新者帐号',`updateIP` varchar(80) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '记录更新者IP',`isDelete` int(11) NULL DEFAULT 0 COMMENT '是否删除',`comment` varchar(250) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '备注',`code` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '编号',`realName` varchar(20) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '真实姓名',`nickName` varchar(80) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '昵称',`sex` int(11) NULL DEFAULT NULL COMMENT '性别:1:男 2:女 3:保密',`tellNumber` varchar(80) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '手机号码',PRIMARY KEY (`userID`) USING BTREE) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;

5. SpringBoot集成数据源连接池-阿里巴巴druid

数据库连接池的作用:

减少创建连接的io过程使用连接的方式更简单,管理也更加简单满足高并发场景下重复读写创建连接的业务

1.引入依赖

<!-- 数据源依赖 --><dependency><groupId>com.alibaba</groupId><artifactId>druid-spring-boot-starter</artifactId><version>1.1.10</version></dependency>

2. 在application.yml中配置druid连接池

# spring框架配置spring:# 数据源配置datasource:# druid连接池type: com.alibaba.druid.pool.DruidDataSource# mysql驱动driver-class-name: com.mysql.cj.jdbc.Driver# 数据库连接地址 !!!! 需要修改url: jdbc:mysql://localhost:3306/webchart?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=Asia/Shanghai# 用户名、密码username: rootpassword: cxk666# druid连接池配置# 初始化连接池最大值,连接中活跃数量最大值initial-size: 10max-active: 8# 获取连接等待的最长时间(毫秒)max-wait: 60000# 申请连接的时候检测,如果空闲时间大于timeBetweenEvictionRunsMillis,执行validationQuery检测连接是否有效。test-while-idle: true# 既作为检测的间隔时间又作为testWhileIdel执行的依据time-between-eviction-runs-millis: 60000# 销毁线程时检测当前连接的最后活动时间和当前时间差大于该值时,关闭当前连接(配置连接在池中的最小生存时间)min-evictable-idle-time-millis: 30000# 用来检测数据库连接是否有效的sql 必须是一个查询语句(oracle中为 select 1 from dual)validation-query: select 1 from dual# 申请连接时会执行validationQuery检测连接是否有效,开启会降低性能,默认为truetest-on-borrow: false# 归还连接时会执行validationQuery检测连接是否有效,开启会降低性能,默认为truetest-on-return: false# 是否缓存preparedStatement, 也就是PSCache,PSCache对支持游标的数据库性能提升巨大,比如说oracle,在mysql下建议关闭。pool-prepared-statements: false# 置监控统计拦截的filters,去掉后监控界面sql无法统计,stat: 监控统计、Slf4j:日志记录、waLL: 防御sqL注入filters: stat,wall,slf4j# 要启用PSCache,必须配置大于0,当大于0时,poolPreparedStatements自动触发修改为true。在Druid中,不会存在Oracle下PSCache占用内存过多的问题,可以把这个数值配置大一些,比如说100max-pool-prepared-statement-per-connection-size: -1# 合并多个DruidDataSource的监控数据use-global-data-source-stat: true# 通过connectProperties属性来打开mergeSql功能;慢SQL记录connect-properties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=5000web-stat-filter:# 是否启用StatFilter默认值trueenabled: true# 添加过滤规则url-pattern: /*# 忽略过滤的格式exclusions: /druid/*,*.js,*.gif,*.jpg,*.png,*.css,*.icostat-view-servlet:# 是否启用StatViewServlet默认值trueenabled: true# 访问路径为/druid时,跳转到StatViewServlet !!!! 需要修改url-pattern: /druid/*# 是否能够重置数据reset-enable: false# 需要账号密码才能访问控制台,默认为rootlogin-username: adminlogin-password: 123456# IP白名单allow: 127.0.0.1# IP黑名单(共同存在时,deny优先于allow)deny:

启动项目,测试druid连接池是否正常:

http://localhost:9010/druid/index.html

4.SpringBoot+MP的低代码CRUD

package com.webchartserver.user.controller;import com.webchartserver.core.dto.MyResult;import com.webchartserver.user.dto.User;import com.webchartserver.user.service.IUserService;import lombok.extern.slf4j.Slf4j;import org.springframework.web.bind.annotation.*;import javax.annotation.Resource;/**** 用户信息管理* @author GaoJingBo* @since -04-13*/@RestController@RequestMapping("/user")@Slf4jpublic class UserController {// 注入业务层实现@Resource(name = "userServiceImpl")private IUserService userService;/*** 用户添加* @param user 要添加的用户信息* @return*/@PostMapping("/add")public MyResult add(@RequestBody User user){log.debug("-- 添加用户");MyResult result = new MyResult();boolean save = userService.save(user);result.setMsg("用户注册成功!");return result;}/*** 修改用户* @param user 要修改的用户信息(前端需要传递要修改的主键字段值)* @return*/@PutMapping ("/update")public MyResult update(@RequestBody User user){log.debug("-- 修改用户");MyResult result = new MyResult();boolean save = userService.updateById(user);result.setMsg("用户修改成功!");return result;}/*** 删除用户* @param pkID 传递主键字段值* @return*/@DeleteMapping ("/deletes")public MyResult deletes(String pkID){log.debug("-- 删除用户");MyResult result = new MyResult();boolean b = userService.removeById(pkID);result.setMsg("删除成功!");return result;}}

5. SpringBoot整合WebSocket

1. 引入webSocket依赖

<!-- 服务端WebSocket需要的依赖 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-websocket</artifactId></dependency>

2. 编写一个WebSocket服务配置类

搭建一个webSocket服务端

package com.webchartserver.core.config;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;import org.springframework.web.socket.server.standard.ServerEndpointExporter;/*** 模块名称: 开启WebSocket服务* 模块类型:* 编码人:高靖博* 创建时间:/4/14* 联系电话:18587388612*/@Configurationpublic class WebSocketConfig {@Beanpublic ServerEndpointExporter serverEndpointExporter() {return new ServerEndpointExporter();}}

创建一个消息转发的业务类

package com.webchartserver.core.config;import org.ponent;import javax.websocket.*;import javax.websocket.server.PathParam;import javax.websocket.server.ServerEndpoint;import java.util.concurrent.ConcurrentHashMap;import java.util.concurrent.CopyOnWriteArraySet;/*** 模块名称:WebSocket-聊天程序消息转发处理类* 模块类型:* 编码人:高靖博* 创建时间:/4/14* 联系电话:18587388612*/@Component@ServerEndpoint("/wxserver/{wxNumber}")// ws://loaclhost:9010/wxserverpublic class WebSocket {static{System.out.println("-------------------------------------------------");System.out.println("--------------WebSocket服务初始化------------------");System.out.println("-------------------------------------------------");}// 当前客户端的会话对象private Session session;// 当前客户端的微信号private String nowWxNumber;// 用来存在线连接用户信息( 线程安全 )// key: 微信号 value: 每个客户端的session对象private static ConcurrentHashMap<String, Session> sessionPool = new ConcurrentHashMap<String,Session>();// 保存每一个连接的客户端对象(在线客户端)private static CopyOnWriteArraySet<WebSocket> webSockets =new CopyOnWriteArraySet<>();/*** 当客户端连接时会触发该方法*/@OnOpenpublic void onOpen(Session session,@PathParam("wxNumber") String wxNumber){System.err.println("---客户端连接!");sessionPool.put(wxNumber,session);this.session = session;this.nowWxNumber = wxNumber;webSockets.add(this);}/*** 当客户端发送消息给服务器时触发* @param msg 客户端发送给服务器的数据内容*/@OnMessagepublic void onMsg(String msg){System.err.println("客户端发送消息:"+msg);// 遍历所有已连接到服务器的集合进行挨个发送信息for(WebSocket webSocket:webSockets){// 判断客户端是否断开连接if(webSocket.session.isOpen()==true){// 还在线webSocket.session.getAsyncRemote().sendText(msg);}}}/*** 客户端断开连接时触发*/@OnClosepublic void onClose(){System.err.println("--客户端断开连接");}/*** 当客户端发送消息或服务器端出现异常时触发* @param e*/@OnErrorpublic void onErr(Throwable e){e.printStackTrace();System.err.println("--WebSocket异常!!!!");}}

前端测试

<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>测试</title><style>/* 历史信息窗口样式 */.hsDiv{border:1px solid black;border-radius: 11px;width: 100%;height: 500px;overflow: auto;box-sizing: border-box;padding: 8px;}/* 消息的时间文字样式 */.time{font-size: 10px;color:gray;}/* 消息的文字内容样式 */.msgText{color:blue;}/* 发送人信息 */.person{font-size: 7px;color:black; }</style></head><body><span id="state">离线</span><span id="qqNumber"></span><input id="nickName" placeholder="定义一个你的昵称" /><button onclick="toConect()">连接</button><hr/><button onclick="sendMsg()">发送</button><input id="msg" placeholder="请输入消息...." /><hr/><!-- 历史信息框体 --><div class="hsDiv" id="hsDiv"></div></body><script>var qqNumber;var webScoket;var htmls = ""; // 所有历史信息htmlvar nikeName = ""; // 客户端昵称// 连接到服务器function toConect(){// 生成一个唯一的数字qqNumber = parseInt(Math.random()*10000000000000);webScoket = new WebSocket("ws://localhost:9010/wxserver/"+qqNumber);// 定义一个连接成功的回调函数webScoket.onopen = function (){console.dir("-连接成功!");document.getElementById("state").innerHTML = "在线";document.getElementById("qqNumber").innerHTML = qqNumber;// 获取连接的昵称信息var nikeNames = document.getElementById("nickName").value;nikeName = nikeNames;}// 定义一个服务器发送消息给客户端的回调函数webScoket.onmessage = function(data){console.dir("-接收到消息:"+data.data);// QQ信息$消息内容$发送时间$昵称var msgArr = data.data.split("$");htmls += '<span class="time">时间:'+msgArr[2]+'</span><br/>'+'<span class="person">['+msgArr[3]+']</span><br/>'+'<span class="msgText">'+msgArr[1]+'</span>'+'<hr/>';// 动态html代码段添加进入聊天历史信息框中document.getElementById("hsDiv").innerHTML = htmls;}}// 发送消息方法function sendMsg(){// 得到要发送的信息文字var msg = document.getElementById("msg").value;// 发送消息的格式:// QQ信息$消息内容$发送时间$昵称var nowDate = new Date();var sendMsgStr = qqNumber+"$"+msg+"$"+(nowDate.getFullYear() +"-"+nowDate.getMonth()+"-"+nowDate.getDate()+" "+nowDate.getHours()+":"+nowDate.getMinutes()+":"+nowDate.getSeconds()+"$"+nikeName)webScoket.send(sendMsgStr); // 消息发送给服务器了}</script></html>

前端框架搭建

1. npm、cnpm node环境搭建vue脚手架

1. 安装node.js环境

1.进入官网

/en/

2.安装msi,安装目录到C盘

安装好后,使用cmd执行 node- v npm -v看看是否都输出了版本号

3.在除C盘外创建一个nodejsFile文件夹,创建两个文件夹 node_global和node_cache,然后运行以下命令

npm config set prefix "D:\Program Files\nodejs\node_global"npm config set cache "D:\Program Files\nodejs\node_cache"

4.检查当前系统变量中,path路径有没有叫C:\ProgramFiles\nodejs\node_modules

如果有,创建一个同名路径文件夹在C盘之外的盘符,如果没有就不用管了

在path变量中配置你的C:\Program Files\nodejs\node_modules路径

2. 安装淘宝镜像 cnpm

功能:和npm一样,npm是从海外镜像仓库下载,cnmp 是从阿里淘宝镜像仓库下载

npm install -g cnpm --registry=https://registry.

安装完成使用:cnpm -v 查看版本

3.安装webpack

npm install webpack -g

安装完成使用:npm webpack -v 查看版本

4. 下载vue脚手架

1.下载脚手架资源

cnpm install -g vue-cli@2.x

2.去到你的gloab目录查看是否有vue开头的文件

到别的文件夹下创建一个空的文件夹,在文件夹中按住shift+鼠标右键,点击在此处打开pwershell窗口
打开窗口输入:vue init webpack

5.初始化构建vue脚手架

6.运行vue项目

在项目根目录下按住shift+鼠标右键,点击在此处打开pwershell窗口,执行 npm run dev

2. vue项目中安装axios组件(ajax组件)

1.在项目目录下使用cmd执行

//1. 在项目窗口中执行cnpm install axios

代表安装成功

2.main.js配置导入相关组件

import axios from 'axios'Vue.prototype.$axios = axios //全局属性

3. 编写一个请求工具类

作用: 封装关于http请求和响应处理的代码

// 1. 导入axios组件import axios from "axios";// 导入el组件import ElementUI from 'element-ui'// 导入路由组件import router from '@/router'const service = axios.create({// get post delete putbaseURL:'/api', // 后端服务地址timeout:30000 // 请求超时时间});// http request 请求拦截器service.interceptors.request.use(config => {// 需要所有的请求都带有tokenconfig.headers.token = window.localStorage.getItem("token");return config;}, error => {// 对请求错误做些什么return Promise.reject(error);});// 响应拦截器service.interceptors.response.use(response => {// 当后端返回数据或者后端请求错误,我们需要处理相关内容if(response.status==200){// 请求发送响应成功if(response.data.code=="-1"){// 认证失败ElementUI.Notification.error({title: '系统异常',message: response.data.msg+",请重新登录"});router.push("/");}else if(response.data.code=="200"){if(response.data.msg){ElementUI.Message.success(response.data.msg);}}else if(response.data.code=="500"){ElementUI.Message.error(response.data.msg);}return response.data;}else{ElementUI.Notification.error({title: '系统异常',message: error.response.data.msg+",请联系管理员"});return response.data;}});export default service;

4.设置跨域请求问题

在vue中配置一个代理注册工具

3. 使用VSCode构建Vue项目

下载VsCode

/

组件下载

创建vue项目

创建一个空的项目文件夹使用vsCode打开这个文件夹设置vsCode语言:ctrl+shift+P 输入指令:Display language 先选择英文重启后再选择中文再重启就好了打开终端

vue init webpack

会出现错误:not promite 。。。。 vsCode终端控制台没有系统写入权限

使用本机自带的cmd窗口使用管理员权限启动

将目录跳转至项目路径再执行vue init webpack指令

5.启动项目

npm run dev

6.退出运行

ctrl+c

4. 编写第一个vue文件

<!-- Dom页面 --><template><!-- 所有的页面元素都要卸载div之内 --><div id='UserIndex'></div></template><!-- 组件js --><script>export default {name:'UserIndex',data(){}}</script><!-- CSS代码 --><style scoped></style>

使用VSCode创建一个自定义代码片段

文件–》首选项—》配置用户代码片段

{"Print to console": {"prefix": "myvue",// 代码段名称"body": [ //代码内容"<!-- Dom页面 -->","<template>","<div id=''>","","</div>","</template>","","<!-- 组件js -->","<script>","export default {","name:'',","data(){","","}","}","</script>","","<!-- CSS代码 -->","<style scoped>","","</style>"],"description": "myvue"}}

业务实现部分

1.用户注册与登录

1.用户注册功能

后端部分代码

后端接收到注册信息,需要将密码进行MD5加密

引入hutool工具包加密方法加密

<!-- hutool工具 --><dependency><groupId>cn.hutool</groupId><artifactId>hutool-all</artifactId><version>5.8.15</version></dependency>

注册controller 方法修改

@PostMapping("/add")public MyResult add(@RequestBody User user){log.debug("-- 注册用户");MyResult result = new MyResult();// 密码加密String pwd_md5Hex = DigestUtil.md5Hex(user.getPwd());user.setPwd(pwd_md5Hex);boolean save = userService.save(user);result.setMsg("用户注册成功!");return result;}

2.用户登录功能

后端代码部分

前端传递了明文的密码需要将明文密码加密后用密文去比对数据库

@PostMapping("/login")public MyResult login(@RequestBody User user){log.debug("-- 登录");MyResult result = new MyResult();// 1. 查询数据库中和用户名相同的数据QueryWrapper<User> queryWrapper = new QueryWrapper<>(); // from t_user// where nickName = ""queryWrapper.eq("nickName",user.getNickName());// 2. mp 查询 select * from t_user where nickName = "user.getNickName()"List<User> list = userService.list(queryWrapper);if(list.size()>0){// 用户名存在User dbUserData = list.get(0);String pwdMD5 = dbUserData.getPwd();// 取出数据库中保存的密码-密文String pwd_md5Hex = DigestUtil.md5Hex(user.getPwd()); // 将前端的明文密码加密比较if(pwd_md5Hex.equals(pwdMD5)){// 密码输入正确result.setCode(200);result.setMsg("登录成功!");}else{// 密码输入错误result.setCode(500);// 已错误次数累加1dbUserData.setErrCount(dbUserData.getErrCount()+1);// 剩余几次可以输入密码的机会 = errCount - 已错误的次数int lessCount = errCount - dbUserData.getErrCount();// 判断是否需要锁定if(lessCount<=0){//需要锁定dbUserData.setIsLock(1); // 设置账号锁定// 返回错误信息给前端result.setMsg("错误次数过多,账号已锁定!");}else{result.setMsg("用户名或密码错误,还剩【"+lessCount+"】次机会!");}// 更新数据库userService.updateById(dbUserData);}}else{// 用户名不存在result.setCode(500); // 业务编码500描述业务不成功result.setMsg("用户名或密码错误!");}

2. 实现系统鉴权功能

验证用户是否已经完成了登录,只有用户正常登录之后才能访问系统当中的接口

1.实现方法使用JWT框架

1. 引入jwt依赖

<dependency><groupId>com.auth0</groupId><artifactId>java-jwt</artifactId><version>3.19.0</version></dependency>

2. 创建一个JWT工具类

作用:生成token和验证token功能

package com.webchartserver.core.config;import com.auth0.jwt.JWT;import com.auth0.jwt.JWTCreator;import com.auth0.jwt.algorithms.Algorithm;import com.auth0.jwt.interfaces.DecodedJWT;import java.util.Date;/*** 模块名称:JWT权限验证工具包* 模块类型:* 编码人:高靖博* 创建时间:/4/14* 联系电话:18587388612*/public class JWTUtil {private JWTUtil(){}// 过期时间,单位秒private static final long EXP_TIME = 60 * 30L;// 秘钥关键字private static final String SECRET = "webchart";/*** 生成token* @param userName 登录用户名* @return*/// 生成token时,需要添加token信息// userName : 签名信息,保证token无法重复或者无法被篡改public static String getToken(String userName){// 创建Token构造器JWTCreator.Builder builder = JWT.create();//设置过期时间,设置什么时候过期:EXP_TIME计算一个过期的日子Date date = new Date(System.currentTimeMillis() + EXP_TIME * 1000);//创建tokenString sign = builder.withExpiresAt(date).withClaim("userName", userName).withClaim("claimDate", new Date().getTime()).sign(Algorithm.HMAC256(SECRET));return sign;}/*** 验证签名token* @param token* @return*/public static boolean verify(String token){try{DecodedJWT verify = JWT.require(Algorithm.HMAC256(SECRET)).build().verify(token);System.out.println("------- [token认证通过] ---------");System.out.println("------- userName:"+verify.getClaim("userName")+" ---------");System.out.println("------- 过期时间:"+verify.getExpiresAt()+" ---------");return true;}catch (Exception e){return false;}}}

3.创建一个拦截器拦截业务请求去验证token是否有效

编写一个验证token的拦截器

package com.webchartserver.core.intercetes;import com.alibaba.fastjson.JSON;import com.webchartserver.core.config.JWTUtil;import org.springframework.web.servlet.HandlerInterceptor;import org.springframework.web.servlet.ModelAndView;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import java.io.PrintWriter;import java.util.HashMap;import java.util.Map;/*** 模块名称:是否登录过的拦截器(用于验证token是否有效)* 模块类型:拦截器* 编码人:高靖博* 创建时间:/4/14* 联系电话:18587388612*/public class LoginInterceptor implements HandlerInterceptor {// 请求访问controller方法之前会指向性/**** @param request http请求对象* @param response http响应对象* @param handler 执行链路对象* @return 返回值: true: 拦截器放行 false:拦截器阻止* @throws Exception*/@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {response.setCharacterEncoding("UTF-8");response.setContentType("application/json; charset=utf-8");// 所有的token都要放在请求头中 headerString token = request.getHeader("token");//验证if(token==null||token==""){Map<String,String> json = new HashMap<>();json.put("msg","认证失败,token不存在!");json.put("code","-1");PrintWriter writer = response.getWriter();writer.write(JSON.toJSONString(json));writer.flush();writer.close();return false;}else{// 验证boolean verify = JWTUtil.verify(token);if(verify){return true;}else{Map<String,String> json = new HashMap<>();json.put("msg","认证失败!");json.put("code","-1");PrintWriter writer = response.getWriter();writer.write(JSON.toJSONString(json));writer.flush();writer.close();return false;}}}}

配置注册拦截器

规定那些地址会被拦截,哪些地址可以放行

package com.webchartserver.core.intercetes;import org.springframework.context.annotation.Configuration;import org.springframework.web.servlet.config.annotation.InterceptorRegistration;import org.springframework.web.servlet.config.annotation.InterceptorRegistry;import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;/*** 模块名称:配置注册拦截器类* 模块类型:配置类* 编码人:高靖博* 创建时间:/4/14* 联系电话:18587388612*/@Configurationpublic class InterceptConfig implements WebMvcConfigurer {//注册拦截器@Overridepublic void addInterceptors(InterceptorRegistry registry) {// 注册自定义的登录拦截器InterceptorRegistration ic = registry.addInterceptor(new LoginInterceptor());// 设置要拦截的路径有哪些ic.addPathPatterns("/**"); // 所有请求服务端的路径地址都会被拦截// 设置拦截器白名单ic.excludePathPatterns("/user/login/**", // 登录接口不需要拦截"/js/**", // 访问数据监控中心不需要拦截"/css/**","/imgs/**","/druid/**","/v2/**","/webjars/**");}}

修改登录接口,当登录成功时从服务器返回一个token令牌

if(pwd_md5Hex.equals(pwdMD5)){// 密码输入正确result.setCode(200);result.setMsg("登录成功!");// 要返回token令牌到前端String token = JWTUtil.getToken(user.getNickName());result.setData(token);

postman测试

3. 好友列表的添加和历史信息的记录

1. 建表语句

CREATE TABLE `t_user_f` (`infoID` varchar(80) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '记录主键',`insertID` varchar(30) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '记录插入者帐号',`insertIP` varchar(80) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '记录插入者IP',`updateTime` datetime(0) NULL DEFAULT NULL COMMENT '记录更新时间',`updateID` varchar(30) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '记录更新者帐号',`updateIP` varchar(80) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '记录更新者IP',`isDelete` int(11) NULL DEFAULT 0 COMMENT '是否删除',`comment` varchar(250) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '备注',`userID` varchar(80) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '用户id',`fUserID` varchar(80) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '好友用户id',`fNickName` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '好友昵称(用户名)',`fRealName` varchar(10) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '好友真实姓名',PRIMARY KEY (`infoID`) USING BTREE) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;CREATE TABLE `t_msg` (`infoID` varchar(80) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '记录id',`insertID` varchar(30) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '记录插入者帐号',`insertIP` varchar(80) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '记录插入者IP',`updateTime` datetime(0) NULL DEFAULT NULL COMMENT '记录更新时间',`updateID` varchar(30) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '记录更新者帐号',`updateIP` varchar(80) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '记录更新者IP',`isDelete` int(11) NULL DEFAULT 0 COMMENT '是否删除',`comment` varchar(250) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '备注',`sendUserID` varchar(80) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '发送人的用户id',`sendNickName` varchar(80) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '发送人的用户名',`saveUserID` varchar(80) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '接收人的用户id',`saveNickName` varchar(80) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '接收人的用户名称',`msg` varchar(500) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '消息内容',`saveAndSendTime` datetime(0) NULL DEFAULT NULL COMMENT '接收消息时间',PRIMARY KEY (`infoID`) USING BTREE) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;

使用mp代码生成

4. 实现聊天的敏感信息过滤

自定义工具类

package com.webchartserver.core.utils;import cn.hutool.core.collection.ConcurrentHashSet;import org.ponent;import java.io.*;/*** 敏感信息过滤* /4/18*/@Componentpublic class FilterWordsUtil {private FilterWordsUtil(){}// 敏感词汇集合private static ConcurrentHashSet<String> wordsSet = new ConcurrentHashSet<>();// 初始化加载敏感词汇static{System.out.println("------------敏感词汇过滤工具加载-------------------");loadTextFile();}/*** 加载敏感词汇文件*/private static void loadTextFile(){try {InputStream resourceAsStream = FilterWordsUtil.class.getResourceAsStream("filterword.txt");Reader reader = new InputStreamReader(resourceAsStream);BufferedReader bufferedReader = new BufferedReader(reader);String line;while ((line = bufferedReader.readLine()) != null) {wordsSet.add(line);}bufferedReader.close();} catch (IOException e) {e.printStackTrace();}}/*** 替换敏感字符* @param words 原字符串* @param replaceStr 替换的文本* @return*/public static String changeWord(String words,char replaceStr){for(String mgStr:wordsSet){if(words.indexOf(mgStr)!=-1){// 根据敏感词的长度生成*int length = mgStr.length();String repStr = "";for(int i=0;i<length;i++){repStr += replaceStr;}words = words.replaceAll(mgStr,repStr);}}return words;}}

5.前端实现表情包的选择和发送

mysql配置可以存放unicode字符文字

[client]default-character-set = utf8mb4[mysql]#设置mysql客户端默认字符集default-character-set = utf8mb4[mysqld]#服务端使用的字符集默认为8比特编码的latin1字符集character-set-client-handshake = FALSEcharacter-set-server = utf8mb4collation-server = utf8mb4_unicode_ciinit_connect='SET NAMES utf8mb4'

重启mysql服务

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。