赞
踩
(当前使用的eclipse版本 version=4.7.3
)
help -> Eclipse Marketplace
等待插件安装完成,
next之后,填写项目名称,如果是第一次构建项目,可以按照默认的来,然后看下构建出来的项目结构
然后next ,选择所需的支持,这里只选择web, 由于是通过maven下载的,选得越多,下载时间越长,可以抽个空闲时间,下载
然后选择finish即可 ,等待相关jar包的下载
构建完成的项目结构如下
构建出来的项目有3个文件时比较重要的, 对应上图的箭头指示部分
其中 pom.xml是maven项目做版本管理的,需要什么jar包,直接在里面添加
按照上面步骤构建的项目,内容如下:
- <?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.example</groupId>
- <artifactId>demo</artifactId>
- <version>0.0.1-SNAPSHOT</version>
- <packaging>jar</packaging>
-
- <name>demo</name>
- <description>Demo project for Spring Boot</description>
-
- <parent>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-starter-parent</artifactId>
- <version>2.0.6.RELEASE</version>
- <relativePath/> <!-- lookup parent from repository -->
- </parent>
-
- <properties>
- <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
- <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
- <java.version>1.8</java.version>
- </properties>
-
- <dependencies>
- <dependency>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-starter-web</artifactId>
- </dependency>
-
- <dependency>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-starter-test</artifactId>
- <scope>test</scope>
- </dependency>
- </dependencies>
-
- <build>
- <plugins>
- <plugin>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-maven-plugin</artifactId>
- </plugin>
- </plugins>
- </build>
-
-
- </project>
application.properties 是springboot 默认的配置文件地址,可以将配置文件写到里面去 ,默认为空
DemoApplication.java 是程序的入口,名称生成的策略就是 项目名+Application ,项目名就是你在构建项目时填写的;这个类是最重要的,
默认内容如下
- package com.example.demo;
-
- import org.springframework.boot.SpringApplication;
- import org.springframework.boot.autoconfigure.SpringBootApplication;
-
- @SpringBootApplication
- public class DemoApplication {
-
- public static void main(String[] args) {
- SpringApplication.run(DemoApplication.class, args);
- }
- }
首先来看下这个启动类,只有一个注解,一个main方法,
首先里看这个注解 @SpringBootApplication, 直接查看其源码, 由于是maven项目,会自动下载源码,这个很方便
- @Target(ElementType.TYPE)
- @Retention(RetentionPolicy.RUNTIME)
- @Documented
- @Inherited
- @SpringBootConfiguration
- @EnableAutoConfiguration
- @ComponentScan(excludeFilters = {
- @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
- @Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })
- public @interface SpringBootApplication {
-
- ...
- }
可以看到这个注解被其它几个注解所修饰,相当于是 springboot使用这个注解,达到同时使用其它几个注解
其中,上面4个注解,是java.lang.annotation 包下的,是所有注解都要有的
详细一点的说明(均来自java API)
public @interface Documented
指示某一类型的注释将通过 javadoc 和类似的默认工具进行文档化。应使用此类型来注释这些类型的声明:其注释会影响由其客户端注释的元素的使用。如果类型声明是用 Documented 来注释的,则其注释将成为注释元素的公共 API 的一部分。
public @interface Inherited
指示注释类型被自动继承。如果在注释类型声明中存在 Inherited 元注释,并且用户在某一类声明中查询该注释类型,同时该类声明中没有此类型的注释,则将在该类的超类中自动查询该注释类型。此过程会重复进行,直到找到此类型的注释或到达了该类层次结构的顶层 (Object) 为止。如果没有超类具有该类型的注释,则查询将指示当前类没有这样的注释。
注意,如果使用注释类型注释类以外的任何事物,此元注释类型都是无效的。还要注意,此元注释仅促成从超类继承注释;对已实现接口的注释无效。
public @interface Retention
指示注释类型的注释要保留多久。如果注释类型声明中不存在 Retention 注释,则保留策略默认为 RetentionPolicy.CLASS。
只有元注释类型直接用于注释时,Target 元注释才有效。如果元注释类型用作另一种注释类型的成员,则无效。
public @interface Target
指示注释类型所适用的程序元素的种类。如果注释类型声明中不存在 Target 元注释,则声明的类型可以用在任一程序元素上。如果存在这样的元注释,则编译器强制实施指定的使用限制。 例如,此元注释指示该声明类型是其自身,即元注释类型。它只能用在注释类型声明上:
- @Target(ElementType.ANNOTATION_TYPE)
- public @interface MetaAnnotationType {
- ...
- }
下面的3个注释
@SpringBootConfiguration 源码
- @Target(ElementType.TYPE)
- @Retention(RetentionPolicy.RUNTIME)
- @Documented
- @Configuration
- public @interface SpringBootConfiguration {
-
- }
其实就相当于和 @configuratiion的功能一样,使用该注解之后,可以将这个类看做是 一个配置文件
例如
- @Configuration
- public class MyConfig {
- @Bean
- public MyService getUserService(){
- UserService userService = new UserService();
- userService.setUserDAO(null);
- return userService;
- }
-
- @Bean
- public MyDAO getUserDAO(){
- return new UserDAO();
- }
- }
等价于xml的配置 ,
- <beans>
- <bean id = "MyService" class="com.shj.MyService">
- <property name="userDAO" ref = "userDAO"></property>
- </bean>
- <bean id = "MyDAO" class="com.shj.MyDAO"></bean>
- </beans>
@ComponentScan
相当于配置自动扫描
等价于spring的配置文件中的
<context:component-scan>
@EnableAutoConfiguration
- @Target(ElementType.TYPE)
- @Retention(RetentionPolicy.RUNTIME)
- @Documented
- @Inherited
- @AutoConfigurationPackage
- @Import(AutoConfigurationImportSelector.class)
- public @interface EnableAutoConfiguration {
-
- String ENABLED_OVERRIDE_PROPERTY = "spring.boot.enableautoconfiguration";
-
- /**
- * Exclude specific auto-configuration classes such that they will never be applied.
- * @return the classes to exclude
- */
- Class<?>[] exclude() default {};
-
- /**
- * Exclude specific auto-configuration class names such that they will never be
- * applied.
- * @return the class names to exclude
- * @since 1.3.0
- */
- String[] excludeName() default {};
-
- }
查看文档中的文档说明,可以发现 这个注解的作用是 允许spring程序上下文的自动配置
可以帮助SpringBoot应用将所有符合条件的@Configuration
配置都加载到当前SpringBoot创建并使用的IoC容器。
- public static void main(String[] args) {
- SpringApplication.run(DemoApplication.class, args);
- }
查看run()
- public static ConfigurableApplicationContext run(Class<?> primarySource,
- String... args) {
- return run(new Class<?>[] { primarySource }, args);
- }
再查看返回时调用的run()
- public static ConfigurableApplicationContext run(Class<?>[] primarySources,
- String[] args) {
- return new SpringApplication(primarySources).run(args);
- }
可以看到, 首先实例化了一个SpringApplication ,然后运行run()
首先来查看实例化的过程
- public SpringApplication(Class<?>... primarySources) {
- this(null, primarySources);
- }
真正调用的是这个
- @SuppressWarnings({ "unchecked", "rawtypes" })
- public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {
- this.resourceLoader = resourceLoader;
- Assert.notNull(primarySources, "PrimarySources must not be null");
- this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources));
- this.webApplicationType = WebApplicationType.deduceFromClasspath();
- setInitializers((Collection) getSpringFactoriesInstances(
- ApplicationContextInitializer.class));
- setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
- this.mainApplicationClass = deduceMainApplicationClass();
- }
一共进行的操作有 :
- static WebApplicationType deduceFromClasspath() {
- if (ClassUtils.isPresent(WEBFLUX_INDICATOR_CLASS, null)
- && !ClassUtils.isPresent(WEBMVC_INDICATOR_CLASS, null)
- && !ClassUtils.isPresent(JERSEY_INDICATOR_CLASS, null)) {
- return WebApplicationType.REACTIVE;
- }
- for (String className : SERVLET_INDICATOR_CLASSES) {
- if (!ClassUtils.isPresent(className, null)) {
- return WebApplicationType.NONE;
- }
- }
- return WebApplicationType.SERVLET;
- }
其中, 常量的定义
- private static final String[] SERVLET_INDICATOR_CLASSES = { "javax.servlet.Servlet",
- "org.springframework.web.context.ConfigurableWebApplicationContext" };
-
- private static final String WEBMVC_INDICATOR_CLASS = "org.springframework."
- + "web.servlet.DispatcherServlet";
-
- private static final String WEBFLUX_INDICATOR_CLASS = "org."
- + "springframework.web.reactive.DispatcherHandler";
-
- private static final String JERSEY_INDICATOR_CLASS = "org.glassfish.jersey.servlet.ServletContainer";
-
- private static final String SERVLET_APPLICATION_CONTEXT_CLASS = "org.springframework.web.context.WebApplicationContext";
-
- private static final String REACTIVE_APPLICATION_CONTEXT_CLASS = "org.springframework.boot.web.reactive.context.ReactiveWebApplicationContext";
可能会出现三种结果:
1 WebApplicationType.REACTIVE - 当类路径中存在REACTIVE_WEB_ENVIRONMENT_CLASS并且不存在MVC_WEB_ENVIRONMENT_CLASS时
2 WebApplicationType.NONE - 也就是非Web型应用(Standard型),此时类路径中不包含WEB_ENVIRONMENT_CLASSES中定义的任何一个类时
3 WebApplicationType.SERVLET - 类路径中包含了WEB_ENVIRONMENT_CLASSES中定义的所有类型时
- setInitializers((Collection) getSpringFactoriesInstances(
- ApplicationContextInitializer.class));
查看代码
- private <T> Collection<T> getSpringFactoriesInstances(Class<T> type) {
- return getSpringFactoriesInstances(type, new Class<?>[] {});
- }
- private <T> Collection<T> getSpringFactoriesInstances(Class<T> type,
- Class<?>[] parameterTypes, Object... args) {
- ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
- // Use names and ensure unique to protect against duplicates
- //避免重复的元素
- Set<String> names = new LinkedHashSet<>(
- SpringFactoriesLoader.loadFactoryNames(type, classLoader));
- //根据names进行实例化
- List<T> instances = createSpringFactoriesInstances(type, parameterTypes,
- classLoader, args, names);
- //排序实例化后的对象
- AnnotationAwareOrderComparator.sort(instances);
- return instances;
- }
- //根据完全限定名加载
- public static List<String> loadFactoryNames(Class<?> factoryClass, @Nullable ClassLoader classLoader) {
- String factoryClassName = factoryClass.getName();
- return loadSpringFactories(classLoader).getOrDefault(factoryClassName, Collections.emptyList());
- }
- private <T> List<T> createSpringFactoriesInstances(Class<T> type,
- Class<?>[] parameterTypes, ClassLoader classLoader, Object[] args,
- Set<String> names) {
- List<T> instances = new ArrayList<>(names.size());
- for (String name : names) {
- try {
- Class<?> instanceClass = ClassUtils.forName(name, classLoader);
- Assert.isAssignable(type, instanceClass);
- Constructor<?> constructor = instanceClass
- .getDeclaredConstructor(parameterTypes);
- T instance = (T) BeanUtils.instantiateClass(constructor, args);
- instances.add(instance);
- }
- catch (Throwable ex) {
- throw new IllegalArgumentException(
- "Cannot instantiate " + type + " : " + name, ex);
- }
- }
- return instances;
- }
- public void setInitializers(
- Collection<? extends ApplicationContextInitializer<?>> initializers) {
- this.initializers = new ArrayList<>();
- this.initializers.addAll(initializers);
- }
项目启动很快,然后会发现没什么要显示的,可以做个简单的网页 输出点内容
- package com.example.demo.web;
-
- import org.springframework.web.bind.annotation.RequestMapping;
- import org.springframework.web.bind.annotation.RestController;
-
- @RestController
- public class HelloController {
-
- @RequestMapping("/hello")
- public String index() {
- return "hello boot";
- }
-
-
-
-
- }
重启项目,然后访问: http://127.0.0.1:8080/hello
有的小伙伴代码写得一样, 会访问不到,
这个很重要 ,可以参考官方推荐的项目结构:
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。