SpringMVC(10)综合案例练习:计算器,登录

SpringMVC(10)综合案例练习:计算器,登录

文章目录

观前提醒:

如果大家要获取这篇博客涉及到的源代码,从我的 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. 接口一:登录检验接口

    用于判断用户输入的用户名和密码是否正确。

  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;
    }

代码改善:

上面这个代码,有可以改善的地方:

  1. 可以使用 StringUtils(String的工具类)提供的 hasLength() 方法,判断 username 和 password 是否为空。
  2. 判断两个判断两个字符串,是否匹配,建议 常量调用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")

  1. 设置方法路径
  2. 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>

代码解析:

两种跳转页面的方式:

  1. location.href = "index.html";
  2. 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. 总结:

  1. 计算器(简单)
  2. 登录页面

对于后端开发人员来说,要学会使用 ajax 发起请求,注意 前端 的url 和后端的 资源路径相匹配。

至于其他的页面设计,不要求掌握的。

最后,如果这篇博客能帮到你的,请你点点赞,有写错了,写的不好的,欢迎评论指出,谢谢!

下一篇博客:SpringMVC(11)综合案例练习:留言板

相关推荐
roman_日积跬步-终至千里2 小时前
【Java并发】Tomcat 与 Spring:后端项目中的线程与资源管理
java·spring·tomcat
Remember_9933 小时前
Spring 核心原理深度解析:Bean 作用域、生命周期与 Spring Boot 自动配置
java·前端·spring boot·后端·spring·面试
启山智软16 小时前
【中大企业选择源码部署商城系统】
java·spring·商城开发
m0_7400437319 小时前
【无标题】
java·spring boot·spring·spring cloud·微服务
@ chen19 小时前
Spring事务 核心知识
java·后端·spring
RANCE_atttackkk21 小时前
Springboot+langchain4j的RAG检索增强生成
java·开发语言·spring boot·后端·spring·ai·ai编程
她说..1 天前
策略模式+工厂模式实现单接口适配多审核节点
java·spring boot·后端·spring·简单工厂模式·策略模式
从此不归路1 天前
Qt5 进阶【13】桌面 Qt 项目架构设计:从 MVC/MVVM 到模块划分
开发语言·c++·qt·架构·mvc
不光头强1 天前
shiro学习要点
java·学习·spring