匿名函数托管 func-spring-boot-starter
匿名函数托管 func-spring-boot-starter
项目地址
func-spring-boot-starter开源项目地址: https://gitee.com/yiur/func-spring-boot-starter
func-web-simple开源项目地址: https://gitee.com/yiur/func-web-simple
项目搭建
项目树结构
func-web-simple
│ pom.xml
└─ src
└─ main
├─ java
│ └─ com
│ └─ simple
│ └─ web
│ │ FuncApplication.java
│ │
│ ├─ callback
│ │ DefaultCallback.java
│ │
│ ├─ config
│ │ FuncLinkConfig.java
│ │
│ ├─ controller
│ │ ResultController.java
│ │
│ ├─ func
│ │ HttpLink.java
│ │ OutMessage.java
│ │
│ └─ lambda
│ LambdaConfig.java
│
└─ resources
application.yml
pom
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.resolving.func</groupId>
<artifactId>func-web-simple</artifactId>
<version>1.0-SNAPSHOT</version>
<dependencies>
<!--core-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>5.3.9</version>
</dependency>
<!--func-->
<dependency>
<groupId>func.spring.boot</groupId>
<artifactId>func-spring-boot-starter</artifactId>
<version>1.0.4.RELEASE</version>
</dependency>
<!--boot-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
<version>2.3.12.RELEASE</version>
</dependency>
<!--web-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>2.3.12.RELEASE</version>
</dependency>
<!--test-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<version>2.3.12.RELEASE</version>
</dependency>
<!--热部署-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<version>2.3.12.RELEASE</version>
<optional>true</optional>
<scope>runtime</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
yaml
server:
port: 7000
tomcat:
uri-encoding: utf-8
servlet:
encoding:
charset: utf-8
spring:
application:
name: func-web-simple
devtools:
restart:
enabled: true
additional-paths: src/main/java
exclude: WEB-INF/**
func:
link:
# 默认代理模式
singleton: true
# 默认开启lambda模式
lambda: true
# 默认的callback回调函数类
call-back: com.simple.web.callback.DefaultCallback
# logger 配置
logger:
# 默认false 不输出日志
enable-log: false
# 如果FuncLambda配置了turn-on-log为true的话且funcLink中没有对应的log功能,输出已经日志
message: "call method --> ?{methodName}(?{parameterSource})"
配置启动类
@EnableFuncLambda("com.simple.web.lambda")
扫描com.simple.web.lambda包下的接口
@EnableWebMvc
@EnableFuncLambda("com.simple.web.lambda")
@SpringBootApplication
public class FuncApplication {
public static void main(String[] args) {
SpringApplication.run(FuncApplication.class, args);
}
}
配置匿名函数链接
FuncFactory 获取匿名函数链接生产工厂
@Configuration
public class FuncLinkConfig {
@Autowired
public FuncFactory funcFactory;
}
生成匿名函数链接
@Bean
public FuncLink funcLink() {
return funcFactory.build();
}
配置匿名函数链接生命状态
setObject(key, lambda表达式) 链式编程
key: (Bean name 或 refs) + : + FuncToolEnum类定义的可用状态
小工具:
FuncToolKey<String, FuncToolType>用于setObject中的keypublic FuncToolKey<String, FuncToolType> funcToolKey =
(bean, toolEnum) -> FuncString.format(FuncStringType.FUNC_LINK_FORMAT, bean, toolEnum);
funcFactory.build()
.<FuncLogger>setObject(funcToolKey.splice("link-log", FuncToolType.LIFE_START_KEY), set -> "link-log => ?{methodName}");
lambda: setObject 是一个泛型方法,所以前面的泛型用于约束后面的lambda表达式
@Bean
public FuncLink funcLink() {
return funcFactory.build()
.<FuncLogger>setObject("link-log:log", set -> "link-log => ?{methodName}");
}
@Bean
public FuncLink funcLink() {
return funcFactory.build()
.<FuncCallbackThen<String, String>>setObject("outMessage:callback-then", data -> FuncString.format("[ { \"key\": \"replace\", \"value\": \"?\" } ]", data));
}
全配置
@Configuration
public class FuncLinkConfig {
@Autowired
public FuncFactory funcFactory;
/**
* tool key lambda
*/
public FuncToolKey<String, FuncToolType> funcToolKey = (bean, toolEnum) -> FuncString.format(FuncStringType.FUNC_LINK_FORMAT, bean, toolEnum);
@Bean
public FuncLink funcLink() {
FuncLink build = funcFactory.build()
.<FuncLogger>setObject("link-log:log", set -> "link-log => ?{methodName}");
setOutMessage(build);
return build;
}
private void setOutMessage(FuncLink funcLink) {
funcLink // OutMessage State of life
.<FuncLifeStart>setObject(funcToolKey.splice("outMessage", FuncToolType.LIFE_START_KEY), data -> {
if (data.size() > 1) {
data.put("message", FuncString.format("start() -> { ? }", data.get("message")));
}
return data;
})
.<FuncCallbackThen<String, String>>setObject("outMessage:callback-then", data -> FuncString.format("[ { \"key\": \"replace\", \"value\": \"?\" } ]", data))
.<FuncCallbackError<String>>setObject("outMessage:callback-error", error -> error instanceof InvocationTargetException ? ((InvocationTargetException) error).getTargetException().getMessage() : error.getMessage())
.<FuncLifeEnd<String, String>>setObject("outMessage:life-end", data -> data);
}
}
匿名函数链接的用法
life 匿名函数执行前与执行完毕
life 匿名函数执行前与执行完毕生命状态 不推荐
@Bean
public FuncLink funcLink() {
return funcFactory.build()
.<FuncLife<String, String>>setObject("outMessage:life", new FuncLife<String, String>() {
@Override
public Map<String, Object> start(Map<String, Object> map) {
return map;
}
@Override
public String end(String data) {
return data;
}
});
}
life-start 匿名函数执行前生命状态 推荐
@Bean
public FuncLink funcLink() {
return funcFactory.build()
.<FuncLifeStart>setObject(funcToolKey.splice("outMessage:life-start", FuncToolType.LIFE_START_KEY), data -> {
if (data.size() > 1) {
data.put("message", FuncString.format("start() -> { ? }", data.get("message")));
}
return data;
})
}
life-end 匿名函数执行完毕生命状态 推荐
@Bean
public FuncLink funcLink() {
return funcFactory.build()
.<FuncLifeEnd<String, String>>setObject("outMessage:life-end", data -> data);
}
life-start + life-end 组合 推荐
@Bean
public FuncLink funcLink() {
return funcFactory.build()
.<FuncLifeStart>setObject(funcToolKey.splice("outMessage:life-start", FuncToolType.LIFE_START_KEY), data -> {
if (data.size() > 1) {
data.put("message", FuncString.format("start() -> { ? }", data.get("message")));
}
return data;
})
.<FuncLifeEnd<String, String>>setObject("outMessage:life-end", data -> data);
}
callback 匿名函数执行成功或失败,回调函数
callback 匿名函数执行成功或失败回调 不推荐
@Bean
public FuncLink funcLink() {
return funcFactory.build()
.<FuncCallback<String, String>>setObject("outMessage:callback", new FuncCallback<String, String>() {
@Override
public String then(String s) {
return s;
}
@Override
public String error(Exception e) {
return e.getMessage();
}
});
}
callback-then 匿名函数执行成功回调 推荐
@Bean
public FuncLink funcLink() {
return funcFactory.build()
.<FuncCallbackThen<String, String>>setObject("outMessage:callback-then", data -> FuncString.format("[ { \"key\": \"replace\", \"value\": \"?\" } ]", data));
}
callback-error 匿名函数执行失败回调 推荐
@Bean
public FuncLink funcLink() {
return funcFactory.build()
.<FuncCallbackError<String>>setObject("outMessage:callback-error", error -> error instanceof InvocationTargetException ? ((InvocationTargetException) error).getTargetException().getMessage() : error.getMessage());
}
logger 匿名函数执行前输出信息
log 匿名函数执行前输出信息 1.0.4使用
@Bean
public FuncLink funcLink() {
return funcFactory.build()
.<FuncLogger>setObject("link-log:log", set -> "link-log => ?{methodName}");
}
匿名函数配置
编写匿名函数托管的接口
OutMessage
@Component
public interface OutMessage { /**
* 输出
* @param message text
* @param args replace
* @return string
*/
String out(String message, String... args); /**
* 输出
* @param message text
* @return string
*/
String out(String message); }
HttpLink
@Component
public interface HttpLink { /**
* 返回关联
* @return object
*/
Object link(); }
匿名函数写法
@FuncConfiguration 匿名函数配置注解
@FuncConfiguration
public class LambdaConfig {
}
@FuncLambda 声明为匿名函数
- 提供给匿名函数额外功能的注解为
- @FuncParameter: 匿名函数链接想调用到函数参数变量,必须使用
- value: 变量名,匿名函数链接收到Map<K, V>键值对
- @EnableLog: 匿名函数调用前输出函数信息
- @CallbackClass: 匿名函数绑定的回调函数类 不推荐
- @FuncParameter: 匿名函数链接想调用到函数参数变量,必须使用
- @FuncLambda属性解析
- classFile: 匿名函数托管的接口
- refs: 声明一个ref,提供给匿名函数链接使用
- bean: 匿名函数托管的接口,自动装配对象别名,可以不用默认为首字母缩写的类名
- 特性:
- 匿名函数托管的接口方法,返回值可以不一致callback成功回调接收的值就是匿名函数返回的值,但回调函数返回的值必须与接口函数返回的值一致
- refs可以引用多个ref包括Bean,进行统一配置减少耦合度
@FuncLambda(classFile = OutMessage.class, refs = { "link-log" })
public String out(@FuncParameter("message") String message, @FuncParameter("args") String... args) {
return FuncString.format(message, args);
}
全配置
@FuncConfiguration
public class LambdaConfig {
@EnableLog
@FuncLambda(classFile = OutMessage.class, refs = { "link-log" })
public String out(@FuncParameter("message") String message, @FuncParameter("args") String... args) {
return FuncString.format(message, args);
}
@EnableLog
@FuncLambda(classFile = OutMessage.class, refs = { "link-log" })
public String out(@FuncParameter("message") String message) {
return FuncString.format(message + "/no");
}
@EnableLog
@CallbackClass(DefaultCallback.class)
@FuncLambda(classFile = HttpLink.class, refs = { "link-log" })
public Map<String, String> link() {
Map<String, String> map = new HashMap<>(10);
map.put("百度", "http://www.baidu.com");
map.put("BiliBili", "http://www.bilibili.com");
map.put("localhost", "http://localhost:7000");
map.put("博客", "https://www.cnblogs.com/yiur-bgy/p/15521428.html");
return map;
}
}
WEB 测试
@RestController 编写api
@RestController
public class ResultController {
@Autowired
public OutMessage outMessage;
@Autowired
public HttpLink httpLink;
@RequestMapping("/replace")
public String replace(String message, String... args) {
return outMessage.out(message, args);
}
@RequestMapping("/replace/no")
public String replace(String message) {
return outMessage.out(message);
}
@RequestMapping("/hello/{message}")
public String hello(@PathVariable("message") String message) {
return outMessage.out(message);
}
@RequestMapping("/httpLink")
public Object httpLink() {
return httpLink.link();
}
}
测试 api
- 测试成功回调
- [http://localhost:7000/replace?message=hello ?&args=func-spring-boot-starter](http://localhost:7000/replace?message=hello ?&args=func-spring-boot-starter)
- 返回:[ { "key": "replace", "value": "hello func-spring-boot-starter" } ]
- 测试失败回调
- [http://localhost:7000/replace?message=hello??&args=func-spring-boot-starter](http://localhost:7000/replace?message=hello ??&args=func-spring-boot-starter)
- 返回:The current parameter is inconsistent with the number of matching characters
- 其他测试
- http://localhost:7000/httpLink
- 返回:{"localhost":"http://localhost:7000","博客":"https://www.cnblogs.com/yiur-bgy/p/15521428.html","百度":"http://www.baidu.com","BiliBili":"http://www.bilibili.com"}
- http://localhost:7000/replace/no?message=hello
- 返回:[ { "key": "replace", "value": "hello/no" } ]
匿名函数托管 func-spring-boot-starter的更多相关文章
- func-spring-boot-starter 匿名函数托管
func-spring-boot-starter 匿名函数托管 GitHub项目路径: https://github.com/yiurhub/func-spring-boot-starter Gite ...
- Spring Boot (一): Spring Boot starter自定义
前些日子在公司接触了spring boot和spring cloud,有感于其大大简化了spring的配置过程,十分方便使用者快速构建项目,而且拥有丰富的starter供开发者使用.但是由于其自动化配 ...
- Spring Boot Starter 介绍
http://www.baeldung.com/spring-boot-starters 作者:baeldung 译者:http://oopsguy.com 1.概述 依赖管理是任何复杂项目的关键部分 ...
- spring -boot s-tarter 详解
Starter POMs是可以包含到应用中的一个方便的依赖关系描述符集合.你可以获取所有Spring及相关技术的一站式服务,而不需要翻阅示例代码,拷贝粘贴大量的依赖描述符.例如,如果你想使用Sprin ...
- SpringBoot 之Spring Boot Starter依赖包及作用
Spring Boot 之Spring Boot Starter依赖包及作用 spring-boot-starter 这是Spring Boot的核心启动器,包含了自动配置.日志和YAML. spri ...
- Spring boot starter pom的依赖关系说明
Spring Boot 通过starter依赖为项目的依赖管理提供帮助.starter依赖起始就是特殊的maven依赖,利用了传递依赖解析,把常用库聚合在一起,组成了几个为特定功能而定制的依赖. sp ...
- Spring Boot Starter列表
转自:http://blog.sina.com.cn/s/blog_798f713f0102wiy5.html Spring Boot Starter 基本的一共有43种,具体如下: 1)spring ...
- 创建自己的Spring Boot Starter
抽取通用模块作为项目的一个spring boot starter.可参照mybatis的写法. IDEA创建Empty Project并添加如下2个module,一个基本maven模块,另一个引入sp ...
- 自己写spring boot starter
自己写spring boot starter 学习了:<spring boot实战>汪云飞著 6.5.4节 pom.xml <project xmlns="http://m ...
随机推荐
- 铁人三项(第五赛区)_2018_rop
拿到程序依旧老样子checksec和file一下 可以看到是32位的程序开启了nx保护,将程序放入ida进行查看 shift+f12 看到没有system和binsh等字样,考虑用泄露libc来做这道 ...
- [BUUCTF]REVERSE——内涵的软件
内涵的软件 附件 例行检查,32位程序 32位ida载入,shift+f12检索程序里的字符串 看到一个很像flag的字符串,拿去尝试一下,成功 flag{49d3c93df25caad8123213 ...
- 十年后回到百年前?(Excel技巧集团)
在单元格里输入日期,有时可以偷懒,比如明年的日期可以输入至少一位的年+横杠(或斜杠)+至少一位的月+横杠(或斜杠)+至少一位的日,也就是"21-1-1",单元格里就会自动显示&qu ...
- 前置任务(Project)
<Project2016 企业项目管理实践>张会斌 董方好 编著 在[前置任务列]中编辑任务关联,这是个正经的设置. 说他"正经",是因为在[手动模式]下,这个设置也是 ...
- LuoguP7715 「EZEC-10」Shape 题解
Content 有一个 \(n\times m\) 的网格,网格上的格子被涂成了白色或者黑色. 设两个点 \((x_1,y_1)\) 和 \((x_2,y_2)\),如果以下三个条件均满足: \(1\ ...
- 当在myeclipse里发送邮件有错误时,不妨把环境都改成jdk的
当在myeclipse里发送邮件有错误时,不妨把环境都改成jdk的, 如果是jre的环境会出错,改成jdk的就行了.
- 【LeetCode】1460. 通过翻转子数组使两个数组相等 Make Two Arrays Equal by Reversing Sub-arrays (Python)
作者: 负雪明烛 id: fuxuemingzhu 个人博客:http://fuxuemingzhu.cn/ 目录 题目描述 题目大意 解题方法 判断排序后是否相等 统计字符出现次数 日期 题目地址: ...
- 【九度OJ】题目1187:最小年龄的3个职工 解题报告
[九度OJ]题目1187:最小年龄的3个职工 解题报告 标签(空格分隔): 九度OJ http://ac.jobdu.com/problem.php?pid=1187 题目描述: 职工有职工号,姓名, ...
- 【LeetCode】122.Best Time to Buy and Sell Stock II 解题报告(Java & Python & C++)
作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ 目录 题目描述 题目大意 解题方法 日期 题目地址:https://leetcode.c ...
- 更快的Maven来了,我的天,速度提升了8倍!
周末被 maven-mvnd 刷屏了,于是我也下载了一个 mvnd 体验了一把.虽然测试的数据都是基于我本地项目,不具备普适性和权威性,但也足以说明问题.它的测试结果远远超出我的预期,下面一起来看. ...