SpringBoot四大神器之CLI和手写SpringBoot
SpringBoot四大神器
SpringBoot 四大神器之四 CLI
CLI简介
Spring Boot CLI是一个命令行工具,如果想快速开发Spring应用程序,可以使用它。它可以运行Groovy脚本,这意味着您具有类似Java的熟悉语法,而没有太多样板代码。还可以引导一个新项目或为其编写自己的命令。
下载安装
-
下载地址:https://docs.spring.io/spring-boot/docs/current/reference/html/getting-started.html#getting-started.installing
Spring Boot CLI需要Java JDK v1.8或更高版本才能运行。Groovy已经在发行版包中,无需安装。
- 解压spring-boot-cli-2.3.5.RELEASE-bin.zip压缩包,到D:\Program Files\spring-2.3.5.RELEASE
- 配置环境变量SPRINGBOOTCLI
D:\Program Files\spring-2.3.5.RELEASE
-
安装检查
运行cmd命令,输入spring --version
spring --version
使用帮助
查看帮助命令
C:\Users\Admin>spring --help
usage: spring [--help] [--version]
<command> [<args>]
Available commands are:
run [options] <files> [--] [args]
# 运行groovy脚本
Run a spring groovy script
grab
Download a spring groovy script's dependencies to ./repository
# 通过spring groovy脚本,创建可执行的jar应用
jar [options] <jar-name> <files>
Create a self-contained executable jar file from a Spring Groovy script
# 通过spring groovy脚本,创建包含内嵌容器可执行的war应用
war [options] <war-name> <files>
Create a self-contained executable war file from a Spring Groovy script
install [options] <coordinates>
Install dependencies to the lib/ext directory
uninstall [options] <coordinates>
Uninstall dependencies from the lib/ext directory
# 通过init命令可以创建并初始化一个springboot项目
init [options] [location]
Initialize a new project using Spring Initializr (start.spring.io)
encodepassword [options] <password to encode>
Encode a password for use with Spring Security
shell
Start a nested shell
Common options:
--debug Verbose mode
Print additional status information for the command you are running
# 使用spring help <command>针对指定的命令获得帮助信息
See 'spring help <command>' for more information on a specific command.
C:\Users\Admin>
创建应用
C:\Users\Admin>spring --help init
spring init - Initialize a new project using Spring Initializr (start.spring.io)
usage: spring init [options] [location]
Option Description
------ -----------
-a, --artifactId <String> Project coordinates; infer archive name (for
example 'test')
-b, --boot-version <String> Spring Boot version (for example '1.2.0.RELEASE')
--build <String> Build system to use (for example 'maven' or
'gradle') (default: maven)
-d, --dependencies <String> Comma-separated list of dependency identifiers to
include in the generated project
--description <String> Project description
-f, --force Force overwrite of existing files
--format <String> Format of the generated content (for example
'build' for a build file, 'project' for a
project archive) (default: project)
-g, --groupId <String> Project coordinates (for example 'org.test')
-j, --java-version <String> Language level (for example '1.8')
-l, --language <String> Programming language (for example 'java')
--list List the capabilities of the service. Use it to
discover the dependencies and the types that are
available
-n, --name <String> Project name; infer application name
-p, --packaging <String> Project packaging (for example 'jar')
--package-name <String> Package name
-t, --type <String> Project type. Not normally needed if you use --
build and/or --format. Check the capabilities of
the service (--list) for more details
--target <String> URL of the service to use (default: https://start.
spring.io)
-v, --version <String> Project version (for example '0.0.1-SNAPSHOT')
-x, --extract Extract the project archive. Inferred if a
location is specified without an extension
examples:
# 展示springboot 生态圈组件
To list all the capabilities of the service:
$ spring init --list
# 创建一个默认的工程
To creates a default project:
$ spring init
# 创建一个web工程zip包
To create a web my-app.zip:
$ spring init -d=web my-app.zip
# 创建一个带有jpa的gradle管理的web应用,放在my-dir目录下
To create a web/data-jpa gradle project unpacked:
$ spring init -d=web,jpa --build=gradle my-dir
示例创建SSM项目
spring init -d=web,mybatis,mysql,actuator -a=ssm-demo -g=edu.dongnao.springboot --build=maven ssm-demo
运行groovy脚本
Groovy简介
groovy官网:http://www.groovy-lang.org/
快速入门:https://www.jianshu.com/p/e8dec95c4326
Groovy 是 Apache 旗下的一门基于 JVM 平台的动态/敏捷编程语言,在语言的设计上它吸纳了Python、Ruby 和 Smalltalk 语言的优秀特性,语法非常简练和优美,开发效率也非常高(编程语言的开发效率和性能是相互矛盾的,越高级的编程语言性能越差,因为意味着更多底层的封装,不过开发效率会更高,需结合使用场景做取舍)。并且,Groovy 可以与 Java 语言无缝对接,在写 Groovy 的时候如果忘记了语法可以直接按Java的语法继续写,也可以在 Java 中调用 Groovy 脚本,都可以很好的工作,这有效的降低了 Java 开发者学习 Groovy 的成本。Groovy 也并不会替代 Java,而是相辅相成、互补的关系,具体使用哪门语言这取决于要解决的问题和使用的场景。
Groovy和Spring与Spring Boot CLI结合在一起,可以在单个Groovy文件部署中快速编写功能强大,高
性能的微服务。
准备groovy脚本
-
创建app.groovy文件,写入下面内容,类似于java语法
@RestController class UserController{ @Autowired private UserService userservice; @RequestMapping("/") public String getUser(){ return "Hello "+userservice.say(); } } @Service class UserService{ public String say(){ return " CLI World"; } }
-
运行app.groovy
sping run app.groovy
第一运行需要下载依赖项非常慢,第二次运行就很快了。
-
访问验证
-
工程目录组织
Spring Boot会自动在/config目录中搜索application.yml或application.properties
├── app ├── app.groovy ├── config ├── application.yml ...
根据上节课学习的内容还可以在工作目录根目放置配置文件
├── app ├── example.groovy ├── example.yml ...
还可以在groovy脚本中通过@Grab注解在类中,来引用依赖和导入包。例如:
引入actuator健康监测,用@Grab
@Grab("spring-boot-starter-actuator") @RestController class ExampleRestController{ //... }
手写SpringBoot实战
SpringBoot基本的思路
设计一个SpringBoot要做些什么
- TomcatStart 启动Tomcat,依赖、配置、启动
- Servlet DistpatchServlet ,依赖、配置、启动
手写SpringBoot
-
创建一个Maven项目ruby-boot,选择quik-start骨架,jkd版本1.8
-
导入需要的jar包依赖
- SpringFramework
- tomcat
<!--SpringFramework--> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>5.2.9.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-web</artifactId> <version>5.2.9.RELEASE</version> </dependency> <!-- tomcat--> <dependency> <groupId>org.apache.tomcat.embed</groupId> <artifactId>tomcat-embed-core</artifactId> <version>8.5.16</version> </dependency> <dependency> <groupId>org.apache.tomcat</groupId> <artifactId>tomcat-jasper</artifactId> <version>8.5.16</version> </dependency>
-
创建TomcatStart启动类
public class TomcatStart { public static void start(){ try { //创建Tomcat容器,并配置端口 Tomcat tomcat = new Tomcat(); tomcat.setPort(8081); //配置项目信息,创建StandardContext StandardContext context = (StandardContext) tomcat .addWebapp("/",new File("src/main").getAbsolutePath()); context.setReloadable(false); //构建webapp WebResourceRoot resourceRoot = new StandardRoot(context); //获取class文件的读取位置 File classFile = new File("target/classes"); resourceRoot.addPreResources( new DirResourceSet(resourceRoot,"/WEB-INF/classes", classFile.getAbsolutePath(),"/")); //启动 tomcat.start(); tomcat.getServer().await(); } catch (Exception e) { e.printStackTrace(); } } public static void main(String[] args) { start(); } }
-
实现WebApplicationInitializer,创建父子容器的类
DispatchServletInitializer
public class DispatchServletInitializer extends AbstractAnnotationConfigDispatcherServletInitializer implements WebApplicationInitializer { /** * Spring root IOC容器 * @return */ @Override protected Class<?>[] getRootConfigClasses() { return new Class[]{RootConfig.class}; } /** * spring web ioc 容器,子容器 * @return */ @Override protected Class<?>[] getServletConfigClasses() { return new Class[]{ServletConfig.class}; } /** *Spring MVC 访问根路径 * @return */ @Override protected String[] getServletMappings() { return new String[]{"/"}; } }
RootConfig
/** * Spring root IOC容器 */ @ComponentScan(value = "com.fengb.rubyboot" ,excludeFilters={@ComponentScan.Filter(type= FilterType.ANNOTATION,classes = {Controller.class})}) public class RootConfig { }
ServletConfig
/** * SpringMVC 容器 */ @Configuration @ComponentScan(value = "com.fengb.rubyboot.controller", includeFilters = {@ComponentScan.Filter(type = FilterType.ANNOTATION,classes = {Controller.class})}, useDefaultFilters = false) @EnableWebMvc public class ServletConfig implements WebMvcConfigurer { /** *静态资源访问 * @param configurer */ @Override public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) { configurer.enable(); } /** * 置Spring MVC 视图解析器 * @param registry */ @Override public void configureViewResolvers(ViewResolverRegistry registry) { registry.jsp("/WEB-INF/",".jsp"); } }
-
准备注解
RubyBootApplication
@Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface RubyBootApplication { }
-
准备启动类 RubyApplication
public class RubyApplication { public static void run(Class<?> cl){ RubyBootApplication annotation = cl.getAnnotation(RubyBootApplication.class); if(annotation != null){ TomcatStart.start(); } } }
-
准备对外入口 RubyBootDemoApplication
@RubyBootApplication public class RubyBootDemoApplication { public static void main(String[] args) { RubyApplication.run(RubyBootDemoApplication.class); System.out.println("RubyBootApplication服务启动了"); } }
-
编写测试类
@RestController public class UserController { @Autowired private UserService userService; @RequestMapping("/getUser") public String getUser(){ return "RubyBoot : "+userService.getUsre(); } } @Service public class UserService { public String getUsre(){ User user = new User(); user.setName("ruby boot"); user.setAge(19); return user.toString(); } } public class User { private String name; private int age; public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } @Override public String toString() { return "User{" + "name='" + name + '\'' + ", age=" + age + '}'; } }
-
启动,查看控制台日志,如下启动正常,端口8081
Connected to the target VM, address: '127.0.0.1:51201', transport: 'socket' 七月 03, 2022 11:47:38 下午 org.apache.catalina.core.StandardContext setPath 警告: A context path must either be an empty string or start with a '/' and do not end with a '/'. The path [/] does not meet these criteria and has been changed to [] 七月 03, 2022 11:47:39 下午 org.apache.coyote.AbstractProtocol init 信息: Initializing ProtocolHandler ["http-nio-8081"] 七月 03, 2022 11:47:39 下午 org.apache.tomcat.util.net.NioSelectorPool getSharedSelector 信息: Using a shared selector for servlet write/read 七月 03, 2022 11:47:39 下午 org.apache.catalina.core.StandardService startInternal 信息: Starting service [Tomcat] 七月 03, 2022 11:47:39 下午 org.apache.catalina.core.StandardEngine startInternal 信息: Starting Servlet Engine: Apache Tomcat/8.5.16 七月 03, 2022 11:47:39 下午 org.apache.catalina.startup.ContextConfig getDefaultWebXmlFragment 信息: No global web.xml found 七月 03, 2022 11:47:44 下午 org.apache.catalina.core.ApplicationContext log 信息: 1 Spring WebApplicationInitializers detected on classpath 七月 03, 2022 11:47:45 下午 org.apache.jasper.servlet.TldScanner scanJars 信息: At least one JAR was scanned for TLDs yet contained no TLDs. Enable debug logging for this logger for a complete list of JARs that were scanned but no TLDs were found in them. Skipping unneeded JARs during scanning can improve startup time and JSP compilation time. 七月 03, 2022 11:47:45 下午 org.apache.catalina.core.ApplicationContext log 信息: Initializing Spring root WebApplicationContext 七月 03, 2022 11:47:45 下午 org.springframework.web.context.ContextLoader initWebApplicationContext 信息: Root WebApplicationContext: initialization started 七月 03, 2022 11:47:46 下午 org.springframework.web.context.ContextLoader initWebApplicationContext 信息: Root WebApplicationContext initialized in 942 ms 七月 03, 2022 11:47:46 下午 org.apache.catalina.util.SessionIdGeneratorBase createSecureRandom 警告: Creation of SecureRandom instance for session ID generation using [SHA1PRNG] took [622] milliseconds. 七月 03, 2022 11:47:46 下午 org.apache.catalina.core.ApplicationContext log 信息: Initializing Spring DispatcherServlet 'dispatcher' 七月 03, 2022 11:47:46 下午 org.springframework.web.servlet.FrameworkServlet initServletBean 信息: Initializing Servlet 'dispatcher' 七月 03, 2022 11:47:46 下午 org.springframework.web.servlet.FrameworkServlet initServletBean 信息: Completed initialization in 72 ms 七月 03, 2022 11:47:46 下午 org.apache.coyote.AbstractProtocol start 信息: Starting ProtocolHandler ["http-nio-8081"]
-
访问:http://localhost:8081/getUser
页面返回:
RubyBoot : User{name='ruby boot', age=19}
以上就是手写的SpringBoot,实现基本功能
.web.servlet.FrameworkServlet initServletBean
信息: Initializing Servlet ‘dispatcher’
七月 03, 2022 11:47:46 下午 org.springframework.web.servlet.FrameworkServlet initServletBean
信息: Completed initialization in 72 ms
七月 03, 2022 11:47:46 下午 org.apache.coyote.AbstractProtocol start
信息: Starting ProtocolHandler [“http-nio-8081”]
10. 访问:http://localhost:8081/getUser
页面返回:
```properties
RubyBoot : User{name='ruby boot', age=19}
```
[外链图片转存中...(img-1u9qnPdB-1748236831668)]
以上就是手写的SpringBoot,实现基本功能