Spring MVC

 9. 获取Cookie/Session

简洁的获取方式(注解获取)

@CookieValue

2.3 返回数据

1. 返回静态页面

//@RestController
@Controller
public class ReturnController {
    @RequestMapping("/index")
    public String returnIndex() {
        return "/index.html";  //返回页面里面的数据
    }
}

 编写的HTML文件

@Controller: 返回视图  随着前后端分离,后端不处理页面,就返回页面上所需要的数据
@ResponseBody: 返回数据

 两个加起来就是@RestController

 2. 返回数据

    @ResponseBody  //因为上方的注解@Controller是返回视图,就会去找HTML,所以要加@ResponseBody返回数据
    @RequestMapping("/returnDate")
    public String returnDate() {
        return "返回视图需要的数据";
    }

 @Responsebody

可以修饰类,也可以修饰方法

修饰的时候,表示这个类下的所有方法,返回的均为数据

修饰方法的时候,表示该方法返回的都是数据

如果一个类中的所有方法返回的都是数据,我们就把这个注解加在类上

3. 返回html代码片段

    @ResponseBody  //因为上方的注解@Controller是返回视图,就会去找HTML,所以要加@ResponseBody返回数据
    @RequestMapping("/returnHtml")
    public String returnHtml() {
        return "<h1>返回HTML代码片段<h1>";
    }

4. 返回JSON 

    @ResponseBody  //因为上方的注解@Controller是返回视图,就会去找HTML,所以要加@ResponseBody返回数据
    @RequestMapping("/returnJson")
    public Person returnJson() {
        Person person = new Person();  //创建对象
        person.setId(12);
        person.setName("caijun");
        person.setAge(23);
        return person;
    }

 

当我们的接口返回的是String时,content-Type是text/html

当我们的接口返回的是对象/Map时,content-Type自动设置为application/json

5. 设置状态码

 状态码不影响页面的显示

    @ResponseBody  //因为上方的注解@Controller是返回视图,就会去找HTML,所以要加@ResponseBody返回数据
    @RequestMapping("/setStatus")
    public String setStatus(HttpServletResponse response) {
        response.setStatus(401);  //通常表示没有登录
        return "设置状态码";
    }

 

综合练习-加法计算器

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

接口定义: 

  • 请求路径: calc/sum
  • 请求方式: GET/POST
  • 接口描述: 计算两个整数相加

请求参数:

参数名类型是否必须备注
num1        Integer参与计算的第一个数
num2Integer参与计算的第二个数

响应数据:

Content-Type: test/html

响应内容: 计算机计算结果: 8

编写前端html文件放入static文件夹

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

运行代码后直接访问

编写后端代码

//加法计算器
@RequestMapping("/calc")
@RestController
public class CalcController {
    @RequestMapping("/sum")
    public String sum(Integer num1, Integer num2) {
        Integer sum = num1 + num2;
        return "计算结果为: "+ sum;
    }

注意:后端代码的命名要与前端命名一致

综合练习-用户登录

需求:用户输⼊账号和密码,后端进⾏校验密码是否正确
1. 如果不正确,前端进⾏用户告知
2. 如果正确,跳转到首页.首页显⽰当前登录⽤⼾
3. 后续再访首页,可以获取到登录用户信息
 

登录案例

1. 登录接口

        接口: /user/login

        参数: userName = ? & password = ?

        接口返回: 校验成功还是失败(true/false)

2. 获取用户登录信息

        接口: /user/getUserInfo

        接口返回: 当前登录用户的名称

后端服务代码

@RequestMapping("/user")
@RestController
public class UserController {
    @RequestMapping("/login")
    public Boolean login(String userName, String password, HttpSession session) {
        //校验参数的合法性
        if(userName == null || password == null || userName.length() == 0 ||password.length() == 0) {
            return false;
        }
        //另一种 (有没有长度)
//        if (!StringUtils.hasLength(userName) || !StringUtils.hasLength(password)) {
//            return false;
//        }

        //进行用户名和密码的校验
        if ("admin".equals(userName) && "admin".equals(password)) {
            //设置session
            session.setAttribute("userName", "admin");
            return true;
        }
        return false;
    }

  /*  @RequestMapping("/getUserInfo")
    public String getUserInfo(HttpSession session) {  //session如果没有的话会自己创建一个空的
        //从Session 获取登录用户
        String userName = (String) session.getAttribute("userName");
        return userName;
    }*/

