[Spring] 스프링의 정석-1
static이 아니면 객체 생성해야된다. static이면 객체 생성할 필요가 없다. 브라우저와 WAS가 있어야 원격 프로그램을 실행할 수 있다.
인스턴스 메서드 = 객체 생성 후 호출.
public class Hello {
//2.URL과 메서드를 연결
@RequestMapping("/hello")
public static void main() {//static넣어도 되긴 하는데 안넣어도 됨.
System.out.println("HELLO");
}
}
인스턴스 메서드 호출 가능하다 = 중간에 누군가 객체 생성을 해준다.(톰캣이 내부적으로 객체 생성을 해준다.)
HttpServletRequest의 메서드를
쿼리스트링 - 값 전달시 사용
& 표시 이용해서 값을 여러개 보낼 수 있다.
클라이언트 : 서비스를 요청하는 어플리케이션
서버 : 서비스를 제공하는 어플리케이션
브라우저 이용해서 URL 입력해서 요청시 해당 서버에 있는 톰캣이 받아서 객체에 저장 생성하고 나눠서 저장 그리고 메서드의 매개변수로 저장.
우리가 원하는 대로 저장하고 스프링은 알아서 저장해 둠.
쿼리스트링은 네임밸류로 값들이 붙어있다.
1대의 pc에 여러 서버프로그램이 여러개 있다. 이 ip주소로는 구분 안됨 여러개 주소 존재하므로
그떄 구분하는게 포트번호다
Web Server : 웹을 서비스 웹 어플리케이션 서버(WAS): 웹 어플리케이션을 서비스하는 서버
톰캣의 내부 구조
톰캐싱 요청을 하 8080포트로 요청이 간다. 쓰레드 풀에 사용자 요청이 들어간다. 미리 만들어두면 한가한 스레드가 그걸 처리한다. 서비스가 요청 처리하는데 그 안에 커넥터가 있다. 프로토콜 종류에 따라 어떤 프로토콜 처리할게 달라진다.
서버 안에 서비스가 있고 서비스가 엔진(서비스엔진이 있다) 이 있다.
여러개 호스트 있다. 하나의 톰캣 서버에 여러개 톰캣 서버가 있을 수 있다.
컨텍스트가 웹 어플리케이션이다.
하나하나가 sts 프로젝트에 해당한다.
sts는 서로 영향을 주지 않는 독립적인 곳에서 돌아간다.
그 안에 서블릿이 있다.
서블릿 : 작은 서버 프로그램(서버에서 실행되는 프로그램) 컨트롤러랑 같은 개념이라 보면된다.
서블릿이 같은 컨텍스트 안에서 돌아간다.
정리하면 톰캣 서버 안에 서비스가 있고 그 서비스 처리하는게 엔진이고 그 안에 호스트가 여러개 있을 수 있고, 호스트 안에는 컨텍스트가 여러개 있을 수 있다.
그 안에 있는게 서블릿이고 이 둘중에 eventlist가 컨텍스트 이름, 그 앞이 호스트 이름이다.
스레드 풀에 있는 요청을 받아서 엔진에 전달하고 호스트로 가고 호스트에서 컨텍스트로 간다.
dispatcher서블릿이 받아서 메인메서드를 호출한다.
톰캣설치경로 conf server.xml : Tomcat 서버 설정 파일 톰캣설치경로 conf web.xml Tomcat 의 모든 web app 의 공통 설정 웹앱이름 /WEB INF/ web.xml web app 의 개별 설정 [ 참고 STS 에서는 프로젝트 src / webapp /WEB INF/ web.xml IntelliJ 에서는 프로젝트 src / webapp /WEB INF/ web.xml
그리고 sts에는 web.xml이 두개인데 하나는 공통설정 하나는 개별설정이다.
사실 @ Controller와 @ RequestMapping은 스프링에서만 쓰고 서블릿에서는 @ WebServlet을 사용. 서블릿은 후에 설명
그리고 위 처럼 url, 매핑 했는데 이게 너무 길고 불편해서 어노테이션 기반으로 바꿨다.
프로토콜
서로간의 통신을 위한 약속 , 규칙주고 받을 데이터에 대한 형식을 정의한 것
HTTP란?
단순하고 읽기 쉽다 . 텍스트 기반의 프로토콜 상태를 유지하지 않는다 .(stateless) 클라이언트 정보를 저장 X
그래서 클라이언트 요청이 들어오면 중복된 건지 모른다. 이걸 보완하기 위해 나온게 쿠키와 세션이다.
단순하고 읽기 쉽다 . 텍스트 기반의 프로토콜
상태를 유지하지 않는다 .(stateless) 클라이언트 정보를 저장 X
확장 가능하다 . 커스텀 헤더 (header) 추가 가능
http메서드는 편지와 비슷하다.
네트워크 부분을 보면 이렇게 헤더가 나눠진게 보인다
바이너리 파일: 문자 와 숫자 가 저장되어 있는 파일 파일 데이터를 있는 그대로 읽고 쓴다
텍스트 파일: 문자 만 있는 저장되어 있는 파일 숫자를 문자로 변환 후 쓴다
MIME : 텍스트 기반 프로토콜에 바이너리 데이터 전송하기 위해 고안
HTTP 의 Content Type 헤더에 사용 데이터의 타입을 명시
Base64
바이너리 데이터를 텍스트 데이터로 변환할 때 사용 64진법은 ‘0’~’ 9’,’A’~’Z’, a’~’z 모두 64 개 (6 의 문자로 구성)
SpringMVC
1.관심사의 분리 Separation of Concerns
OOP 5대 원칙
- SRP: 단일 책임의 원칙(하나의 메서드는 하나의 책임)
공통 코드의 분리 - 입력의 분
출력의 분리 - 변하는 것과 변하지 않는
처리하는 곳 = Controller 보여주는 곳 = View 실제 왔다갔다 하는 데이터 = Model
이게 코드를 분리해서 전달하기 위해 모델이 필요하다
Dispatcher서블릿이 입력을 받으면 처리하고 해당 컨트롤러에 요청을 처리한다. 그 결과를 다시 주면 뷰에 전달한다.
여기서 모델을 컨트롤러에 주면 모델에 결과 저장한다.
뷰에서는 전달받은 걸 응답 만들어서 클라이언트에 전송한다.
이게 단순화 된 MVC다
서블릿과 JSP(둘은 같은 말)
서블릿의 생명주기
그리고 서블릿은 싱글톤이다. 1개 인스턴스고 재활용한다.
jsp 는 따로 웹 서블릿이든 뭐든 매핑할 필요 없다. 자동으로 매핑되기 때문
서블릿은 늦은 초기화 (지연된 초기화, lazy init)), 스프링은 빠른 초기화(early-init)
#####jsp 기본객체 : 생성 없이 사용할 수 있는 객체
유효 범위(scope)와 속성(attribute)
@RequestParam과 @ModelAttribute
###1. @RequestParam
요청의 파라미터를 연결할 매개변수에 붙이는 어노테이션
###2. @ModelAttribute 적용 대상을 Model의 속성으로 자동 추가해주는 어토네이션 반환 타입 또는 컨트롤러 메서드의 매개변수에 적용 가능
###3. @WebDataBinder
에러와 결과를 BindingResult에 저장
브라우저 통해서 요청값이 객체에 바인딩 될 때 중간역할을 해주는게 데이터 바인더고 크게 2가지로 먼저 타입변환 하고 데이터 검증한다. 그 결과를 바인딩 리절트에 저장하고 컨트롤러에 넘겨줘서 컨트롤러가 그 결과를 본다는거만 알아두자.
src/main/webapp/WEB-INF/spring에서 root-context.xml 은 non-web관련 설정 파일 그 안에 appServlet 안의 servlet-context.xml은 web관련 설정파일.
그리고 servlet-context.xml 안
Redirect 와 Forward
1. 처리 과정 비교
redirect는 브라우저가 로케이션에서 알려준대로 수동으로 클라이언트가 요청하면 응답이 자동으로 들어온다.(get이건 post건 상관없이 리다이렉트 됨.)
forward는 request 요청하고 response
그냥 요청만 보내면 write.jsp가 처리하는지 다른게 처리하느닞 모름(MVC 기능을 수행)
리다이렉트는 요청 2번, 포워드는 1번이다.
쿠키
- 이름과 값의 쌍으로 구성된 정보, 아스키 코드만 가능
- 서버에서 생성 후 전송, 브라우저에 저장, 유효기간 이후 자동 삭제
세션
- 서로 관련된 요청을 하나로 묶은 것 : 쿠키 이용
- Browser 마다 개별 저장소(session객체)를 서버에서 제공.
쿠키 | 세션 |
---|---|
브라우저에 저장 | 서버에 저장 |
서버 부담 X | 서버 부담 O |
보안에 불리 | 보안에 유리 |
서버 다중화에 유리 | 서버 다중화에 불리 |
세션이 있을 때(True)와 없을때 (false)가 있다 트루면 생성, 폴스면 생성 안함. true가 디폴트라 만들게 되어있는데 세션ㅇ니 필요 없는 페이지에 false로 줘서 줄일 수 있다.
session 이 false면
- 세션이 필요 없는 JSP라면
- Session false가 기존 세션에 영향을 미치지 않는다.(세션 false면 세션 끊어진 줄 아는데 그게 아니라 세션 시작여부만 true, false로 주지 시작 한 후에는 true false가 상관이 없다.)
Session = “false”일 떄 sessionScope와 pageContext.session은 사용 불가.
sessionScope.id를 pageContext.request.getSession(false).getAttribute(“id”)로 변경해야됨.
STS에서 에러라고 표시해도 무시하면 됨.
[참고] getSession(true)는 session 이 없는 경우 session 을 새로 생성하기 때문에 session이 없어도 새로 생성하지 않도록 getSession(false)를 사용.
예외처리 위한 메서드를 만들고 @ ExceptionHandler를 붙인다.
@ ControllerAdvice로 전역 처리 예외 클래스 작성 가능(패키지 지정기능)
예외 처리 메서드가 중복된 경우, 컨트롤러 내의 예외 처리 메서드가 우선(가까운 곳에서 우선 처리)
@ ResponseStatus
응답 메시지의 상태코드 변경시 사용
web.xml은
상태 코드별 뷰 매핑
SimpleMappingExceptionResolver 상태코드 말고 예외 종류별로도 매핑이 가능하다(servlet-context.xml) , view-Controller와 비슷
ExceptionResolver
예외처리 기본전략(스프링이 가지고 있음)
정리
Dispatcher Servlet
각 컨트롤러나 서비스에서 공통적으로 해야될 일을 Dispatcher서블릿이 다 처리해준다.(그걸 전처리라고 한다.)
단순한 전처리 외에도 다양하게 하는 일이 많다.
요청이 오면 요청을 받아서 해당 컨트롤러의 메서드를 호출하고 결과로 뷰 이름을 받는다.
뷰 이름으로 해당 뷰를 찾아서 응답한다.
여기서 핸들러 매핑은 key-value로 관리하는데 URL, 메서드 2개를 매핑시키고 저장하다가 요청 오면 그 요청을 어떤 메서드가 처리하면 좋은지 핸들러 매핑한테 물어본다.
이 핸들러 매핑은 등록된 이 맵을 뒤져서 URL과 일치하는 걸 찾아서 반환해줌.
디스패처 서블릿이 호출해준다.
관심사의 분리
디스패처 서블릿이 다 처리하기 보다는 핸들러 매핑으로 분류해두고 거기에 물어봐서 메서드에 대한 정보 얻는 식으로 관심사의 분리를 해둠.
컨트롤러 호출부분도 중간에 핸들러 어댑터가 들어간다.
직접 호출이 아니라 핸들러 어댑터를 거쳐서 호출함.
핸들러 어댑터가 종류가 여러개일 수 있다.
핸들러 매핑이 알려준 메서드를 어떤 핸들러 어댑터가 넘겨줄 수 있는지 보고 그 핸들러 어댑터 한테 넘겨줌.
그럼 어떤 컨트롤러가 처리할 수 있는 지 보고 그 컨트롤러에 넘겨준다.
핸들러 매핑을 넣어서 느슨한 연결이 되었다. 느슨한 연결이 되면 변경에 유리해진다.
데이터의 변환과 검증
WebDataBinder
RegisterController에 변환 기능 추가하기
- PropertyEditor
- 양방향 타입변환(String -> 타입 , 타입 -> String) 특정 타입이나 이름의 필드에 적용 가능
- 디폴트 PropertyEditor : 스프링이 기본적으로 제공
- 커스텀 PropertyEditor : 사용자가 직접 구현. PropertyEditorSupport를 상속하면 편리
모든 컨트롤러 내에서 반환: WebBindingInitailizer를 구현한 후 등록
특정 컨트롤러 내에서 반환: 커늩롤에 @ InintBinder를 붙은 메서드를 작성.
- Converter와 ConversionService
- Converter : 단방향 타입 변환(타입 A-> 타입 B) PropertyEditor의 단점을 개선(stateful -> stateless)
ConversionService : 타입 변환 서비스를 제공. 여러 Converter를 등록 가능
- WebDataBinder에 DefaultFormattingConversionService가 기본 등록
- 모든 컨트롤러 내에서의 반환: ConfiguableWebBindingInitializer를 설정해서 사용
- 특정 컨트롤러 내에서의 반환: 컨트롤러에 @ InitBinder가 붙은 메서드를 작성
PropertyEditor는 양방향, Converter는 단방향 그리고 프로퍼티 에디터의 단점은 개선. 다만 변환 작업은 비슷하다.
- Formatter
양방향 타입 변환 (String->타입, 타입-> String) 바인딩 할 필드에 적용 - @ NumberFormat, @ DateTimeFormat)
- Validator
객체를 검증하기 위한 인터페이스. 객체 검증기(Validator) 구현에 사용.
- Validator 검증 - 수동
- Validator 검증 - 자동
- Global Validator
하나의 Validator로 여러 객체를 검증할 때, 글로벌 Validator로 등록
- MessageSource
다양한 리소스에서(파일, 배열) 메시지를 읽기 위한 인터페이스
- 검증 메시지의 출력
스프링이 제공하는 커스텀 태그 라이러리를 사용
중간에 오타. add가 아니라 save경로
Spring DI
변경 포인트가 2개에서 1개로 줄었다-> 변경이 용이함.(다형성)
어떻게 하면 변경에 더 유리한 코드가 되는가에 중점
메서드 하나만 고치면 되서 변경에 아주 유리하다.
변경에 유리한 코드- Map과 외부파일
프로퍼티 객체 만들면 키밸류 저장할 수 있는 공간이 생성. 이 파일을 로드해서 config.txt에 (car가 키, 패키지 안의 값이 값)저장.
전에 만든 클래스 중 DispatcherServletProperties 이런게 다 이런 파일이다.
여기에 스프링의 기본전략들이 다 있었다.( 기본적으로 사용할 파일들이 프로퍼티 파일이였는데 이렇게 적어줬다.)
이론보다 실습(배운거 복습도 실습이지만. 자기가 생각해서 만드는 것도 실습이다.)
OOP는 변경에 유리한 코드 작성하는 것
그 핵심은 분리 가 있다.
- 분리는 변하는 것과 변하지 않는 것 분리하고
- 관심사 분리하고
- 중복된 코드 분리하는 것(OOP)
OOP는 그냥 중복코드 분리하려고 하는 거다.
위에서 txt파일만 바꾸면 메서드나 내부 소스 하나도 안 바꾸고 원하는 결과 출력시켰다.(car든 트럭이든)
이걸 object로 묶어서 뭐 넣든 바꾸게 하는 것도 가능할 것 같다.
그 외에도 클래스 앞에 컴포넌트 붙이고 컴포넌트 붙인 거 찾아서 그 객체를 맵에 저장함.
객체 찾기 - by Name, by Type
객체를 자동 연결하기1 - @ Autowired
@ Autowired는 byType, @ Resouces는 byName
객체를 자동 연결하기2 - @ Autowired
이렇게 -Duser.language=en 으로 vm 옵션을 주면 로그에 한글이 안 깨진다.
IOC와 DI
제어의 역전 IOC- 제어의 흐름을 전통적인 방식과 다르게 바꾸는 법.
터보 엔진 쓰는데 슈퍼 엔진 쓰고 싶으면 바뀌어야 하는데 변하지 않는 부분이 있다.(잘 변하는 부분, 잘 변하지 않는 부분)
분리
- 관심사의 분리
- 변하는 것 변하지 않는 것
- 중복 코드
사용할 부분을 사용자 코드에서 제공해준다. 그래서 왼쪽을 오른쪽 처럼 고치면 된다.
의존성 주입 (DI)- 사용할 객체를 외부에서 주입하는 것.
의존성이라는게 사용할 객체. DI는 사용할 코드 의존성 제공하는거 new 하고 클래스 지정하는 건 수동 지정이고 Autowired는 자동지정이다.
그리고 오른쪽 코드는 디자인 패턴으로는 전략패턴
슈퍼엔진 필요하면 슈퍼엔진 넣고 터보엔진 필요하면 터보 넣고.
스프링 애너테이션 @ Autowired,
인스턴스 변수 (iv), setter, 참조형 매개변수를 가진 생성자 , 메서드에 적용
위 코드에서 valid로 지정된 값 이외에는 다 Autowired로 자동 지정된다.
생성자가 여러개면 어떤 생성자를 써야 되는 지 알려줘야 하므로 @ Autowired를 써서 명확하게 해줘야 한다.
Spring Container에서 타입으로 빈을 검색 해서 참조 변수에 자동 주입 (DI) 검색된 빈이 n개이면, 그 중에 참조 변수와 이름이 일치 하는 것 을 주입.
주입 대상이 변수 일 때 , 검색 된 빈이 1개 아니면 예외 발생
주입 대상이 배열 일 때 , 검색 된 빈이 n개 아니면 예외 발생
스프링 애너테이션 @ Resouces
@ Autowired는 byType으로 검색 @ Resources는 byName으로 검색
components-scan으로 @ components 클래스를 자동으로 검색해서 빈으로 등록
@ Controller, @ Service, @ Repository, @ ControllerAdvice의 메타 어노테이션
스프링 애너테이션 @ Value, @ PropertySource
스프링 애너테이션 vs 표준 에너테이션 (JSR-330)
빈의 초기화 - 와 setter
프로퍼티 태그 쓰면 우측 처럼 따로 호출 안해도 됨. 작성과 관리할 코드가 설정파일에 다 들어있어서 줄어들게 된다.
마찬가지로 conostructor-args도 동일한 역할을 하는데 이건 생성자로 관리
빈의 초기화 - list, set, mapping
이런건 굳이 외울 필요는 없다.
Transaction
더 이상 나눌 수 없는 작업의 단위
계좌 이체의 경우 입금, 출금이 하나의 트랜잭션으로 엮여야 됨.(출금 따로 입급 따로 나눌수 없으므로 출금만 되고 입금이 안되거나 반대의 경우도 말이 안됨.)
- 원자성(Atomicity): 나눌 수 없는 하나의 작업으로 이뤄져야 한다.
- 일관성(Consistency) - Tx 수행 전과 후가 일관된 상태를 유지해야 한다.
- 고립성(Isolation) - 각 Tx는 독립적으로 수행되어야 한다.
- 영속성(Duration)- 성공한 Tx의 결과는 유지되어야 한다.
커밋과 롤백
- 커밋(Commit) : 작업 내용을 DB에 영구적으로 저장
- 롤백(Rollback) : 최근 변경 사항을 취소(마지막으로 복귀)
- 자동 커밋(auto commit) : 명령 실행 후, 자동으로 커밋이 수행(rollback 불가)
- 수동 커밋 : 명령 실행 후 , 명시적으로 commit, rollback 실행.
트랜잭션의 Isolation Level
: 각 Tx을 고립시키는 정도
- Read Uncommited - 커밋되지 않은 데이터
- Read Commited - 커밋된 데이터만 읽기 가능
- Repeatable - Tx가 시작된 이후 변경은 무시됨 (Default)
- Serialzable - 한번에 하나의 Tx만 독립적으로 수행 (고립도 최고)
InteliJ의 경우 위에서 트랜잭션 고립 정도를 설정할 수 있다.
AOP의 개념과 용어
AOP란
관점 지향 프로그래밍, 횡단 관심사 부가기능(advice)을 동적으로 추가해주는 기능
메서드의 시작 또는 끝에 자동으로 코드(advice)를 추
AOP 관련 용어
용어 | 설명 |
---|---|
target | advice가 추가될 객체 |
advice | target에 동적으로 추가 될 부가기능(코드) |
join point | advice 가 추가될(join) 대상(메서드) |
point cut | joint 포인트를 정의한 패턴 |
proxy | target에 advice가 동적으로 추가어 생성된 객체 |
weaving | target에 advice를 추가하여 메서드를 생성하는 것 |
AOP는 분리에 유리한 코드 (변경에 유리한 코드)
Advice의 종류
|종류|애너테이션|설명| |—|—|—| |around advice|@Around|메서드의 시작과 끝 부분에 추가되는 기능| |before advice|@Before|메서드의 시작부분에 추가되는 부가기능| |after advice|@Before|메서드의 끝부분에 추가되는 부가기능| |after returning|@AfterReturning|예외가 발생하지 않았을 때 실행되는 부가기능| |after throwing|@AfterThrowing|예외가 발생했을 때 실행되는 부가기능| —-
TransactionManager란?(서비스 계층의 분리와 @ Transactional)
같은 Tx내에서 Connection을 사용할 수 있게 관리.
DAO 에서 Connection을 얻거나 반환시 DAtaSourceUtils를 사용해야됨.
@ Transactional로 Transaction 적용하기
- AOP를 이용한 핵심 기능과 부가기능의 분리 @ Transactional은 클래스나 인터페이스에도 붙일 수 있음.
Propagation 속성의 값
용어 | 설명 |
---|---|
Required | Tx가 진행중이면 참여하고 없으면, 새로운 Tx시작(디폴트) |
Requireds_New | Tx가 진행중이건 아니건, 새로 Tx시작 |
Nested | Tx가 진행중이면 Tx의 내부 Tx로 실행 |
Mandatory | 반드시 진행중인 Tx 내에서만 실행 |
Supports | Tx가 진행중이건 아니건 상관없이 실행 |
Not_Supported | Tx없이 처리. Tx가 진행중이면 잠시 중단 (Supported) |
Never | Tx없이 처리. Tx가 진행중이면 예외발생 |
.
MyBatis
- SQL Mapping Framework - Easy & Simple
- 자바 코드로부터 SQL문을 분리해서 관리
- 매개변수 설정과 쿼리 결과를 읽어오는 코드를 제거
- 작성할 코드가 줄어서 생산성 향상 & 유지보수 편리
(참고: 스프링에서 mybatis를 쓰려면 그냥 mybatis도 필요하고 mybatis-spring도 필요하다 (2개 필요 )
SqlSessionFactoryBean과 SqlSessionTemplate
- SqlSessionFactory: Sql을 생성해서 제공
SqlSession: SQL 명령을 수행하는 데 필요한 메서드 제공
- SqlSessionFactoryBean: SqlSessionFactory를 Spring에서 사용하기 위한 빈
- SqlSession Template: SQL명령을 수행하는데 필요한 메서드 제공. thread-safe
root-context.xml에 저장한다.
그리고 SqlSessionFactoryBean 등록시 Mapper.xml을 저장한다.
*.Mapper.xml은 SQL이 들어있는 xml이다.
그리고 SqlSessionTemplate이 Thread-safe인데 이건 SqlSessionTemplatedmfh Dao를 구성하는데 이 Dao가 여럿이 될 수 있다.
BoardDao, UserDao 등 이 Dao들이 Threadsafe이기 떄문에 SqlSessionTemplate을 공유한다.
DTO (Data Transfer Object)
- 계층간 데이터를 주고 받기 위해 사용되는 객체.
관심사, 역할, 계층 분리 그리고 VO는 값 객체다. Value Object 는 immutable으로 변경이 불가다.
{}와 ${}의 차이
- #는 값에 대해서만 ?를 사용가능(오로지 들어갈 값들만)
- #은 PreparedStatement로 받는다.(PreparedStatement로 바뀜)
- ${}는 일반 statement로 쓴다. 일반 문자열로 받으며 더 유연하다.
URI과 URL의 차이
URL : 원래는 URI밖에 없었다. 리소스 경로
URN : 어떤 리소스의 유일한 이름 붙이고 URN이라 부름
URI : 이 두개를 퉁쳐서 부르기 위한 이름이 필요했는데 그게 바로 URI(I = Identify(유일한 이름, 명칭))다.
거의 비슷한 느낌인데 URL은 전체경로, URL 일부 적을떄는 URI라한다. 일반적으로 이렇게 씀.
게시판별 CRUD
기본 API 정리 문서
읽기
boardList.jsp 게시물 목록에서 링크 가면 요청이 간다. 게시물 번호가 자동으로 따라감.
그럼 boardController의 read메서드가 이 게시물 번호를 받아서 read이 boardService의 read 메서드를 호출함
그럼 디비와 게시물 하나 읽어옴.
board,dto담아서 주면 이 read메서드가 board.jsp에 boardDTO를 컨트롤러가 넘겨준다.
{boardDTO.title}, $ {boardDTO.name}등 이런 요소들이 boardDTO에 담겨서 넘어간다.
위에서 DTO 받아서 뿌려주는 걸 하고 그 다음은 게시판 읽기에서 목록 버튼을 누르게 되면 boardController로 요청이 가서 list메서드가 호출이 되고 boardService를 호출해서 getPage를 호출해서 한 페이지를 가져온다
그리고 가져온 페이지를 리스트에 담겨서 반환한다.
그리고 boardList.jsp에 담겨서 보여주게 된다.
근데 만약 3페이지 갔었는데 게시물 하나 보고 다시 돌아가면 3페이지로 가야한다. 그냥 리스트만 보내면 페이지 정보가 없으므로 바로 3페이지로 가는게 아닌 1페이지로 가게 됨.
이걸 Board.jsp에 전달해야.
삭제
boardController에 삭제할 게시물 번호를 넘겨준다.(Post)로 그럼 Controller는 boardService의 remove를 호출.(bno,writer 두개 정보를 넘겨준다.)
그리고 수정 삭제 버튼은 보는 사람이 작성자일때만 보여줘야 로그인한 사람 id 넘겨줘서 writer가 맞으면 삭제되도록 한다.
삭제 된 후는 redirect되게 함.
쓰기
게시물 목록에서 글쓰기 버튼 추가하고 글쓰기 누르면 BoardController에 write라는 메서드를 호출함.
이 메서드가 할일은 board.jsp를 보여주면 됨(이게 다)
읽기일 떈 readonly, 글쓰기에서는 readonly해제
입력 다 한다음에 등록 누르면 Controller의 write메서드 호출함
수정
읽기 하다가 수정버튼 클릭하면 제목 바뀜 readonly였다가 해제되고 이렇게 됨(제이쿼리 이용)
태그가 되어있는데(input 태그, url textarea태그)
얘들이 다 attribute라 한다.
속성도 있다.
attribute vs property(둘다 번역하면 속성)
attribute는 html태그 안에다 다 적어줌. property는 태그 하나하나를 브라우저가 읽으면 왼쪽거 생성함.
아래 제이쿼리에 prop이란 메서드(property)라는 메서드도 있다.
그 다음 등록버튼 누르면 Controller의 modify메서드에 post로 전달이 되고 service에 modify는 작성한 내용이 DB쪽으로 전달 됨.(write와 과정은 같다. 호출된 메서드만 다르지)
list로 redirect해서 list가 페이지 보여줌
MyBatis의 동적 쿼리 - 과
검색기능 넣으려면 동적쿼리 알아야됨. 검색할 대상 설정에 따라 쿼리가 달라져야 하기 때문
그리고 페이지 이동 처리도 마찬가지로 잘 알아야 한다.
위 sql문 사진 경우 전체로 감싸고 안에 옵션으로 줬다.(물론 요구사항에 따라 추가해도 됨)
공통 부분을
XML의 특수문자 처리
- XML 내의 특수문자 (<,>,&,..)는 <,>로 변환해야 한다. 또는 특수문자가 포함된 쿼리를 <![CDATA[와 ]] 로 감싼다.
Rest API와 AJAX
JSON
JavaScript Object Notation - 자바스크립트 객체 표기법
XML은 데이터 교환하는데 태그가 너무 많고 복잡해서 좀 더 간단하게 데이터를 전송하는 걸 찾다가 json을 쓰게 되었다.
Stringfy() 와 parse()
JS객체를 서버로 전송하려면 직렬화(문자열로 변환)가 필요.
- JSON.stringfy() : 객체를 JSON 문자열로 변환 (직렬화 , JS 객체->문자열)
- JSON.parse() : JSON 문자열을 객체로 변환(역질렬화, 문자열->JS 객체)
왜 객체를 문자열로 바꾸나? 전송하기 위해. http가 문자열 기반이라 문자열로 변환 후 전환
AJAX란?
Asynchronous javascript and XML - 요즘은 JSON을 주로 사용
비동기 통신은 데이터를 주고 받기 위한 기술
웹페이지 전체(data+UI)가 아닌 일부(data)만 업데이트 가능
@ RegisterController에
@ ResponseBody 대신 클래스에 @ RestController 사용 가능
REST란?
- 웹 서비스 디자인 아키텍쳐 접근 방식
- 프로토콜에 독립적이며 주로 HTTP를 사용해서 구현
- 리소스 중심의 API 디자인 - HTTP 메서드로 수행할 작업을 정의
REST API
- REST 규약을 준수하는 API