SpringMVC(10)综合案例练习:计算器,登录
文章目录
- SpringMVC(10)综合案例练习:计算器,登录
- 观前提醒:
- 预备知识:接口
- [1. 计算器](#1. 计算器)
- [2. 登录](#2. 登录)
-
- 预期效果:
- 接口文档描述:
- 后端代码:
- [1. 登录检验接口](#1. 登录检验接口)
-
- 代码改善:
-
- [1. 使用 StringUtils(String的工具类)](#1. 使用 StringUtils(String的工具类))
- [2. 常量调用equals()方法(常量在前,变量在后):](#2. 常量调用equals()方法(常量在前,变量在后):)
- 最终代码:
- 后端代码的第二种写法(if嵌套):
- 关于校验:
- [2. 返回用户登录用户的用户名接口](#2. 返回用户登录用户的用户名接口)
-
- [登录检验接口,设置 Session](#登录检验接口,设置 Session)
- 获取用户名接口
- 前端代码:
- 运行结果:
- [3. 总结:](#3. 总结:)
观前提醒:
如果大家要获取这篇博客涉及到的源代码,从我的 gitee中获取:
计算器,登录功能代码获取
预备知识:接口
这里的接口和 SE语法 阶段,学的 Interface 不是一个接口,我们这里讲的接口是这样的:
java
// 2.上传一个文件,读取它里面的内容
@RequestMapping("/f2")
public String getFileContent(MultipartFile file) throws IOException {
InputStream inputStream = file.getInputStream();
StringBuilder stringBuilder = new StringBuilder();
// 读取文件内容
byte[] bytes = new byte[4096];
while(true) {
int read = inputStream.read(bytes);
if(read == -1) {
break;
}else {
stringBuilder.append(new String(bytes, 0, read));
}
}
return stringBuilder.toString();
}
接口包括 :
功能 :具体是完成什么样的功能
路径 :也就是资源路径 的定义
参数 :完成这个功能,需要哪些材料(参数)
返回结果:这个功能,需要返回什么样的结果给前端。
1. 计算器
预期效果:

接口文档描述:

实际开发工作中,需要严格按照接口文档的描述,进行接口的定义。
后端代码:
java
@RequestMapping("/calc")
@RestController
public class CalcController {
@RequestMapping("/sum")
public String sum(Integer num1, Integer num2) {
if (num1 == null || num2 == null) {
return "参数不合法,请重新传输参数";
}
int sum = num1 + num2;
return "<h1>" + "计算相加的结果是:" + sum + "</h1>";
}
}
接口测试结果:

前端代码:
html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<form action="calc/sum" method="post">
<h1>计算器</h1>
数字1:<input name="num1" type="text"><br>
数字2:<input name="num2" type="text"><br>
<input type="submit" value=" 点击相加 ">
</form>
</body>
</html>
前端代码解释:

运行注意 :
不要点击 IDEA显示html代码时, 右上角的浏览:


这样是访问不到资源的。
还是要使用 浏览器输入URL 的方式:http://127.0.0.1:8080/calc.html
进行项目的访问:

使用 浏览器输入URL 进行访问
运行结果:

能够得出正确的结果。
2. 登录
预期效果:

接口文档描述:
通过上面的预期效果图,我们需要分析,我们需要设计几个接口。
通过分析,需要设计两个:
-
接口一:登录检验接口
用于判断用户输入的用户名和密码是否正确。
-
接口二:返回登录用户的用户名
用于显示,登录用户的用户名是什么。
接口描述:

上图是 登录检验接口的设计

上图是 用户登录用户的用户名接口的设计
后端代码:
根据接口文档,设计接口:
1. 登录检验接口
java
@RequestMapping("/login")
public Boolean login(String username, String password) {
// 1.判断两个字符串是否为空
if (username == null || username.equals("") || password == null || password.equals("")) {
return false;
}
//由于,目前没有学习数据库相关的操作,我们把 username 和 password 写死
// 均为 admin
// 2.判断两个字符串,是否匹配
if (username.equals("admin") && password.equals("admin")){
return true;
}
return false;
}
代码改善:
上面这个代码,有可以改善的地方:
- 可以使用 StringUtils(String的工具类)提供的 hasLength() 方法,判断 username 和 password 是否为空。
- 判断两个判断两个字符串,是否匹配,建议 常量调用equals()方法(常量在前,变量在后)
1. 使用 StringUtils(String的工具类)
java
@RequestMapping("/login")
public Boolean login(String username, String password) {
// 1.判断两个字符串是否为空
if (!StringUtils.hasLength("username") || !StringUtils.hasLength("password")) {
return false;
}
//由于,目前没有学习数据库相关的操作,我们把 username 和 password 写死
// 均为 admin
// 2.判断两个字符串,是否匹配
if (username.equals("admin") && password.equals("admin")){
return true;
}
return false;
}
StringUtils.hasLength():
如果字符串为空,返回 false。
如果字符串不为空,返回 true。
!StringUtils.hasLength() :如果字符串为空,返回 false,!false == true
字符串为空,!StringUtils.hasLength() 的结果为 true。
执行 if语句 内的代码。
2. 常量调用equals()方法(常量在前,变量在后):
java
@RequestMapping("/login")
public Boolean login(String username, String password) {
// 1.判断两个字符串是否为空
if (!StringUtils.hasLength("username") || !StringUtils.hasLength("password")) {
return false;
}
//由于,目前没有学习数据库相关的操作,我们把 username 和 password 写死
// 均为 admin
// 2.判断两个字符串,是否匹配
if ("admin".equals(username) && "admin".equals(password)) {
return true;
}
return false;
}
解释:为什么建议 常量调用equals()方法(常量在前,变量在后)?
答:变量放在前面,有可能会引发 空指针异常(NullpointException),放在后面,不会引发空指针异常。
常量,永远不会引发空指针异常。
前面不是检验两个变量是否为空了吗?怎么还会引发 空指针异常?
答:并不是每时每刻,你都记得开头进行校验的。
但是,如果你把 常量调用equals()方法(常量在前,变量在后)这种习惯养成了,哪怕忘记开头校验 变量是否为空,后续也不会引发空指针异常。
总结:字符串匹配,建议 常量调用equals()方法(常量在前,变量在后),这是一个好习惯。

最终代码:
java
@RequestMapping("/login")
public Boolean login(String username, String password) {
// 1.判断两个字符串是否为空
if (!StringUtils.hasLength("username") || !StringUtils.hasLength("password")) {
return false;
}
//由于,目前没有学习数据库相关的操作,我们把 username 和 password 写死
// 均为 admin
// 2.判断两个字符串,是否匹配
if ("admin".equals(username) && "admin".equals(password)) {
return true;
}
return false;
}
测试:

后端代码的第二种写法(if嵌套):
代码:
java
@RequestMapping("/login")
public Boolean login2(String username, String password) {
// 1.判断两个字符串是否为空
if (StringUtils.hasLength("username") && StringUtils.hasLength("password")) {
if ("admin".equals(username) && "admin".equals(password)) {
return true;
}
}
return false;
}
这种 if嵌套 的语句,不建议这样写,能不写就不写。
嵌套的写法,可读性较差。
关于校验:
无论是后端还是前端,都需要进行各自的校验工作,开发是团队开发,不可以把麻烦扔给别人帮你解决,同事会骂你的。
2. 返回用户登录用户的用户名接口
从后端返回用户的用户名,从哪里拿?
答:目前,还没有学习数据库相关的操作,我们可以在登录的时候,将用户的用户名保存到 Session中,再从 Session 中获取用户名。
登录检验接口,设置 Session
所以,登录检验接口,需要设置 Session,保存信息:
java
@RequestMapping("/login")
public Boolean login(String username, String password, HttpSession session) {
// 1.判断两个字符串是否为空
if (!StringUtils.hasLength("username") || !StringUtils.hasLength("password")) {
return false;
}
//由于,目前没有学习数据库相关的操作,我们把 username 和 password 写死
// 均为 admin
// 2.判断两个字符串,是否匹配
if ("admin".equals(username) && "admin".equals(password)) {
// 用户名和密码正确,保存至 Session
session.setAttribute("username", username);
return true;
}
return false;
}
获取用户名接口
java
@RequestMapping(value = "/getLoginUser",produces = "text/html")
public String getLoginUser(HttpSession session) {
String username = (String) session.getAttribute("username");
return username;
}
@RequestMapping(value = "/getLoginUser",produces = "text/html"):
- 设置方法路径
- produces = "text/html",手动指定 Content-Type 类型。
前端代码:
项目目录:

login页面
使用 Ajax 的方式,提交数据,发送请求:
代码:
html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>登录页面</title>
</head>
<body>
<h1>用户登录</h1>
用户名:<input name="userName" type="text" id="userName"><br> 密码:
<input name="password" type="password" id="password"><br>
<input type="button" value="登录" onclick="login()">
<script src="js/jquery-3.7.1.min.js"></script>
<script>
function login() {
$.ajax({
type: "post",
url: "/user/login",
data: {
// $("#userName").val() 表示的是 name="userName"的input 框中输入的值
username: $("#userName").val(),
// $("#password").val() 表示的是 name="password"的input 框中输入的值
password: $("#password").val()
},
success: function(result) {
if (result) {
// 密码正确
location.href = "index.html";
// location.assign("index.html");
} else {
// 密码错误
alert("密码错误,请确认")
}
}
});
}
</script>
</body>
</html>
代码解析:


两种跳转页面的方式:
- location.href = "index.html";
- location.assign("index.html");
index页面(显示用户的用户名)
代码:
html
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>用户登录首页</title>
</head>
<body>
登录人: <span id="loginUser"></span>
<script src="js/jquery-3.7.1.min.js"></script>
<script>
$.ajax({
type: "get",
url: "/user/getLoginUser",
// 显示信息,没有传参信息,不用写 data
success: function(username) {
// 将 username 放入 span标签
$("#loginUser").text(username);
}
});
</script>
</body>
</html>
运行结果:


浏览器工具:
键盘按下 F12,选择 Network,可以查看我们的页面资源,是否加载成功。
以及我们发送的请求。

3. 总结:
- 计算器(简单)
- 登录页面
对于后端开发人员来说,要学会使用 ajax 发起请求,注意 前端 的url 和后端的 资源路径相匹配。
至于其他的页面设计,不要求掌握的。
最后,如果这篇博客能帮到你的,请你点点赞,有写错了,写的不好的,欢迎评论指出,谢谢!
下一篇博客:SpringMVC(11)综合案例练习:留言板