├── .gitignore ├── 1.png ├── 2.png ├── 3.png ├── LICENSE ├── README.MD ├── clojure.gif ├── pom.xml └── src └── main ├── java └── repl │ ├── R.java │ └── config │ ├── StarterAutoConfigure.java │ └── StarterServiceProperties.java └── resources └── META-INF └── spring.factories /.gitignore: -------------------------------------------------------------------------------- 1 | /target/ 2 | !.mvn/wrapper/maven-wrapper.jar 3 | 4 | ### STS ### 5 | .apt_generated 6 | .classpath 7 | .factorypath 8 | .project 9 | .settings 10 | .springBeans 11 | .sts4-cache 12 | 13 | ### IntelliJ IDEA ### 14 | .idea 15 | *.iws 16 | *.iml 17 | *.ipr 18 | .mvn 19 | .vscode 20 | mvnw 21 | mvnw.cmd 22 | ### NetBeans ### 23 | /nbproject/private/ 24 | /nbbuild/ 25 | /dist/ 26 | /nbdist/ 27 | /.nb-gradle/ 28 | /build/ 29 | -------------------------------------------------------------------------------- /1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MatrixSeven/clojure-nrepl-starter/71c30342b846d3419d4b2b2610b4af062ecc11a8/1.png -------------------------------------------------------------------------------- /2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MatrixSeven/clojure-nrepl-starter/71c30342b846d3419d4b2b2610b4af062ecc11a8/2.png -------------------------------------------------------------------------------- /3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MatrixSeven/clojure-nrepl-starter/71c30342b846d3419d4b2b2610b4af062ecc11a8/3.png -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 Accelerator 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.MD: -------------------------------------------------------------------------------- 1 | # clojure-nrepl-starter 2 | 3 | ![Apache License, Version 2.0, January 2004](https://img.shields.io/github/license/apache/maven.svg?label=License) 4 | ![Jenkins Status](https://img.shields.io/jenkins/s/https/builds.apache.org/job/maven-box/job/maven/job/master.svg?style=flat-square) 5 | 6 | 7 | 8 | 9 | ### 这是什么? 10 | 这个是一个Spring-boot的nrepl快速启动组件,在Maven中引入该依赖后可以快速在Spring-boot项目中启动一个`Clojure-Cider-Nrepl`. 11 | 12 | ### 可以做什么? 13 | 启动`Nrepl`后可以在终端使用`lein connect`直接连接到该服务,连接后可以直接获取Spring上下文中的Bean,并且直接调用Bean的方法/查看当前属性状态 14 | 结合`Jrebel`可以实现JavaCode热加载并且Repl不断开,但是在终端里并没有代码补全,如果想体验补全的快感建议使用`Emacs+Cider`环境. 15 | 16 | ### 为啥出来了个这么个玩意 17 | 突发奇想,然后就被无聊的搞出来了 18 | 19 | ### 如何使用 20 | 直接在项目的`pom.xml`里引入依赖 21 | ```xml 22 | 23 | com.github.matrixseven 24 | clojure-nrepl-starter 25 | 1.0.0 26 | 27 | ``` 28 | 然后配置 29 | ```properties 30 | #是否启动,默认不启动 31 | clojure.nrepl.state=true 32 | #服务绑定的端口,默认7888 33 | clojure.nrepl.port=7888 34 | #仅在以下环境中启动,默认为dev,优先级高于state 35 | clojure.nrepl.mode=dev,test 36 | ``` 37 | 38 | ### 使用场景 39 | 某日你突然要临时发几条`kafka/mq`消息又或者热加载某个`bean`后需要调用某个方法测试,以前可能要写个`Test`用例或者`web`项目调用下接口等等.那么现在so easy,无论是本地还是跑在测试线的环境,只要您开启了`nrepl`服务,你就可以直接连接上去,干你想干的事情,直接发消息/调用某个方法而不要重启/发布你的项目. 40 | 41 | 42 | 43 | ### eg: 44 | #### 体验 45 | ![](clojure.gif) 46 | 47 | #### 直接emacs中启动nrepl链接 48 | ![](1.png) 49 | 50 | #### 或者直接在idea中添加远程repl 51 | ![](2.png) 52 | 53 | #### 然后尝试使用它. 54 | ![](3.png) 55 | 56 | ## Enjoy it! 57 | * 一个emacs配置文件 [https://github.com/MatrixSeven/SEmacs](https://github.com/MatrixSeven/SEmacs) 58 | * 吾爱Java(QQ群):[170936712(点击加入)](https://link.zhihu.com/?target=https%3A//jq.qq.com/%3F_wv%3D1027%26k%3D41oCCMn) -------------------------------------------------------------------------------- /clojure.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MatrixSeven/clojure-nrepl-starter/71c30342b846d3419d4b2b2610b4af062ecc11a8/clojure.gif -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 4.0.0 5 | 6 | org.springframework.boot 7 | spring-boot-starter-parent 8 | 2.1.3.RELEASE 9 | 10 | 11 | com.github.matrixseven 12 | clojure-nrepl-starter 13 | 1.0.1-SNAPSHOT 14 | clojure-nrepl-starter 15 | Clojure Nrepl Starter 16 | 17 | 1.8 18 | 19 | 20 | 21 | 22 | 23 | true 24 | always 25 | 26 | https://repo.clojars.org 27 | clojars 28 | Codehaus Snapshots 29 | default 30 | 31 | 32 | 33 | 34 | org.springframework.boot 35 | spring-boot-starter 36 | 37 | 38 | org.slf4j 39 | slf4j-api 40 | 1.7.26 41 | 42 | 43 | org.clojure 44 | clojure 45 | 1.10.0 46 | 47 | 48 | org.clojure 49 | tools.nrepl 50 | 0.2.12 51 | 52 | 53 | cider 54 | cider-nrepl 55 | 0.18.0 56 | 57 | 58 | org.springframework.boot 59 | spring-boot-configuration-processor 60 | true 61 | 62 | 63 | com.alibaba 64 | fastjson 65 | 1.2.62 66 | provided 67 | 68 | 69 | org.springframework.boot 70 | spring-boot-autoconfigure 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | maven-assembly-plugin 122 | 123 | 124 | jar-with-dependencies 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | make-assembly 135 | package 136 | 137 | single 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | -------------------------------------------------------------------------------- /src/main/java/repl/R.java: -------------------------------------------------------------------------------- 1 | package repl; 2 | 3 | import clojure.lang.Var; 4 | import com.alibaba.fastjson.JSON; 5 | import repl.config.StarterServiceProperties; 6 | import org.slf4j.Logger; 7 | import org.slf4j.LoggerFactory; 8 | import org.springframework.context.ApplicationContext; 9 | import org.springframework.core.env.Environment; 10 | import org.springframework.stereotype.Service; 11 | import clojure.lang.RT; 12 | 13 | import java.util.Arrays; 14 | import java.util.List; 15 | 16 | 17 | //======================================================= 18 | // .----. 19 | // _.'__ `. 20 | // .--(^)(^^)---/!\ 21 | // .' @ /!!!\ 22 | // : , !!!! 23 | // `-..__.-' _.-\!!!/ 24 | // `;_: `"' 25 | // .'"""""`. 26 | // /, ya ,\\ 27 | // //狗神保佑\\ 28 | // `-._______.-' 29 | // ___`. | .'___ 30 | // (______|______) 31 | //======================================================= 32 | 33 | /** 34 | * @author Seven 35 | * FileName: R.java 36 | * Created by Seven on 2019/11/12 37 | **/ 38 | 39 | @Service 40 | @SuppressWarnings({"all"}) 41 | public class R { 42 | 43 | private static Logger logger = LoggerFactory.getLogger(R.class); 44 | 45 | private static final Var EVAL = var("eval"); 46 | private static final Var READ_STRING = var("read-string"); 47 | private static ApplicationContext applicationContext; 48 | private StarterServiceProperties starterServiceProperties; 49 | private Environment environment; 50 | 51 | public R(StarterServiceProperties properties, ApplicationContext applicationContext, Environment env) { 52 | environment = env; 53 | starterServiceProperties = properties; 54 | repl.R.applicationContext = applicationContext; 55 | } 56 | 57 | private static Var var(String varName) { 58 | return RT.var("clojure.core", varName); 59 | } 60 | 61 | public static T getBean(String name) { 62 | return (T) applicationContext.getBean(name); 63 | } 64 | 65 | public static T getBean(Class clazz) { 66 | return (T) applicationContext.getBean(clazz); 67 | } 68 | 69 | 70 | public static T asJavaObj(Object object, Class tClass) { 71 | String jsonString = JSON.toJSONString(object); 72 | return JSON.parseObject(jsonString, tClass); 73 | } 74 | 75 | public static List asJavaList(Object object, Class tClass) { 76 | String jsonString = JSON.toJSONString(object); 77 | return JSON.parseArray(jsonString, tClass); 78 | } 79 | 80 | public static Object fromJava(Object object) { 81 | String jsonString = JSON.toJSONString(object); 82 | return JSON.parse(jsonString); 83 | } 84 | 85 | public void init() { 86 | final List mode = starterServiceProperties.getMode(); 87 | final List active = Arrays.asList(environment.getActiveProfiles()); 88 | final boolean runMode = active.stream().anyMatch(mode::contains); 89 | if (starterServiceProperties.getState() && runMode) { 90 | Integer port = starterServiceProperties.getPort(); 91 | Thread replThread = new Thread(() -> { 92 | eval("(use '[clojure.tools.nrepl.server :only (start-server)])"); 93 | eval("(use '[cider.nrepl :only (cider-nrepl-handler)])"); 94 | eval("(def repl-server (start-server :port " + port + " :handler cider-nrepl-handler))"); 95 | logger.info("Clojure nrepl is started on port(s): {} ", port); 96 | logger.info("Clojure nrepl services running only on {} mode", mode); 97 | }); 98 | replThread.setName("Nrepl-Service"); 99 | replThread.start(); 100 | } else { 101 | logger.info("Clojure nrepl service is Loaded,but not start"); 102 | logger.info("Clojure nrepl service running only on {} mode", mode); 103 | } 104 | 105 | } 106 | 107 | private static T eval(String... code) { 108 | return (T) EVAL.invoke(readString(String.join("\n", code))); 109 | } 110 | 111 | private static T readString(String s) { 112 | return (T) READ_STRING.invoke(s); 113 | } 114 | } 115 | -------------------------------------------------------------------------------- /src/main/java/repl/config/StarterAutoConfigure.java: -------------------------------------------------------------------------------- 1 | package repl.config; 2 | 3 | import org.springframework.beans.factory.annotation.Autowired; 4 | import org.springframework.boot.context.properties.EnableConfigurationProperties; 5 | import org.springframework.context.ApplicationContext; 6 | import org.springframework.context.annotation.Bean; 7 | import org.springframework.context.annotation.Configuration; 8 | import org.springframework.core.env.Environment; 9 | import repl.R; 10 | 11 | 12 | //======================================================= 13 | // .----. 14 | // _.'__ `. 15 | // .--(^)(^^)---/!\ 16 | // .' @ /!!!\ 17 | // : , !!!! 18 | // `-..__.-' _.-\!!!/ 19 | // `;_: `"' 20 | // .'"""""`. 21 | // /, ya ,\\ 22 | // //狗神保佑\\ 23 | // `-._______.-' 24 | // ___`. | .'___ 25 | // (______|______) 26 | //======================================================= 27 | 28 | /** 29 | * [Zhihu]https://www.zhihu.com/people/Sweets07 30 | * [Github]https://github.com/MatrixSeven 31 | * Created by Seven on 2019-03-17 16:33 32 | */ 33 | @Configuration 34 | @EnableConfigurationProperties(StarterServiceProperties.class) 35 | public class StarterAutoConfigure { 36 | 37 | @Autowired 38 | private StarterServiceProperties properties; 39 | 40 | @Autowired 41 | private Environment env; 42 | 43 | @Autowired 44 | private ApplicationContext applicationContext; 45 | 46 | @Bean(initMethod="init") 47 | public R starterService (){ 48 | return new R(properties, applicationContext, env); 49 | } 50 | 51 | 52 | } -------------------------------------------------------------------------------- /src/main/java/repl/config/StarterServiceProperties.java: -------------------------------------------------------------------------------- 1 | package repl.config; 2 | 3 | import org.springframework.boot.context.properties.ConfigurationProperties; 4 | 5 | import java.util.Arrays; 6 | import java.util.List; 7 | 8 | //======================================================= 9 | // .----. 10 | // _.'__ `. 11 | // .--(^)(^^)---/!\ 12 | // .' @ /!!!\ 13 | // : , !!!! 14 | // `-..__.-' _.-\!!!/ 15 | // `;_: `"' 16 | // .'"""""`. 17 | // /, ya ,\\ 18 | // //狗神保佑\\ 19 | // `-._______.-' 20 | // ___`. | .'___ 21 | // (______|______) 22 | //======================================================= 23 | 24 | /** 25 | * [Zhihu]https://www.zhihu.com/people/Sweets07 26 | * [Github]https://github.com/MatrixSeven 27 | * Created by Seven on 2019-03-17 16:33 28 | */ 29 | @ConfigurationProperties(prefix = "clojure.nrepl") 30 | public class StarterServiceProperties { 31 | private boolean state = true; 32 | private Integer port = 7888; 33 | private List mode = Arrays.asList("dev","test"); 34 | 35 | 36 | public Integer getPort() { 37 | return port; 38 | } 39 | 40 | public void setPort(Integer port) { 41 | this.port = port; 42 | } 43 | 44 | public boolean getState() { 45 | return state; 46 | } 47 | 48 | public void setState(boolean state) { 49 | this.state = state; 50 | } 51 | 52 | public List getMode() { 53 | return mode; 54 | } 55 | 56 | public void setMode(List mode) { 57 | this.mode = mode; 58 | } 59 | 60 | @Override 61 | public String toString() { 62 | return "StarterServiceProperties{" + "state=" + state + ", port=" + port + ", mode=" + mode + '}'; 63 | } 64 | } -------------------------------------------------------------------------------- /src/main/resources/META-INF/spring.factories: -------------------------------------------------------------------------------- 1 | org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ 2 | repl.config.StarterAutoConfigure --------------------------------------------------------------------------------