当前位置: 首页 > news >正文

Java SpringMVC(二) --- 响应,综合性练习

文章目录

  • SpringMVC
    • 响应
      • 返回静态页面
      • 返回数据@Responsebody
      • 返回html的代码片段
      • 返回一个JSON
      • 设置状态码
      • 设置Header
      • 总结
    • 综合性练习
      • 1. 加法计算器
      • 2. 用户登陆
      • 项目如何debug
      • 3. 留言板
      • lombok
      • 留言板
      • 4. 图书管理系统
    • 应用分层

SpringMVC

响应

返回静态页面

  1. 返回静态页面
    1.元注解:可以被其他注解使用的叫做元注解
    @Target:表示注解修饰的对象
    {ElementType.TYPE}表示可以修饰类和接口
    @Documnted:文档,比如jdk有很多的注释,表示要不要保留这些注释

2.@RestController包括:@Controller和@ResponseBody
现在@RestController被用来返回数据了
在这里插入图片描述

3.@Controller的作用:告诉Spring,帮我们管理这个代码,我们后续访问时,才能访问到,才能使用我们写的代码,不写这个注解,Spring是不管这个代码的
在这里插入图片描述
注解的生命周期:
在这里插入图片描述
举个例子,写一个简单的静态页面(会打印index.html文件上的内容):
在这里插入图片描述
如果有多个注解,注解的顺序是不影响结果的

@RequestMapping("/return")
//@RestController // 返回数据
@Controller // 返回视图
public class ReturnController {@RequestMapping("/index")public String returnIndex(){// 使用@RestController时返回数据// 这时是返回这个数据,不是返回这个页面return "/index.html";}
}

返回数据@Responsebody

  1. @Responsebody可以修饰类,也可以修饰方法,修饰类的时候,表示这个类下的所有方法,返回的均为数据
    修饰方法时,表示该方法返回的是数据
  2. 如果一个类中的所有方法返回的都是数据,我们可以把这个注解加在类上

返回一个数据

@ResponseBody@RequestMapping("/returnData")public String returnData(){return "返回的是一个数据";}

返回html的代码片段

  1. 返回html的代码片段
// 返回代码片段@ResponseBody@RequestMapping("/returnHtml")public String returnHtml(){return "<h1>这是一个代码</h1>";}

在这里插入图片描述
在这里插入图片描述

返回一个JSON

  1. 返回一个JSON
 // 返回的是一个json对象@ResponseBody@RequestMapping("/returnJson")public Person returnJson(){Person person = new Person();person.setId(1);person.setAge(5);person.setName("zhangsan");return person;}

在这里插入图片描述
2. 返回一个Map对象

// 返回的是一个json对象@ResponseBody@RequestMapping("/returnJson")public Person returnJson(){Person person = new Person();person.setId(1);person.setAge(5);person.setName("zhangsan");return person;}@ResponseBody@RequestMapping("/returnMap")public Map<String,String> returnMap(){Map<String,String> map = new HashMap<>();map.put("k1","v1");map.put("k2","v2");map.put("k3","v3");return map;}

返回一个对象时,会自动帮我们设置为json格式,所以说返回的类型会被自动设置

设置状态码

