spring boot 참고: https://start.spring.io/ (👉 해당 사이트는 spring boot기반으로 프로젝트를 만들어주는 사이트입니다.)
maven과 gradle이란 spring에 필요한 라이브러리들을 끌어다 오고, 빌드하는 라이프 사이클까지 관리해주는 Tool이다.
과거에는 maven을 많이 썻지만 최근에는 gradle을 더 많이 쓴다.
해당 사진에서 볼것은 부분이다.
[Grop]에는 기업명을 주로 작성해준다.
[Artifact] 프로젝트 결과물이 build되어 나오는 결과물로 보면 된다. (프로젝트 명이라고 생각해도 된다.)
[Dependencies] 부분이 굉장히 중요한데,spring boot로 프로젝트를 시작할 것인데 어떤 라이브러리들을 땡겨다가 쓸 것인지를 결정해주는 곳이다.
Dependencies에서 선택해줄 것은 spring web과 html을 만드러주는 templete engine이 필요하기 떄문에, thymeleaf를 사용한다.
generate를 누르면 파일이 다운로드 된다!
프로젝트 파일을 열어보면 위 사진과같이 나온다
.idea는 해당 인텔리제이에서 사용하는 파일이다.
.gradle은 gradle을 사용하는 폴더이다.
.src 폴더를 열어보면 main과 test폴더가 나누어져 있고 이것은 gradle로 spring boot을 만들든, maven으로 만들든 마찬가지로 구성이 되어있다.
src - main - java - 실제 프로젝트 소스파일이 있는것을 확인 할 수 있다.
test폴더에는 테스트 코드와 관련된게 들어가게된다.
위 사진을 통해 알 수 있는것은
resources란 자바 실제 코드 파일을 제외한 나머지 즉, xml이나 properties나 설정파일들과 관련된 정보가 들어있는 폴더입니다.
java파일을 제외한 것들이 resources에 들어간다고 생각하면 된다.
<build.gradle>
gradle이 버전을 설정하고 라이브러리를 땡겨오는데 사용하는 역할을 하는 구나 정도로만 우선 넘어가자!
sourceCompatibility = '11' 👉 java의 버전을 의미합니다.
repositories {
mavenCentral()
}
👉node로 치면 npm 같은것이라고 생각하면 될거같다.
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-thymeleaf'
implementation 'org.springframework.boot:spring-boot-starter-web'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
}
👉 node로 치면, package.json의 dependency를 설정해 놓는 부분이라고 생각하면 편할거같다.
👉 spring boot에서 dependencies로 다운로드 받았던 부분들이라는 것을 알 수 있다.
👉 마지막 testImplementation의 경우에는, spring boot을 다운로드 받을떄 기본적으로 들어가는 라이브러리이다.
<프로젝트 실행>
해당 프로젝트를 실행하면
. ____ _ __ _ _
/\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
\\/ ___)| |_)| | | | | || (_| | ) ) ) )
' |____| .__|_| |_|_| |_\__, | / / / /
=========|_|==============|___/=/_/_/_/
:: Spring Boot :: (v2.6.4)
2022-03-12 14:45:25.903 INFO 6332 --- [ main] h.hellospring.HelloSpringApplication : Starting HelloSpringApplication using Java 11.0.11 on insungsong.local with PID 6332 (/Users/insungsong/Documents/spring-study/hello-spring/build/classes/java/main started by insungsong in /Users/insungsong/Documents/spring-study/hello-spring)
2022-03-12 14:45:25.905 INFO 6332 --- [ main] h.hellospring.HelloSpringApplication : No active profile set, falling back to 1 default profile: "default"
2022-03-12 14:45:26.598 INFO 6332 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat initialized with port(s): 8080 (http)
2022-03-12 14:45:26.605 INFO 6332 --- [ main] o.apache.catalina.core.StandardService : Starting service [Tomcat]
2022-03-12 14:45:26.605 INFO 6332 --- [ main] org.apache.catalina.core.StandardEngine : Starting Servlet engine: [Apache Tomcat/9.0.58]
2022-03-12 14:45:26.652 INFO 6332 --- [ main] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring embedded WebApplicationContext
2022-03-12 14:45:26.653 INFO 6332 --- [ main] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: initialization completed in 706 ms
2022-03-12 14:45:26.929 INFO 6332 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat started on port(s): 8080 (http) with context path ''
2022-03-12 14:45:26.937 INFO 6332 --- [ main] h.hellospring.HelloSpringApplication : Started HelloSpringApplication in 1.365 seconds (JVM running for 1.744)
이러한 화면 이 나온다 여기서 중요한 것은,
2022-03-12 14:45:26.929 INFO 6332 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat started on port(s): 8080 (http) with context path ''
이부분이 가장 중요하다.
이제 실행이 성공적으로 완료되었다면, localhost:8080에 접속하면
에러 페이지가 나온다.
이렇게 실행만으로도 코드가 실행되는 이유는,
@SpringBootApplication 👉 요녀석 즉 SpringBootApplication이 어노테이션 때문에 가능한 것이다.
public class HelloSpringApplication {
public static void main(String[] args) {
SpringApplication.run(HelloSpringApplication.class, args);
}
}
//@SpringBootApplication의 내부 모습을 보자
/*
* Copyright 2012-2020 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.boot.autoconfigure;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.springframework.beans.factory.support.BeanNameGenerator;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.SpringBootConfiguration;
import org.springframework.boot.context.TypeExcludeFilter;
import org.springframework.context.annotation.AnnotationBeanNameGenerator;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.ComponentScan.Filter;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.FilterType;
import org.springframework.core.annotation.AliasFor;
import org.springframework.data.repository.Repository;
/**
* Indicates a {@link Configuration configuration} class that declares one or more
* {@link Bean @Bean} methods and also triggers {@link EnableAutoConfiguration
* auto-configuration} and {@link ComponentScan component scanning}. This is a convenience
* annotation that is equivalent to declaring {@code @Configuration},
* {@code @EnableAutoConfiguration} and {@code @ComponentScan}.
*
* @author Phillip Webb
* @author Stephane Nicoll
* @author Andy Wilkinson
* @since 1.2.0
*/
@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 {
/**
* Exclude specific auto-configuration classes such that they will never be applied.
* @return the classes to exclude
*/
@AliasFor(annotation = EnableAutoConfiguration.class)
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
*/
@AliasFor(annotation = EnableAutoConfiguration.class)
String[] excludeName() default {};
/**
* Base packages to scan for annotated components. Use {@link #scanBasePackageClasses}
* for a type-safe alternative to String-based package names.
* <p>
* <strong>Note:</strong> this setting is an alias for
* {@link ComponentScan @ComponentScan} only. It has no effect on {@code @Entity}
* scanning or Spring Data {@link Repository} scanning. For those you should add
* {@link org.springframework.boot.autoconfigure.domain.EntityScan @EntityScan} and
* {@code @Enable...Repositories} annotations.
* @return base packages to scan
* @since 1.3.0
*/
@AliasFor(annotation = ComponentScan.class, attribute = "basePackages")
String[] scanBasePackages() default {};
/**
* Type-safe alternative to {@link #scanBasePackages} for specifying the packages to
* scan for annotated components. The package of each class specified will be scanned.
* <p>
* Consider creating a special no-op marker class or interface in each package that
* serves no purpose other than being referenced by this attribute.
* <p>
* <strong>Note:</strong> this setting is an alias for
* {@link ComponentScan @ComponentScan} only. It has no effect on {@code @Entity}
* scanning or Spring Data {@link Repository} scanning. For those you should add
* {@link org.springframework.boot.autoconfigure.domain.EntityScan @EntityScan} and
* {@code @Enable...Repositories} annotations.
* @return base packages to scan
* @since 1.3.0
*/
@AliasFor(annotation = ComponentScan.class, attribute = "basePackageClasses")
Class<?>[] scanBasePackageClasses() default {};
/**
* The {@link BeanNameGenerator} class to be used for naming detected components
* within the Spring container.
* <p>
* The default value of the {@link BeanNameGenerator} interface itself indicates that
* the scanner used to process this {@code @SpringBootApplication} annotation should
* use its inherited bean name generator, e.g. the default
* {@link AnnotationBeanNameGenerator} or any custom instance supplied to the
* application context at bootstrap time.
* @return {@link BeanNameGenerator} to use
* @see SpringApplication#setBeanNameGenerator(BeanNameGenerator)
* @since 2.3.0
*/
@AliasFor(annotation = ComponentScan.class, attribute = "nameGenerator")
Class<? extends BeanNameGenerator> nameGenerator() default BeanNameGenerator.class;
/**
* Specify whether {@link Bean @Bean} methods should get proxied in order to enforce
* bean lifecycle behavior, e.g. to return shared singleton bean instances even in
* case of direct {@code @Bean} method calls in user code. This feature requires
* method interception, implemented through a runtime-generated CGLIB subclass which
* comes with limitations such as the configuration class and its methods not being
* allowed to declare {@code final}.
* <p>
* The default is {@code true}, allowing for 'inter-bean references' within the
* configuration class as well as for external calls to this configuration's
* {@code @Bean} methods, e.g. from another configuration class. If this is not needed
* since each of this particular configuration's {@code @Bean} methods is
* self-contained and designed as a plain factory method for container use, switch
* this flag to {@code false} in order to avoid CGLIB subclass processing.
* <p>
* Turning off bean method interception effectively processes {@code @Bean} methods
* individually like when declared on non-{@code @Configuration} classes, a.k.a.
* "@Bean Lite Mode" (see {@link Bean @Bean's javadoc}). It is therefore behaviorally
* equivalent to removing the {@code @Configuration} stereotype.
* @since 2.2
* @return whether to proxy {@code @Bean} methods
*/
@AliasFor(annotation = Configuration.class)
boolean proxyBeanMethods() default true;
}