4、SpringMVC 实战小项目【加法计算器、用户登录、留言板、图书管理系统】

发布于:2024-06-24 ⋅ 阅读:(19) ⋅ 点赞:(0)

3.1 加法计算器

需求: 输⼊两个整数, 点击"点击相加"按钮, 显⽰计算结果

在这里插入图片描述

3.1.1 准备⼯作

创建SpringBoot项⽬: 引⼊Spring Web依赖, 把前端⻚⾯放在项⽬中(课件中提供)

前端
<!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>

3.1.2 约定前后端交互接⼝

需求分析

加法计算器功能, 对两个整数进⾏相加, 需要客⼾端提供参与计算的两个数, 服务端返回这两个整数计算的结果

接⼝定义

在这里插入图片描述

请求路径:calc/sum
请求⽅式:GET/POST
接⼝描述:计算两个整数相加
请求参数:

在这里插入图片描述

⽰例: num1=5&num2=3

响应数据:
Content-Type: text/html
响应内容: 计算机计算结果: 8

3.1.3 服务器代码

@RestController
@RequestMapping("/calc")
public class CalcController {
	@RequestMapping("/sum")
	public String sum(Integer num1,Integer num2){
		Integer sum = num1+num2;
		return "<h1>计算机计算结果: "+sum+"</h1>";
	}
}

3.2 ⽤⼾登录

需求: ⽤⼾输⼊账号和密码, 后端进⾏校验密码是否正确

  1. 如果不正确, 前端进⾏⽤⼾告知
  2. 如果正确, 跳转到⾸⻚. ⾸⻚显⽰当前登录⽤⼾
  3. 后续再访问⾸⻚, 可以获取到登录⽤⼾信息

在这里插入图片描述

3.2.1 准备⼯作

把前端⻚⾯放在项⽬中(课件中提供)
码云地址: 前端代码/⽤⼾登录

<!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="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.4/jquery.min.js"></script>
  <script>
    function login() {
      $.ajax({
        type: "post",
        url: "/login/check",
        data:{
          userName: $("#userName").val(),
          password: $("#password").val()
        },
        success: function(result){
          if(result==true){
            //用户名和密码正确
            location.href = "index.html";
            // location.assign("index.html");
            // location.replace("index.html")
          }else{
            alert("用户名或密码错误!");
          }
        }
      });
    }

  </script>
</body>

</html>

3.2.2 约定前后端交互接⼝

需求分析
对于后端开发⼈员⽽⾔, 不涉及前端⻚⾯的展⽰, 只需要提供两个功能

  1. 登录⻚⾯: 通过账号和密码, 校验输⼊的账号密码是否正确, 并告知前端
  2. ⾸⻚: 告知前端当前登录⽤⼾. 如果当前已有⽤⼾登录, 返回登录的账号, 如果没有, 返回空

接⼝定义

  1. 校验接⼝
请求路径:/user/login
请求⽅式:POST
接⼝描述:校验账号密码是否正确

在这里插入图片描述

3.2.3 实现服务器端代码

@RequestMapping("/login")
@RestController
public class LoginController {
    @RequestMapping("/check")
    public boolean check(String userName, String password, HttpSession session){
        System.out.println("接收到参数 userName:"+userName + ",password:"+password);
        //校验账号和密码是否为空
//        if (userName==null || "".equals(userName) || password==null || "".equals(password)){
//            return false;
//        }
        if (!StringUtils.hasLength(userName) || !StringUtils.hasLength(password)){
            return false;
        }
        //校验账号和密码是否正确
        //数据模拟
        if ("zhangsan".equals(userName) && "123456".equals(password)){
            session.setAttribute("userName",userName);
            return true;
        }
        return false;
    }

    @RequestMapping("/index")
    public String index(HttpSession session){
        String userName = (String)session.getAttribute("userName");
        return userName;
    }
}

3.3 留⾔板

需求:
界⾯如下图所⽰

  1. 输⼊留⾔信息, 点击提交. 后端把数据存储起来.
  2. ⻚⾯展⽰输⼊的表⽩墙的信息

