- LogForJ (?) ⇒ 로그 남기는 라이브러리 (설정을 .xml 파일로 함 ⇒ resources 내에 넣을 것)
- 내부 폴더 구조 /test/ 는 단위 테스트를 위한
프로젝트 전체 폴더 구조
라이브러리 설치
- 간단한 블로그 프로젝트
- 사용할 라이브러리들 다운 받을 것
프로젝트 디펜던시 설정하기 Logging 관련
Library Description
log4j-core | The Apache Log4j Implementation |
log4j-api | The Apache Log4j API |
log4j-slf4j2-impl | The Apache Log4j SLF4J 2.0 API binding to Log4j 2 Core |
slf4j-api | The slf4j API |
- 구글 maven central repository 검색 ⇒ Maven Central Repository - Sonatype 이동
- Maven Central Repository - Sonatype 페이지에서 log4j-core 검색
- 그룹 아이디가 org.apache.logging.log4j 인 페키지 이용
- 버전에 alpha나 beta가 붙어있는 라이브러리들은 테스트 버전 → 그 이외 최신 버전 선택
- https://central.sonatype.com/artifact/org.apache.logging.log4j/log4j-core/2.21.1
- Maven Central Repository - Sonatype 페이지에서 log4j-api 검색
- log4j-core와 같은 버전을 사용해야 함
- https://central.sonatype.com/artifact/org.apache.logging.log4j/log4j-api/2.21.1
- Maven Central Repository - Sonatype 페이지에서 log4j-slf4j2-impl 검색
- The Apache Log4j SLF4J 2.0 API binding to Log4j 2 Core
- 다운 페이지
- Maven Central Repository - Sonatype 페이지에서 slf4j-api 검색
- The slf4j API
- 다운 페이지
- slf4j-api의 2.대 버전은, log4j의 2.21 버전과 호환이 되지 않기 때문에(컴파일 자체 실패) 1.7.36 사용
- : pom.xml에 버전 명을 1.7.36으로 변경
- log4j 는 아파치에서 만들었고, slf4j 같이 log4j 관련 의존성들은 slf4j에서 만들어서 그룹명이 상이함
- Log4j2 홈페이지 가기 - Apache log4j2 > configuration > logging 속성들 설정할 수 있음
- Status Messages https://logging.apache.org/log4j/2.x/manual/configuration.html#status-messages
- /src/main/resources/log4j2.xml 파일
- %d, %date : 로그가 발생한 날짜와 시간
- %p, %level : 로그 레벨. all < debug < info < warn < error < fatal < off
- %c, %logger : 로그를 쓰는 로거(logger)의 이름
- %m, %msg, %message : 로그 메세지
- %n : 줄바
- %L, %line : 로그가 발생한 소스의 라인 번호
- <?xml version="1.0" encoding="UTF-8" standalone="no"?> <Configuration> <Appenders> <Console name="console" target="SYSTEM_OUT"> <PatternLayout pattern="%d{HH:mm:ss.SSS} %-5p [%-40.40logger] %m%n"/> </Console> </Appenders> <Loggers> <Root level="debug" additivity="false"> <AppenderRef ref="console"/> <!-- Console 태그 내에 정의한 이름을 ref해주어야 함. --> </Root> </Loggers> </Configuration>
프로젝트 디펜던시 설정하기 Junit 관련
- Junit-jupiter-engine
- Module "junit-jupiter-engine" of JUnit 5.
- https://central.sonatype.com/artifact/org.junit.jupiter/junit-jupiter-engine
- Jupiter-api
- assertionNull, assertionNotNull 같은 개발자가 예측한 결과와 동일한 결과를 보이고 있는지를 확인할 수 있다.
프로젝트 디펜던시 설정하기 OJDBC 관련
- Oracle jdbc lib
- Oracle JDBC Driver compatible with JDK11, JDK12, JDK13, JDK14 and JDK15
- https://central.sonatype.com/artifact/com.oracle.database.jdbc/ojdbc11
- HikariCP
- Ultimate JDBC Connection Pool
- 업계 표준처럼 사용
- db와 여러 개의 연결이 가능함
- hicariCP는 log4j를 사용하고 있다. 그래서 우리도 쓰는 것…!
- https://central.sonatype.com/artifact/com.zaxxer/HikariCP
JUnitTest
- select 의 결과가 ArrayList로 만들어지느냐만 하고 싶은데 FE 까지 모두 봐야 된다고…? ⇒
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
<version>5.10.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
<version>5.10.1</version>
<scope>test</scope>
</dependency>
- scope 에 test를 설정해주면 /test 경로 내에 있는 파일만 사용 가능하다.
- JUnit 테스트(자바 단위 테스트)를 하기 위한 클래스 작성
- main 메세지를 작성하지 않음
- @Test 에너테이션을 사용한 메서드를 작성
- Run AS → JUnit Test를 실행하면, junit-jupiter-engine에서 테스트 메서드를 실행
- Test 메서드 작성:
- @Test 에너테이션을 사용
- public void로 선언
4.0.0
com.itwill
lb_contacts
1.0-SNAPSHOT
lb_contacts
war
UTF-8
11
11
5.9.2
jakarta.servlet.jsp.jstl
jakarta.servlet.jsp.jstl-api
3.0.0
org.junit.jupiter
junit-jupiter-api
5.10.1
org.junit.jupiter
junit-jupiter-engine
5.10.1
org.glassfish.web
jakarta.servlet.jsp.jstl
3.0.1
org.apache.logging.log4j
log4j-core
2.21.1
org.apache.logging.log4j
log4j-api
2.21.1
org.apache.logging.log4j
log4j-slf4j2-impl
2.21.1
org.slf4j
slf4j-api
2.0.9
com.oracle.database.jdbc
ojdbc11
23.2.0.0
org.apache.maven.plugins
maven-war-plugin
3.3.2
CREATE TABLE POSTS (
ID NUMBER(10),
TITLE VARCHAR2(100 CHAR) NOT NULL,
CONTENT VARCHAR2( 4000 CHAR) NOT NULL,
AUTHOR VARCHAR2(30 BYTE) NOT NULL,
CREATED_TIME TIMESTAMP DEFAULT SYSTIMESTAMP,
MODIFIED_TIME TIMESTAMP DEFAULT SYSTIMESTAMP,
CONSTRAINT POSTS_PK PRIMARY KEY (ID)
);
INSERT INTO POSTS (TITLE, CONTENT, AUTHOR) VALUES ('test', 'Servlet/Jsp Connection Pool', 'admin' );
rollback;
commit;
<%@ page language="java" contentType="text/html; charset=${encoding}"
pageEncoding="${encoding}" trimDirectiveWhitespaces="true" %>
${cursor}
Mac
- 위 버전 : Jakarta EE 10버전 ⇒ Tomcat 버전인것임
- Servlet ⇒ 웹 버전 어떻게 할 거냐고 물어봤던…
DTO (Data Transfer Object)
계층 간 데이터 전달 할 때 사용하는 객체를 사용해도 되고,
- Post Model Class를 따로 사용해도 되지만, DTO를 따로 사용할 것
- Controller, Service, Dao 간 전달할 때 사용한다고
💡 주요 차이 : DB의 테이블과 완전 똑같은 형태로 만들어야 한다. VS
PRG 패턴
Post → redirect → Get
<aside> 💡 리팩터링을 합니다!
- (repository 폴더 내) dao의 메서드들은 DB와의 연결 시 Connection, Stateement, ResultSet(nullable)을 사용한다,
- 사용한 위 3가지 리소스들은 finally 구문에서 모두 해제해주어야 하는데, try {} catch{} finaaly{} 구문 내에 다시 try-catch 구문이 등장하므로 매우 복잡해짐
Connection conn = null;
PreparedStatement stmt = null;
ResultSet rs = null;
try {
conn = ds.getConnection();
stmt = conn.prepareStatement(SQL_SELECT);
rs = stmt.executeQuery();
while (rs.next()) {
list.add(makePostInstance(rs));
}
} catch (SQLException e) {
e.printStackTrace();
} finally {
try {
rs.close();
stmt.close();
conn.close();
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
리소스 해제 메서드 만들기
private void closeResources(Connection conn, Statement stmt) {
closeResources(conn, stmt, null);
}
private void closeResources(Connection conn, Statement stmt, ResultSet rs) {
try {
if (rs != null) {
rs.close();
}
if (stmt != null) {
stmt.close();
}
if (conn != null) {
conn.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
}
- 오버로딩 사용
</aside>
<aside> ♻️ input box
<form style="display:inline" action="${postDeleteUrl}" method="post">
<input type="hidden" name="id" value="${post.id}"/>
<input type="submit" value="삭제하기"/>
</form>
- input type=”hidden” 의 경우, display:none과 동일한 효과 </aside>
시나리오
HTML에서 textarea
textarea의 innerHtml 과 value는 다름
innerHtml ⇒
value ⇒
로그인 로그아웃
- 로그인 기능은 상당히 까다로운 작업
- 로그인하고 나면 로그인 한 상태로 지속되고 해당 유저에게 맞는 페이지를 보여줌
- 로그인을 하게되면 보던 페이지로 다시 되돌아가야됨.
- **FILTER** 인터페이스 : 클라이언트의 상태에 따라 각 요청들의 권한 유무를 체크할 수 있음
- 로그인 시 쿼리 스트링으로 로그인 버튼을 누른 해당 페이지의 요청 주소를 쿼리 스트링으로 보낸다.
FILTER
package com.itwill.jsp1.filter;
import jakarta.servlet.FilterChain;
import jakarta.servlet.FilterConfig;
import jakarta.servlet.ServletException;
import jakarta.servlet.annotation.WebFilter;
import jakarta.servlet.http.HttpFilter;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import java.io.IOException;
@WebFilter(filterName = "filter", urlPatterns = {"/*"})
public class filterEx1 extends HttpFilter {
public filterEx1() {
System.out.println("생성자 FilterEx1");
}
@Override
public void destroy() {
System.out.println("FilterEx1::destroy() 호출");
}
@Override
protected void doFilter(HttpServletRequest req, HttpServletResponse res, FilterChain chain)
throws IOException, ServletException {
System.out.println("------- FilterEx1: doFilter() 호출 전");
System.out.println(req.getRequestURI());
// pass the request along the filter chain
chain.doFilter(req, res); // ------ (1)
System.out.println("------- FilterEx2: doFilter() 호출 후");
}
@Override
public void init(FilterConfig config) throws ServletException {
System.out.println("------- filterEx1::init() 호출");
super.init(config);
}
}
- annotation을 사용하면 필터 순서를 지정하지 못하기 때문에, web.xml에 작성하여 순서를 지정해주는 것이 좋다.
[🐔] Cookie And Session
<aside> 💡
쿠키
- 웹 브라우저가 저장하는 데이터
- 동작방식
- 웹 브라우저의 최초 요청 시 웹 서버는 쿠키를 생성해서 브라우저로 전송
- 웹 브라우저는 쿠키를 저장
- 웹 브라우저가 같은 서버에 접속할 때는 저장된 쿠키를 요청에 실어서 보냄
- 쿠키의 구성 요소
- 이름 : 각각의 쿠키를 구별하는데 사용되는 이름
- 값 : 쿠키의 이름에 저장할 값
- 유효 시간 : 쿠키 유지 시간
- 도메인 : 쿠키를 전송할 도메인
- 경로 : 쿠키를 전송할 요청 경로
- 쿠키 생성 및 전송 : new Cookie(”name”, ”value”);
- 쿠키에 필요한 설정 : setValue(String), setMaxAge(int), setDomain(String), setPath(String), setSecure(boolean), ….
- 응답에 쿠키를 포함시켜서 클라이언트에게 전송 : response.addCookie()
- 웹 브라우저가 보낸 쿠키의 사용
- 요청에서 쿠키를 가져옴 : req.getCookie
- 배열을 리턴
- 이름.값의 쌍으로 이루어진 쿠키들의 배열에서 정보 추출
- Cookie.getName(), Cookie.getValue()
세션
- 클라이언트와의 상태를 유지하기 위해 웹 서버에서 웹 컨테이너에 저장하는 정보
- 웹 브라우저마다 1개씩 생성되어 웹 컨테이너에 저장
- 웹 브라우저와 웹 서버의 상태 유지가 훨씬 안정적
- 쿠키가 가지고 있는 보안상의 문제를 해결
- 웹 서버는 각각의 웹 브라우저로부터 발생한 요청에 대해 특정한 식별자를 부여
- 예 : JSESSIONID
- 이 식별자를 사용해서 세션을 구분하고 유지 및 사용할 수 있음
- 식별자를 알아서 구분하고, 해당 식별자들에 관한 정보들을 각각 </aside>
로그아웃
- 세션에 저장된 로그인 관련 정보 삭제
- 세션 객체 무효화
url의 queryString에 url이 포함될 경우,
Query parameter가 포함되었을 때, parameter로 들어가는 url에 인코딩하여 보내야 한다. 그렇지 앟을 경우, 쿼리 스트링의 구분자인 ? 가 중복으로 나타나여 문제가 생길 수 있다.
Servlet 으로 프론트(JSP)와 소통하기
- 오해 : Servlet은 본래 JSP로 프론트 서버를 만들기 위해 사용하는 프로그램이다.
- 추가1+ : PrintWriter out = resp.getWriter()**;**는 화면을 그릴 수 있게 해주는 메서드이다.
- 서블릿에서 out의 print 메서드에 들어가는 값은, 프론트로 보내는 데이터를 보낼 뿐이지 화면에 그려주는 목적의 메서드가 아님.
- 화면에 그려지는 기능은, 데이터를 받은 브라우저가 단순 문자열을 받았을 때 데이터를 해결하는 방법일 뿐.
'programming > Java [notion 정리본 업로드]' 카테고리의 다른 글
중첩 클래스와 람다 (0) | 2024.04.15 |
---|---|
입출력 스트림 (0) | 2024.04.15 |
Collection (0) | 2024.04.13 |
예외처리 (Exception) (0) | 2024.04.13 |
추상클래스와 인터페이스 (0) | 2024.04.13 |