【JavaEE】留言板与图书管理系统

2024-06-06 07:28

本文主要是介绍【JavaEE】留言板与图书管理系统,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

目录

        • 留言板
          • 1. 准备工作
          • 2. 约定前后端交互接口
          • lombok
          • 3. 服务器代码
          • 4. 调整前端页面代码
        • 图书管理系统
          • 1. 准备工作
          • 2. 约定前后端交互接口
          • 3. 服务器代码
          • 4. 调整前端页面代码


留言板

需求:

界⾯如下图所⽰

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

前端没有保存数据的功能,后端把数据保存下来(内存或者数据库中…,这里先存内存中)

把前端⻚⾯放在项⽬中

<!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>function submit(){//1. 获取留言的内容var from = $('#from').val();var to = $('#to').val();var say = $('#say').val();if (from== '' || to == '' || say == '') {return;}//2. 构造节点var divE = "<div>"+from +"对" + to + "说:" + say+"</div>";//3. 把节点添加到页面上    $(".container").append(divE);//4. 清空输入框的值$('#from').val("");$('#to').val("");$('#say').val("");}</script>
</body></html>
2. 约定前后端交互接口

需求分析

后端需要提供两个服务

  1. 提交留⾔: ⽤⼾输⼊留⾔信息之后, 后端需要把留⾔信息保存起来
  2. 展⽰留⾔: ⻚⾯展⽰时, 需要从后端获取到所有的留⾔信息

接⼝定义

  1. 获取全部留⾔

全部留⾔信息, 我们⽤List来表⽰, 可以⽤JSON来描述这个List数据.

请求:

参数:无

GET /message/getList

响应: JSON 格式

返回结果:List<MessageInfo>

[{"from": "⿊猫","to": "⽩猫","message": "喵"},{"from": "⿊狗","to": "⽩狗","message": "汪"},//...
]

浏览器给服务器发送⼀个 GET /message/getList这样的请求, 就能返回当前⼀共有哪些留⾔记录. 结果以 json 的格式返回过来

  1. 发表新留⾔

请求: body 也为 JSON 格式.

参数:MessageInfo(from,to,message)

POST /message/publish{"from": "⿊猫","to": "⽩猫","message": "喵"
}

响应: JSON 格式.

返回结果:true/false

{ok: 1
}

我们期望浏览器给服务器发送⼀个 POST /message/publish 这样的请求, 就能把当前的留⾔提交给服务器.

lombok

在这个环节, 我们介绍⼀个新的⼯具包 lombok

Lombok是⼀个Java⼯具库,通过添加注解的⽅式,简化Java的开发.

简单来学习下它的使⽤

  1. 引⼊依赖
<!-- https://mvnrepository.com/artifact/org.projectlombok/lombok -->
<dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><version>1.18.24</version><scope>provided</scope>
</dependency>

引入后记得刷新

  1. 使用

lombok通过⼀些注解的⽅式, 可以帮助我们消除⼀些冗⻓代码, 使代码看起来简洁⼀些

⽐如之前的Person对象 就可以改为

@Data
public class Person {private int id;private String name;private String password;
}

@Data 注解会帮助我们⾃动⼀些⽅法, 包含getter/setter, equals, toString

  1. 原理解释

可以观察加了 @Data 注解之后, Idea反编译的class⽂件

这不是真正的字节码⽂件, ⽽是 IDEA 根据字节码进⾏反编译后的⽂件

反编译是将可执⾏的程序代码转换为某种形式的⾼级编程语⾔, 使其具有更易读的格式. 反编译是⼀种逆向⼯程,它的作⽤与编译器的作⽤相反

即.java文件就是用了注解的,.class文件是把加了这个注解的功能反编译了,变成你本应该自己写的代码

可以看出来, lombok是⼀款在编译期⽣成代码的⼯具包.

Java 程序的运⾏原理:

Lombok 的作⽤如下图所⽰:

  1. 更多使⽤

如果觉得@Data⽐较粗暴(⽣成⽅法太多), lombok也提供了⼀些更精细粒度的注解

注解作用
@Getter⾃动添加 getter ⽅法
@Setter⾃动添加 setter ⽅法
@ToString⾃动添加 toString ⽅法
@EqualsAndHashCode⾃动添加 equals 和 hashCode ⽅法
@NoArgsConstructor⾃动添加⽆参构造⽅法
@AllArgsConstructor⾃动添加全属性构造⽅法,顺序按照属性的定义顺序
@NonNull属性不能为 null
@RequiredArgsConstructor⾃动添加必需属性的构造⽅法,final + @NonNull 的属性为必需

@Data = @Getter + @Setter + @ToString + @EqualsAndHashCode + @RequiredArgsConstructor + @NoArgsConstructor

更快捷的引⼊依赖

上述引⼊lombok依赖, 需要去找lombok的坐标

接下来介绍更简单引⼊依赖的⽅式

  1. 安装插件EditStarter, 重启Idea

  1. 在pom.xml⽂件中, 单击右键, 选择Generate, 操作如下图所⽰

进⼊Edit Starters的编辑界⾯, 添加对应依赖即可.

注意:

不是所有依赖都可以在这⾥添加的, 这个界⾯和SpringBoot创建项⽬界⾯⼀样.

依赖不在这⾥的, 还需要去Maven仓库查找坐标, 添加依赖.

3. 服务器代码

定义留⾔对象 MessageInfo 类

@Data
public class MessageInfo {private String from;private String to;private String message;
}

创建 MessageController 类

使⽤ List<MessageInfo> 来存储留⾔板信息

@RestController
@RequestMapping("/message")
public class MessageController {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);return false;}@RequestMapping("/getMessageInfo")public List<MessageInfo> getMessage(){//直接返回留言return messageInfos;}
}

