tomcat의 shutdown.sh 를 실행해서 서비스는 불가능 한 상태가 되지만 tomcat 프로세스는 살아 있는 경우가 있다.

tomcat의 서블릿이 

 

@WebListener

public class SchedulerManager implements ServletContextListener {

    @Override

    public void contextDestroyed(ServletContextEvent sce) {

        for (ThreadPoolTaskScheduler sch : SchedulingFongifurer.threadPoolTaskSchedulerList) { // 스케줄러 설정 class에서 스제출러 설정 목록을 static 으로 저장해 둔 목록

             sch.shutdown();

        }

    }

}

Thymeleaf 적용한 프로젝트에서 title 부분을 전체 똑같이 적용해 달라는 요청이 있었다.

 

Thymeleaf Layout 이 적용된 상태에서

 

layout.html 

의 <title> 부분이 없는 상태였고

각 페이지에서 <title> 값을 설정한 상태였다.

layout.html 에 <title>LAYOUT</title> 을 추가해도

각 페이지의 <title> 이 layout.html 의 title을 대체하게 된다.

 

layout:title-pattern 속성을 이용하면 전체 페이지의 title을 패턴화 할수 있다.

lauout.html 에 아래 태그를 추가하면

<title layout:title-pattern="$LAYOUT_TITLE - $CONTENT_TITLE">MY SITE</title>

$LAYOUT_TITLE - 레이아웃의 타이틀 (구버전 : $DECORATOR_TITLE 는 deprecated 됨)

$CONTENT_TITLE - 각 페이지의 타이틀

 

실제 각 페이지에서는

<title>MY SITE - 각페이지 타이틀</title> 과 같이 된다.

 

해당 요청 사항은

<title layout:title-pattern="$LAYOUT_TITLE">MY SITE</title>

로 해결했다.

 

참고 : title-pattern - Thymeleaf Layout Dialect (ultraq.github.io)

1. jdk 1.8 설치

openjdk를 다운로드 받아서 설치한다.

oralce java를 다운로드 받아서 설치해도 상관없지만 zip버전을 제공하지 않으므로 

openjdk를 다운로드 받아 설치한다.

 

https://github.com/ojdkbuild/ojdkbuild

중간쯤에 Downloads for Windows x86_64 항목이 있다. 여기서 zip파일을 다운로드 한다.

openjdk 다운로드

d:\에 springboot라는 폴더를 생성해서 이곳에 다운받은 openjdk를 압축해제 합니다.

폴더명이 너무 길어서 버전만 알수 있도록 정리했습니다.

이후 이클립스 설치 이후 이클립스 설정에서 해당 폴더로 연결을 할겁니다.

 

2. 이클립스 설치

이클립스를 다운받아 설치합니다. 아래 링크로 이동하여 파일을 다운받습니다.

https://www.eclipse.org/downloads/

최신버전보다는 어느정도  지난 버전을 받는걸 추천합니다.

다운로드 버튼 아래의 Download Packages 링크를 클릭하고 들어가서

다른 버전을 받을 수 있습니다.

 

자신의 운영체제에 맞는 이클립스를 선택해서 다운로드 하면 됩니다.

 

다운로드시 미러 사이트를 선택할 수 있는데 한국의 카카오를 선택하면 빠른 속도로 다운로드가 가능합니다.

 

다운받은 zip파일을 D:\springboot 로 복사하여 압축을 해제 합니다.

 

D:\springboot\eclipse 폴더로 이동하여 eclipse.ini 파일을 문서편집기로 열어서 -vmargs 위에 -vm을 추가합니다.

다운받은 openjdk를 이클립스에서 기본으로 사용하도록 하는 설정입니다.

-vm
D:\springboot\openjdk-1.8.0.222-2.b10\bin\javaw.exe

eclipse.ini 파일

-startup
plugins/org.eclipse.equinox.launcher_1.5.200.v20180922-1751.jar
--launcher.library
plugins/org.eclipse.equinox.launcher.win32.win32.x86_64_1.1.900.v20180922-1751
-product
org.eclipse.epp.package.jee.product
-showsplash
org.eclipse.epp.package.common
--launcher.defaultAction
openFile
--launcher.defaultAction
openFile
--launcher.appendVmargs
-vm
D:\springboot\openjdk-1.8.0.222-2.b10\bin\javaw.exe
-vmargs
-Dosgi.requiredJavaVersion=1.8
-Dosgi.instance.area.default=@user.home/eclipse-workspace
-XX:+UseG1GC
-XX:+UseStringDeduplication
--add-modules=ALL-SYSTEM
-Dosgi.requiredJavaVersion=1.8
-Dosgi.dataAreaRequiresExplicitInit=true
-Xms1024m
-Xmx1024m
--add-modules=ALL-SYSTEM

 

