Skip to content

raywang21/springboot1

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

5 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

250828, 实现了一个最简单的spring boot程序,当访问/hello时返回一个字符串。 返回的函数直接在HelloController.java中定义 但这里又调用了clojure,通过import clojure.lang.RT 动态加载"com/example/demo/clojure_utils.clj"文件,并调用其中的foo函数。

在启动web服务器后,可以随时修改clojure脚本,修改将立即生效,无需重启服务器。 但请注意这个clj文件不是在src\main下的原始文件,而是编译后存放在 build\resources\main\com\example\demo\clojure_utils.clj下的这个文件。

有了这个机制,未来可以实现热加载clojure脚本,无需重启整个应用程序。 用clojure来做业务逻辑层,再去调用数据访问层的java程序。

注意这里是每次动态调用clj文件,这样效率较低,未来投入生产环境, 要么改成用static { // Require the Clojure namespace Clojure.var("clojure.core", "require").invoke(Clojure.read("com.example.demo.clojure-utils")); }静态调用clojure文件,要么把clojure文件改成java实现。

实际开发中,controller层,每次新增一个endpoint,改动倒是不多。但是参数传递,采用@RequestBody,把传入参数转换为一个对象,这里涉及到新建UserDto对象,基本要复制User对象的全部内容,显得重复。 UserDto对象里面,还可以使用注解来做参数校验,比如@NotBlank,@Email等。 使用BeanUtil.copyProperties来把userDto对象的内容拷贝到User对象,然后使用userRepository.save来把User对象存入数据库。 User对象定义了数据库表结构和各个字段的名称,userRepository来做CRUD,这些都不用改。

导致tomcat不断重启的,是校验部分和service层调用userRepository的代码。

250829, 用SpringBoot结合Clojure来开发web后端: 用户--显示层--控制层--服务层--数据层--数据库 显示层是前端,用react或者vue之类来写 控制层负责指定访问那个endpoint 服务器负责业务逻辑 数据层负责数据库写入

为了避免重复启动tomcat,影响开发迭代速度,我们考虑 把相对变化较少的控制层和数据层用Java来写, 服务层用clojure来写。这样,修改业务逻辑之后不用重启tomcat 只要重新加载clj文件即可。

首先准备好数据层,以访问mysql的jpa为例,只有简单的一个文件,而且基本不用变化

然后在控制层需要用注解方式完成UserRepository类的实例化, 然后把这个对象传递给cloujure,clj文件中就可以操作数据库 @Autowired private UserRepository userRepository;

在控制层中以addUser方法为例,客户端以post方式提交,访问方式类似: curl -X POST http://localhost:8080/adduser -H "Content-Type: application/json" -d '{"name": "test", "email": "zhangsan@example.com"}' 在控制层中 @PostMapping("/adduser")来对应post方式处理对adduser端点的访问 public String addUser(@RequestBody Map<String, Object> payload) 方法签名为java.util.Map,SpringBoot会自动把json解析为java map。

用RT.load来实现对clj文件的动态加载: try { // Dynamically load the Clojure script on each request RT.load("com/example/demo/clojure_utils"); } catch (Exception e) { // Handle potential IOException or other loading errors return "Error loading Clojure script: " + e.getMessage(); } 注意源文件中clj文件位于src\main\clojure\com\example\demo\clojure_utils.clj 编译后就位于build\resources\main\com\example\demo\clojure_utils.clj 编译后的改动,要改动resouces目录下的clj文件,然后记得把改动结果同步回 src目录下。

将java map转化为clojur map // Convert Java Map to Clojure IPersistentMap IPersistentMap userMap = clojure.lang.PersistentHashMap.create(payload);

调用clojure中的函数,以repo对象(访问数据库用)和map对象(输入参数)作为参数 // Get a reference to the Clojure function IFn addUserFunction = Clojure.var("com.example.demo.clojure-utils", "add-user-to-db"); // Invoke the Clojure function with the repository and the user map addUserFunction.invoke(userRepository, userMap); return "User added successfully via Clojure!";

这样就把控制权传递到clj文件中(clj文件来实现业务层的逻辑处理) clj文件中需要引入java对象(注意编译配置中要先编译java,再编译clojure,才能实现clj文件中的import) (ns com.example.demo.clojure-utils (:import [com.example.demo User])) 根据输入参数拼接出User对象,然后调用repo实现数据库写入 (let [user (doto (User.) (.setName user-name) (.setEmail user-email))] (.save user-repo user) 如果需要调试日志,可以直接用println,就可以在tomcat中看到 (println "Received user-map:" user-map) (println "Keys in user-map:" (keys user-map)) (println "Type of first key:" (type (first (keys user-map)))) (let [user-name (get user-map "name") user-email (get user-map "email")] (println "Retrieved name (using string key):" user-name) (println "Retrieved email (using string key):" user-email)

About

spring boot with clojure as service layer

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published