概述
鉴于之前跟着视频做了一个前后端分离的小案例,这里总结一下做做笔记
所用到的一些技术:
mybatis-plus+springboot+element ui+axios
springboot入门
idea新建一个springboot项目
可以有多种方式
- 在联网情况下:
然后如下:
再然后在这里选择我们需要在这个工程里所需要的技术,左边是目录,将所需要的技术进行勾选,然后创建工程的时候就会自动导入对应的Maven的坐标。选好后点击next就会进行创建
如果需要的技术这里面没有,或者没有勾选,则我们可以在创建好后自己手动添加对应的坐标
- 在联网的情况下,我们可以使用aliyun提供的网站记进行下载
其他操作和官网版的一模一样
- 或者我们直接手动创建
很简单,我们先创建一个Maven项目,然后导入springboot相关的依赖坐标
然后创建一个类用注解将其设置为springboot的启动类
一个目录结构中,一般这个类放在这里:
设置为启动类的方法:
隐藏不想看见的文件或文件夹
其实如果我们不是手动创建的springboot项目,里面会有一些很杂的文件,如果我们不想看见1,可以把他隐藏起来,idea这里这样设置
我的idea是19版的,所以这里是这样,假设我们要隐藏后缀名是iml的文件,则在下面的框中添加这个:*.iml
,或者要隐藏文件夹mvnw,则添加mvnw
,或者隐藏vssver.scc文件,则添加vssver.scc
每个之间用;
隔开
springboot的程序优点
springboot主要是靠这四个来实现上面的优点的
parent、starter、引导类、内嵌tomcat
- parent
定义了java的编译版本1.8
使用的编码格式是utf-8
继承了 spring-boot-dependencies,这里定义了依赖的版本号,这也正是我们在写依赖的时候可以不用写版本号。
执行打包后的配置
自动化的插件配置
自动化的资源过滤 - starter
用依赖传递引入该场景的组件的所有需要的依赖
如spring-boot-starter-web会引入spring-webmvc等模块的依赖,我们引入spring-boot-starter-web就等于引入了spring-boot-starter-web所引用的依赖
这里面两个包含了基础的springboot所需的依赖
下面这个是spring-boot-starter-web
中所包含的依赖,包含了web基本所需的依赖
- 引导类
引导类就是启动类,就是这个加了@SpringBootApplication
注解的东西
运行他会产生一个spring容器,我们定义的bean就会加载到这个里面,如果我们定义的bean所在的目录结构大于启动类所在的目录结构,则无法扫描加载到 - 内嵌tomcat
这属于springboot的辅助功能,tomcat其实也是用java写的,在springboot中,将tomcat包装成一个对象,也交给bean容器去管理,当然,这些也都可以更换,比如使用jetty服务器,则可以将tomcat的依赖排除出去,然后导入jetty的依赖
springboot中还有着很多其他的辅助功能
配置文件
创建一个boot项目,boot会自动生成一个默认的配置属性的文件
书写方式:
按照key=value的方式来书写
在这里可以对spring各种属性进行配置,如配置每次启动spring控制台显示的那些东西,这属于banner的
可以根据需求进行各种设置
这里面可以设置的属性在boot的官方文档里面都可以找到,需要什么都可以去文档里面找
很重要一点,要学会一门技术,官方文档是必不可少的,下面是进入springboot官方文档的方法
查找spring boot的官方文档
先进入官网,然后选择spring boot,进入,然后就是下面这样的页面
点红圈这里
然后进到这个页面(这里我是用google带的页面翻译翻译过的)
这里等于是一个目录,给出各种文档的链接
配置文件类型
其实boot自己默认给我们创建的那种配置文件不如我们自己创建的一种以yml
为后缀的配置文件类型用起来舒服。即文件名.yml
这种的是以层级关系来展示属性之间的父子关系,按照
key:value
的方式来书写
yml入门
yml的教程,这里推荐看菜鸟教程,链接在这:https://www.runoob.com/w3cnote/yaml-intro.html
下面在补充一点东西:
配置文件后缀为 .yml的被称为YAML
- 引用数据
如果想将上面中的\t
变为制表符,则为其加上引号
- 在程序中使用我们属性配置文件中的数据
第一种方法是:
设置一个属性,为其加上注解@Value()
注解,参数填"${所要注入的配置文件中的key名字}"
key是什么?比如上面的一个属性tempDir:c:\windows\temp
,则key是temoDir,c:\windows\temp则是value
第二种方法是:
创建一个Environment类型的对象,加上自动装配的注解,那么这个对象就等于是把那个配置文件封装到这个对象里面
如果要使用某个key的value值,则可以这样env.getProperty("key")
获得 - 通过封装对象获取配置文件信息(重要!!!这是现在的主流)
假设此时yaml文件中有这么一组数据:
要将配置文件信息封装到对象中一般有三步:
1.定义数据模型封装yaml文件中对应的数据
这个数据模型必须有对应的属性,这些属性名必须跟yaml中对应的属性名一致,并且,需要为其提供get,set方法,这里我没写
2.定义为spring管控的bean
这个数据模型需要定义为spring管控的bean,为其加上@Componet
这样的注解,表示交由spring管控
3.指定加载的数据
然后指定加载的数据,需要在数据模型上面加上注解@ConfigurationProperties(属性的前缀)
如下:
如果要加载使用这些个数据,可以这样
跟正常的spring注入一样,定义一个这样类的属性,然后加注解,自动装配
这样,我们获得的这个对象就封装了我们前面配置文件中的那些属性信息,后面就直接使用即可
手动为springboot设置属性配置文件
我们可以手动为当前项目设置属性配置文件
整合junit之springboot测试
JUnit是一个Java语言的单元测试框架。多数Java的开发环境都已经集成了JUnit作为单元测试的工具。
我们创建一个springboot项目会自动导入包含junit的test包,这里面就包含了junit的包
这里主要是记录springboot中如何测试一个单元
生成的那个被加上@SpringBootTest
注解的就是测试类
有一个小问题,如果测试类所在的包的层级大于引导类所在的层级,则测试类无法拿到spring容器,这时候我们需要在@SpringBootTest
这个注解加上一个参数来指向引导类
这样:@SpringBootTest(classes = 引导类.class)
这里所说的"大于引导类所在的层级"中"层级"的意思是类上面的这个东西:
整合第三方技术
一般分为三步:
- 导入对应的starter(导入对应的依赖包)
- 做相应的配置
- 使用技术进行开发
整合mybatis
在创建项目的时候勾选上mybatis和mysql的选项,pom中就会导入对应的依赖
springboot中使用mybatis很简单,不需要进行很多乱七八糟的配置,这里我们只需要告诉boot一些他不知道的信息就行,就下面这些:
这属于属性配置,写在属性配置的配置文件中
这样就能用了
整合mybatis-plus
MyBatis-Plus (opens new window)(简称 MP)是一个 MyBatis (opens new window)的增强工具,在 MyBatis 的基础上只做增强不做改变,为简化开发、提高效率而生。
MP中为我们写好了很多常用的方法,我们可以直接调用
第一步导入对应的依赖包,创建项目的时候选择Mysql,但是没有MP的选项,我们需要自己去找对应的坐标。Maven查找对应的坐标的网站在这https://mvnrepository.com/
我们搜索MyBatis-Plus就能找到
MP基础用法:
首先依然先写Dao层的接口,这和正常的mybatis一样。
要用MP,则需要让这个类继承一下MP的相关东西,传入这个模块的泛型
在BaseMapper<>中包含了大量的常用的sql操作,我们就可以不用手动去写
然后我们直接使用就行
整合druid
第一步,导入依赖包,依然需要我们在手动在https://mvnrepository.com/
上找对应的坐标
然后设置配置
然后就能使用
Vue入门
VUE官方文档对新手很友好,中文版本很不错,学习VUE必用官方文档
- 入门
- test_data
- 指令
- v-on指令基础
- v-show
- v-if
- v-bind
- v-on补充
- v-model
restful风格的开发
1、每一个URI代表1种资源;
2、客户端使用GET、POST、PUT、DELETE4个表示操作方式的动词对服务端资源进行操作:GET用来获取资源,POST用来新建资源(也可以用于更新资源),PUT用来更新资源,DELETE用来删除资源;
3、通过操作资源的表现形式来操作资源;
4、资源的表现形式是XML或者HTML;
5、客户端与服务端之间的交互在请求之间是无状态的,从客户端到服务端的每个请求都必须包含理解请求所必需的信息。
RESTful风格要求每个资源都使用 URI (Universal Resource Identifier) 得到一个唯一的地址。所有资源都共享统一的接口,以便在客户端和服务器之间传输状态。使用的是标准的 HTTP 方法,比如 GET、PUT、POST 和 DELETE。
简单来说,RESTful风格要求每个资源都使用一样的URI,所有资源都共享统一的接口,通过请求方式和所传递的参数个数的不同,来分辨使用哪个方法来处理对应的请求
restful风格最核心的是他的请求方式
大致有这五种
GET(SELECT):从服务器取出资源(一项或多项)。查询
POST(CREATE):在服务器新建一个资源。插入(新增)
PUT(UPDATE):在服务器更新资源(客户端提供完整资源数据)。修改(全部字段)
DELETE(DELETE):从服务器删除资源。删除
PATCH(UPDATE):在服务器更新资源(客户端提供需要修改的资源数据)。修改(部分字段)
前四种更常用一点
通过设置method属性的CRUD,可以将同一个URL映射到不同的HandlerMethod方法上。
如下:
上面是控制层中的几个处理请求的方法,两个get请求,但是参数个数不同,get请求中,传递对应的参数,进入对应的处理方法
开始小案例
代码在这里https://github.com/AFatFox/FOX01
一开始,先搞这几件事
1.创建一个springboot项目或者模块,勾选SpringMVC与MySQL坐标
2.修改配置文件为yml格式
3.设置端口为80方便访问
用lombok创建实体类
Lombok项目是一个Java库,它会自动插入编辑器和构建工具中,Lombok提供了一组有用的注释,用来消除Java类中的大量样板代码。仅五个字符(@Data)就可以替换数百行代码从而产生干净,简洁且易于维护的Java类。
常用注解:
@Setter :注解在类或字段,注解在类时为所有字段生成setter方法,注解在字段上时只为该字段生成setter方法。
@Getter :使用方法同上,区别在于生成的是getter方法。
@ToString :注解在类,添加toString方法。
@EqualsAndHashCode: 注解在类,生成hashCode和equals方法。
@NoArgsConstructor: 注解在类,生成无参的构造方法。
@RequiredArgsConstructor: 注解在类,为类中需要特殊处理的字段生成构造方法,比如final和被@NonNull注解的字段。
@AllArgsConstructor: 注解在类,生成包含类中所有字段的构造方法。
@Data: 注解在类,生成setter/getter、equals、canEqual、hashCode、toString方法,如为final属性,则不会为该属性生成setter方法。
@Slf4j: 注解在类,生成log变量,严格意义来说是常量。
然后,创建实体类,这里使用lombok快速开发
数据层开发
这里用mybatis-plus(即mp)和druid
- 先导入坐标
- 属性配置
- 然后创建dao层接口
条件查询中的QueryWrapper
附上对应部分的官方文档链接:https://baomidou.com/pages/10c804/#abstractwrapper
queryWrapper是mybatis plus中实现查询的对象封装操作类,是用来封装查询条件的,我们可以用它来构建查询条件
QueryWrapper是Wrapper家族中的一员,他们都属于条件构造器,下面是在网上找到的一张他们继承关系的图(侵删)
使用方法:
- 创建对应的对象
QueryWrapper qw=new QueryWrapper<>(); - 调用相关的方法设置查询条件
- 使用的时候将对象作为参数传入需要的地方即可
这里是在小案例中使用的一个例子
在这里就可以看出,在这种条件构造器中,有两点很重要:
1.所有查询操作封装成方法调用
2.查询条件支持动态条件拼装
命名的注意事项
在对不同层的接口进行命名的时候,根据不同的层级我们应该有不同的命名规范
比如数据层,我们应该关注的是对数据的操作,所以在Dao层中,我们的命名规范应该围绕对数据的操作来展开,比如登录操作中,dao层的命名可以这样:selectByUserNameAndPassword ( String username , String password);
又比如在业务层,我们应该关注的是业务操作,我们的命名应该围绕着业务的操作来展开,比如登录操作在业务层中,应该这样命名:login(String username, String password) ;
业务层
MP为了方便咱们的开发,也为业务层提供了一个通用接口,就跟Dao层的mp一样,咱们继承就行
什么是通用接口?在这里,意思就是MP中对业务层一些常用的方法进行了封装,封装成的这个接口就是这里的通用接口
1.创建一个业务层接口
2.继承MP中的业务层通用接口(ISerivce)
这样一来就有一个问题,如果我们要实现这个接口,那么通用接口里面的方法都需要实现,要我们一个一个去实现是不现实的
所以,MP又给咱们提供了业务层通用接口的实现类(ServiceImpl<M,T> ),我们在实现业务层接口的同时继承这个接口就可以了,然后后续想用这里面的哪个方法就用哪个方法
表现层(控制层)
这里表现层,我们就用restful风格进行开发
下面是restful风格和前后端分离的开发
restful在这里的体现是路径的设置、请求的方式。如这里在类上设置一个路径,类中的方法不设置路径,仅通过客户端请求的方式来决定进入哪个方法
前后端分离体现在参数的设置上,在需要接收Book实例的方法中,用于接收客户端传来的Json串,在结束整形类型的方法中,用于接收URL后面跟的数字,如/books/1
表现层数据一致性处理
前后端分离中比较重要的操作,保证返回数据的统一性,不然前端人员会破防的
为了后端返回给前端的数据统一,可以在控制层(表现层)写一个能把所有的数据都封装起来的类,然后所有的返回操作都返回这个类的实例
对于数据层的操作,一般有两种,一种是有返回数据的,即查询,一种是不用返回数据的,如增删改
对于查询 ,这个类至少需要两个属性,一个用于表示对于请求的处理有没有异常(比如在查询操作,无法连接数据库,这就是服务端的异常),
假设设置一个Boolean类型的属性用于记录是否有异常,如果服务端无异常则返回true,如果有异常,则返回flase
另一个属性设置为Object类型,用于存储所有返回的数据。比如查询单个用户返回的实体类型,可直接放在Object中,或者查询全部返回的集合,也可直接放在Object中
或者是查询操作未查到,返回的null也可放在object中。
对于增删改,因为我们的结果只有一个true或者flase,表示成功或未成功,所以这个类我们只用用到一个属性
前端的工作
按照常规的前后端分离项目,前端结构应该放在前端服务器中,这里我们这是单体工程,放在static文件夹中,整个案例的代码在这里:https://github.com/AFatFox/FOX01
这里只关注于和后端连接紧密的那一部分前端的开发,即VUE中涉及到增删改查和分页那部分的工作
单体工程(单体架构)?
单体工程(单体架构)虽然在软件设计中划分了经典的 3 层模型,但是对业务场景没有划分。一个典型的单体应用就是将所有的业务场景的表示层、业务逻辑层和数据访问层放在一个工程中,最终经过编译、打包,部署在一台服务器上。
就是三层架构全放在一个一个工程中最终经过编译、打包,部署在一台服务器上。
axios发送异步请求
Axios 是一个基于promise网络请求库,作用于node.js和浏览器中,它是 isomorphic 的(即同一套代码可以运行在浏览器和node.js中)。在服务端它使用原生node.js http模块, 而在客户端 (浏览端) 则使用XMLHttpRequests。
axios实现了对ajax的封装。axios是ajax ajax不止axios。
基本用法:
- 先导如依赖文件
- 然后
axios.请求方式(url,参数传递).then(fun1,fun2)
或axios.get(url?参数列表).then(fun1,fun2)
无异常则调用fun1函数,有异常则调用fun2函数
需要注意一点,在fun1和fun2中,this不再表示当前这个vue对象,因为axios中也有this关键字和vue的冲突了
如果我们需要在axios中调用当前vue对象,我们可以定义一个变量在axios前面来保存当前的vue对象,
或者使用箭头函数
箭头函数:
(参数列表)=> {} 是一个箭头函数,箭头函数有个特性:
函数体内的this对象,就是定义时所在的对象,而不是使用时所在的对象,箭头函数继承而来的this指向永远不变。
案例展示
包含增删改查基础操作还有分页
VUE除了methods部分的内容
这里面的created钩子函数用于在VUE对象初始化后对列表进行初始化,这里就是调用getAll()函数来加载所有的数据
加载列表+查找+分页
先写一个方法,用于得到数据库的数据,可以把查询功能也写在这里面,当无条件,则表示返回当前页的所有数据。为了方便,把分页也写在这里面
这里返回的R对象的data数据是一个page类型的对象,我们把对应的数据的值赋给VUE中对应分页的数据
MP这里的分页在操作之前,需要先写一个拦截器,并为其添加一个分页功能:
这样,分页操作才能正常进行
切换页码
下面是对应分页查询的控制层的方法,前端通过路径后的参数传递过来的查询条件会自动封装到我们这个方法的第三个参数的Book对象中
对应的业务层的方法:
对应Dao层我们用的是MP不需要再特意编写对应的代码
添加
第一件事,弹出添加的窗口
然后若确定,则发送异步请求:
取消的操作
控制层部分代码
业务层和Dao层都用的MP
删除
控制层代码
业务层和dao层都用的MP
修改
控制层
业务层和dao层用MP
异常的处理
在我们的项目中,有的时候因为一些无法预料的情况可能会出现异常,为了处理这些无法预料的异常我们可以创建一个类来专门处理各种异常。这个类所属的层级应该是前端控制器
操作
创建一个类,此类作为springmvc的异常处理器,出现异常都会进到这个类中。
当出现异常,我们在这里做好出现异常的工作后,接下来正确的操作的操作应该是,返回的一个和不出现异常返回的数据类型相同的数据,所以在R类中我们加一个属性msg,用于记录异常信息,然后返回给前端
所以我们这样做,如下,对应的R类的开发在文章的上面,可以在目录中寻找
这里的异常处理就是MVC中的处理方法
都是这样
即在三层架构中无论哪里出现问题,或者无论出现了多少问题,我们全部通过throws Exception往上层抛,然后我们定义一个异常处理器,最后由SpringMVC前端控制器交由异常处理器进行异常处理
一点收获
1.数据一致性之R,前端的提示框中的信息也可由后端传入,即R中的msg属性
在前端中对操作的执行状态进行的信息提示也由后端提供信息,保证数据的一致性处理
如:
2.异常处理
所有的异常集中到一个异常处理器中进行处理,并需要保证数据的一致性,返回想同类型的数据,并根据异常的类型,为前端传递不同的msg属性