  1. 状态码不影响页面的展示(显示的还是代码返回的内容,只是使用fiddler抓包时看到响应是401)
@ResponseBody@RequestMapping("/returnStaus")public String returnStaus(HttpServletResponse response){// 401通常表示没有登录response.setStatus(401);return "设置状态码";}

在这里插入图片描述

设置Header

  1. RequestMapping
    method用来设置(限制)请求的方式
    在这里插入图片描述
    下面这些方式通常都不会使用,限制的太多了
    在这里插入图片描述

  2. 使用produces来设置Header返回的类型

// 通过produces改变返回类型@ResponseBody@RequestMapping(value = "/r1",produces = "application/json; charset=utf-8")public String r1(HttpServletResponse response){// 可以设置header// header是键值对形式的response.setHeader("myhead","myhead");return "{'OK',1}";}

在这里插入图片描述
在这里插入图片描述

总结

  1. 对上面内容的总结:
    在这里插入图片描述

综合性练习

  1. 练习前端和后端的交互过程,请求,响应的处理

1. 加法计算器

  1. 前端代码(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><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>
  1. 后端代码:
package com.example.demo.controller;import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;@RequestMapping("/calc")
@RestController
public class CalcController {@RequestMapping("/sum")public String sum(Integer num1,Integer num2){// 这就是打印日志System.out.println("--------------------sum");Integer sum = num1 + num2;return "计算的结果为: " + sum;}
}

3. 如果报错了,该如何定位错误位置:
1.先定位前端还是后端问题
通过日志
(1) 前端:F12 看控制台
(2) 后端:接口,控制台日志

检测请求是否到达后端的方法:
(1) 可以进行抓包,看请求的路径

(2) 可以在后端进行打印信息,如果请求到了就会打印信息,否则不会打印信息(打印日志)

(3) 后端可以通过url或者是postman进行接口的测试(测试接口)

测试接口:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

2. 用户登陆

  1. 用户登录时,前端存在缓存问题,还是显示之前的页面信息,那么我们该如何清理缓存?

显示的不是登录后,用户的信息,而是显示之前这个html中的信息
在这里插入图片描述
可以点击maven中的clean清除里面的缓存,直接运行代码里面就包含了打包的工作,浏览器中也是存在缓存的,可能还需要清理浏览器中的缓存(清除浏览器的记录就可以了)

  1. 写代码之前做的工作:
    在这里插入图片描述

  2. 为什么登录时要设置Session的信息?
    在这里插入图片描述

  3. 可以先测试后端的接口(后端的接口和前端的代码是没有关系的),然后再写前端的代码

  4. 前端的代码:

登录的逻辑:

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="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>

登录成功后,进行页面跳转,显示用户名信息:

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="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. 后端的代码:
package com.example.demo.controller;import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;@RequestMapping("/user")
// 返回的是信息就使用这个注解
@RestController
public class UserController {// 检测是否登录成功@RequestMapping("/login")public Boolean login(String userName, String password, HttpSession session){// 1. 检验输入的用户名和密码是合法的(校验参数的合法性)
//        if(usename == null || usename.length() == 0 || password == null ||
//        password.length() == 0){
//            return false;
//        }// Spring也提供了一种方式检验用户名和密码是否和法的// StringUtils.hasLength()检验字符串是否有长度if(!StringUtils.hasLength(userName) || !StringUtils.hasLength(password)){return false;}// 2. 进行用户名和密码的校验if("admin".equals(userName) && "admin".equals(password)){// 设置Session,存储用户这次登录的信息session.setAttribute("usename","admin");return true;}return false;}// 第一种写法:// 如果登录成功,返回登录的用户的信息
//    @RequestMapping("getUserInfo")
//    // HttpSession session 没有session,会自动创建一个session
//    public String getUserInfo(HttpSession session){
//        // 从Session中获取用户的登录名
//        String usename = (String)session.getAttribute("usename");
//
//        return usename;
//    }// 第二种写法:@RequestMapping("/getUserInfo")public String getUserInfo(HttpServletRequest request){// 从Session中获取用户的登录名// 没有Session,就不要创建一个SessionHttpSession session = request.getSession(false);String usename = null;if(session != null) {usename = (String) session.getAttribute("usename");}return usename;}
}

展示效果:
在这里插入图片描述
登录后进行跳转页面:
在这里插入图片描述

项目如何debug

  1. 先打一个断点
  2. 然后点击这个小虫子,进行启动代码

断点打成功,会有一个√号
在这里插入图片描述

在这里插入图片描述
3. 后面步骤的调试项目和我们平常调试代码是一样的

3. 留言板

  1. 前端没有保存数据的功能,后端把数据保存下来(保存在内存,数据库,文件中等等…)
    为了让留言板刷新内容不会消失
    在这里插入图片描述
  2. 接口定义
    (1) 提交留言(给服务器)
    /message/publish
    参数:MessageInfo(from,to,message)
    返回结果:true/false

(2) 查看所有留言(后端显示所有留言)
/message/getMessageList
参数:无
返回结果:List< MessageInfo >

  1. lombok:工具包
    (1) 作用:如果一个类中有许多的变量,都需要get和set方法来设置,那就会很麻烦,这时使用lombok,就可以不用写这些get和set方法了

(2) 对于不熟悉的包,如何选择maven版本,建议选择次新版本(使用频率比较高的版本)

在这里插入图片描述
(3) @Data这个注解帮我们写了get方法和set方法,这个工具可以针对所有属性写get和set方法,也可以单独对某个属性写get和set方法
在这里插入图片描述
单独对某个属性写get和set方法
在这里插入图片描述
SpringBoot帮我们管理了这些包,所以应该集成了这些包,安装一个插件就可以使用插件导入这个包了,就需要从Maven仓库中导入这个包了

在这里插入图片描述
在这里插入图片描述

lombok

  1. lombo中的一些注解
    在这里插入图片描述
    在这里插入图片描述

  2. @ToString:自动帮我们写了ToString方法
    在这里插入图片描述

留言板

  1. 为什么前端校验之后,后端还需要校验?
    可能不是通过前端页面发起的请求,可能是一个非法的请求,这是最重要的原因

在这里插入图片描述
VSCode格式化:alt + shift + F,进行代码的对齐

  1. 前端代码:

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="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) {//2. 拼接节点的 htmlvar divE = "<div>" + m.from + "对" + m.to + "说:" + m.message + "</div>";//3. 把节点添加到页面上 $(".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: {"from": from,"to": to,"message": say},success: function (result) {if (result) {//添加成功//2. 拼接节点的 htmlvar divE = "<div>" + from + "对" + to + "说:" + say + "</div>";//3. 把节点添加到页面上 $(".container").append(divE);//4. 清空输入框的值$('#from').val("");$('#to').val("");$('#say').val("");} else {//添加失败alert("留言发布失败");}}});}</script>
</body></html>
  1. 后端代码:

MessageController:

package com.example.demo.controller;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<>();// 1. 提交留言@RequestMapping("/publish")public Boolean publishMessage(MessageInfo messageInfo){// 1. 进行参数的校验//    hasLenght表示没有为空if(!StringUtils.hasLength(messageInfo.getFrom()) ||!StringUtils.hasLength(messageInfo.getTo())||!StringUtils.hasLength(messageInfo.getMessage())){// 只要一个为空,就不发送return false;}// 2.添加留言messageInfos.add(messageInfo);return true;}// 2. 查看留言@RequestMapping("/getMessageInfo")public List<MessageInfo> getMessageInfo(){return messageInfos;}
}

用到的类:
MessageInfo:

package com.example.demo.controller;import lombok.Data;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;import java.util.Date;@Data
class MessageInfo {private String from;private String to;private String message;// private Date CreateTime;
}

效果展示:
在这里插入图片描述

4. 图书管理系统

  1. 目标:
    在这里插入图片描述

  2. 定义前后端交互接口
    (1) 登录
    url:/user/login
    参数:useName = ? & password = ?
    响应:true / false

(2) 图书列表展示
url:/book/getBookList
参数:无
响应:List< BookInfo >

  1. 后端代码:

图书类:BookInfo

package com.example.book2;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;// 图书的中文状态说明
}

登录:
UserController:

package com.example.book2;import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;import javax.servlet.http.HttpSession;@RequestMapping("/user")
@RestController
public class UserController {@RequestMapping("/login")public Boolean login(String useName, String password, HttpSession session){// 1. 校验参数// useName和password只要一个为空就返回falseif(!StringUtils.hasLength(useName) || !StringUtils.hasLength(password)){return false;}/*useName.equasl("admin"),如果useName为空时,会报空指针异常这是一个开发习惯*/// 2. 验证账号,密码是否正确if("admin".equals(useName) && "admin".equals(password)){// 账号密码正确// 存储Session,把用户名存起来session.setAttribute("useName",useName);return true;}return false;}
}

图书列表展示:

BookController:

package com.example.book2;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);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 ? 2 : 1);bookInfos.add(bookInfo);}return bookInfos;}
}

