Spring Web MVC综合案例

news2025/1/20 16:33:35

  承接上篇文章——Spring Web MVC探秘,在了解Spring Web MVC背后的工作机制之后,我们接下来通过三个实战项目,来进一步巩固一下前面的知识。

 

一、计算器

效果展示:访问路径:http://127.0.0.1:8080/calc.html

 

 

前端代码:(文件名:calc.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>
     <!--点击“按钮”后,页面会跳转到calc/sum页面-->
     <form action="calc/sum" method="post">
        <h1>计算器</h1>
        数字1:<input name="num1" type="text"><br>
        数字2:<input name="num2" type="text"><br>
        <!-- 只有<input>标签且具有name属性的内容才会被作为表单参数,传递给后端-->
        <input type="submit" value=" 点击相加 ">
    </form>
</body>

</html>

 

后端代码: 

package com.example.mvc_test1;

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

@RestController
@RequestMapping("/calc")
public class CalcController {
    @RequestMapping("/sum")//访问路径=类路径+方法路径:/calc/sum
    public String sum(Integer num1,Integer num2){
        Integer sum= num1+num2;
        return "计算的结果是:"+sum;
    }
}

 

代码解析:

前端部分:

  当用户在num1和num2输入框中输入数字后,点击 “点击相加” 按钮,浏览器会根据<form>标签的action属性("calc/sum")和method属性("post"),将表单数据以POST请求的方式发送到后端对应的/calc/sum路径。

后端部分:

  1、后端的CalcController类被@RestController注解标记,表明它是一个处理 RESTful 请求的控制器,并且被@RequestMapping("/calc")映射到/calc路径下。


  2、sum方法被@RequestMapping("/sum")注解,意味着它处理/calc/sum路径的请求。


  3、当后端发送请求到calc/sum路径时,后端代码从前端参数表单中获取参数num1和num2,赋值给sum方法的两个名称对应的参数num1、num2


  4、Integer sum = num1 + num2;:在后端接收到这两个参数后,将它们相加,得到结果sum。
return "计算的结果是:" + sum;:最后,将计算结果以字符串的形式返回给前端,前端会根据响应进行相应的显示或处理。

二、用户登录界面


效果展示:访问路径:http://127.0.0.1:8080/login.html

用户名错误登录: 

 

用户名和密码正确登录:
 

 

 

后端代码:

  我们先来分析一下这个”登录界面”的需求,当用户输入用户名和密码之后,后端服务器需要做两件事:

1、判断用户是否进行合法的输入

2、校验用户名和密码是否正确

3、将用户名存入Session中

4、返回用户名给前端,

我们将这四件事封装到两个方法中:login方法和getUser方法

@RestController
@RequestMapping("/user")
public class UserController {

    //login方法:负责1、2、3件事务的完成
    @RequestMapping("/login") //访问路径:/user/login
    public boolean login(String userName,String password,HttpServletRequest request){
        //当用户输入空字符或者没有输入,返回false
        if(!StringUtils.hasLength(userName)||!StringUtils.hasLength(password)){
            return false;
        }else if("admin".equals(userName)&&"admin".equals(password)){//校验用户名和密码是否正确
            //用户名和密码这里都设置为admin
            //登录成功,将用户名设置到Session中
            HttpSession session=request.getSession();
            session.setAttribute("userName",userName);
            return true;
        }
        //其他情况,返回false
        return false;
    }


    //getUser方法,负责第4个事务的完成
    @RequestMapping("/getUser") //访问路径:user/getUser
    public String  getUserName(HttpServletRequest request){
        HttpSession session=request.getSession();//从请求报文中获取Session
        String userName=(String) session.getAttribute("userName");//从Session中获取userName
        return userName;
    }
}

   注:StringUtils.hasLength()是一个工具方法,用于检查字符串是否有长度(即不为null且长度大于0)。

  前端代码:登录页面(login.html) 和登录成功的页面(index.html)

由于这两个页面的实现,需要引入一个js文件,我们先来讲一下如何有引入?

1、js下载文件网址: https://code.jquery.com/jquery-3.7.1.min.js

 

2、将刚刚下载的js文件,赋值粘贴到static文件夹下面:

  

登录页面:login.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="jquery-3.7.1.min.js"></script>  <!--  引入js文件-->
  <script>
    function login() {
      $.ajax({
        type:"post",//请求类型
        url:"/user/login",//访问后端服务器的user/login
        data:{
          //获取标签的值,赋值给后端指定的参数
          //左边的usrName表示后端/user/login 方法中的参数userName
          //右边userName表示id为userName的标签
          "userName":$("#userName").val(),//val()获取标签的值
          "password":$("#password").val()
        },
        success:function (result){//访问成功,后端返回一个结果,作为function的参数result
          //访问/user/login时,后端会将这个请求交给login方法处理,处理结果返回true或false,表示登录成功与否
          if(result==true){//用户名和密码正确,后端返回true
            location.href="index.html";
          }else{
            alert("用户名或者密码错误");
          }
        }
      });
    }

  </script>
</body>

</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="jquery-3.7.1.min.js"></script> <!--  引入js文件-->
    <script>
        $.ajax({
            type:"get",
            url:"/user/getUser",
            success:function (userName){//访问成功,后端返回的结果作为function方法的参数
                //访问user/getUser时,后端会将这个请求交给getUser方法处理,结果返回用户名
                $("#loginUser").text(userName);
        }
        });

    </script>
</body>

</html>

 

前端代码解析:

  或许你有一个疑问,用户在输入用户名和密码后,校验工作是在后端中的login方法完成的,那么校验完成后,前端是如何获取后端检验后的结果呢?这其实借助了一个技术——Ajax。

  Ajax(Asynchronous JavaScript and XML)即异步 JavaScript 和 XML,是一种创建快速动态网页的技术。

  这里截取了login.html前端代码中使用到Ajax的部分代码(省略注释版):

$.ajax({
    type: "post", 
    url: "/user/login", 
    data: {
        "userName": $("#userName").val(), 
        "password": $("#password").val()
    },
    success: function (result) {
        if (result == true) {
            location.href = "index.html";
        } else {
            alert("用户名或者密码错误");
        }
    }
});

 1、  $.ajax({...}):这是 jQuery 的 ajax 函数,用于发起HTTP 请求。


 2、type: "post":指定请求的类型为 POST。这意味着会向服务器发送一个 POST 请求。


 3、url: "/user/login":指定请求的 URL,即要发送请求的后端服务地址,这里会将请求发送到 /user/login 路径。


 4、data:这是要发送给服务器的数据,是一个对象。"userName": $("#userName").val():使用 jQuery 的 $("#userName") 选择器选中 id 为 userName 的元素,并通过 val() 方法获取其值,将其赋值给 userName 属性。


5、"password": $("#password").val():同理,获取 id 为 password 的元素的值,并将其赋值给 password 属性。


6、success: function (result) {...}:定义请求成功时的回调函数。result:当请求成功后,服务器返回的数据将作为 result 参数传递给该回调函数。


7、if (result == true) {...} else {...}:根据服务器返回的结果进行不同的操作。location.href = "index.html";:如果结果为 true,说明登录成功,将页面重定向到 index.html。alert("用户名或者密码错误");:如果结果不为 true,弹出一个警告框,提示用户用户名或密码错误。

三、留言板

效果展示:访问路径:http://127.0.0.1:8080/messagewall.html

 

后端代码:

  让我们来分析一下这个“留言板”,首先,在打开这个留言板的时候,留言板会加载历史的留言记录,然后,在用户添加新留言之后,点击“提交”,新的留言会添加到页面上。

  根据功能,后端代码需要完成两件事:

1、在前端打开这个页面的时候,返回历史留言内容给前端,用于前端加载历史留言内容

2、在用户添加新的留言的时候,将这条新留言存储在后端服务器中

MessageInfo类:

@Data//会自动生成该类的成员的Getter和Setter等方法,需要在pom.xml引入lombok依赖
public class MessageInfo {
    String from;
    String to;
    String say;
}

在pom.xml中引入lombok依赖(@Data注解使用需要) 

 

 

MessageController类:

@RestController
@RequestMapping("/message")
public class MessageController {
    List<MessageInfo> list=new ArrayList<>();//存放留言内容
    
    //getList方法:返回历史留言内容给前端(访问路径:/message/getList)
    @RequestMapping("/getList")
    public List<MessageInfo> getList(){
        return list;
    }


    
    //publish方法:将用户新添加的留言存在后端服务器中(访问路径:/message/publish)
    //获取用户输入的内容,添加到list,返回一个json字符串
    @RequestMapping(value = "/publish",produces = "application/json")
    //指定该方法返回的数据类型为application/json,表明此方法返回的内容是 JSON 格式。告知前端返回的数据是 JSON 格式。
    public String publish(@RequestBody MessageInfo message){
        if(StringUtils.hasLength(message.from)&&
           StringUtils.hasLength(message.to)&&
           StringUtils.hasLength(message.say)){
            list.add(message);
            return "{\"ok\":1}";//1表示添加成功
        }
        return "{\"ok\":0}";//0表示添加失败

    }
}

前端代码: messagewall.html

<!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="jquery-3.7.1.min.js"></script> <!--  引入js文件-->
    <script>
        //加载历史留言记录
        $.ajax({
            type:"get",
            url:"/message/getList",
            success:function (list){
                for(let msg of list){
                    console.log(1);
                    let divE = "<div>"+msg.from +"对" +msg.to + "说:" + msg.say+"</div>";//拼接留言
                    $(".container").append(divE);//把留言内容添加到页面上
                }
            }
        });
        function submit(){
            //获取留言的内容
            var from = $('#from').val();
            var to = $('#to').val();
            var say = $('#say').val();
            if (from== '' || to == '' || say == '') {
                return;
            }
            //传递留言内容给前端
            $.ajax({
                type:"post",
                url:"/message/publish",
                contentType:"application/json",
                data:JSON.stringify({
                    "from":from,
                    "to":to,
                    "say":say
                }),
                success:function (result){
                    if(result.ok==1){
                        alert("添加成功")
                        //构造节点
                        let divE = "<div>"+from +"对" + to + "说:" + say+"</div>";
                        //把节点添加到页面上
                        $(".container").append(divE);
                        //清空输入框的值
                        $('#from').val("");
                        $('#to').val("");
                        $('#say').val("");
                    }else{
                        alert("添加失败")
                    }
                }
            });

            
        }
        
    </script>
</body>

</html>

 

 前端代码解析:

1、注释“传递留言内容给前端部分”代码:

   contentType: "application/json":告诉后端,我要传给你一个Json字符串的数据。
   data: JSON.stringify({...}):将包含from、to、say的对象转换为 JSON 字符串作为请求数据发送给后端,让后端的publish方法中的message接收。

  success:function(result):当后端返回一个json字符串给前端接收时,前端会自动将这个json字符串转换为一个对象,例如这里的publish方法返回的如果是 {“ok”:1} 的json字符串,将其作为参数传送给function时,此时的result就成为了一个包含“ok”属性的对象,其属性值为1。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2279444.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

数据结构与算法面试专题——引入及归并排序

数据结构与算法引入 我们都知道数据结构与算法很重要&#xff0c;甚至会将其称为程序员的“内功”&#xff0c;但是我们花了很多时间学的算法和数据结构&#xff0c;好像就只是为了应对算法面试&#xff0c;对日常的开发工作没有什么帮助。 这点对于我们数据工程师来说&#…

OpenHarmony 4.1 SDK11 北向应用开发笔记

目录 声明 1、开启其他应用 2、延时切换页面 3、设置页面切换效果 4、设置背景图片和背景铺满屏幕 5、设置隐藏状态和导航条 6、设置组件大小和对齐方式 7、设置按钮类型改变按钮边框圆角半径 8、常用布局方式 9、布局技巧 声明 本笔记基于OpenHarmony 4.1 SDK11&am…

【Linux】进程的程序替换

前言&#xff1a; 在未进行进程的程序替换时&#xff0c;父子进程的数据是独立的通过页表进行映射进行实现进程数据的独立性&#xff0c;但是父子进程的代码还是共享的&#xff0c;我父进程将子进程进行创建出来不仅仅只会有父子进程只进行执行共享代码的需求&#xff0c;有的…

Java测试开发平台搭建(九)前端

1. 搭建前端vue环境 Vue3 安装 | 菜鸟教程 2. 创建项目 1.进入ui vue ui 2. create项目 3. 成功之后添加插件&#xff1a; cli-plugin-router vue-cli-plugin-vuetify 4. 添加依赖 axios 5. 点击任务开始运行 如果报错&#xff1a; 修改vue.config.jsconst { defineConfig }…

Asp .Net Core 实现微服务:集成 Ocelot+Nacos+Swagger+Cors实现网关、服务注册、服务发现

什么是 Ocelot ? Ocelot是一个开源的ASP.NET Core微服务网关&#xff0c;它提供了API网关所需的所有功能&#xff0c;如路由、认证、限流、监控等。 Ocelot是一个简单、灵活且功能强大的API网关&#xff0c;它可以与现有的服务集成&#xff0c;并帮助您保护、监控和扩展您的…

【机器学习实战入门】使用Pandas和OpenCV进行颜色检测

Python 颜色检测项目 今天的项目将非常有趣和令人兴奋。我们将与颜色打交道&#xff0c;并在项目过程中学习许多概念。颜色检测对于识别物体来说是必要的&#xff0c;它也被用作各种图像编辑和绘图应用的工具。 什么是颜色检测&#xff1f; 颜色检测是检测任何颜色名称的过程…

如何实现文本相关的显示功能

文章目录 1 概念介绍2 使用方法3 示例代码 我们在上一章回中介绍了页面之间传递数据相关的内容,本章回中将介绍如何使用Text Widget。闲话休提&#xff0c;让我们一起Talk Flutter吧。 1 概念介绍 我们在这里说的Text Widget就是显示文字内容的组件&#xff0c;其实我们一直在…

精度论文:【Focaler-IoU: More Focused Intersection over Union Loss】

Focaler-IoU: 更聚焦的交并比损失 Focaler-IoU: More Focused Intersection over Union Loss Focaler-IoU: 更聚焦的交并比损失I. 引言II. 相关工作III. 方法IV. 实验V. 结论 原文地址&#xff1a;官方论文地址 代码地址&#xff1a;官方代码地址 摘要——边界框回归在目标检…

计算机组成原理--笔记二

目录 一.计算机系统的工作原理 二.计算机的性能指标 1.存储器的性能指标 2.CPU的性能指标 3.系统整体的性能指标&#xff08;静态&#xff09; 4.系统整体的性能指标&#xff08;动态&#xff09; 三.进制计算 1.任意进制 > 十进制 2.二进制 <> 八、十六进制…

BERT与CNN结合实现糖尿病相关医学问题多分类模型

完整源码项目包获取→点击文章末尾名片&#xff01; 使用HuggingFace开发的Transformers库&#xff0c;使用BERT模型实现中文文本分类&#xff08;二分类或多分类&#xff09; 首先直接利用transformer.models.bert.BertForSequenceClassification()实现文本分类 然后手动实现B…

MySQL - 主从同步

​​​​​​1.主从同步原理&#xff1a; MySQL 主从同步是一种数据库复制技术&#xff0c;它通过将主服务器上的数据更改复制到一个或多个从服务器&#xff0c;实现数据的自动同步。 主从同步的核心原理是将主服务器上的二进制日志复制到从服务器&#xff0c;并在从服务器上执…

[Python学习日记-78] 基于 TCP 的 socket 开发项目 —— 模拟 SSH 远程执行命令

[Python学习日记-78] 基于 TCP 的 socket 开发项目 —— 模拟 SSH 远程执行命令 简介 项目分析 如何执行系统命令并拿到结果 代码实现 简介 在Python学习日记-77中我们介绍了 socket 基于 TCP 和基于 UDP 的套接字&#xff0c;还实现了服务器端和客户端的通信&#xff0c;本…

STM32Cubemx配置RS485通信

文章目录 一、RS485协议概念讲解RS485 协议概念1. **差分信号传输**2. **半双工通信**3. **多点通信**4. **最大通信距离和速度**5. **终端电阻与偏置电阻**6. **RS485 接口的工作模式**7. **RS485 协议的数据帧结构**8. **RS485 的优点与应用** 总结 二、TTL电平和RS485的关系…

STM32使用DSP库 Keil方式添加

文章目录 前言一、添加DSP库二、使能FPU及配置1. 使能FPU2. 增加编译的宏3.增加头文件的检索路径三. 验证1. 源码中添加2.代码测试前言 添加DSP有两种方案,本文采用的是是Keil 中添加。 一、添加DSP库 在创建好的工程中添加DSP库:步骤如下: 步骤1:选择运行环境管理; 步…

Kotlin Bytedeco OpenCV 图像图像54 透视变换 图像矫正

Kotlin Bytedeco OpenCV 图像图像54 透视变换 图像矫正 1 添加依赖2 测试代码3 测试结果 在OpenCV中&#xff0c;仿射变换&#xff08;Affine Transformation&#xff09;和透视变换&#xff08;Perspective Transformation&#xff09;是两种常用的图像几何变换方法。 变换方…

【Flink系列】10. Flink SQL

10. Flink SQL Table API和SQL是最上层的API&#xff0c;在Flink中这两种API被集成在一起&#xff0c;SQL执行的对象也是Flink中的表&#xff08;Table&#xff09;&#xff0c;所以我们一般会认为它们是一体的。Flink是批流统一的处理框架&#xff0c;无论是批处理&#xff08…

【STM32-学习笔记-11-】RTC实时时钟

文章目录 RTC实时时钟一、RTC简介二、RTC框图三、RTC基本结构四、RTC操作注意事项五、RTC函数六、配置RTCMyRTC.c 七、示例&#xff1a;实时时钟①、main.c②、MyRTC.c③、MyRTC.h RTC实时时钟 一、RTC简介 RTC&#xff08;Real Time Clock&#xff09;实时时钟 RTC是一个独立…

Spring的IoC、Bean、DI的简单实现,难度:※※※

目录 场景描述 第一步&#xff1a;初始化Maven项目 第二步&#xff1a;Maven导入Spring包&#xff08;给代码&#xff09; 第三步&#xff1a;创建Spring配置文件 第四步 创建Bean 第五步 简单使用Bean &#xff08;有代码&#xff09; 第六步 通过依赖注入使用Bean&…

Tensor 基本操作1 | PyTorch 深度学习实战

目录 创建 Tensor常用操作unsqueezesqueezeSoftmax代码1代码2代码3 argmaxitem 创建 Tensor 使用 Torch 接口创建 Tensor import torch参考&#xff1a;https://pytorch.org/tutorials/beginner/basics/tensorqs_tutorial.html 常用操作 unsqueeze 将多维数组解套&#xf…

自然语言处理——自注意力机制

一、文字表示方法 在自然语言处理中&#xff0c;如何用数据表示文字是基础问题。独热编码&#xff08;One-hot Encoding &#xff09;是一种简单的方法&#xff0c;例如对于 “我”“你”“他”“猫”“狗” 等字&#xff0c;会将其编码为如 “我 [1 0 0 0 0 ……]”“你 [0 …