对于一个后端开发者来说,自己去开发前端页面的各种特效和交互效果,是一件挺复杂的事情。所以对于一个较为完整的项目开发上,作为后端开发来说,使用成型的模版就是一个很好的选择。这里就使用Fly Template来构建前端页面。Fly Template是基于 layui 搭建而成,提供了全屏和固宽两类排版,并且具备响应式适配能力,可很好地作为简约型问答社区的页面支撑。
layui下载地址(非官方),官方网站已经下线了:layui下载地址(非官方)
fly template下载地址:fly template下载地址
|–html 可以直接预览的模板文件
|–res 静态资源
…|–css
…|–images
…|–layui
…|–modes 模板业务模块
|–views 动态模板参考
创建数据库与用户表,用户表主要包含一些常见的字段,例如登陆信息、头像、简介等。
CREATE
DATABASE /*!32312 IF NOT EXISTS*/`my_bbs_db` /*!40100 DEFAULT CHARACTER SET utf8 */;
USE `my_bbs_db`;
DROP TABLE IF EXISTS `tb_bbs_user`;
CREATE TABLE `tb_bbs_user` (
`user_id` bigint NOT NULL AUTO_INCREMENT COMMENT '用户主键id',
`login_name` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT '登陆名称(默认为邮箱号码)',
`password_md5` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT 'MD5加密后的密码',
`nick_name` varchar(8) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT '昵称',
`head_img_url` varchar(128) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT '头像',
`gender` varchar(4) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT '性别',
`location` varchar(4) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT '居住地',
`introduce` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT '个人简介',
`user_status` tinyint NOT NULL DEFAULT '0' COMMENT '用户状态 0=正常 1=禁言',
`last_login_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '最新登录时间',
`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '注册时间',
PRIMARY KEY (`user_id`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci ROW_FORMAT=DYNAMIC;
创建Spring Boot项目,此项目是web项目,所以开始添加web依赖即可,之后需要什么依赖就添加什么依赖。然后将fly template的文件资源添加到项目中,这样我们就可以不用自己去设计前端页面,只需要做简要修改即可。
首先主要将前端模版的css文件夹和layui文件夹的内容添加到Spring Boot项目的static文件夹下。这样就可以基本使用该前端模板的功能了。接着创建一个简单的index.html,创建一个控制器进行跳转,检查项目是否能正常运行。
index.html
DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>indextitle>
<link rel="stylesheet" th:href="@{layui/layui.js}">
<link rel="stylesheet" th:href="@{css/global.css}">
head>
<body>
<div class="nav-user">
<a class="unlogin" href="user/login.html"><i class="iconfont icon-touxiang">i>a>
<span><a href="user/login.html">登入a><a href="user/reg.html">注册a>span>
<p class="out-login">
<a href="" onclick="layer.msg('正在通过QQ登入', {icon:16, shade: 0.1, time:0})" class="iconfont icon-qq" title="QQ登入">a>
<a href="" onclick="layer.msg('正在通过微博登入', {icon:16, shade: 0.1, time:0})" class="iconfont icon-weibo" title="微博登入">a>
p>
div>
body>
html>
IndexController.java
@Controller
public class IndexController {
@RequestMapping("hello")
public String index(){
return "index";
}
}
最后启动项目,检查我们的layui是否可一在项目中使用。由下图可以看到我们可以引用layui的样式功能。保证初始化项目正常运行,接下来接可以完成具体功能设计了。
在 controller/rest 包下新建 BBSUserController.java,添加页面跳转功能。
@Controller
public class BBSUserController {
/**
* 注册页面跳转
* @return
*/
@GetMapping({"/register", "/register.html"})
public String registerPage() {
return "user/reg";
}
}
该方法用于处理 /register 请求,是注册页面的跳转处理方法,请求方法为 GET,在发起请求后会分别跳转到 templates 模板目录中 user 目录下的 reg.html 中。
注册页面的整体布局参考了 fly 论坛的注册页面,在 templates 目录中新建 user 目录和 reg.html 模板页面。
在此之前需要将一些图片文件、公共js文件和一些公共页面先创建完成在说,比如页面的头部等;添加到Spring Boot项目中。
header.html
DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head th:fragment="head-fragment(title)">
<meta charset="utf-8">
<title th:text="${title}">首页title>
<link rel="shortcut icon" th:href="@{/images/my-bbs-icon.png}">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
<meta name="description" content="My-BBS,bbs,论坛,SpringBoot论坛,论坛系统,Java论坛,SpringBoot,spring-boot,java">
<meta name="description" content="My BBS 是由 SpringBoot + Mybatis + Thymeleaf 等技术实现的 Java BBS论坛系统">
<link rel="stylesheet" th:href="@{/layui/css/layui.css}">
<link rel="stylesheet" th:href="@{/css/global.css}">
head>
<div th:fragment="header-fragment" class="fly-header layui-bg-black">
<div class="layui-container">
<a class="fly-logo" href="/">
<img th:src="@{/images/my-bbs-logo.png}" alt="My-BBS">
a>
<ul class="layui-nav fly-nav layui-hide-xs">
<li class="layui-nav-item layui-this">
<a href="添加自己的文档地址"><i class="iconfont icon-wenda">i>开发文档a>
li>
<li class="layui-nav-item">
<a href="添加自己的源码下载地址"><i class="iconfont icon-daima">i>源码a>
li>
<li class="layui-nav-item layui-this">
<a href="添加自己的博客地址"><i class="iconfont icon-jiaoliu">i>交流a>
li>
ul>
<ul class="layui-nav fly-nav-user">
<th:block th:if="${session.myBBSUser==null}">
<li class="layui-nav-item">
<a class="iconfont icon-touxiang layui-hide-xs" href="user/login.html">a>
li>
<li class="layui-nav-item">
<a th:href="@{/login}">登入a>
li>
<li class="layui-nav-item">
<a th:href="@{/register}">注册a>
li>
th:block>
<th:block th:unless="${session.myBBSUser==null}">
<li class="layui-nav-item">
<a class="fly-nav-avatar" href="javascript:;">
<cite class="layui-hide-xs" th:text="${session.myBBSUser.nickName}">picachocite>
<th:block th:if="${session.myBBSUser.gender=='男'}">
<i class="iconfont icon-nan">i>
th:block>
<th:block th:if="${session.myBBSUser.gender=='女'}">
<i class="iconfont icon-nv">i>
th:block>
<th:block th:if="${session.myBBSUser.gender=='未知'}">
<i class="iconfont icon-biaoqing">i>
th:block>
<img th:src="@{${session.myBBSUser.headImgUrl}}">
<span class="layui-nav-more">span>
a>
<dl class="layui-nav-child">
<dd><a th:href="@{/userSet}"><i class="layui-icon">i>基本设置a>dd>
<dd><a th:href="@{/myCenter}"><i class="layui-icon" style="margin-left: 2px; font-size: 22px;">i>我的主页a>
dd>
<hr style="margin: 5px 0;">
<dd><a th:href="@{/logout}" style="text-align: center;">退出a>dd>
dl>
li>
th:block>
ul>
div>
div>
试着分析下页面结构是大致实现即可,毕竟作为后端开发来说写页面太难了(要自己写是真的不会啊)。
reg.html
DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head th:replace="header::head-fragment('注册')">
head>
<body>
<div th:replace="header::header-fragment">div>
<div class="layui-container fly-marginTop">
<div class="fly-panel fly-panel-user" pad20>
<div class="layui-tab layui-tab-brief" lay-filter="user">
<ul class="layui-tab-title">
<li><a th:href="@{/login}">登入a>li>
<li class="layui-this">注册li>
ul>
<div class="layui-form layui-tab-content" id="LAY_ucm" style="padding: 20px 0;">
<div class="layui-tab-item layui-show">
<div class="layui-form layui-form-pane">
<form method="post" id="registerForm" onsubmit="return false;" action="##">
<div class="layui-form-item">
<label for="loginName" class="layui-form-label">邮箱label>
<div class="layui-input-inline">
<input type="text" id="loginName" name="loginName" required lay-verify="email"
autocomplete="off" class="layui-input">
div>
<div class="layui-form-mid layui-word-aux">将会成为您唯一的登入名div>
div>
<div class="layui-form-item">
<label for="nickName" class="layui-form-label">昵称label>
<div class="layui-input-inline">
<input type="text" id="nickName" name="nickName" required lay-verify="required"
autocomplete="off" class="layui-input">
div>
div>
<div class="layui-form-item">
<label for="password" class="layui-form-label">密码label>
<div class="layui-input-inline">
<input type="password" id="password" name="password" required lay-verify="required"
autocomplete="off" class="layui-input">
div>
<div class="layui-form-mid layui-word-aux">6到20个字符div>
div>
<div class="layui-form-item">
<label for="repass" class="layui-form-label">确认密码label>
<div class="layui-input-inline">
<input type="password" id="repass" name="repass" required lay-verify="required"
autocomplete="off" class="layui-input">
div>
div>
<div class="layui-form-item">
<label for="verifyCode" class="layui-form-label">验证码label>
<div class="layui-input-inline">
<input type="text" id="verifyCode" name="verifyCode" required lay-verify="required"
placeholder="请输入验证码" autocomplete="off" class="layui-input">
div>
<div class="layui-form-mid">
<span><img data-tooltip="看不清楚?换一张"
th:src="@{/common/captcha}"
onclick="this.src='/common/captcha?d='+new Date()*1"
alt="单击图片刷新!">span>
div>
div>
<div class="layui-form-item">
<button class="layui-btn" lay-filter="*" lay-submit onclick="register()">立即注册button>
div>
form>
div>
div>
div>
div>
div>
div>
<div class="fly-footer">
<p>My-BBS社区 2021 © <a href="填写自己的额博客地址" target="_blank">picachoa>p>
div>
<script th:src="@{/js/public.js}">script>
<script th:src="@{/layui/layui.js}">script>
<script type="text/javascript">
layui.use(['layer', 'jquery'], function () {
var layer = layui.layer;
var $ = layui.$;
window.register = function () {
var $ = layui.$;
var loginName = $("#loginName").val();
if (!validEmail(loginName)) {
layer.alert('请输入正确的登录名!', {title: '提醒', skin: 'layui-layer-molv', icon: 2});
return false;
}
var nickName = $("#nickName").val();
if (!validUserName(nickName)) {
layer.alert('请输入正确的昵称!', {title: '提醒', skin: 'layui-layer-molv', icon: 2});
return false;
}
var password = $("#password").val();
if (!validPassword(password)) {
layer.alert('请输入正确的密码格式!', {title: '提醒', skin: 'layui-layer-molv', icon: 2});
return false;
}
var repass = $("#repass").val();
if (!validPassword(repass)) {
layer.alert('请输入正确的密码格式!', {title: '提醒', skin: 'layui-layer-molv', icon: 2});
return false;
}
if (repass != password) {
layer.alert('确认密码与密码字段不相同!', {title: '提醒', skin: 'layui-layer-molv', icon: 2});
return false;
}
var verifyCode = $("#verifyCode").val();
if (!validLength(verifyCode, 5)) {
layer.alert('请输入正确的验证码!', {title: '提醒', skin: 'layui-layer-molv', icon: 2});
return false;
}
// 将表单数据序列化,用于网络传输数据
var params = $("#registerForm").serialize();
var url = '/register';
$.ajax({
type: 'POST',// 方法类型
url: url,
data: params,
success: function (result) {
if (result.resultCode == 200) {
layer.alert('注册成功!', {title: '信息', skin: 'layui-layer-molv', icon: 1});
} else {
layer.msg(result.message);
}
;
},
error: function () {
layer.alert('操作失败!', {title: '提醒', skin: 'layui-layer-molv', icon: 2});
}
});
}
});
script>
body>
html>
启动项目访问请求路径,可以看到如下画面,表示注册跳转页面功能完成了。
接着需要完成验证码功能,这个功能在这篇博客讲到过基于Servlet的验证码登陆demo,这里使用第三方工具实现即可。在controller/common文件夹下创建CaptchaController控制器处理验证码相关的功能。
CaptchaController.java
@Controller
public class CaptchaController {
@GetMapping("/common/captcha")
public void defaultKaptcha(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws Exception {
httpServletResponse.setHeader("Cache-Control", "no-store");
httpServletResponse.setHeader("Pragma", "no-cache");
httpServletResponse.setDateHeader("Expires", 0);
httpServletResponse.setContentType("image/gif");
// 三个参数分别为宽、高、位数
GifCaptcha captcha = new GifCaptcha(75, 30,4);
// 设置类型 数字和字母混合
captcha.setCharType(Captcha.TYPE_DEFAULT);
//设置字体
captcha.setCharType(Captcha.FONT_9);
// 验证码存入session
// 这里设置全局变量Constants.VERIFY_CODE_KEY,也可以自己设置
httpServletRequest.getSession().setAttribute(Constants.VERIFY_CODE_KEY, captcha.text().toLowerCase());
// 输出图片流
captcha.out(httpServletResponse.getOutputStream());
}
}
在实现注册功能时,选择后端接口 + 前端 Ajax 调用方式来实现的。BBSUserController 类已经创建,之后在 service 包下新建业务层代码 BBSUserService.java 及实现类,之后参照接口分别功能实现即可。
在common包下创建ServiceResultEnum枚举类型,用于统一定义返回的信息。在util包下创建Result
类统一包装返回结果。在util包下创建ResultGenerator类生成Result对象返回给前端。
public enum ServiceResultEnum {
ERROR("error"),
SUCCESS("success"),
DATA_NOT_EXIST("未查询到记录!"),
SAME_LOGIN_NAME_EXIST("用户名已存在!"),
LOGIN_NAME_NULL("请输入登录名!"),
LOGIN_NAME_NOT_EMAIL("请输入正确的邮箱!"),
LOGIN_PASSWORD_NULL("请输入密码!"),
LOGIN_VERIFY_CODE_NULL("请输入验证码!"),
LOGIN_VERIFY_CODE_ERROR("验证码错误!"),
LOGIN_ERROR("登录失败!"),
DB_ERROR("database error");
private String result;
ServiceResultEnum(String result) {
this.result = result;
}
public String getResult() {
return result;
}
public void setResult(String result) {
this.result = result;
}
}
public class Result<T> implements Serializable {
private static final long serialVersionUID = 1L;
private int resultCode;
private String message;
private T data;
public Result() {
}
public Result(int resultCode, String message) {
this.resultCode = resultCode;
this.message = message;
}
public int getResultCode() {
return resultCode;
}
public void setResultCode(int resultCode) {
this.resultCode = resultCode;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public T getData() {
return data;
}
public void setData(T data) {
this.data = data;
}
@Override
public String toString() {
return "Result{" +
"resultCode=" + resultCode +
", message='" + message + '\'' +
", data=" + data +
'}';
}
}
public class ResultGenerator {
private static final String DEFAULT_SUCCESS_MESSAGE = "SUCCESS";
private static final String DEFAULT_FAIL_MESSAGE = "FAIL";
private static final int RESULT_CODE_SUCCESS = 200;
private static final int RESULT_CODE_SERVER_ERROR = 500;
public static Result genSuccessResult() {
Result result = new Result();
result.setResultCode(RESULT_CODE_SUCCESS);
result.setMessage(DEFAULT_SUCCESS_MESSAGE);
return result;
}
public static Result genSuccessResult(String message) {
Result result = new Result();
result.setResultCode(RESULT_CODE_SUCCESS);
result.setMessage(message);
return result;
}
public static Result genSuccessResult(Object data) {
Result result = new Result();
result.setResultCode(RESULT_CODE_SUCCESS);
result.setMessage(DEFAULT_SUCCESS_MESSAGE);
result.setData(data);
return result;
}
public static Result genFailResult(String message) {
Result result = new Result();
result.setResultCode(RESULT_CODE_SERVER_ERROR);
if (!StringUtils.hasLength(message)) {
result.setMessage(DEFAULT_FAIL_MESSAGE);
} else {
result.setMessage(message);
}
return result;
}
public static Result genErrorResult(int code, String message) {
Result result = new Result();
result.setResultCode(code);
result.setMessage(message);
return result;
}
}
接口的映射地址为 /register,请求方法为 POST。
/**
* 注册功能
*/
@PostMapping("/register")
@ResponseBody
public Result register(@RequestParam("loginName") String loginName,
@RequestParam("verifyCode") String verifyCode,
@RequestParam("nickName") String nickName,
@RequestParam("password") String password,
HttpSession httpSession) {
if (!StringUtils.hasLength(loginName)) {
return ResultGenerator.genFailResult(ServiceResultEnum.LOGIN_NAME_NULL.getResult());
}
if (!PatternUtil.isEmail(loginName)) { // 使用正则工具类处理昵称,判断是否符合邮箱格式
return ResultGenerator.genFailResult(ServiceResultEnum.LOGIN_NAME_NOT_EMAIL.getResult());
}
if (!StringUtils.hasLength(password)) {
return ResultGenerator.genFailResult(ServiceResultEnum.LOGIN_PASSWORD_NULL.getResult());
}
if (!StringUtils.hasLength(verifyCode)) {
return ResultGenerator.genFailResult(ServiceResultEnum.LOGIN_VERIFY_CODE_NULL.getResult());
}
String kaptchaCode = httpSession.getAttribute(Constants.VERIFY_CODE_KEY) + "";
if (!StringUtils.hasLength(kaptchaCode) || !verifyCode.equals(kaptchaCode)) {
return ResultGenerator.genFailResult(ServiceResultEnum.LOGIN_VERIFY_CODE_ERROR.getResult());
}
String registerResult = bbsUserService.register(loginName, password, nickName);
//注册成功
if (ServiceResultEnum.SUCCESS.getResult().equals(registerResult)) {
httpSession.removeAttribute(Constants.VERIFY_CODE_KEY);//删除session中的验证码
return ResultGenerator.genSuccessResult();
}
//注册失败
return ResultGenerator.genFailResult(registerResult);
}
首先对参数进行校验,之后调用 bbsUserService 业务层代码在数据库中新增一条论坛用户记录,最后根据业务层的结果来返回对应的 Result 对象。
首先查询数据库中是否有相同登录名的记录,如果存在则不再执行后续逻辑,返回 “用户名已存在” 的错误信息,如果不存在则证明可以新增这条记录。同时由于用户注册时只填写了登录名称和密码,数据库存储所需的两个字段,还有其他字段并没有传入,所以对头像、介绍、居住地等字段都进行了默认值的设置,这些字段可以在个人中心页面进行修改。最后将密码进行 MD5 转换后执行 insert 语句把这条用户信息插入到数据库中,并返回成功的业务信息。
public interface BBSUserService {
/**
* 用户注册
*
* @param loginName
* @param password
* @return
*/
String register(String loginName, String password, String nickName);
}
@Service
public class BBSUserServiceImpl implements BBSUserService {
@Autowired
private BBSUserMapper bbsUserMapper;
@Override
public String register(String loginName, String password, String nickName) {
if (bbsUserMapper.selectByLoginName(loginName) != null) {
return ServiceResultEnum.SAME_LOGIN_NAME_EXIST.getResult();
}
//注册用户
BBSUser registerUser = new BBSUser();
registerUser.setLoginName(loginName);
registerUser.setNickName(nickName);
//默认头像
registerUser.setHeadImgUrl("/images/avatar/default.png");
//默认介绍
registerUser.setIntroduce("这个人很懒,什么都没留下~");
//居住地
registerUser.setLocation("未知");
registerUser.setGender("未知");
String passwordMD5 = MD5Util.MD5Encode(password, "UTF-8");
registerUser.setPasswordMd5(passwordMD5);
if (bbsUserMapper.insertSelective(registerUser) > 0) {
return ServiceResultEnum.SUCCESS.getResult();
}
return ServiceResultEnum.DB_ERROR.getResult();
}
}
主要的 SQL 方法为 selectByLoginName() 和 insertSelective()。selectByLoginName() 方法是根据用户名查询用户记录信息,然后与要注册的用户名比较,如果存在则不插入,否则就插入。
package top.picacho.bbs.entity;
import java.util.Date;
/**
* 论坛用户-实体类
*/
public class BBSUser {
private Long userId;
private String loginName;
private String passwordMd5;
private String nickName;
private String headImgUrl;
private String gender;
private String location;
private String introduce;
private Byte userStatus;
private Date lastLoginTime;
private Date createTime;
public Long getUserId() {
return userId;
}
public void setUserId(Long userId) {
this.userId = userId;
}
public String getLoginName() {
return loginName;
}
public void setLoginName(String loginName) {
this.loginName = loginName == null ? null : loginName.trim();
}
public String getPasswordMd5() {
return passwordMd5;
}
public void setPasswordMd5(String passwordMd5) {
this.passwordMd5 = passwordMd5 == null ? null : passwordMd5.trim();
}
public String getNickName() {
return nickName;
}
public void setNickName(String nickName) {
this.nickName = nickName == null ? null : nickName.trim();
}
public String getHeadImgUrl() {
return headImgUrl;
}
public void setHeadImgUrl(String headImgUrl) {
this.headImgUrl = headImgUrl == null ? null : headImgUrl.trim();
}
public String getGender() {
return gender;
}
public void setGender(String gender) {
this.gender = gender == null ? null : gender.trim();
}
public String getLocation() {
return location;
}
public void setLocation(String location) {
this.location = location == null ? null : location.trim();
}
public String getIntroduce() {
return introduce;
}
public void setIntroduce(String introduce) {
this.introduce = introduce == null ? null : introduce.trim();
}
public Byte getUserStatus() {
return userStatus;
}
public void setUserStatus(Byte userStatus) {
this.userStatus = userStatus;
}
public Date getLastLoginTime() {
return lastLoginTime;
}
public void setLastLoginTime(Date lastLoginTime) {
this.lastLoginTime = lastLoginTime;
}
public Date getCreateTime() {
return createTime;
}
public void setCreateTime(Date createTime) {
this.createTime = createTime;
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append(getClass().getSimpleName());
sb.append(" [");
sb.append("Hash = ").append(hashCode());
sb.append(", userId=").append(userId);
sb.append(", loginName=").append(loginName);
sb.append(", passwordMd5=").append(passwordMd5);
sb.append(", nickName=").append(nickName);
sb.append(", headImgUrl=").append(headImgUrl);
sb.append(", gender=").append(gender);
sb.append(", location=").append(location);
sb.append(", introduce=").append(introduce);
sb.append(", userStatus=").append(userStatus);
sb.append(", lastLoginTime=").append(lastLoginTime);
sb.append(", createTime=").append(createTime);
sb.append("]");
return sb.toString();
}
}
public interface BBSUserMapper {
int insertSelective(BBSUser record);
BBSUser selectByLoginName(String loginName);
}
DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="top.picacho.bbs.dao.BBSUserMapper">
<resultMap id="BaseResultMap" type="top.picacho.bbs.entity.BBSUser">
<id column="user_id" jdbcType="BIGINT" property="userId" />
<result column="login_name" jdbcType="VARCHAR" property="loginName" />
<result column="password_md5" jdbcType="VARCHAR" property="passwordMd5" />
<result column="nick_name" jdbcType="VARCHAR" property="nickName" />
<result column="head_img_url" jdbcType="VARCHAR" property="headImgUrl" />
<result column="gender" jdbcType="VARCHAR" property="gender" />
<result column="location" jdbcType="VARCHAR" property="location" />
<result column="introduce" jdbcType="VARCHAR" property="introduce" />
<result column="user_status" jdbcType="TINYINT" property="userStatus" />
<result column="last_login_time" jdbcType="TIMESTAMP" property="lastLoginTime" />
<result column="create_time" jdbcType="TIMESTAMP" property="createTime" />
resultMap>
<sql id="Base_Column_List">
user_id, login_name, password_md5, nick_name, head_img_url, gender, location, introduce,
user_status, last_login_time, create_time
sql>
<select id="selectByLoginName" resultType="top.picacho.bbs.entity.BBSUser">
select
<include refid="Base_Column_List" />
from tb_bbs_user
where login_name = #{loginName,jdbcType=VARCHAR} limit 1
select>
<insert id="insertSelective" parameterType="top.picacho.bbs.entity.BBSUser">
insert into tb_bbs_user
<trim prefix="(" suffix=")" suffixOverrides=",">
<if test="userId != null">
user_id,
if>
<if test="loginName != null">
login_name,
if>
<if test="passwordMd5 != null">
password_md5,
if>
<if test="nickName != null">
nick_name,
if>
<if test="headImgUrl != null">
head_img_url,
if>
<if test="gender != null">
gender,
if>
<if test="location != null">
location,
if>
<if test="introduce != null">
introduce,
if>
<if test="userStatus != null">
user_status,
if>
<if test="lastLoginTime != null">
last_login_time,
if>
<if test="createTime != null">
create_time,
if>
trim>
<trim prefix="values (" suffix=")" suffixOverrides=",">
<if test="userId != null">
#{userId,jdbcType=BIGINT},
if>
<if test="loginName != null">
#{loginName,jdbcType=VARCHAR},
if>
<if test="passwordMd5 != null">
#{passwordMd5,jdbcType=VARCHAR},
if>
<if test="nickName != null">
#{nickName,jdbcType=VARCHAR},
if>
<if test="headImgUrl != null">
#{headImgUrl,jdbcType=VARCHAR},
if>
<if test="gender != null">
#{gender,jdbcType=VARCHAR},
if>
<if test="location != null">
#{location,jdbcType=VARCHAR},
if>
<if test="introduce != null">
#{introduce,jdbcType=VARCHAR},
if>
<if test="userStatus != null">
#{userStatus,jdbcType=TINYINT},
if>
<if test="lastLoginTime != null">
#{lastLoginTime,jdbcType=TIMESTAMP},
if>
<if test="createTime != null">
#{createTime,jdbcType=TIMESTAMP},
if>
trim>
insert>
mapper>
在主类上添加包扫描路径(不能缺少,不然无法扫描到Mapper接口),配置主文件后启动项目,验证注册功能。
# 禁止使用thymeleaf模版的缓存功能呢
spring.thymeleaf.cache=false
# 数据库连接信息
spring.datasource.name=my-bbs-datasource
spring.datasource.driverClassName=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/my_bbs_db?useUnicode=true&serverTimezone=Asia/Shanghai&characterEncoding=utf8&autoReconnect=true&useSSL=false&allowMultiQueries=true
spring.datasource.username=root
spring.datasource.password=12345678
spring.datasource.hikari.minimum-idle=5
spring.datasource.hikari.maximum-pool-size=15
spring.datasource.hikari.auto-commit=true
spring.datasource.hikari.idle-timeout=60000
spring.datasource.hikari.pool-name=hikariCP
spring.datasource.hikari.max-lifetime=600000
spring.datasource.hikari.connection-timeout=30000
spring.datasource.hikari.connection-test-query=SELECT 1
# mybatis config
mybatis.mapper-locations=classpath:mapper/*Mapper.xml