测试一下后端接口

为什么前端校验之后,后端还需要校验呢?

  1. 这是两个团队的事情
  2. 后端可能会收到攻击,收到非正常请求,比如什么爬虫之类的
4. 调整前端页面代码

修改 messagewall.html

vscode的代码格式化:alt+shift+F

  1. 添加函数, ⽤于在⻚⾯加载的时候获取数据
//页面加载时,请求后端,获取留言列表$.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);}}});
  1. 修改原来的点击事件函数. 在点击按钮的时候给服务器发送添加留⾔请求
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("留言发布失败");}}});}

测试http://127.0.0.1:8080/messagewall.html输入信息后点击刷新然后fiddler抓包

此时我们每次提交的数据都会发送给服务器. 每次打开⻚⾯的时候⻚⾯都会从服务器加载数据. 因此及时关闭⻚⾯, 数据也不会丢失.

但是数据此时是存储在服务器的内存中 ( private List<Message> messages = new ArrayList<Message>(); )

⼀旦服务器重启, 数据仍然会丢失.

要想数据不丢失, 需要把数据存储在数据库中, 后⾯再讲

图书管理系统

需求:

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

创建新项⽬, 引⼊对应依赖, 把前端⻚⾯放在项⽬中

系统后续其他功能也会完善, 此处建议创建新项⽬

在这里插入图片描述

2. 约定前后端交互接口

需求分析

图书管理系统是⼀个相对较⼤⼀点的案例, 咱们先实现其中的⼀部分功能.

1. ⽤⼾登录

2. 图书列表

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

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

接⼝定义

  1. 登录接口
[URL]
POST /user/login[请求参数]
userName=admin&password=admin[响应]
true //账号密码验证成功
false//账号密码验证失败
  1. 图书列表展示
[URL]
POST /book/getBookList[请求参数]
⽆[响应]
返回图书列表
[{"id": 1,"bookName": "活着","author": "余华","count": 270,"price": 20,"publish": "北京⽂艺出版社","status": 1,"statusCN": "可借阅"},...
]

字段说明:

字段含义
id图书ID
bookName图书名称
author作者
count数量
price定价
publish图书出版社
status图书状态 1-可借阅, 其他-不可借阅
statusCN图书状态中⽂含义
3. 服务器代码

创建图书类 BookInfo

@Data
public class BookInfo {//图书IDprivate Integer id;//书名private String bookName;//作者private String author;//数量private Integer conut;//价格private BigDecimal price;//出版社private String publish;//状态private Integer status;//1-可借阅 2-不可借阅private String statusCN;
}

这里为什么priceBigDecimal可以去查一下

https://www.cnblogs.com/jayworld/p/10107335.html

还有什么这里状态statusInteger而不是用字符串表示?

是因为这里数据库只能存数字,如果后续改需求了,就需要大改,而我们存的是数字,可以通过数字来映射成文字

创建 UserController, 实现登录验证接⼝

@RestController
@RequestMapping("/user")
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.equals("admin")这种写法,如果userName为null就会报空指针异常//这是开发习惯,要养成if("admin".equals(userName)&&"admin".equals(password)){//账号密码正确//存sessionsession.setAttribute("userName",userName);return true;}return false;}
}

创建 BookController, 获取图书列表

@RestController
@RequestMapping("/book")
public class BookController {@RequestMapping("/getBookList")public List<BookInfo> getBookList(){//1.获取图书数据List<BookInfo> bookInfos=mockData();//2.对图书数据进行修改处理for(BookInfo bookInfo:bookInfos){if(bookInfo.getStatus()==1){bookInfo.setStatusCN("可借阅");}else{bookInfo.setStatusCN("不可借阅");}}//3.返回数据return bookInfos;}//mock - 虚拟数据,假数据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.setConut(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;}
}

数据采⽤mock的⽅式, 实际数据应该从数据库中获取

mock:模拟的, 假的

在开发和测试过程中,由于环境不稳定或者协同开发的同事未完成等情况下, 有些数据不容易构造或者不容易获取,就创建⼀个虚拟的对象或者数据样本,⽤来辅助开发或者测试⼯作.

简单来说, 就是假数据。

上述经过Postman测试都没有问题

4. 调整前端页面代码

登录⻚⾯:

添加登录处理逻辑

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

图书列表展⽰:

删除前端伪造的代码, 从后端获取数据并渲染到⻚⾯上.

