Java大作业【即时聊天Java版】有一个需求如下
用户登录及登录验证:用户能够使用固定帐号(帐号程序内置即可,无需完成额外的注册功能)登录系统,系统能对预定的帐号、密码进行验证。
登录功能是大部分系统的入口
登录的目的一来是为了识别每一个用户,搭建系统的用户体系;二来是登录了之后方便维护登录态,实现用户相关业务。
所以这也是很多人学习web开发的第一道坎,实现一个简单的登录功能。因此这篇文章就从零开始,使用SpringBoot+Mybatis
实现一个简单的登录功能。(账号程序内置,本篇文章不涉及到注册功能,大家可以自行去实现)
该项目代码已提交到Gitee仓库,仓库地址:https://gitee.com/smietao/GDUT_2020_JavaBigWork。
欢迎clone
和fork
,觉得对你们有所帮助的,可以点个star
。项目会不断更新直至 Java大作业 deadline —— 6月22日。
MYSQL
数据库存储,因此需要在本机搭建MYSQL
环境或是使用云数据库。SpringBoot+Mybatis
开发,因此需要配置Maven
环境方便拉jar包。没配置过Maven
的可以参考我的另外一篇博客:初学者必备——win10搭建Java后台开发环境大集合lombok
。(不知道lombok是什么的可以自行百度)HTML+CSS+JS
前端相关知识打开IDEA,在编辑器左上角选择File -> New -> Project
选择Spring Initializr创建Spring Boot工程,这里选择的是Default
,因此需要联网才能Next
填写POM相关配置
勾选依赖。勾选了的依赖会默认写入pom.xml
,不需要我们再次去导入
Spring Boot
官方推荐的模板引擎,类似于jspJava
代码连接MYSQL
Mybatis
轻量级持久层框架输入工程名以及工程的本地路径,这里根据自己的情况以及老师要求填写即可
工程创建完成后,如果之前没有使用过Maven,则Maven会根据pom.xml
去远程仓库拉取jar包,不过IDEA内置的Maven是去国外中央仓库下载的,会比较慢。可以根据上文的链接配置好Maven,之后在IDEA中选择自己本地的Maven进行后续操作。
File -> settings -> 搜索框输入maven
点击OK,之后IDEA会根据新的Maven配置重新下载jar包,这时候如果右下角弹窗则选择auto import
——当pom.xml
中有修改会自动更新
这是使用的是Javaweb
经典的MVC三层架构,即Model、view、controller。工程结构如图:
新建的项目是没有这些包和文件夹的,需要自己一点点搭建起来
resourcs
文件夹,可以看到application.properties
。这是Spring Boot默认的配置文件。这里我的习惯是使用yml
格式的,因此将其修改为application.yml
,并写入以下代码server:
port: 8081
spring:
devtools:
restart:
enabled: false
datasource:
url: jdbc:mysql://your ip address:端口号/数据库名?useUnicode=true&serverTimezone=GMT%2B8
username: smietao
password: xxxxxxx
mybatis:
type-aliases-package: com.smietao.instantchat
mapper-locations: classpath*:mapper/*.xml
check-config-location: true
configuration:
# 开启二级缓存
cache-enabled: true
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
map-underscore-to-camel-case: true
mapper:
mappers:
- com.smietao.instantchat.base.BaseMapperWeiLT
- tk.mybatis.mapper.common.Mapper
not-empty: true
identity: mysql
这里配置的有五点
MySQL
数据源配置(这个很重要)static
目录,用于存放静态资源文件,例如css、font、img、jstemplates
目录,用于存放动态页面,例如html、ftlindex.html
,即项目首页。放入templates。打开Application
类,运行main方法,启动项目,在浏览器输入localhost:8081
看看能否访问在src/main/java目录下创建
@Data
@Table(name = "we_user")
public class UserWeiLT {
@Id
@Column(name = "id")
public Integer id;
@Column(name = "email")
public String email;
@Column(name = "password")
public String password;
@Column(name = "username")
public String username;
@Column(name = "create_time")
private Date createTime;
@Column(name = "update_time")
private Date updateTime;
}
该类是与数据库表映射的实体类,即类中的每一个属性对应数据库表的每一个字段;@Data是lombok
的注解,用于快速生成get\set
方法;@Table和@Column是通用Mapper的注解。至于通用Ma
pper是什么、怎么使用,不是本文的重点,大家可以自行百度学习使用。而且这里也可以不使用通用Mapper,直接在mapper.xml
文件写sql语句。
mapper是Mybatis
框架操作数据库的方式,通过xxxMapper
中定义的接口方法,在底层根据xml文件自动生成实现方法,供我们使用。
@Mapper
@Repository
public interface UserMapperWeiLT extends BaseMapperWeiLT<UserWeiLT,String> {
}
这里的UserMapper
没有任何的抽象方法是因为其继承了BaseMapper
,其中封装了对单表的基础操作,一般业务我们使用这些就足够了。对通用Mapper不熟悉的同学我还是建议去网上找资料学习一下如何使用。
Spring IOC
管理,Repository
标识这是Model(Dao)
层的一个类当然这里不使用通用Mapper而是用Mybatis
的基本写法——xml文件中写sql语句,也是同理的,大家实现的时候可以多多尝试。
Service层在MVC三层架构中是负责实现业务的,所以根据规范我们的业务代码也是写在此处。
就拿登录注册来说,其中的业务便是检测——
以上两点判断都应该在Service层调用Dao层方法来实现,并将结果传递给Controller层。
Service层根据规范需要定义接口,方便我们调用的时候能在上层方法看到如何入参、回参的含义以及方法的作用。
interface
接口定义
public interface UserServiceWeiLT extends BaseServiceWeiLT<UserWeiLT,String> {
/**
* 检查用户输入的邮箱和密码是否正确
* @param loginDTOWeiLT 邮箱、密码 DTO类
* @return 1表示成功,-1表示邮箱账号不存在,-2表示密码不匹配
*/
int checkUserLogin(LoginDTOWeiLT loginDTOWeiLT);
}
Impl
类实现
@Service
public class UserServiceImplWeiLT extends BaseServiceImplWeiLT<UserWeiLT, String> implements UserServiceWeiLT {
@Autowired
private UserMapperWeiLT userMapperWeiLT;
@Override
public BaseMapperWeiLT<UserWeiLT, String> getMappser() {
return userMapperWeiLT;
}
@Override
public int checkUserLogin(LoginDTOWeiLT loginDTOWeiLT) {
Example example = new Example(UserWeiLT.class);
example.and().andEqualTo("email",loginDTOWeiLT.getEmail());
UserWeiLT user = userMapperWeiLT.selectOneByExample(example);
if (user == null) {
// 如果查询不出数据,说明账号不存在
return -1;
} else {
// 数据库中的密码
String password = user.getPassword();
// 用户输入的密码
String inputPassword = loginDTOWeiLT.getPassword();
if (!password.equals(inputPassword)) {
// 如果密码不匹配
return -2;
} else {
return 1;
}
}
}
}
UserMapper
类,即依赖注入,在方法中可以直接调用该类的方法而不需要new一个新的对象BaseServiceImplWeiLT
,所以必须覆写getMappser()
方法,该方法需要返回一个Mapper
对象,用于通用Service操作数据库checkUserLogin()
方法中的Example是通用Mapper的写法,用于拼接sql查询条件,已实现自己预期的业务Controller层是控制层,与页面进行交互数据。在这里先编写一个接口,用于登录表单的提交。
/**
* @author smietao
* 登录系统
*/
@Controller
public class LoginControllerWeiLT {
@Autowired
private UserServiceWeiLT userService;
@GetMapping(value = "")
public String loginInit() {
return autoLogin();
}
@GetMapping(value = "/login")
public String autoLogin() {
return "login";
}
@PostMapping("/weLogin")
public String weLogin(Model model,LoginDTOWeiLT loginDTOWeiLT) {
int res = userService.checkUserLogin(loginDTOWeiLT);
String msg = "";
if (res == -1) {
// 邮箱账号不存在
msg = "邮箱账号不存在,请重新输入";
} else if (res == -2) {
// 密码错误
msg = "密码错误,请重新输入";
}
if (res == -1 || res == -2) {
// 如果是错误的登录
model.addAttribute("message", msg);
return "login";
}
// 通过验证,登录成功
return "success";
}
}
controller
层的类,同时将该类交给Spring IOC管理。loginInit()
是为了访问项目localhost:8081
能跳转到登录页。而weLogin()
方法则是登录页用户输入账号密码后向后端服务器请求的方法。weLogin()
方法解析:
@PostMapping
是Servlet mapping
请求路径映射,Post
表示客户端必须以post
方式发起请求,发起请求的路径就是该注解的值
方法返回String类型是SpringMVC
的视图解析器写法,这里return templates
下的页面文件名即可跳转至该页面
model.addAttribute()
方法可以将后端的数据封装进域对象,便于在页面中展示数据或是提示信息
至此,后端的代码已经over了,剩下的就是前端代码的小改了。
这里的首页只是一个登录窗口,因此大家可以在网络社区上找一个自己觉得养眼的登录模板(很多的),拿来就用(疯狂白嫖)。
这里就不贴我的登录代码了,挑一些重要的讲。
表单的action
属性配置后端接口请求路径<form method="post" action="/weLogin" class="login100-form validate-form layui-form">
css、js
使用绝对路径@{}的方式,如此后台使用请求转发的方式跳转页面后就不会因为使用了相对路径,导致引用路径的改变而丢失样式。<script type="text/javascript" th:src="@{/js/layui/layui.all.js}">script>
<script th:inline="javascript">
var layer;
$(function () {
layui.use(['form', 'layer'], function () {
var form = layui.form;
form.verify({
email: function (value) {
if (value.trim() == '') {
return '邮箱不能为空';
}
if (value != "") {
if (!/^([a-zA-Z0-9_-])+@([a-zA-Z0-9_-])+(.[a-zA-Z0-9_-])+/.test(value)) {
return "邮箱格式不正确";
}
}
}, password: function (v) {
if (v.trim() == '') {
return "密码不能为空";
}
}
});
form.render();
});
layer = layui.layer;
var msg = [[${message}]];
// var msg = '${message}';
if (msg.trim() != "") {
layer.msg(msg, {icon: 5, anim: 6, offset: 't'});
}
});
if (window != top)
top.location.href = location.href;
</script>
[[${message}]]
是从后端拿到controller
在model中设置的message值,用于登录业务的错误信息提示弹窗。(邮箱不存在、密码错误)
可以简单创建一个登录成功的html页面,用于测试登录成功后的跳转功能,在此基础上继续开发后续的业务。
<html lang="en">
<head>
<meta charset="UTF-8">
<title>WeTalk聊天室title>
head>
<body>
<h1 style="color: red">恭喜你登录成功WeTalk系统h1>
body>
html>
逐步完成上述的所有内容,一个简单的登录功能(带数据库)就实现成功了。其中涉及到的知识点有
SpringBoot
自动配置\配置文件html、css、js
前端三件套如果光是使用而不深究其原理的话,这些东西其实并不多,也不复杂。(这也框架的好处)因此希望大家能亲手去实践一下,如果是第一次做这类程序的话,会很有体验\收获的。
你会发现,写代码不仅仅是完成老师的作业,更奇妙的是经你之手敲出来的代码,真正地实现了一个日常使用的功能之时,你会找回在学习第一门编程语言,对着电脑屏幕以及教学课本,一个字母一个字母地把Hello World!
的 demo示例代码敲在编译器上并运行时内心的喜悦。这看似微不足道的入门程序,却是你开启编程世界的敲门砖、垫脚石。奔涌吧后浪~
在我小的时候,总以为这个世界很单纯。没有赢不了的比赛,努力付出就会有所回报,一切皆有可能…