四则运算API及其简单的前端页面
写这篇博客时,时间已经来到了周六的第一个六十分钟。很显然,这不是我第一次在这样的时间点盯着电脑屏幕,赶一个deadline;然而不同的是在此之前我并未在这样的时间点做过诸如此类文字记录的事。、
也许是自作多情,此时此时这样的一些deadline对于我来说到底意味着什么?足够成为忧伤或快乐的原因吗?
足够简单的产品描述
如题所述,这是一个基于Spring Boot的REST API,用于四则运算,它足够简单。
为了提高程序的可用性,我当然是听了zygg的建议啦,做了一个简单的前端界面 如下图:
简单而又朴素,不是吗?很显然,我们可以在第一个下拉列表处选择加减乘除 会不会有人不认识英文单词呢?乐
当你选择好加减乘除之后(默认为加法),输入参数a和参数b就可以进行计算了,当然你填入的顺序无所谓,也可以最后选择下拉列 表,最后点击开始计算就会得到你的计算结果。很遗憾,这里并没有实现隐式刷新并将结果放入到当前页面文本框中。
然而你可能会犯贱,输入一些奇奇怪怪的字符串。可¿?看到这里,你应该能想到你的计谋将要落空。
为了防止非法字符串发送到后端,我在前端防止了非数字输入空输入,以及溢出输入的情况:
其实这个工作交给后端也能做,然而我想不如直接在前端拦截,这样就可以后端的压力 后端:你在说什么,我在喝茶
同样的对于结果溢出也是做了简单处理,这次就轮到后端咯,直接if条件语句做了判断,当结果超过int类型范围时返回0.0000000
同样足够简单的文档学习
欧耶,当然是把zygg发来的文档全都看了一遍,然而大一因某种神秘力量gg的我对Spring Boot的了解确实太少(实话!!)链接也几乎都看了看,很遗憾,仍然有部分内容没办法理解,也许该请时间之神来帮帮我?不,我要纳西妲!!!paimon你肯定不会背叛我的是吧!
学习
关于Spring Boot:
spring是一个基于java的开源框架,很明显,这是为了简化java开发,提高开发效率。
sp
(暂且这么称呼它,可不能多想)提供了控制反转特性(IOC)的容器,在此之上,sp结合注入依赖的控制反转实现了对对象管理的生命周期容器化;除此之外,面向切面编程(AOP)也对开发管理提供了方便。spbt
(spring boot)是基于spring4.0设计的,它通过集成大量的框架使得内部解决依赖包版本冲突得到实现,同时也解决了部分的引用不稳定性,在sp的基础上,spbt进一步简化了搭建开发过程。关于Spring Bean 容器:
Spring bean是Spring框架在运行时管理的对象。Spring bean是Spring应用程序的基本构建模块Spring
bean的管理包括:
- 创建对象
- 提供依赖项
- 拦截对象方法调用以提供额外的框架功能
- 销毁对象
Spring负责创建bean对象,我们需要怎么做才能让框架创建呢
答案是提供bean定义
三种不同的bean定义方法:
1.使用构造型@Component注释注释类
2.编写在自定义Java配置类中用@Bean注释的bean工厂方法
3.在XML配置文件中声明bean定义
在现在的项目开发中一般只使用前两类定义Bean定义告诉Spring框架应该将哪些类用作bean
第一种:拥有源代码,通常直接在类上使用@Component注释。
在运行时,Spring会找到使用@Component或其派生类进行注释的类,并将它们用作bean定义。查找带注释的类的过程称为组件扫描。@Component派生:
它们是Spring构造型注释,它们本身用@Component注释,@Component派生列表包括:
@Service
@Repository
@Controller你可以使用这些注释将bean类标记为特定应用程序层的成员,Spring框架会将它们全部视为@Components。这些标识是传递给开发人员不同的结构化层次信息,无构造性实质区别。
第二种:当一个类属于外部库而无法使用@Component注释,就需要在自定义bean的配置类中使用@ Bean注释创建工厂方法。
@Configuration注释也来自Spring。其实它也是@Component的衍生物,但具有特殊用途。
Bean属性:
无论选择哪种bean定义方法,它们都允许描述同一组bean属性,在这个方面上方法没有什么区别。
属性提供有关Spring应如何创建对象的详细信息。属性包括:
- 类
- 名称
- 依赖
- 范围
- 初始化模式
- 初始化回调
- 破坏回调
Spring为几乎所有属性提供了默认值
类:创建bean定义时,将其与应用程序中的单个具体类连接。这个类本身是bean的主要属性
当Spring查找依赖项时,class属性是bean的默认标识符;在这种情况下仍然允许单个类多个bean定义,为避免歧义查找,需 要使用name标识名称:是Spring用于标识bean的自定义字符串。与bean类不同,名称在整个应用程序中是唯一的
Spring在运行时为bean内部使用生成名称,除非需要按名称识别bean,否则可以安全地使用默认设置依赖:用作bean的对象可以使用其他bean来执行。当创建一个定义某些依赖项的对象时,框架首先创建这些依赖项,这些依赖 项也可以有自己的依赖项。
当你有一个用@Component标记的类并且只有一个构造函数时,Spring使用构造函数参数列表作为必需依赖项列表。默 认框架使用构造函数参数类型来提供适当的对象。
如果bean类定义了多个构造函数,则应使用@Autowired标记一个。这样Spring知道哪个构造函数包含bean依赖项列表。范围:Spring bean的范围定义了框架在运行时创建的特定类的实例数。作用域还描述创建新对象的条件
Spring为你的bean提供了几个作用域。框架的核心有两个:单例 - 单个实例 / 原型 - 多个实例
此外,Spring还附带了专门用于Web应用程序的bean作用域:请求,会话,全局会话,应用级别Application
所有bean的默认作用域是单例 使用@Scope批注及其字符串属性选择范围
对于Web作用域,Spring附带了额外的别名注释。你可以使用这些注释代替@Scope:
- @RequestScope
- @SessionScope
- @ApplicationScope
Bean初始化模式:当应用程序启动时,立即创建所有单例bean
使用@Lazy注释可以将bean的创建延迟到实际需要的时刻Bean初始化回调:为了确保在Spring初始化对象之后运行逻辑(可选依赖),你应该使用初始化回调;在逻辑不依赖于框架本身 的时候,可以选择在构造函数中运行
设置初始化回调:
使用@Component定义bean :
使bean类实现InitializingBean。接口将强制实现初始化方法。
编写自定义初始化方法并使用javax @PostContruct注释进行标记
工厂方法定义的bean:
使用@Bean及其名为initMethod的属性设置初始化回调破坏回调:
可以访问源代码时:实现DisposableBean接口。Spring使用其唯一的方法进行销毁回调。
或者:
1. 编写自定义方法并使用Javax API中的@PreDestroy注释它。 2. 对于工厂方法,使用*@Bean*批注及其*destroyMethod*属性
Spring如何从Bean定义创建对象:
当你启动Spring应用程序时,框架首先会创建一个名为ApplicationContext的特殊对象。ApplicationContext,也称为控制反转(IoC)容器,是框架的核心。
ApplicationContext是存在bean对象的容器。上下文负责检测和读取Spring bean定义。一旦ApplicationContext加载了bean定义,它就可以根据提供的bean属性及其依赖关系开始为应用程序创建bean对象关于Maven:
由于时间关系,我并未学习到很多关于Maven的概念和实现
Maven在管理spbt的开发中有很大优势,它可以简洁地导入外部依赖包,使得构建,开发更加容易。
关于注解:
学习到了一些简单的诸如以下一些注释:@Component,@Repository,@Service,@Controller,@Mapper,@Autowired,@RestController, @GetMapping,@PostMapping,@PathVariable,@RequestParam,@Select,@Delete,@Update,@Insert、
对于后几种关于数据库的注释在此前项目中有所了解,然而对它们的实现还需要时间学习
关于前端:
emmmm?如何说呢,似乎是在复习?=¿()perhapshtml和css这类更加类似工具型的标记语言确实如同复习和重复使用,然而又如读小说,每次再用都还能学到一些新的东西,属于是
学艺不精了 ~~ 当然是认真学习的效果好吧 ~~仅限大二jvavscript的语法同样也又如读小说
说起来仍然是Ajax和JQuery的用法比较有趣,也许前后端一起写的快乐就来源于此?什么,还要写大型项目,爬
基本上对异步做了一次复盘,然而这一次并没有用上,so?准备开始爬咯
Code
@RestController
public class Main {
@GetMapping("/Operations")
public Double operations(@RequestParam String select , @RequestParam double a, @RequestParam double b){
if (Objects.equals(select, "add")&&a*b<=Integer.MAX_VALUE&& a * b >= Integer.MIN_VALUE) {
return a+b;
}else if(Objects.equals(select, "subtract")&&a*b<=Integer.MAX_VALUE&& a * b >= Integer.MIN_VALUE){
return a-b;
}else if(Objects.equals(select, "multiply")&&a*b<=Integer.MAX_VALUE&& a * b >= Integer.MIN_VALUE){
return a*b;
}else if(b!=0&&a*b<=Integer.MAX_VALUE&& a * b >= Integer.MIN_VALUE){
return a/b;
}
return 0.00000000;
}
}
<body>
<h4 style="text-align:center">这是一个支持结果在int类型大小之间的四则运算器</h4>
<div style="text-align:center">
<form action="http://localhost:8080/Operations" method="get" onsubmit=" return verify()">
<label><select name="select">
<option value="add">add</option>
<option value="subtract">subtract</option>
<option value="multiply">multiply</option>
<option value="divide">divide</option>
</select><br></label>
<label>参数1:<input type="text" id="a" name="a" required = required><br></label>
<label>参数2:<input type="text" id="b" name="b" required = required><br></label>
<input type="submit" value="开始计算" >
</form>
</div>
<script type="text/javascript">
function verify()
{
let x = document.getElementById("a").value;
let y = document.getElementById("b").value;
if(isNaN(x))
{
alert("失败,a参数不是数字");
return false;
}
if(isNaN(y))
{
alert("失败,b参数不是数字");
return false;
}
if(x>=1.7976931348623157e+308||x<4.9e-324){
alert("失败,a参数超出范围")
return false;
}
if(y>=1.7976931348623157e+308||x<4.9e-324){
alert("失败,b参数超出范围")
return false;
}
}
</script>
</body>