func-spring-boot-starter test

项目地址

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中的key

    • public 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: 匿名函数绑定的回调函数类 不推荐
  • @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

func-spring-boot-starter 快速上手的更多相关文章

  1. 一个简单易上手的短信服务Spring Boot Starter

    前言 短信服务在用户注册.登录.找回密码等相关操作中,可以让用户使用更加便捷,越来越多的公司都采用短信验证的方式让用户进行操作,从而提高用户的实用性. Spring Boot Starter 由于 S ...

  2. spring -boot s-tarter 详解

    Starter POMs是可以包含到应用中的一个方便的依赖关系描述符集合.你可以获取所有Spring及相关技术的一站式服务,而不需要翻阅示例代码,拷贝粘贴大量的依赖描述符.例如,如果你想使用Sprin ...

  3. Spring Boot (一): Spring Boot starter自定义

    前些日子在公司接触了spring boot和spring cloud,有感于其大大简化了spring的配置过程,十分方便使用者快速构建项目,而且拥有丰富的starter供开发者使用.但是由于其自动化配 ...

  4. Spring Boot【快速入门】简单案例

    Spring Boot[快速入门]   Spring Boot 概述 Build Anything with Spring Boot:Spring Boot is the starting point ...

  5. 最详细的自定义Spring Boot Starter开发教程

    1. 前言 随着Spring的日渐臃肿,为了简化配置.开箱即用.快速集成,Spring Boot 横空出世. 目前已经成为 Java 目前最火热的框架了.平常我们用Spring Boot开发web应用 ...

  6. Spring Boot中快速操作Mongodb

    Spring Boot中快速操作Mongodb 在Spring Boot中集成Mongodb非常简单,只需要加入Mongodb的Starter包即可,代码如下: <dependency> ...

  7. Spring Boot Starter 介绍

    http://www.baeldung.com/spring-boot-starters 作者:baeldung 译者:http://oopsguy.com 1.概述 依赖管理是任何复杂项目的关键部分 ...

  8. Spring Boot项目简单上手+swagger配置+项目发布(可能是史上最详细的)

    Spring Boot项目简单上手+swagger配置 1.项目实践 项目结构图 项目整体分为四部分:1.source code 2.sql-mapper 3.application.properti ...

  9. SpringBoot 之Spring Boot Starter依赖包及作用

    Spring Boot 之Spring Boot Starter依赖包及作用 spring-boot-starter 这是Spring Boot的核心启动器,包含了自动配置.日志和YAML. spri ...

  10. Spring boot starter pom的依赖关系说明

    Spring Boot 通过starter依赖为项目的依赖管理提供帮助.starter依赖起始就是特殊的maven依赖,利用了传递依赖解析,把常用库聚合在一起,组成了几个为特定功能而定制的依赖. sp ...

随机推荐

  1. 人工水母搜索算法—matlab代码

    clc clear foj = @ Sphere; Lb = -100; % 搜索空间下界 Ub = 100; % 搜索空间上界 N_iter = 1000; % 最大迭代次数 n_pop = 50; ...

  2. [BUUCTF]PWN——xdctf2015_pwn200

    xdctf2015_pwn200 附件 步骤 例行检查,32位程序,开启了nx保护 本地试运行一下程序,看看大概的情况 32位ida载入,习惯性的检索程序里的字符串,没有发现什么铭感的地方,直接看ma ...

  3. [BUUCTF]PWN11——get_started_3dsctf_2016

    [BUUCTF]PWN11--get_started_3dsctf_2016 题目网址:https://buuoj.cn/challenges#get_started_3dsctf_2016 步骤: ...

  4. 自动造数据利器,Faker 了解一下?

    1. 背景 在软件需求.开发.测试过程中,有时候需要使用一些测试数据,针对这种情况,我们一般要么使用已有的系统数据,要么需要手动制造一些数据.由于现在的业务系统数据多种多样,千变万化.在手动制造数据的 ...

  5. LuoguP2556 [AHOI2002]黑白图像压缩 题解

    Content 题目描述太过于繁琐而无法简化,请前往原题面查看. 数据范围:\(1\leqslant n\leqslant 8\times 10^4\). Solution & Code 一个 ...

  6. Python的 垃圾回收机制

    垃圾回收 1. 小整数对象池 整数在程序中的使用非常广泛,Python为了优化速度,使用了小整数对象池, 避免为整数频繁申请和销毁内存空间. Python 对小整数的定义是 [-5, 257) 这些整 ...

  7. Mysql 主从复制机制

    https://blog.csdn.net/girlgolden/article/details/89226528 MySQL异步复制及semi-sync半同步复制,它们都基于MySQL binlog ...

  8. Postman环境变量的使用

    前言 请注意,Postman新版有ui上的改动,本文使用的Postman 版本8.4.0 for Mac, ui有调整,但是功能无改变. Postman是一款接口调测的软件,服务端开发的同学肯定会对自 ...

  9. element UI遇到的问题

    1. 在el-dialog中获取el-table的ref为undefined 问题:虽然设置了el-dialog的visible为true,但此时Dom并没有更新,因此在Dom更新前取不到el-tab ...

  10. java判断一个字符串是否为数字(整型、int)

    引入commons-lang 的jar包 /** * 判断是否是数字类型 * @param str * @return 如果为空返回false 匹配返回true */ public static bo ...