在这里插入图片描述

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>留言板</title>
    <style>
        .container {
            width: 350px;
            height: 300px;
            margin: 0 auto;
            /* border: 1px black solid; */
            text-align: center;
        }

        .grey {
            color: grey;
        }

        .container .row {
            width: 350px;
            height: 40px;

            display: flex;
            justify-content: space-between;
            align-items: center;
        }

        .container .row input {
            width: 260px;
            height: 30px;
        }

        #submit {
            width: 350px;
            height: 40px;
            background-color: orange;
            color: white;
            border: none;
            margin: 10px;
            border-radius: 5px;
            font-size: 20px;
        }
    </style>
</head>

<body>
    <div class="container">
        <h1>留言板</h1>
        <p class="grey">输入后点击提交, 会将信息显示下方空白处</p>
        <div class="row">
            <span>谁:</span> <input type="text" name="" id="from">
        </div>
        <div class="row">
            <span>对谁:</span> <input type="text" name="" id="to">
        </div>
        <div class="row">
            <span>说什么:</span> <input type="text" name="" id="say">
        </div>
        <input type="button" value="提交" id="submit" onclick="submit()">
        <!-- <div>A 对 B 说: hello</div> -->
    </div>

    <script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.4/jquery.min.js"></script>
    <script>
        //页面加载时, 显示留言信息
        //从后端获取到留言信息, 并显示在页面上
        $.ajax({
            type: "get",
            url: "/message/getList",
            success: function(messages){
                for(var message of messages){
                    var html = "<div>"+message.from+" 对 "+message.to+" 说: "+message.message+"</div>";
                    $(".container").append(html);
                }
            }
        });


        function submit() {
            //1. 获取留言的内容
            var from = $('#from').val();
            var to = $('#to').val();
            var say = $('#say').val();
            if (from == '' || to == '' || say == '') {
                return;
            }
            $.ajax({
                type: "post",
                url: "/message/publish",
                data: {
                    from: from,
                    to: to,
                    message: say
                },
                success: function (result) {
                    if (result == true) {
                        //添加成功
                        //2. 构造节点
                        var divE = "<div>" + from + "对" + to + "说:" + say + "</div>";
                        //3. 把节点添加到页面上
                        $(".container").append(divE);
                        //4. 清空输入框的值
                        $('#from').val("");
                        $('#to').val("");
                        $('#say').val("");
                    }else{
                        alert("发表失败");
                    }
                }
            });
        }

    </script>
</body>

</html>

实现服务器端代码

@Data
public class MessageInfo {
    private Integer id;
    private String from;
    private String to;
    private String message;
    private Integer deleteFlag;
    private Date createTime;
    private Date updateTime;

}

@RequestMapping("/message")
@RestController
public class MessageController {
    @Autowired
    private MessageService messageService;

    private List<MessageInfo> messageInfos = new ArrayList<>();

    @RequestMapping("/publish")
    public boolean publishMessage(MessageInfo messageInfo){
        if (!StringUtils.hasLength(messageInfo.getFrom())
                || !StringUtils.hasLength(messageInfo.getTo())
                || !StringUtils.hasLength(messageInfo.getMessage())){
            return false;
        }
        //暂时存放在内存中
//        messageInfos.add(messageInfo);
        //把数据放在mysql当中
        messageService.insertMessage(messageInfo);
        return true;
    }

    @RequestMapping("/getList")
    public List<MessageInfo> getList(){
        return messageService.queryList();
    }
}

3.4 图书管理系统

需求:

  1. 登录: ⽤⼾输⼊账号,密码完成登录功能
  2. 列表展⽰: 展⽰图书

在这里插入图片描述

准备

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <link rel="stylesheet" href="css/bootstrap.min.css">
    <link rel="stylesheet" href="css/login.css">
    <script type="text/javascript" src="js/jquery.min.js"></script>
</head>