展示效果:
在这里插入图片描述
在这里插入图片描述

应用分层

  1. 三层架构
    在这里插入图片描述
  2. 代码中数据分层的表现
    在这里插入图片描述
  3. 那么这些代码的包也可以进行分层
    在这里插入图片描述
http://www.dtcms.com/a/465081.html

相关文章:

  • 【保姆级教程】VMware Workstation Pro 17安装及基础使用
  • 网站开发源代码mvc电子商务网站建设与管理实训报告
  • Bootstrap4 提示框详解
  • 数据分析硬件配置——选购计算机
  • 在Java中,如何实现封装?
  • 【实录】使用 patch-package 修复第三方 npm 包中的 Bug
  • Warm-Flow 1.8.2版本发布|新增功能和优化,体验更稳定
  • 电池组PACK自动化生产线介绍|深圳比斯特自动化
  • 云手机的挂机功能涉及到哪些内容
  • 手机群控软件在游戏运营中的风险管控技术实现
  • js打开网站做欧美市场的网站
  • MongoDB源码delete分析oplog:从删除链路到核心函数实现
  • 运维面试准备——综合篇(一)
  • 线性代数 · 矩阵 | SVD 与 PCA 应用区别
  • 网站漏洞扫描服务个人怎么做公众号
  • 云计算综合标准化体系建设提供系统性指引
  • 阿里云智能集团首席技术官云栖大会要点总结
  • 6. React useState基础使用:useState修改状态的规则;useState修改对象状态的规则
  • 凡科做的网站怎么打不开了天津做再生资源交易的网站
  • AWS Shield 与海外高防服务器的对比分析
  • CTF攻防世界WEB精选基础入门:cookie
  • Vue 中 props 传递数据的坑
  • Descheduler for Kubernetes(K8s 重调度器)
  • Embedding(嵌入):让机器理解世界的通用语言
  • sql练习题单-知识点总结
  • 网站空间域名续费湖南送变电建设公司 网站
  • 国产化PDF处理控件Spire.PDF教程:C#中轻松修改 PDF 文档内容
  • 文件预览(pdf、docx、xlsx)
  • AutoCAD如何将指定窗口导出成PDF?
  • 测试DuckDB电子表格读取插件rusty_sheet 0.2版