이클립스를 실행하면 workspace를 선택하는 창이 나옵니다. springboot에 workspace라는 폴더를 만들고 해당 폴더를 선택합니다.

 

 

 

3. 이클립스에 스프링(STS) 설치

이클립스가 실행되면 메뉴 Help > Eclipse Marketplace 메뉴를 클릭하여 

marketplace로 들어갑니다.

검색창에 sts를 입력하고 검색합니다.

Spring Tools 4 를 선택하여 Install 합니다.

 

 

4. 프로젝트 생성 및 테스트 페이지 접속

메뉴 : File > New > Other > Spring Boot > Spring Starter Project 를 선택하고 Next 클릭

 

 

 

 

 

<?xml version="1.0" encoding="UTF-8"?>

앞에 에러표시가 나는 경우 프로젝트 진행에는 문제가 없습니다. 하지만 x박이 계속뜨므로

properties에

<maven-jar-plugin.version>3.1.1</maven-jar-plugin.version> 

를 추가합니다.

	<properties>
		<java.version>1.8</java.version>
		<maven-jar-plugin.version>3.1.1</maven-jar-plugin.version> <!-- prevent pom config error-->
	</properties>

 

 

com.example.demo 패키지안에 DemoApiController class를 새로 만듭니다.

package com.example.demo;

import java.util.HashMap;
import java.util.Map;

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class DemoApiController {

	@GetMapping("/demoapistring")
	public String demoapistring() {

		return "데모 스트링 타입 리턴";
	}
	
	@GetMapping("/demoapi")
	public Map<String, Object> demoapi() {
		Map<String, Object> map = new HashMap<>();
		map.put("name", "홍길동");
		map.put("birthday", 15920505);
		return map;
	}
}

 

DemoApplication.java 파일을 열고 Run As > Spring Boot App 을 클릭하여 실행합니다.

Demo(프로젝트명)Application.java 는 스프링 부트의 시작점 입니다.

 

  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::        (v2.1.7.RELEASE)

2019-08-21 15:53:06.169  INFO 13044 --- [           main] com.example.demo.DemoApplication         : Starting DemoApplication on WIN-F2I020EETH2 with PID 13044 (D:\springboot\workspace\demo\target\classes started by kyoborealco in D:\springboot\workspace\demo)
2019-08-21 15:53:06.171  INFO 13044 --- [           main] com.example.demo.DemoApplication         : No active profile set, falling back to default profiles: default
2019-08-21 15:53:06.807  INFO 13044 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat initialized with port(s): 8080 (http)
2019-08-21 15:53:06.827  INFO 13044 --- [           main] o.apache.catalina.core.StandardService   : Starting service [Tomcat]
2019-08-21 15:53:06.827  INFO 13044 --- [           main] org.apache.catalina.core.StandardEngine  : Starting Servlet engine: [Apache Tomcat/9.0.22]
2019-08-21 15:53:06.897  INFO 13044 --- [           main] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring embedded WebApplicationContext
2019-08-21 15:53:06.897  INFO 13044 --- [           main] o.s.web.context.ContextLoader            : Root WebApplicationContext: initialization completed in 697 ms
2019-08-21 15:53:07.042  INFO 13044 --- [           main] o.s.s.concurrent.ThreadPoolTaskExecutor  : Initializing ExecutorService 'applicationTaskExecutor'
2019-08-21 15:53:07.168  INFO 13044 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat started on port(s): 8080 (http) with context path ''
2019-08-21 15:53:07.171  INFO 13044 --- [           main] com.example.demo.DemoApplication         : Started DemoApplication in 1.216 seconds (JVM running for 1.737)
2019-08-21 15:53:15.125  INFO 13044 --- [nio-8080-exec-1] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring DispatcherServlet 'dispatcherServlet'
2019-08-21 15:53:15.125  INFO 13044 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet        : Initializing Servlet 'dispatcherServlet'
2019-08-21 15:53:15.129  INFO 13044 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet        : Completed initialization in 4 ms
2019-08-21 15:56:16.330  INFO 13044 --- [n(12)-127.0.0.1] inMXBeanRegistrar$SpringApplicationAdmin : Application shutdown requested.
2019-08-21 15:56:16.332  INFO 13044 --- [n(12)-127.0.0.1] o.s.s.concurrent.ThreadPoolTaskExecutor  : Shutting down ExecutorService 'applicationTaskExecutor'

콘솔 로그를 보면 톰캣이 8080으로 기동되었다고 표시됩니다.

http://localhost:8080/demoapistring

 

http://localhost:8080/demoapi

@RestController 을 추가한 경우

return 타입이 Object 인 경우 해당 object 에 맞게 json 형식으로 표시됩니다.

 

 