<body>
    <div class="container-login">
        <div class="container-pic">
            <img src="pic/computer.png" width="350px">
        </div>
        <div class="login-dialog">
            <h3>登陆</h3>
            <div class="row">
                <span>用户名</span>
                <input type="text" name="userName" id="userName" class="form-control">
            </div>
            <div class="row">
                <span>密码</span>
                <input type="password" name="password" id="password" class="form-control">
            </div>
            <div class="row">
                <button type="button" class="btn btn-info btn-lg" onclick="login()">登录</button>
            </div>
        </div>
    </div>
    <script src="js/jquery.min.js"></script>
    <script>
        function login() {
            $.ajax({
                type:"post",
                url: "/user/login",
                data:{
                    userName: $("#userName").val(),
                    password: $("#password").val()
                },
                success:function(result){
                    console.log(result);
                    if(result.code==200 && result.data==true){
                        //验证成功
                        location.href = "book_list.html";
                    }else{
                        alert("用户名或密码失败");
                    }
                }
            });
           
        }
    </script>
</body>

</html>
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>图书列表展示</title>
    <link rel="stylesheet" href="css/bootstrap.min.css">

    <link rel="stylesheet" href="css/list.css">
    <script type="text/javascript" src="js/jquery.min.js"></script>
    <script type="text/javascript" src="js/bootstrap.min.js"></script>
    <script src="js/jq-paginator.js"></script>

</head>

<body>
    <div class="bookContainer">
        <h2>图书列表展示</h2>
        <div class="navbar-justify-between">
            <div>
                <button class="btn btn-outline-info" type="button" onclick="location.href='book_add.html'">添加图书</button>
                <button class="btn btn-outline-info" type="button" onclick="batchDelete()">批量删除</button>
            </div>
        </div>

        <table>
            <thead>
                <tr>
                    <td>选择</td>
                    <td class="width100">图书ID</td>
                    <td>书名</td>
                    <td>作者</td>
                    <td>数量</td>
                    <td>定价</td>
                    <td>出版社</td>
                    <td>状态</td>
                    <td class="width200">操作</td>
                </tr>
            </thead>
            <tbody>

            </tbody>
        </table>

        <div class="demo">
            <ul id="pageContainer" class="pagination justify-content-center"></ul>
        </div>
        <script>

            getBookList();


            function getBookList() {
                $.ajax({
                    type: "get",
                    url: "/book/getListByPage" + location.search,
                    success: function (result) {
                        console.log("后端返回成功");
                        if (result.code == -1) {
                            alert("发生内部错误, 请联系管理员");
                            return;
                        }
                        var data = result.data;
                        var books = data.records;
                        console.log(books);
                        var finalHtml = "";
                        for (var book of books) {
                            //拼接html
                            finalHtml += '<tr>';
                            finalHtml += '<td><input type="checkbox" name="selectBook" value="' + book.id + '" id="selectBook" class="book-select"></td>';
                            finalHtml += '<td>' + book.id + '</td>';
                            finalHtml += '<td>' + book.bookName + '</td>';
                            finalHtml += '<td>' + book.author + '</td>';
                            finalHtml += '<td>' + book.count + '</td>';
                            finalHtml += '<td>' + book.price + '</td>';
                            finalHtml += '<td>' + book.publish + '</td>';
                            finalHtml += '<td>' + book.stateCN + '</td>';
                            finalHtml += '<td>';
                            finalHtml += '<div class="op">';
                            finalHtml += '<a href="book_update.html?bookId=' + book.id + '">修改</a>';
                            finalHtml += '<a href="javascript:void(0)" οnclick="deleteBook(' + book.id + ')">删除</a>';
                            finalHtml += '</div>';
                            finalHtml += '</td>';
                            finalHtml += '</tr>';
                        }

                        $("tbody").html(finalHtml);

                        //处理翻页信息
                        //翻页信息
                        $("#pageContainer").jqPaginator({
                            totalCounts: data.count, //总记录数
                            pageSize: 10,    //每页的个数
                            visiblePages: 5, //可视页数
                            currentPage: data.pageRequest.currentPage,  //当前页码
                            first: '<li class="page-item"><a class="page-link">首页</a></li>',
                            prev: '<li class="page-item"><a class="page-link" href="javascript:void(0);">上一页<\/a><\/li>',
                            next: '<li class="page-item"><a class="page-link" href="javascript:void(0);">下一页<\/a><\/li>',
                            last: '<li class="page-item"><a class="page-link" href="javascript:void(0);">最后一页<\/a><\/li>',
                            page: '<li class="page-item"><a class="page-link" href="javascript:void(0);">{{page}}<\/a><\/li>',
                            //页面初始化和页码点击时都会执行
                            onPageChange: function (page, type) {
                                console.log("第" + page + "页, 类型:" + type);
                                if (type == "change") {
                                    // console.log("book_list.html"+location.search);
                                    location.href = "book_list.html?currentPage=" + page;
                                }

                            }
                        });
                    },
                    error: function (error) {
                        console.log(error);
                        if (error != null && error.status == 401) {
                            location.href = "login.html";
                        }
                    }



                });
            }


            function deleteBook(id) {
                var isDelete = confirm("确认删除?");//弹出确认框
                if (isDelete) {
                    console.log(id);
                    //删除图书
                    $.ajax({
                        type: "post",
                        url: "/book/updateBook",
                        data: {
                            id: id,
                            status: 0
                        },
                        success: function (result) {
                            if (result.code == 200 && result.data == true) {
                                alert("删除成功");
                                location.href = "book_list.html";
                            }
                        }
                    });
                }
            }
            function batchDelete() {
                var isDelete = confirm("确认批量删除?");
                if (isDelete) {
                    //获取复选框的id
                    var ids = [];
                    $("input:checkbox[name='selectBook']:checked").each(function () {
                        ids.push($(this).val());
                    });
                    console.log(ids);
                    $.ajax({
                        type: "post",
                        url: "/book/batchDelete?ids=" + ids,
                        success: function (result) {
                            if (result.code==200 && result.data == true) {
                                //删除成功
                                location.href = "book_list.html";
                            } else {
                                alter("删除失败, 请联系管理员");
                            }
                        }
                    });
                }
            }

        </script>
    </div>
