JPA?

자바 퍼시스턴스(Java Persistence, 이전 이름: 자바 퍼시스턴스 API/Java Persistence API) 또는 자바 지속성 API(Java Persistence API, JPA)는 자바 플랫폼 SE 자바 플랫폼 EE를 사용하는 응용프로그램에서 관계형 데이터베이스의 관리를 표현하는 자바 API이다. -위키글-

 

https://ko.wikipedia.org/wiki/%EC%9E%90%EB%B0%94_%ED%8D%BC%EC%8B%9C%EC%8A%A4%ED%84%B4%EC%8A%A4

 

자바 퍼시스턴스 - 위키백과, 우리 모두의 백과사전

위키백과, 우리 모두의 백과사전. 자바 퍼시스턴스(Java Persistence, 이전 이름: 자바 퍼시스턴스 API/Java Persistence API) 또는 자바 지속성 API(Java Persistence API, JPA)는 자바 플랫폼 SE와 자바 플랫폼 EE를

ko.wikipedia.org

 

간단하게 jpa에 위키글을 요약하자면 데이터베이스를 관리하는 api라고 생각하면 됩니다.

그렇다면 jpa에 사용법과 구조에 대해서 정확하게 알아 보도록 하겠습니다.

 

간단한 entity와 해당 repository부터 보겠습니다.

@Entity
class Person {

  @Id @GeneratedValue(strategy = GenerationType.AUTO)
  private Long id;
  private String name;

  // getters and setters ommited for brevity
}

interface PersonRepository extends Repository<Person, Long> {

  Person save(Person person);

  Optional<Person> findById(long id);
}

 

메인에서 예제를 확인해보겠습니다.

@SpringBootApplication
public class DemoApplication {

  public static void main(String[] args) {
    SpringApplication.run(DemoApplication.class, args);
  }

  @Bean
  CommandLineRunner runner(PersonRepository repository) {
    return args -> {

      Person person = new Person();
      person.setName("John");

      repository.save(person);
      Person saved = repository.findById(person.getId()).orElseThrow(NoSuchElementException::new);
    };
  }
}

 

Repsoitory 인스턴스들은 자동적으로 실행됩니다. 

메소드의 @Bean의 파라미터들을 사용할때, annotation이 추가적으로 필요 없이 autowired 하게 됩니다.

기본적으로 repsoitory 는 repsoitory 확장합니다(?)

일반적으로 우리는 api surface  사용자의 application에 노출을 원하는 만큼 고려하여 제안하다(?)