    @RequestMapping("/getUserInfo")
    public String getUserInfo(HttpServletRequest request) {  //session如果没有的话会自己创建一个空的
        //从Session 获取登录用户
        HttpSession session = request.getSession();
        String userName = null;
        if (session != null) {
            userName = (String) session.getAttribute("userName");
        }
        return userName;
    }
}

前端页面代码

登录页

<!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() {
      console.log("登录...");
      $.ajax({
        url: "/user/login",
        type: "post",
        data:{
          "userName": $("#userName").val(),
          "password": $("#password").val()
        },
        success:function(result){
          if(result){
            location.href = "/index.html";
            // location.assign();
          }else{
            alert("密码错误");
          }
        }
      });
    }

  </script>
</body>

</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="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.4/jquery.min.js"></script>
    <script>

        //页面加载时, 就去调用后端请求
        $.ajax({
            url: "/user/getUserInfo",
            type:"get",
            success:function(username){
                $("#loginUser").text(username);
            }
        });
    </script>
</body>

</html>

运行测试

综合练习-留言板

 需求: 

界面如下图所示

  1. 输入留言信息,点击提交,后端把数据存储起来
  2. 页面展示输入的表白信息

前端服务代码

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

<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({
        url:"/message/getMessageInfo",
        type:"get",
        success:function (messages){
            for (var m of messages) {
                //拼接节点的HTML
                var divE = "<div>" + m.from + "对" + m.to + "说:" + m.say + "</div>";
                //把节点添加到页面上
                $(".container").append(divE);
            }
        }
    })

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

                    //4. 清空输入框的值
                    $('#from').val("");
                    $('#to').val("");
                    $('#say').val("");
                } else {
                    //添加失败
                    alert("留言板发布失败")
                }
            }
        })


    }

</script>
</body>

</html>

写后端代码之前要进行接口定义

  1. 提交留言: /message/publish    参数对象: MessageInfo(from, to, message)    返回结果: true/false
  2. 查看所有留言: /message/getMessageList  参数:     返回结果: List<MessageInfo>

编写后端服务代码

package org.example.demo.controller;

import org.apache.logging.log4j.message.Message;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.ArrayList;
import java.util.List;
@RequestMapping("/message")
@RestController
public class MessageController {

    private List<MessageInfo> messageInfos = new ArrayList<>();
    //提交留言
    @RequestMapping("/publish")
    public Boolean publishMessage(MessageInfo messageInfo) {
        //进行参数的校验
        if (!StringUtils.hasLength(messageInfo.getMessage()) ||
                !StringUtils.hasLength(messageInfo.getTo()) ||
                !StringUtils.hasLength(messageInfo.getFrom()) )  {
            return false;
        }

        //添加留言
        messageInfos.add(messageInfo);  //添加进内存
        return true;
    }

    //查看留言
    @RequestMapping("/getMessageInfo")
    public List<MessageInfo> getMessages() {
        return messageInfos;  //返回集合里所添加的数
    }
}

利用postman测试接口

 

综合练习-图书管理系统

需求: 

  1. 登录: 用户输入账号,.密码完成登录功能
  2. 列表展示: 展示图书

定义前后端交互接口

1. 登录

URL: /user/login

参数: userName = ?& password = ? 

响应: true/false

2. 图书列表展示

URL: /book/getBookList

参数:

响应: List<BookInfo>

编写后端服务代码

建一个图书类

package org.example.demo;

import lombok.Data;

import java.math.BigDecimal;

@Data
public class BookInfo {
    private Integer id;
    private String bookName;
    private String author;
    private Integer count;
    private BigDecimal price;  //价格
    private String publish;
    private Integer status;  //1-可借阅  2-不可借阅
    private String statusCN;


}

登录接口

package org.example.demo;

import jakarta.servlet.http.HttpSession;
import jakarta.websocket.Session;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RequestMapping("/user")
@RestController
public class UserController {
    @RequestMapping("/login")   //登录接口
    public boolean login(String userName, String password, HttpSession session) {
        //检验参数
        if(!StringUtils.hasLength(userName) || !StringUtils.hasLength(password)) {
            return false;
        }

        /*
        if(userName.("admin")) {}  这种写法,如果userName为null,会报空指针异常
         */
        //验证账号密码是否正确
        if("admin".equals(userName) && "admin".equals(password)) {  //"admin"写在前面
            //账号密码正确 存Session
            session.setAttribute("userName",userName);
            return true;
        }
        return false;
    }
}