  1. 删除 标签中的内容

  1. 完善获取图书⽅法
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.count+'</td>';finalHtml+='<td>'+book.price+'</td>';finalHtml+='<td>'+book.publish+'</td>';finalHtml+='<td>'+book.statusCN+'</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>';}console.log(finalHtml);$("tBody").html(finalHtml);}});}

运行测试:http://127.0.0.1:8080/login.html,输⼊账号密码: admin admin, 登录成功, 跳转到 图书列表⻚

界⾯展⽰:

在这里插入图片描述

这篇关于【JavaEE】留言板与图书管理系统的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1035454

相关文章

JVM 的类初始化机制

前言 当你在 Java 程序中new对象时,有没有考虑过 JVM 是如何把静态的字节码(byte code)转化为运行时对象的呢,这个问题看似简单,但清楚的同学相信也不会太多,这篇文章首先介绍 JVM 类初始化的机制,然后给出几个易出错的实例来分析,帮助大家更好理解这个知识点。 JVM 将字节码转化为运行时对象分为三个阶段,分别是:loading 、Linking、initialization

Spring Security 基于表达式的权限控制

前言 spring security 3.0已经可以使用spring el表达式来控制授权,允许在表达式中使用复杂的布尔逻辑来控制访问的权限。 常见的表达式 Spring Security可用表达式对象的基类是SecurityExpressionRoot。 表达式描述hasRole([role])用户拥有制定的角色时返回true (Spring security默认会带有ROLE_前缀),去

浅析Spring Security认证过程

类图 为了方便理解Spring Security认证流程,特意画了如下的类图,包含相关的核心认证类 概述 核心验证器 AuthenticationManager 该对象提供了认证方法的入口,接收一个Authentiaton对象作为参数; public interface AuthenticationManager {Authentication authenticate(Authenti

Spring Security--Architecture Overview

1 核心组件 这一节主要介绍一些在Spring Security中常见且核心的Java类,它们之间的依赖,构建起了整个框架。想要理解整个架构,最起码得对这些类眼熟。 1.1 SecurityContextHolder SecurityContextHolder用于存储安全上下文(security context)的信息。当前操作的用户是谁,该用户是否已经被认证,他拥有哪些角色权限…这些都被保

Spring Security基于数据库验证流程详解

Spring Security 校验流程图 相关解释说明(认真看哦) AbstractAuthenticationProcessingFilter 抽象类 /*** 调用 #requiresAuthentication(HttpServletRequest, HttpServletResponse) 决定是否需要进行验证操作。* 如果需要验证,则会调用 #attemptAuthentica

Spring Security 从入门到进阶系列教程

Spring Security 入门系列 《保护 Web 应用的安全》 《Spring-Security-入门(一):登录与退出》 《Spring-Security-入门(二):基于数据库验证》 《Spring-Security-入门(三):密码加密》 《Spring-Security-入门(四):自定义-Filter》 《Spring-Security-入门(五):在 Sprin

Java架构师知识体认识

源码分析 常用设计模式 Proxy代理模式Factory工厂模式Singleton单例模式Delegate委派模式Strategy策略模式Prototype原型模式Template模板模式 Spring5 beans 接口实例化代理Bean操作 Context Ioc容器设计原理及高级特性Aop设计原理Factorybean与Beanfactory Transaction 声明式事物

Java进阶13讲__第12讲_1/2

多线程、线程池 1.  线程概念 1.1  什么是线程 1.2  线程的好处 2.   创建线程的三种方式 注意事项 2.1  继承Thread类 2.1.1 认识  2.1.2  编码实现  package cn.hdc.oop10.Thread;import org.slf4j.Logger;import org.slf4j.LoggerFactory

JAVA智听未来一站式有声阅读平台听书系统小程序源码

智听未来,一站式有声阅读平台听书系统 🌟&nbsp;开篇:遇见未来,从“智听”开始 在这个快节奏的时代,你是否渴望在忙碌的间隙,找到一片属于自己的宁静角落?是否梦想着能随时随地,沉浸在知识的海洋,或是故事的奇幻世界里?今天,就让我带你一起探索“智听未来”——这一站式有声阅读平台听书系统,它正悄悄改变着我们的阅读方式,让未来触手可及! 📚&nbsp;第一站:海量资源,应有尽有 走进“智听

在cscode中通过maven创建java项目

在cscode中创建java项目 可以通过博客完成maven的导入 建立maven项目 使用快捷键 Ctrl + Shift + P 建立一个 Maven 项目 1 Ctrl + Shift + P 打开输入框2 输入 "> java create"3 选择 maven4 选择 No Archetype5 输入 域名6 输入项目名称7 建立一个文件目录存放项目,文件名一般为项目名8 确定