5. Boot Dashboard 설정 및 서버 포트 변경

 

파일들이 많이 지면 Application.java 에서 실행하는게 귀찮아 질 수 있습니다.

그래서 Boot Dashboard에서 바로 실행을 할 수 있도록 설정을 합니다.

 

window > show view > Other > Other > Boot Dashboard 선택

 

포트 변경은 src/main/resources/application.properties 파일에서

server.port=8888

로 설정하면 톰캣이 8888번 포트로 기동됩니다.

-- 가장 빨리 만나는 스프링부트

1) 포트 사용 에러

 

오류: 에이전트에 예외사항이 발생했습니다. : java.rmi.server.ExportException: Port already in use: 35199; nested exception is: 
java.net.BindException: Address already in use: JVM_Bind

 

실행 중지를 하지 않고 다시 실행하는 경우 위와 같은 에러가 종종 발생한다.

 

사용하려는 포트가 이미 사용중이라는 말로 사용중인 포트의 프로세스아이디를 찾아서 해당 프로세스를 죽여줘야 한다.

 

윈도우키+r -> cmd -> netstat 명령어로 사용중인 포트의 프로세스아이디를 찾아 킬하면 됩니다.

 

8080 사용 프로세스 검색 및 프로세스 종료시키기

 

cmd > netstat -ano | findstr 8080

실행을 하면 8080포트를 사용하는 프로세스 목록이 나옵니다.

가장 오른쪽의 프로세스 아이디를 킬해주면 됩니다.

cmd > taskkill /F /PID 8964

 

리소스 모니터에서 해당 프로세스 종료하기

작업관리자의 리소스모니터에서 해당 프로세스를 종료할 수 도 있습니다.

 

2) Unable to start embedded container

톰캣과 언더토우의 충돌

org.apache.tomcat.websocket.WsWebSocketContainer cannot be cast to io.undertow.websockets.jsr.ServerWebSocketContainer

 

org.springframework.context.ApplicationContextException: Unable to start embedded container; nested exception is java.lang.ClassCastException: org.apache.tomcat.websocket.WsWebSocketContainer cannot be cast to io.undertow.websockets.jsr.ServerWebSocketContainer
at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.onRefresh(EmbeddedWebApplicationContext.java:133)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:474)
at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.java:118)
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:686)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:320)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:957)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:946)
at com.example.App.main(App.java:13)
Caused by: java.lang.ClassCastException: org.apache.tomcat.websocket.WsWebSocketContainer cannot be cast to io.undertow.websockets.jsr.ServerWebSocketContainer
at io.undertow.websockets.jsr.Bootstrap.handleDeployment(Bootstrap.java:62)
at io.undertow.servlet.core.DeploymentManagerImpl.handleExtensions(DeploymentManagerImpl.java:244)
at io.undertow.servlet.core.DeploymentManagerImpl.deploy(DeploymentManagerImpl.java:149)
at org.springframework.boot.context.embedded.undertow.UndertowEmbeddedServletContainerFactory.createDeploymentManager(UndertowEmbeddedServletContainerFactory.java:340)
at org.springframework.boot.context.embedded.undertow.UndertowEmbeddedServletContainerFactory.getEmbeddedServletContainer(UndertowEmbeddedServletContainerFactory.java:203)
at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.createEmbeddedServletContainer(EmbeddedWebApplicationContext.java:157)
at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.onRefresh(EmbeddedWebApplicationContext.java:130)
... 7 common frames omitted

 

 

pom.xml 에서 스프링 부트의 기본 서버인 톰캣과 추가된 서버 언더토우의 충돌문제

 

	<dependency>
  		<groupId>org.springframework.boot</groupId>
  		<artifactId>spring-boot-starter-web</artifactId>
  	</dependency>
 
  	<dependency>
  		<groupId>org.springframework.boot</groupId>
  		<artifactId>spring-boot-starter-undertow</artifactId>
  	</dependency>

디팬던시에 undertow가 추가된 경우

spring-boot-starter-web 부분에서 톰캣을 사용하지 않는다는 설정을 추가해 주어야 한다.

  	<dependency>
  		<groupId>org.springframework.boot</groupId>
  		<artifactId>spring-boot-starter-web</artifactId>
 		<exclusions>
  			<exclusion>
  				<groupId>org.apache.tomcat.embed</groupId>
  				<artifactId>tomcat-embed-websocket</artifactId>
  			</exclusion>
  		</exclusions>
  	</dependency>
  	<dependency>
  		<groupId>org.springframework.boot</groupId>
  		<artifactId>spring-boot-starter-undertow</artifactId>
  	</dependency>

또는 undertow를 사용하지 않는 방법이 있다.

 

+ Recent posts