图书列表接口

package org.example.demo;

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;

@RequestMapping("/book")
@RestController
public class BookController {
    @RequestMapping("getBookList")   //图书列表的接口
    public List<BookInfo> getBookList() {
        //1. 获取图书的数据
        //2. 对图书的数据进行处理
        //3. 返回数据
        //mock表示虚拟数据
        List<BookInfo> bookInfos = mockData();
        for (BookInfo bookInfo: bookInfos) {
            if(bookInfo.getStatus()==1){
                bookInfo.setStatusCN("可借阅");
            }else {
                bookInfo.setStatusCN("不可借阅");
            }
        }
        return bookInfos;
    }

    private List<BookInfo> mockData() {
        //对于已知的数据量可以创建List时指定初始容量
        List<BookInfo> bookInfos = new ArrayList<>(15);  //15设置为固定长度
        for (int i = 0; i < 15; i++) {
            BookInfo bookInfo = new BookInfo();
            bookInfo.setId(i);
            bookInfo.setBookName("图书"+i);
            bookInfo.setAuthor("作者"+i);
            bookInfo.setCount(new Random().nextInt(200));  //库存随机
            bookInfo.setPrice(new BigDecimal(new Random().nextInt(100)));  //价格随机
            bookInfo.setPublish("出版社"+i);
            bookInfo.setStatus(i%5==0?1:0);
            bookInfos.add(bookInfo);
        }
        return bookInfos;

    }
}

打开postman进行登录接口测试

 打开postman进行图书列表接口测试

后端代码测试完成,接下来就可以写前端代码了

<!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({
                url:"user/login",
                type:"post",
                data:{    //接口:传送数据给后端
                    "userName": $("#userName").val(),
                    "password": $("#password").val(),
                },
                success:function (result){  //后端返回
                    if(result) {
                        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>

                <tr>
                    <td><input type="checkbox" name="selectBook" value="1" id="selectBook" class="book-select"></td>
                    <td>4</td>
                    <td>大秦帝国第四册</td>
                    <td>我是作者</td>
                    <td>23</td>
                    <td>33.00</td>
                    <td>北京出版社</td>
                    <td>可借阅</td>
                    <td>
                        <div class="op">
                            <a href="book_update.html?bookId=4">修改</a>
                            <a href="javascript:void(0)" onclick="deleteBook(4)">删除</a>
                        </div>
                    </td>
                </tr>
            </tbody>
        </table>

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

            getBookList();
            function getBookList() {
                $.ajax({
                    type:"get",
                    url:"/book/getBookList",
                    success:function (books) {
                        var finalHtml = "";
                        for (var book of books){
                            //根据每一条记录拼接html,也就是一个tr
                            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.author+'</td>';
                            finalHtml+='<td>'+book.price+'</td>';
                            finalHtml+='<td>'+book.publish+'</td>';
                            finalHtml+='<td>'+book.statusCN+'</td>';
                            finalHtml+='<td><div class="op">';
                            finalHtml+='<a href="book_update.html?bookId='+book.id+'">修改</a>';
                            finalHtml+='<a href="javascript:void(0)" onclick="deleteBook('+book.id+')">删除</a>';
                            finalHtml+='</div></td></tr>';
                        }
                        console.log(finalHtml);
                        $("tbody").html(finalHtml);
                    }
                })
            }

            //翻页信息
            $("#pageContainer").jqPaginator({
                totalCounts: 100, //总记录数
                pageSize: 10,    //每页的个数
                visiblePages: 5, //可视页数
                currentPage: 1,  //当前页码
                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);
                }
            });
            function deleteBook(id) {
                var isDelete = confirm("确认删除?");
                if (isDelete) {
                    //删除图书
                    alert("删除成功");
                }
            }
            function batchDelete() {
                var isDelete = confirm("确认批量删除?");
                if (isDelete) {
                    //获取复选框的id
                    var ids = [];
                    $("input:checkbox[name='selectBook']:checked").each(function () {
                        ids.push($(this).val());
                    });
                    console.log(ids);
                    alert("批量删除成功");
                }
            }



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

</html>

测试:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值