</body>

</html>

根据需求可以得知, 后端需要提供两个接⼝

  1. 账号密码校验接⼝: 根据输⼊⽤⼾名和密码校验登录是否通过
  2. 图书列表: 提供图书列表信息

在这里插入图片描述

后端

@RequestMapping("/user")
@RestController
public class UserController {
	@RequestMapping("/login")
	public boolean login(String name, String password, HttpSession session){
		//账号或密码为空
		if (!StringUtils.hasLength(name) || !StringUtils.hasLength(password)){
			return false;
		}
		//模拟验证数据, 账号密码正确
		if("admin".equals(name) && "admin".equals(password)){
			session.setAttribute("userName",name);
			return true;
		}
		//账号密码错误
		return false;
	}
}
@RequestMapping("/book")
@RestController
public class BookController {
	@RequestMapping("/getList")
	public List<BookInfo> getList(){
		//获取数据
		List<BookInfo> books = mockData();
		//处理⻚⾯展⽰
		for (BookInfo book:books){
			if (book.getStatus()==1){
				book.setStatusCN("可借阅");
			}else {
				book.setStatusCN("不可借阅");
			}
		}
		return books;
	}
	/**
	* 数据Mock 获取图书信息
	*
	* @return
	*/
	public List<BookInfo> mockData() {
		List<BookInfo> books = new ArrayList<>();
		for (int i = 0; i < 5; i++) {
			BookInfo book = new BookInfo();
			book.setId(i);
			book.setBookName("书籍" + i);
			book.setAuthor("作者" + i);
			book.setCount(i * 5 + 3);
			book.setPrice(new BigDecimal(new Random().nextInt(100)));
			book.setPublish("出版社" + i);
			book.setStatus(1);
			books.add(book);
		}
		return books;
	}
}