(아마 제가 볼때 Repository 상속받아서 사용하는 그런부분인것 같습니다... 확실히 모르겠네요

(아래 내용은 api surface(api 표면) 즉 api 상호 작용할수 있는 코드부분을 뜻한다고 하네요.

즉 가용할수 있는 api surface부분을 고려하면서 repsoitory를 확장해서 사용하라는 뜻 같네요

틀리면 지적 부탁드립니다.)

 마지막으로 

더욱 복잡한 인터페이스들인 ListCrudRepository, JpaRepository들이 존재합니다.

https://docs.spring.io/spring-data/jpa/reference/jpa/getting-started.html

 

Getting Started :: Spring Data JPA

Let’s start with a simple entity and its corresponding repository: @Entity class Person { @Id @GeneratedValue(strategy = GenerationType.AUTO) private Long id; private String name; // getters and setters ommited for brevity } interface PersonRepository ex

docs.spring.io

 

https://www.acmicpc.net/problem/2665

 

2665번: 미로만들기

첫 줄에는 한 줄에 들어가는 방의 수 n(1 ≤ n ≤ 50)이 주어지고, 다음 n개의 줄의 각 줄마다 0과 1이 이루어진 길이가 n인 수열이 주어진다. 0은 검은 방, 1은 흰 방을 나타낸다.

www.acmicpc.net

 

다이크스트라를 이해하고 잇어야 쉽게 풀었겟네요.

 

한 5일정도 풀다가 더이상 안풀려서 대학때 배운 다이크스트라 다시 보니 좀 이해가 되네요 ㅠ 

으휴 ㅠ 다음에 비슷한문제로 좀 풀어봐야겟네요 ㅠ 

import java.util.*;

public class Main {
    private int x;
    private int y;

    public Main(int x, int y) {
        this.x = x;
        this.y = y;
    }

    public int getX() {
        return this.x;
    }

    public int getY() {
        return this.y;
    }

    public static void main(String[] args) {
        Scanner scan = new Scanner(System.in);
        int n = scan.nextInt();
        scan.nextLine(); 

        int[] dx = {1, -1, 0, 0};
        int[] dy = {0, 0, 1, -1};
        int[][] maps = new int[n][n];
        int[][] dist = new int[n][n];

        for (int i = 0; i < n; i++) {
            String tmp = scan.nextLine();
            for (int j = 0; j < tmp.length(); j++) {
                maps[i][j] = tmp.charAt(j) - '0';
                dist[i][j] = -1;
            }
        }

        Queue<Main> queue = new LinkedList<>();
        queue.add(new Main(0, 0));
        dist[0][0] = 0; 

        while (!queue.isEmpty()) {
            Main current = queue.poll();

            for (int i = 0; i < 4; i++) {
                int tmpDiri = current.getX() + dx[i];
                int tmpDirj = current.getY() + dy[i];

                if (tmpDiri < 0 || tmpDirj < 0 || tmpDiri >= n || tmpDirj >= n) {
                	continue; 
                } 

                int nextDist = dist[current.getX()][current.getY()];
                if (maps[tmpDiri][tmpDirj] == 0) {
                	nextDist += 1; 
                }

                if (dist[tmpDiri][tmpDirj] == -1 || dist[tmpDiri][tmpDirj] > nextDist) {
                    dist[tmpDiri][tmpDirj] = nextDist;
                    queue.add(new Main(tmpDiri, tmpDirj));
                }
            }
        }

        System.out.println(dist[n - 1][n - 1]); 
    }
}

'알고리즘 공부' 카테고리의 다른 글

백준 컨베이어 밸트 위의 로봇  (1) 2024.02.17
백준 빗물  (0) 2024.02.11
백준 괄호의 값  (1) 2024.01.24
백준 톱니바퀴  (0) 2024.01.17
백준 숨바꼭질4  (0) 2024.01.12

2024.01.06 - [웹/Spring vue 웹 개발] - JWT(json web token) 개발하며 이해하기

 

JWT(json web token) 개발하며 이해하기

JWT 구조 이해헤더(Header): 토큰의 타입 (주로 JWT)과 사용된 해싱 알고리즘 (예: HMAC, SHA256, RSA)을 명시합니다.페이로드(Payload): 토큰에 담을 클레임(claims)을 포함합니다. 클레임은 토큰 사용자에 대

kwaksh2319.tistory.com

 

https://youtu.be/Q7V7R3bhRQg

 

 

이번에 jwt 토큰을 개발하면서 swagger에 간단히 적용해봤습니다.

package kr.co.kshproject.webDemo.Common;

import io.swagger.v3.oas.models.Components;
import io.swagger.v3.oas.models.media.Schema;
import io.swagger.v3.oas.models.media.StringSchema;
import io.swagger.v3.oas.models.security.SecurityRequirement;
import io.swagger.v3.oas.models.security.SecurityScheme;
import io.swagger.v3.oas.models.servers.Server;
import org.springdoc.core.GroupedOpenApi;
import org.springdoc.core.customizers.OpenApiCustomiser;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpHeaders;

import java.util.ArrayList;
import java.util.List;


@Configuration
public class SwaggerConfig {

    @Bean
    public SecurityScheme customSecurityScheme() {
        return new SecurityScheme()
                .type(SecurityScheme.Type.HTTP)
                .scheme("bearer")
                .bearerFormat("JWT")
                .in(SecurityScheme.In.HEADER)
                .name(HttpHeaders.AUTHORIZATION);
    }

    @Bean
    public GroupedOpenApi commonApi() {
        return GroupedOpenApi.builder()
                .group("api")
                .addOpenApiCustomiser(serverCustomizer())
                .packagesToScan("kr.co.kshproject.webDemo")
                .pathsToMatch("/**")
                .build();
    }

    @Bean
    public OpenApiCustomiser serverCustomizer() {
        return openApi -> {
            // 기존 Components 객체에 접근
            Components components = openApi.getComponents();
            if (components == null) components = new Components();

            // ErrorResult 스키마 추가
            components.addSchemas("ErrorResult", new Schema<>()
                    .type("object")
                    .addProperty("message", new StringSchema())
                    .addProperty("errorCode", new StringSchema()));

            // SecurityScheme 추가
            openApi.addSecurityItem(new SecurityRequirement().addList("bearerAuth")); // 엔드포인트 전부 적용
            components.addSecuritySchemes("bearerAuth", customSecurityScheme());  // swagger auth 버튼 
            openApi.components(components);

            List<Server> servers=new ArrayList<>();
            servers.add(new Server().url("http://localhost:8080").description("for local usages"));
            openApi.setServers(servers);
        };
    }
}

 

 

https://www.acmicpc.net/problem/2504

 

2504번: 괄호의 값

4개의 기호 ‘(’, ‘)’, ‘[’, ‘]’를 이용해서 만들어지는 괄호열 중에서 올바른 괄호열이란 다음과 같이 정의된다. 한 쌍의 괄호로만 이루어진 ‘()’와 ‘[]’는 올바른 괄호열이다. 만일 X

www.acmicpc.net

이틀이나 걸렸네용 ㅠ 

그렇게 어려운건 아닌데 좀 헷갈리는 문제네요.


import java.util.*;

public class Main {
    public static void main(String[] args) {
    	//한쌍의 괄호 (), []
    	//만일 x 가 올바른 괄호열 '(x)' 이나 [x] 도 ㅇ모두 올바른 괄호열이다
    	Scanner scan=new Scanner(System.in);
    	String str=scan.nextLine();
    	
    	//ArrayList<Character>stack=new ArrayList<>();
    	Stack<Character> stack=new Stack<>();
    	Stack<Character> sign=new Stack<>();
    	Stack<Character> anw=new Stack<>();
    	char pre='v';
    	boolean bCheck=false;
    	int sum=1;
    	int anws=0;
    	boolean isValid = true;
    	for(int i=0;i<str.length();i++) {
    		char c = str.charAt(i);
    		
    		if(c=='(' || c=='[') {
    			stack.add(c);
    			if(c=='(') {
    				sum=sum*2;
    			}
    			else {
    				sum=sum*3;
    			}
    			bCheck=true;
    			
    		}else {
    			
    			if(stack.isEmpty()) {
    				anws=0;
    				i=str.length()+1;
    				continue;
    			}
    			
    			char tmp=stack.peek();
    			stack.pop();
    			
    			if(c==')'&& tmp!='(') {
    				anws=0;
    				i=str.length()+1;
    				continue;
    			}
    			else if(c==']'&&tmp!='[') {
    				anws=0;
    				i=str.length()+1;
    				continue;
    			}
    			
    			if(bCheck==true) {
    				anws+=sum;
    			}
    			
    			if(c==')') {
    				sum=sum/2;
    			}else if(c==']') {
    				sum=sum/3;
    			}
    			
    			
    			bCheck=false;
    		}
    	}
    	if (!stack.isEmpty()) isValid = false;

        System.out.println(isValid ? anws : 0);

    }
}

'알고리즘 공부' 카테고리의 다른 글

백준 빗물  (0) 2024.02.11
백준 미로 만들기  (1) 2024.02.02
백준 톱니바퀴  (0) 2024.01.17
백준 숨바꼭질4  (0) 2024.01.12
백준 미세먼지 안녕!  (1) 2024.01.06

2024.01.13 - [웹/Spring vue 웹 개발] - jenkins 연결 작업 01

 

jenkins 연결 작업 01

먼저 현재 git 프로젝트와 jenkins을 연결 했는데요. 아직 정확하게 사용법을 잘 모르겠습니다. 사용하는 방법 관련해서는 내일 해보도록 하겠습니다.

kwaksh2319.tistory.com

 

음 현재 계획중인건 

다른 port를 이용해서 docker위에 젠킨슨을 설치후에 다른 도커 이미지에 있는 웹사이트를 빌드할수 있게 하려 햇는데요.

무언가 문제인지 계속 사이트가 느려지거나 e2c 환경이 문제가 생기는것같습니다 .

cpu 이용률이 너무 높아져서 (계속  aws 인스턴스만 껏다 켯네요.. 처음엔 설치 문제에다가 ㅠㅠ ) 

도커에 이미지 두개를 사용하는게 상당히 문제가 되는것같네요.

프리티어의 ram이 1기가? 이 정도로 알고 있어서 아마 도커 이미지 2개의 감당이 안되는듯하다.

 

 

그래서 음 조금 고민 해봣는데요. 아무래도 aws의 인스턴스를 하나 추가하면 프리티어가 아니기 때문에 

제 pc에서 .젠킨슨을 사용하고 

윈도우에서 이용하는 방법으로 하겠습니다. 

 

https://www.acmicpc.net/problem/14891

 

14891번: 톱니바퀴

첫째 줄에 1번 톱니바퀴의 상태, 둘째 줄에 2번 톱니바퀴의 상태, 셋째 줄에 3번 톱니바퀴의 상태, 넷째 줄에 4번 톱니바퀴의 상태가 주어진다. 상태는 8개의 정수로 이루어져 있고, 12시방향부터

www.acmicpc.net

3일이나 걸렷네요 ㅠ 

package test01;

import java.util.Scanner;

public class Main {
    private static int[][] gears = new int[4][8];

    // 톱니바퀴를 시계 방향으로 회전
    public static void reverseClocks(int gearNum) {
        int firstnum = gears[gearNum][0];
        for (int j = 1; j < 8; j++) {
            gears[gearNum][j - 1] = gears[gearNum][j];
        }
        gears[gearNum][7] = firstnum;
    }

    // 톱니바퀴를 반시계 방향으로 회전
    public static void clocks(int gearNum) {
        int lastnum = gears[gearNum][7];
        for (int j = 7; j > 0; j--) {
            gears[gearNum][j] = gears[gearNum][j - 1];
        }
        gears[gearNum][0] = lastnum;
    }

    // 톱니바퀴 상태 출력
    public static void Prints() {
        for (int i = 0; i < 4; i++) {
            for (int j = 0; j < 8; j++) {
                System.out.print(gears[i][j]);
            }
            System.out.println();
        }
        System.out.println();
    }

    // 점수 계산
    public static void Score() {
        int sc = 0;
        for (int i = 0; i < 4; i++) {
            if (gears[i][0] == 1) {
                sc += (1 << i);
            }
        }
        System.out.println(sc);
    }

    // 주어진 방향에 따라 톱니바퀴 이동 확인
    public static void checkingmove(int num, int dir, boolean[] visited) {
        if (num < 0 || num > 3) {
            return;
        }

        visited[num] = true;

        if (num > 0 && !visited[num - 1]) {
            if (gears[num][6] != gears[num - 1][2]) {
                checkingmove(num - 1, -dir, visited);
            }
        }

        if (num < 3 && !visited[num + 1]) {
            if (gears[num][2] != gears[num + 1][6]) {
                checkingmove(num + 1, -dir, visited);
            }
        }

        if (dir == 1) {
            clocks(num);
        } else {
            reverseClocks(num);
        }
    }

    public static void main(String[] args) {
        Scanner scan = new Scanner(System.in);

        // 사용자 입력을 통한 톱니바퀴 상태 설정
        for (int i = 0; i < 4; i++) {
            String str = scan.nextLine();
            for (int j = 0; j < str.length(); j++) {
                gears[i][j] = str.charAt(j) - '0';
            }
        }
      //  Prints();

        // 회전 명령의 횟수 입력 받기
        int k = scan.nextInt();
        for (int i = 0; i < k; i++) {
            int gearNum = scan.nextInt() - 1;
            int dir = scan.nextInt();
            boolean[] visited = new boolean[4];
            checkingmove(gearNum, dir, visited);
           // Prints();
        }
        Score();

        scan.close();
    }
}

 

'알고리즘 공부' 카테고리의 다른 글

백준 미로 만들기  (1) 2024.02.02
백준 괄호의 값  (1) 2024.01.24
백준 숨바꼭질4  (0) 2024.01.12
백준 미세먼지 안녕!  (1) 2024.01.06
백준 - 경쟁적 전염  (1) 2024.01.02

공부하게 된 계기는 팀장님의 피드백으로 인해서 많은 생각을 하게 되었습니다.

그리고 코드를 분석하는 방법에 대해서도 결과부터가 아니라 순차적으로 분석해야 한다는 느낌을 많이 받았습니다.

 

기존에 개발하면서 결과적인 시각으로 많이 바라본게 아닌가 라는 생각을 많이 하게되었습니다. 아직 조금 그러한 습관이 남아 있어서 천천히 없애도록 노력해야겠다는 생각이 들었습니다. (한번에 없어지는게 이상한거겠지만 ㅎㅎ 일단은 조금씩 바꾸면 언젠간 바뀐다고 믿는 성격이어서 열심히 해볼생각입니다. 생각해보면 블로그 작성이나 공부하는 습관들도 처음부터 생겼던건 아니었으니까요. ㅎㅎ) 

 

과연 war 실행의 구동원리를 정확하게 이해하고 있는가? 에 대해서 다시 한번 돌아보게 되었습니다.

조금 더 섬세하게 체크 해야겟다는 생각이 많이 들었습니다.

 

톰캣 이용되는곳?

 

정확하게 웹이 실행될때 일반적으로 톰캣을 이용하여 사용하는경우가 많다.

물론  iis 서버 같은걸로 할수 있지만 일단 저희 회사에선 톰캣을 이용하기도 하고 많은 회사들이 톰캣을 이용하기 때문에 

톰캣동작에 대해서 먼저 정리해보도록 하겠습니다.

 

톰캣(tomcat) 설치 링크:

https://tomcat.apache.org/

 

Apache Tomcat® - Welcome!

The Apache Tomcat® software is an open source implementation of the Jakarta Servlet, Jakarta Server Pages, Jakarta Expression Language, Jakarta WebSocket, Jakarta Annotations and Jakarta Authentication specifications. These specifications are part of the

tomcat.apache.org

기본적인 형태는 이렇습니다.

/bin            -   시작, 종료 및 기타 스크리트 파일

/conf          -  구성 파일 및 관련 DTD, 여기서 중요한 파일은 sever.xml입니다. 컨테이너 기본 구성 파일입니다.

/logs          -  로그 파일은 기본적으로 여기있습니다.

/webapps  - 웹앱은 여기에 있습니다.

 

Catalina_Home 및 Catalina_Base?

  • catalina_home: 톰캣 설치 루트를 나타냅니다. ( 예: /home/tomcat/apache-tomcat-9.0x, C:\program Files\ apache-tomcat-9.0x )
  • catalina_base:특정 Tomact 인스턴스의 런타임 구성 루트를 나타냅니다. 한 시스템에 여러 Tomcat 인스턴스를 갖고 싶다면 이 Catlian_base 속성을 사용하면 됩니다.
  • 속성을 다른 위치로 설정하면 catilina_home 위치에 .jar 파일이나 바이너리 파일과 정적 소스가 포함됩니다. catalina_base위치에는 구성 파일, 로그 파일, 배포된 애플리케이션 및 기타 런타임 요구 사항이 포함됩니다.

Catalina_base를 사용하는 이유?

기본적으로 Catalina_home과 Catlina_base는 동일한 디렉토리를 가리킵니다. 하나의 시스템에서 여러 톰캣 인스턴스를 실행해야하는 경우 Catalina_base를 수동으로 설정하십시오.

  • 최신버전의 톰캣으로 업그레이드 관리가 더 쉬워졌습니다. 단일 Catalina_home위치를 가진 모든 인스턴스는 하나의 파일 및 바이너리 파일 세트를 공유하므로, .jar파일을 최신 버전으로 쉽게 업그레이드하고 동일한 Catalina_home 디렉터리를 사용하는 모든 톰캣 인스턴스에 변경사항을 전파할수 있습니다.
  • 동일한 정적 .jar 파일의 중복을 방지합니다.
  • sentenv운영 체제에 따라 쉘 또는 bat 스크립트 파일과 같은 특정 설정을 공유할수 있습니다.

코드에 대해서 한번 분석 해보겠습니다.

우선 startup.bat을 실행하면 

보시면 rem 은 주석이므로 쓸데 없는 앞부분은 지웟습니다.

@echo off

rem ---------------------------------------------------------------------------
rem Start script for the CATALINA Server
rem ---------------------------------------------------------------------------

setlocal

set "CURRENT_DIR=%cd%"

if not "%CATALINA_HOME%" == "" goto gotHome
set "CATALINA_HOME=%CURRENT_DIR%"
if exist "%CATALINA_HOME%\bin\catalina.bat" goto okHome

cd ..
set "CATALINA_HOME=%cd%"

cd "%CURRENT_DIR%"
:gotHome
if exist "%CATALINA_HOME%\bin\catalina.bat" goto okHome
echo The CATALINA_HOME environment variable is not defined correctly
echo This environment variable is needed to run this program
goto end
:okHome

set "EXECUTABLE=%CATALINA_HOME%\bin\catalina.bat"

rem Check that target executable exists

if exist "%EXECUTABLE%" goto okExec
echo Cannot find "%EXECUTABLE%"
echo This file is needed to run this program
goto end
:okExec

rem Get remaining unshifted command line arguments and save them in the

set CMD_LINE_ARGS=
:setArgs
if ""%1""=="""" goto doneSetArgs
set CMD_LINE_ARGS=%CMD_LINE_ARGS% %1
shift
goto setArgs
:doneSetArgs

call "%EXECUTABLE%" start %CMD_LINE_ARGS%

:end

 

코드를 보시면 

startup.bat->catalina.bat을 호출하죠. 

catalina.bat을 한번 보겠습니다. 마찬가지로 앞부분 rem은 조금 삭제하겠습니다.

 

@echo off

setlocal

rem Suppress Terminate batch job on CTRL+C
if not ""%1"" == ""run"" goto mainEntry
if "%TEMP%" == "" goto mainEntry
if exist "%TEMP%\%~nx0.run" goto mainEntry
echo Y>"%TEMP%\%~nx0.run"
if not exist "%TEMP%\%~nx0.run" goto mainEntry
echo Y>"%TEMP%\%~nx0.Y"
call "%~f0" %* <"%TEMP%\%~nx0.Y"
rem Use provided errorlevel
set RETVAL=%ERRORLEVEL%
del /Q "%TEMP%\%~nx0.Y" >NUL 2>&1
exit /B %RETVAL%
:mainEntry
del /Q "%TEMP%\%~nx0.run" >NUL 2>&1

rem Guess CATALINA_HOME if not defined
set "CURRENT_DIR=%cd%"
if not "%CATALINA_HOME%" == "" goto gotHome
set "CATALINA_HOME=%CURRENT_DIR%"
if exist "%CATALINA_HOME%\bin\catalina.bat" goto okHome
cd ..
set "CATALINA_HOME=%cd%"
cd "%CURRENT_DIR%"
:gotHome

if exist "%CATALINA_HOME%\bin\catalina.bat" goto okHome
echo The CATALINA_HOME environment variable is not defined correctly
echo This environment variable is needed to run this program
goto end
:okHome

rem Copy CATALINA_BASE from CATALINA_HOME if not defined
if not "%CATALINA_BASE%" == "" goto gotBase
set "CATALINA_BASE=%CATALINA_HOME%"
:gotBase

rem Ensure that neither CATALINA_HOME nor CATALINA_BASE contains a semi-colon
rem as this is used as the separator in the classpath and Java provides no
rem mechanism for escaping if the same character appears in the path. Check this
rem by replacing all occurrences of ';' with '' and checking that neither
rem CATALINA_HOME nor CATALINA_BASE have changed
if "%CATALINA_HOME%" == "%CATALINA_HOME:;=%" goto homeNoSemicolon
echo Using CATALINA_HOME:   "%CATALINA_HOME%"
echo Unable to start as CATALINA_HOME contains a semicolon (;) character
goto end
:homeNoSemicolon

if "%CATALINA_BASE%" == "%CATALINA_BASE:;=%" goto baseNoSemicolon
echo Using CATALINA_BASE:   "%CATALINA_BASE%"
echo Unable to start as CATALINA_BASE contains a semicolon (;) character
goto end
:baseNoSemicolon

rem Ensure that any user defined CLASSPATH variables are not used on startup,
rem but allow them to be specified in setenv.bat, in rare case when it is needed.
set CLASSPATH=

rem Get standard environment variables
if not exist "%CATALINA_BASE%\bin\setenv.bat" goto checkSetenvHome
call "%CATALINA_BASE%\bin\setenv.bat"
goto setenvDone
:checkSetenvHome
if exist "%CATALINA_HOME%\bin\setenv.bat" call "%CATALINA_HOME%\bin\setenv.bat"
:setenvDone

rem Get standard Java environment variables
if exist "%CATALINA_HOME%\bin\setclasspath.bat" goto okSetclasspath
echo Cannot find "%CATALINA_HOME%\bin\setclasspath.bat"
echo This file is needed to run this program
goto end
:okSetclasspath
call "%CATALINA_HOME%\bin\setclasspath.bat" %1
if errorlevel 1 goto end

rem Add on extra jar file to CLASSPATH
rem Note that there are no quotes as we do not want to introduce random
rem quotes into the CLASSPATH
if "%CLASSPATH%" == "" goto emptyClasspath
set "CLASSPATH=%CLASSPATH%;"
:emptyClasspath
set "CLASSPATH=%CLASSPATH%%CATALINA_HOME%\bin\bootstrap.jar"

if not "%CATALINA_TMPDIR%" == "" goto gotTmpdir
set "CATALINA_TMPDIR=%CATALINA_BASE%\temp"
:gotTmpdir

rem Add tomcat-juli.jar to classpath
rem tomcat-juli.jar can be over-ridden per instance
if not exist "%CATALINA_BASE%\bin\tomcat-juli.jar" goto juliClasspathHome
set "CLASSPATH=%CLASSPATH%;%CATALINA_BASE%\bin\tomcat-juli.jar"
goto juliClasspathDone
:juliClasspathHome
set "CLASSPATH=%CLASSPATH%;%CATALINA_HOME%\bin\tomcat-juli.jar"
:juliClasspathDone

if not "%JSSE_OPTS%" == "" goto gotJsseOpts
set JSSE_OPTS="-Djdk.tls.ephemeralDHKeySize=2048"
:gotJsseOpts
set "JAVA_OPTS=%JAVA_OPTS% %JSSE_OPTS%"

rem Register custom URL handlers
rem Do this here so custom URL handles (specifically 'war:...') can be used in the security policy
set "JAVA_OPTS=%JAVA_OPTS% -Djava.protocol.handler.pkgs=org.apache.catalina.webresources"

if not "%LOGGING_CONFIG%" == "" goto noJuliConfig
set LOGGING_CONFIG=-Dnop
if not exist "%CATALINA_BASE%\conf\logging.properties" goto noJuliConfig
set LOGGING_CONFIG=-Djava.util.logging.config.file="%CATALINA_BASE%\conf\logging.properties"
:noJuliConfig

if not "%LOGGING_MANAGER%" == "" goto noJuliManager
set LOGGING_MANAGER=-Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager
:noJuliManager

rem Configure JAVA 9 specific start-up parameters
set "JDK_JAVA_OPTIONS=%JDK_JAVA_OPTIONS% --add-opens=java.base/java.lang=ALL-UNNAMED"
set "JDK_JAVA_OPTIONS=%JDK_JAVA_OPTIONS% --add-opens=java.rmi/sun.rmi.transport=ALL-UNNAMED"

rem ----- Execute The Requested Command ---------------------------------------

echo Using CATALINA_BASE:   "%CATALINA_BASE%"
echo Using CATALINA_HOME:   "%CATALINA_HOME%"
echo Using CATALINA_TMPDIR: "%CATALINA_TMPDIR%"
if ""%1"" == ""debug"" goto use_jdk
echo Using JRE_HOME:        "%JRE_HOME%"
goto java_dir_displayed
:use_jdk
echo Using JAVA_HOME:       "%JAVA_HOME%"
:java_dir_displayed
echo Using CLASSPATH:       "%CLASSPATH%"

set _EXECJAVA=%_RUNJAVA%
set MAINCLASS=org.apache.catalina.startup.Bootstrap
set ACTION=start
set SECURITY_POLICY_FILE=
set DEBUG_OPTS=
set JPDA=

if not ""%1"" == ""jpda"" goto noJpda
set JPDA=jpda
if not "%JPDA_TRANSPORT%" == "" goto gotJpdaTransport
set JPDA_TRANSPORT=dt_socket
:gotJpdaTransport
if not "%JPDA_ADDRESS%" == "" goto gotJpdaAddress
set JPDA_ADDRESS=localhost:8000
:gotJpdaAddress
if not "%JPDA_SUSPEND%" == "" goto gotJpdaSuspend
set JPDA_SUSPEND=n
:gotJpdaSuspend
if not "%JPDA_OPTS%" == "" goto gotJpdaOpts
set JPDA_OPTS=-agentlib:jdwp=transport=%JPDA_TRANSPORT%,address=%JPDA_ADDRESS%,server=y,suspend=%JPDA_SUSPEND%
:gotJpdaOpts
shift
:noJpda

if ""%1"" == ""debug"" goto doDebug
if ""%1"" == ""run"" goto doRun
if ""%1"" == ""start"" goto doStart
if ""%1"" == ""stop"" goto doStop
if ""%1"" == ""configtest"" goto doConfigTest
if ""%1"" == ""version"" goto doVersion

echo Usage:  catalina ( commands ... )
echo commands:
echo   debug             Start Catalina in a debugger
echo   debug -security   Debug Catalina with a security manager
echo   jpda start        Start Catalina under JPDA debugger
echo   run               Start Catalina in the current window
echo   run -security     Start in the current window with security manager
echo   start             Start Catalina in a separate window
echo   start -security   Start in a separate window with security manager
echo   stop              Stop Catalina
echo   configtest        Run a basic syntax check on server.xml
echo   version           What version of tomcat are you running?
goto end

:doDebug
shift
set _EXECJAVA=%_RUNJDB%
set DEBUG_OPTS=-sourcepath "%CATALINA_HOME%\..\..\java"
if not ""%1"" == ""-security"" goto execCmd
shift
echo Using Security Manager
set "SECURITY_POLICY_FILE=%CATALINA_BASE%\conf\catalina.policy"
goto execCmd

:doRun
shift
if not ""%1"" == ""-security"" goto execCmd
shift
echo Using Security Manager
set "SECURITY_POLICY_FILE=%CATALINA_BASE%\conf\catalina.policy"
goto execCmd

:doStart
shift
if "%TITLE%" == "" set TITLE=Tomcat
set _EXECJAVA=start "%TITLE%" %_RUNJAVA%
if not ""%1"" == ""-security"" goto execCmd
shift
echo Using Security Manager
set "SECURITY_POLICY_FILE=%CATALINA_BASE%\conf\catalina.policy"
goto execCmd

:doStop
shift
set ACTION=stop
set CATALINA_OPTS=
goto execCmd

:doConfigTest
shift
set ACTION=configtest
set CATALINA_OPTS=
goto execCmd

:doVersion
%_EXECJAVA% -classpath "%CATALINA_HOME%\lib\catalina.jar" org.apache.catalina.util.ServerInfo
goto end


:execCmd
rem Get remaining unshifted command line arguments and save them in the
set CMD_LINE_ARGS=
:setArgs
if ""%1""=="""" goto doneSetArgs
set CMD_LINE_ARGS=%CMD_LINE_ARGS% %1
shift
goto setArgs
:doneSetArgs

rem Execute Java with the applicable properties
if not "%JPDA%" == "" goto doJpda
if not "%SECURITY_POLICY_FILE%" == "" goto doSecurity
%_EXECJAVA% %LOGGING_CONFIG% %LOGGING_MANAGER% %JAVA_OPTS% %CATALINA_OPTS% %DEBUG_OPTS% -classpath "%CLASSPATH%" -Dcatalina.base="%CATALINA_BASE%" -Dcatalina.home="%CATALINA_HOME%" -Djava.io.tmpdir="%CATALINA_TMPDIR%" %MAINCLASS% %CMD_LINE_ARGS% %ACTION%
goto end
:doSecurity
%_EXECJAVA% %LOGGING_CONFIG% %LOGGING_MANAGER% %JAVA_OPTS% %CATALINA_OPTS% %DEBUG_OPTS% -classpath "%CLASSPATH%" -Djava.security.manager -Djava.security.policy=="%SECURITY_POLICY_FILE%" -Dcatalina.base="%CATALINA_BASE%" -Dcatalina.home="%CATALINA_HOME%" -Djava.io.tmpdir="%CATALINA_TMPDIR%" %MAINCLASS% %CMD_LINE_ARGS% %ACTION%
goto end
:doJpda
if not "%SECURITY_POLICY_FILE%" == "" goto doSecurityJpda
%_EXECJAVA% %LOGGING_CONFIG% %LOGGING_MANAGER% %JAVA_OPTS% %JPDA_OPTS% %CATALINA_OPTS% %DEBUG_OPTS% -classpath "%CLASSPATH%" -Dcatalina.base="%CATALINA_BASE%" -Dcatalina.home="%CATALINA_HOME%" -Djava.io.tmpdir="%CATALINA_TMPDIR%" %MAINCLASS% %CMD_LINE_ARGS% %ACTION%
goto end
:doSecurityJpda
%_EXECJAVA% %LOGGING_CONFIG% %LOGGING_MANAGER% %JAVA_OPTS% %JPDA_OPTS% %CATALINA_OPTS% %DEBUG_OPTS% -classpath "%CLASSPATH%" -Djava.security.manager -Djava.security.policy=="%SECURITY_POLICY_FILE%" -Dcatalina.base="%CATALINA_BASE%" -Dcatalina.home="%CATALINA_HOME%" -Djava.io.tmpdir="%CATALINA_TMPDIR%" %MAINCLASS% %CMD_LINE_ARGS% %ACTION%
goto end

:end

 

엄청많죠 여기서 조금 핵심적으로 봐야하는게 

setenv.bat -> setclasspath.bat -> bootstrap.jar -> tomcat-juli.jar 입니다.

 

setenv.bat 는 JAVA_OPTS, CATALINA_OPTS등의 환경변수 설정을 하는데 이용됩니다.

이 동작이 jvm의 동작에도 영향을 줍니다.

 

setclassthpath.bat은 java class 와 libarary에 대한 class_path  설정을 합니다. 

jar 파일의 경로가 포함될수 있습니다.

 

bootstrap.jarTomcat 서버의 초기화와 시작을 담당합니다.

https://tomcat.apache.org/tomcat-8.5-doc/api/org/apache/catalina/startup/Bootstrap.html

 

Bootstrap (Apache Tomcat 8.5.98 API Documentation)

public final class Bootstrap extends Object Bootstrap loader for Catalina. This application constructs a class loader for use in loading the Catalina internal classes (by accumulating all of the JAR files found in the "server" directory under "catalina.hom

tomcat.apache.org

 

tomcat-juli.jar는 로깅시스템 처리하는데 사용됩니다.

bootstarp.jar와 함께 클래스 패스에 포함되어 로그 관리 기능을 제공합니다.

 

그렇다면 bootstrap.jar 이 server.xml을 읽어와야하는데요. 이부분을 한번 확인해보겠습니다.

 

https://tomcat.apache.org/download-90.cgi

 

Apache Tomcat® - Apache Tomcat 9 Software Downloads

Welcome to the Apache Tomcat® 9.x software download page. This page provides download links for obtaining the latest version of Tomcat 9.0.x software, as well as links to the archives of older releases. Unsure which version you need? Specification version

tomcat.apache.org

zip파일을 읽어와서 압축푼후 코드를 한번 보겠습니다.

 

bootstarp.jar 파일이 아닌 코드로 보면 

/java/org/apache/catalina/startip/Catalina.java 파일을 보면요.

 

conf/server.xml을 읽어옵니다. 

주석은 제거하고 

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

<Server port="8005" shutdown="SHUTDOWN">
  <Listener className="org.apache.catalina.startup.VersionLoggerListener" />
  <Listener className="org.apache.catalina.core.AprLifecycleListener" SSLEngine="on" />
  <Listener className="org.apache.catalina.core.JreMemoryLeakPreventionListener" />
  <Listener className="org.apache.catalina.mbeans.GlobalResourcesLifecycleListener" />
  <Listener className="org.apache.catalina.core.ThreadLocalLeakPreventionListener" />

  <GlobalNamingResources>
    <Resource name="UserDatabase" auth="Container"
              type="org.apache.catalina.UserDatabase"
              description="User database that can be updated and saved"
              factory="org.apache.catalina.users.MemoryUserDatabaseFactory"
              pathname="conf/tomcat-users.xml" />
  </GlobalNamingResources>

  <Service name="Catalina">

    <Connector port="8080" protocol="HTTP/1.1"
               connectionTimeout="20000"
               redirectPort="8443" />

    <Connector port="8009" protocol="AJP/1.3" redirectPort="8443" />

    <Engine name="Catalina" defaultHost="localhost">

      <Realm className="org.apache.catalina.realm.LockOutRealm">
   
        <Realm className="org.apache.catalina.realm.UserDatabaseRealm"
               resourceName="UserDatabase"/>
      </Realm>

      <Host name="localhost"  appBase="webapps"
            unpackWARs="true" autoDeploy="true">

        <Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs"
               prefix="localhost_access_log" suffix=".txt"
               pattern="%h %l %u %t &quot;%r&quot; %s %b" />

      </Host>
    </Engine>
  </Service>
</Server>

 

 xml 코드를 보시면 사용되는 port 번호 appbase webapps 파일 위치나 host 읽어올수 잇게 하는거죠.

 

정리하면 

 

startup.bat->catlina.bat->  (setenv.bat -> setclasspath.bat) 환경설정 -> (bootstrap.jar ( read file server.xml )  )앱서버 실행 -> tomcat-juli.jar 로깅 

 

이런식으로 이해하면 좋을것 같습니다. 잘못된부분 지적 부탁드리겠습니다.

 

그리고 조금 톰켓 부분을 수정하는 부분이 있으면 분석하면서 더 작성도 해보도록 하겠습니다.

 

참고:

 

https://tomcat.apache.org/tomcat-9.0-doc/introduction.html

 

Apache Tomcat 9 (9.0.85) - Introduction

Before you start using CATALINA_BASE, first consider and create the directory tree used by CATALINA_BASE. Note that if you do not create all the recommended directories, Tomcat creates the directories automatically. If it fails to create the necessary dire

tomcat.apache.org

 

' > Spring' 카테고리의 다른 글

Spring Data JPA - 핵심 개념  (0) 2024.02.03
Spring Data JPA에 대해서  (0) 2024.02.03
Gradle에서 compileOnly와 implementation 차이  (0) 2024.01.09
multiple gradle 빌드 시키기!  (0) 2024.01.08
gradle과 maven의 차이  (1) 2024.01.08

먼저 현재 git 프로젝트와 jenkins을 연결 했는데요.

 

 

 

아직 정확하게 사용법을 잘 모르겠습니다.

 

사용하는 방법 관련해서는 내일 해보도록 하겠습니다. 

+ Recent posts