Spring Boot对MongoDB支持也能精简我们当初写的相关代码,所以这一节我们把方向放在MongoDB的Spring Boot化上。

启动时自动连接MongoDB

早先,我们使用的是java代码,DatabaseMan在服务器初始化的时候,手动连接到对应的数据库。这一块是让读者明白底层的方式,现在来把这个拿掉。用配置的方式让连接自动化。

  • 工程中,找到DatabaseMan文件,用键盘Delete删除
  • 工程中,打开Program.java文件,删除掉DatabaseMan调用的一行,然后这个文件内容如下:
package


  • 工程中,打开application.properties,在内容后面添加如下:
# Database Connection
spring.data.mongodb.database=PersonalBlog
spring.data.mongodb.port=27017
spring.data.mongodb.host=127.0.0.1



注意:在application.properties中,#开头的行是整行注释,也是这类文件唯一的注释方式

现在可以尝试运行服务器。在Intellij的Console窗口能看到mongodb连接的输出,如图一:




FreeMarker模板列表数据 freemarker数据库_mongodb


图一:数据库自动连接

事实上,现在的本地连接(数据库),不写那些配置信息,mongodb也会自动靠默认的信息连接上。我们写配置的原因在于:后面会加用户认证(默认的mongodb连接是不需要用户验证),而主机地址(host)、端口(port)都是在实际生产环境中会变化的,如果改变其中一个为不是默认的值,不配置就不可能连接上。如果想验证的话,最简单的方式就是把host随便改成192.133.1.3这样的类似值。你就会在初始连接中看到异常。

另外,上面的三行非注释的写法,在我们用的mongodriver版本下,可以用下面的一行代替:


spring.data.mongodb.uri=mongodb://localhost:27017/PersonalBlog


我们保留两种写法在这个文件里,整个文件内容如下:


spring.freemarker.template-loader-path: classpath:/templates
spring.freemarker.suffix: .ftl

# Database Connection
#spring.data.mongodb.database=PersonalBlog
#spring.data.mongodb.port=27017
#spring.data.mongodb.host=127.0.0.1
spring.data.mongodb.uri=mongodb://localhost:27017/PersonalBlog


创建和实现文章的CRUD类

自动连接后,我们原来使用手动得到数据库、集合,然后新增记录,以及以后会遇到的各种删除、更新、查询等操作,都可以Spring Boot化。举原来的增加记录来说,我们可以用手动的方式,用java代码像以前一样,通过mongodb的sdk,创建一个Document,然后使用insertOne()加这个记录到MongoDB数据库中。在技术上,这并不会造成什么困扰。只不过不够Spring Boot化。

来看怎么把这块改动。跟我一步一步走。

  • pom.xml中,加入依赖
<!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-data-mongodb -->


整体pom.xml内容如下:


<?xml version="1.0" encoding="UTF-8"?>


加入的依赖,会带来一些注解,比如@Repository,和相应的执行类,能支撑MongoDB的常规操作自动化。

  • 工程中,在Database目录下,建立新的java类文件,名字“ArticleRepository”,里面所有的内容写入后如下:
package


注意:这里我们把class改成了interface,并且继承自MongoRepository<Aticle, String>,而且给接口添加了@Repository 注解。

  • 修改原来的Article,主要是去除测试用的test变量和相关的getter和setter,最后内容:
package


  • 修改ArticleApi.java,最后内容如下:
package


代码中,使用了@Autowired 注解,定义了一个变量articleRepository,类型是刚刚加入的ArticleRepository。

然后,我们使用接口中的save()方法。该方法由基类提供,功能是往数据库中写入对应的数据。

对于第一次使用@Autowired 的人来说,会觉得奇怪,照理说,所有的代码真正能跑的时候(排除静态数据和方法),必须有对象存在。而且,似乎我们没有实现接口的对象?原理很简单,这个注解修饰的变量,会由Spring Boot扫描到,在需要的时候创建合适的对象并且连接到该变量上,而这个实现接口的类,则有添加的库实现。@Autowired 是控制反转(IoC)思想的具体实现,可以最大化的解耦具体的实现和使用者。

到这里,就可以运行服务器测试了。

测试结果是服务器不能运行,错误如下:


***************************
APPLICATION FAILED TO START
***************************

Description:

Field articleRepository in API.ArticleApi required a bean of type 'Database.ArticleRepository' that could not be found.

The injection point has the following annotations:
	- @org.springframework.beans.factory.annotation.Autowired(required=true)


Action:

Consider defining a bean of type 'Database.ArticleRepository' in your configuration.

Disconnected from the target VM, address: '127.0.0.1:61814', transport: 'socket'

Process finished with exit code 1


错误信息很明显:找不到bean“Database.ArticleRepository“。如果机灵的话,第一时间你可能会去扫描包的地方(代码入口上方)加入我们的包,以为加入这个包就能像以前一样搞定这个错误,但结果一样让你沮丧。

来,解决它!只要一步:工程中,直接把整个Database目录拖到DefaultMain目录中即可。具体步骤见图二、图三:


FreeMarker模板列表数据 freemarker数据库_mongodb_02

图二:拖动文件夹出现的问询画面


图二是刚拖动文件夹后发生的画面,这里我们需要点击图中红色箭头,会进入下一步。


FreeMarker模板列表数据 freemarker数据库_mongodb_03

图三:执行拖动动作最后确认的画面

图二的按钮点下后,会看到图三的画面,这里我们需要再次按箭头所示的按钮才能使动作真正生效。

最后的成果画面如图四:


FreeMarker模板列表数据 freemarker数据库_mongodb_04

图四:Database包移到了DefaultMain中

好了,先不管我们这些包的逻辑性上的清洁性,后面我们整理。现在先测试结果。

服务器可以正常运行!

浏览器进入编辑画面,输入点啥,然后保存。

还是有错误!如图五:


FreeMarker模板列表数据 freemarker数据库_mongodb_05

图五:浏览器点保存后看到的错误

这个错误我第一次遇到,第一时间就怀疑是相关的库太新,里面有bug。所以找了最简单的方式(却最有效),降库的版本!

打开pom.xml,把<parent>里面的version内容,改成2.2.0.RELEASE。所以整体内容如下:


<?xml version="1.0" encoding="UTF-8"?>


瞬间解决了上面的错误。图六是我截取的Robo 3T数据画面:


FreeMarker模板列表数据 freemarker数据库_mongodb_06

图六:数据保存成功

在看一看Chrome的控制台输出,似乎还有点问题(图七):


FreeMarker模板列表数据 freemarker数据库_mongodb_07

图七:保存成功时控制台的输出

Ajax发生错误这样的字眼,是我们原来在javascript的error回调写的。这个说明,虽然服务器上的写数据事实上成功了,但是ajax得到的结果却是错误。看一眼java那边的代码:


@PostMapping


代码很简单,就两行做事情的。一行保存,事实证明没有错误发生。下面一行原来用ResponseEntity.ok()返回字符串,照理说也不会错。事实上在第一次手动写数据到MongoDB中的时候,我们还用过这个,那时候可没有错误。怎么回事?

原因是我们修改过了ajax调用时的dataType,从最早的text到现在的json。这个修改,导致服务器回给ajax结果时,必须使用json格式。所以我们原来返回的字符串,就会引起客户端认为的错误。

解决它:ResponseEntity也支持json的格式,我们只要对上面的两行代码做一些修改,整体的ArticleApi变成:


package


在此基础上,在此运行服务器测试。这下在Chrome的控制台中,保存成功就回来了!