Required는 필수 프로퍼티임을 명시하는 것으로 설정하지 않을 경우 빈 생성시 예외를 발생
public class TestBean{
@Required
private TestDao testDao;
public void setTestDao(TestDao testDao){
this.testDao = testDao;
}
}
RequiredAnnotationBeanPostProcessor 클래스는 스프링 컨테이너에 등록된 bean 객체를 조사하여 @Required 어노테이션으로 설정되어 있는 프로퍼티의 값이 설정되어 있는지 검사한다.
사용하려면 <bean class="org.springframework.beans.factory.annotation.RequiredAnnotationBeanPostProcessor" /> 클래스를 빈으로 등록시켜줘야 하지만 이를 대신하여 <context:annotation-config> 태그를 사용해도 된다.
@Autowired
의존관계를 자동설정할 때 사용하며타입을 이용하여 의존하는 객체를 삽입해 준다. (해당 타입의 빈객체가 존재하지 않거나 또는 2개 이상 존재할 경우 스프링은 예외를 발생시킨다.)
*option
required: 필수여부
@Autowired(required=false)
Test test = new TestTwo();
// bean 객체가 존재하지 않을 경우 testTwo 생성
같은 타입의 빈이 2개 이상 존재하게 되면 예외가 발생하는, 이럴때 @Qualifier를 사용하여 특정빈을 사용하도록 한다.
@Autowired
@Qualifier("test")
private Test test;
@Qualifier
location : with @Autowired
@Autowired 동일 타입의 빈객체가 존재시 특정빈을 삽입할 수 있게 설정
*option
name: alias 명
@Resource
@Autowired와 흡사하지만 @Autowired(by type), @Resource(by name)으로 연결한다는 점이 다르다.
*option
name: 연결될 빈객체 이름 입력 @Resource(name="test")
@Scope
설정 : prototype, singleton, request, session, globalSession
기본적 빈의 범위 "singleton"
@componet
@Scope(value="prototype")
public class User(){}
@PostConstruct
location : 해당 작업 메서드 앞
의존하는 객체를 설정한 이후에 초기화 작업을 수행하기 위해 사용. 스프링에 의해 인스턴스가 생성된 후 어노테이션이 적용된 메서드 호출. CommonAnnotationBeanPostProcessor 클래스를 빈으로 등록(<context:annotation-config> 태그로 대신 가능)
해당 클래스가 Controller/Service/Repository로 사용됨을 Spring Framework에 알린다.
참고) @WebServlet vs @Controller
@RequestMapping
@Controller @RequestMapping("/home")// 1) Class LevelpublicclassHomeController{/* an HTTP GET for /home */ @RequestMapping(method = RequestMethod.GET)// 2) Handler Levelpublic String getAllEmployees(Model model){...}/* an HTTP POST for /home/employees */ @RequestMapping(value ="/employees", method = RequestMethod.POST)public String addEmployee(Employee employee){...}} https://gmlwjd9405.github.io/2018/12/02/spring-annotation-types.html
@RequestMapping에 대한 모든 매핑 정보는 Spring에서 제공하는 HandlerMapping Class가 가지고 있다.
1) Class Level Mapping
모든 메서드에 적용되는 경우
“/home”로 들어오는 모든 요청에 대한 처리를 해당 클래스에서 한다는 것을 의미한다.
2) Handler Level Mapping
요청 url에 대해 해당 메서드에서 처리해야 되는 경우
“/home/employees” POST 요청에 대한 처리를 addEmployee()에서 한다는 것을 의미한다.
value: 해당 url로 요청이 들어오면 이 메서드가 수행된다.
method: 요청 method를 명시한다. 없으면 모든 http method 형식에 대해 수행된다.
@RestController
@Controller + @ResponseBody
@ResponseBody를 모든 메소드에서 적용한다.
메소드의 반환 결과(문자열)를 JSON 형태로 반환한다.
@Controller 와 @RestController 의 차이
@Controller
API와 view를 동시에 사용하는 경우에 사용
대신 API 서비스로 사용하는 경우는 @ResponseBody를 사용하여 객체를 반환한다.
view(화면) return이 주목적
@RestController
view가 필요없는 API만 지원하는 서비스에서 사용 (Spring 4.0.1부터 제공)
@RequestMapping 메서드가 기본적으로 @ResponseBody 의미를 가정한다.
data(json, xml 등) return이 주목적
즉, @RestController = @Controller + @ResponseBody
@Required
setter method에 사용한다.
영향을 받는 bean property 구성 시 XML 설정 파일에 반드시 property를 채워야 한다. (엄격한 체크)
그렇지 않으면 BeanInitializationException 예외를 발생
예시
<!-- Definition for student bean --><bean id ="student"class="com.tutorialspoint.Student"><property name ="name" value ="Zara"/><property name ="age" value ="11"/></bean> https://gmlwjd9405.github.io/2018/12/02/spring-annotation-types.html
필드, 생성자, 입력 파라미터가 여러 개인 메소드(@Qualifier는 메소드의 파라미터)에 적용 가능
Type을 먼저 확인한 후 못 찾으면 Name에 따라 주입한다.
Name으로 강제하는 방법: @Qualifier을 같이 명시
예시
사진 삭제
사진 설명을 입력하세요.
TIP) Bean을 주입받는 방식 (3가지)
@Autowired
setter
생성자 (@AllArgsConstructor 사용) -> 권장방식
@Qualifier
같은 타입의 빈이 두 개 이상이 존재하는 경우에 스프링이 어떤 빈을 주입해야 할지 알 수 없어서 스프링 컨테이너를 초기화하는 과정에서 예외를 발생시킨다.
이 경우 @Qualifier을 @Autowired와 함께 사용하여 정확히 어떤 bean을 사용할지 지정하여 특정 의존 객체를 주입할 수 있도록 한다.
예시
사진 삭제
사진 설명을 입력하세요.
xml 설정에서 bean의 한정자 값(qualifier value)을 설정한다.
@Autowired 어노테이션이 적용된 주입 대상에 @Qualifier 어노테이션을 설정한다.
@Resource
javax.annotation.Resource
표준 자바(JSR-250 표준) Annotation으로, Spring Framework 2.5.* 부터 지원 가능한 Annotation이다.
Annotation 사용으로 인해 특정 Framework에 종속적인 어플리케이션을 구성하지 않기 위해서는 @Resource를 사용할 것을 권장한다.
@Resource를 사용하기 위해서는 class path 내에 jsr250-api.jar 파일을 추가해야 한다.
필드, 입력 파라미터가 한 개인 bean property setter method에 적용 가능
[Data Validation]
@Vaild
import javax.validation.Valid;
@Size(max=10, min=2, message=”errMsg”)
@Email(message=”errMsg”)
@NotEmpty(message=”errMsg”)
[Configuration]
@Configuration
@EnableWebSecurity
@SpringBootApplication
@EnableWebMvc
@RestControllerAdvice
@ExceptionHandler
@ResponseStatus
[Parameter를 받는 방법]
@RequestParam
HTTP GET 요청에 대해 매칭되는 request parameter 값이 자동으로 들어간다.
url 뒤에 붙는 parameter 값을 가져올 때 사용한다.
Ex) `http://localhost:8080/home?index=1&page=2`
@GetMapping("/home")public String show(@RequestParam("page") int pageNum {}
위의 경우 GET /home?index=1&page=2와 같이 uri가 전달될 때 page parameter를 받아온다.
@RequestParam 어노테이션의 괄호 안의 문자열이 전달 인자 이름(실제 값을 표시)이다.
@PathVariable
HTTP 요청에 대해 매칭되는 request parameter 값이 자동으로 들어간다.
uri에서 각 구분자에 들어오는 값을 처리해야 할 때 사용한다.
Ex) `http://localhost:8080/index/1`
REST API에서 값을 호출할 때 주로 많이 사용한다.
@PostMapping("/index/{idx}")
@ResponseBody public boolean deletePost(@PathVariable("idx") int postNum){return postService.deletePost(postNum);}
위의 경우 POST /index/{idx}와 같이 uri가 전달될 때 해당하는 구분자 {idx}를 받아온다.
참고 @RequestParam와 @PathVariable 동시 사용 예제
@GetMapping("/user/{userId}/invoices")public List<Invoice>listUsersInvoices(@PathVariable("userId") int user, @RequestParam(value ="date", required =false) Date dateOrNull){}
위의 경우 GET /user/{userId}invoices?date=190101 와 같이 uri가 전달될 때
구분자 {userId}는 @PathVariable(“userId”)로,
뒤에 이어붙은 parameter는 @RequestParam(“date”)로 받아온다.
@RequestBody
반드시 HTTP POST 요청에 대해서만 처리한다.
HTTP POST 요청에 대해 request body에 있는 request message에서 값을 얻어와 매칭한다.
RequestData를 바로 Model이나 클래스로 매핑한다.
이를테면 JSON 이나 XML같은 데이터를 적절한 messageConverter로 읽을 때 사용하거나 POJO 형태의 데이터 전체로 받는 경우에 사용한다.
@ModelAttribute
@RequestParam과 비슷하다.
form 값
[공용 생성일/수정일을 위한 Annotation]
@EnableJpaAuditing
JPA Auditing을 활성화한다.
@MappedSuperclass
JPA Entity 클래스들이 BaseTimeEntity을 상속할 경우 필드들(createdDate, modifiedDate)도 컬럼으로 인식하도록 한다.
@EntityListeners(AuditingEntityListener.class)
BaseTimeEntity 클래스에 Auditing 기능을 포함한다.
@CreatedDate
Entity가 생성되어 저장될 때 시간이 자동으로 저장된다.
@LastModifiedDate
조회한 Entity의 값을 변경할 때 시간이 자동으로 저장된다.
@Transactional
메소드 내에서 Exception이 발생하면 해당 메소드에서 이루어진 모든 DB 작업을 초기화한다.
즉, save 메소드를 통해서 10개를 등록해야 하는데 5번째에서 Exception이 발생하면 앞에 저장된 4개 까지 모두 롤백한다.
(정확히 얘기하면, 이미 넣은걸 롤백시키는건 아니며, 모든 처리가 정상적으로 됐을때만 DB에 커밋하며 그렇지 않은 경우엔 커밋하지 않는 것이다.)
비지니스 로직과 트랜잭션 관리는 모두 Service에서 관리한다.
따라서 일반적으로 DB 데이터를 등록/수정/삭제 하는 Service 메소드는 @Transactional를 필수적으로 가져간다.
[JPA에서 제공하는 Annotation]
JPA를 사용하면 DB 데이터에 작업할 경우 실제 쿼리를 날리지 않고 Entity 클래스의 수정을 통해 작업한다.
@Table
엔티티 클래스에 매핑할 테이블 정보를 알려준다.
Ex) @Table(name = "USER")
이 어노테이션을 생략하면 클래스 이름을 테이블 이름 정보로 매핑한다.
@Entity
실제 DB의 테이블과 매칭될 클래스임을 명시한다.
즉, 테이블과 링크될 클래스임을 나타냅니다.
Entity Class
가장 Core한 클래스
클래스 이름을 언더스코어 네이밍(_)으로 테이블 이름을 매칭한다.
Ex) SalesManage스.java -> sales_manager table
TIP) Controller에서 쓸 DTO 클래스란
Request와 Response용 DTO는 View를 위한 클래스로, 자주 변경이 필요한 클래스이다.
Entity 클래스와 DTO 클래스를 분리하는 이유
View Layer와 DB Layer를 철저하게 역할 분리를 하는게 좋다.
테이블과 매핑되는 Entity 클래스가 변경되면 여러 클래스에 영향을 끼치게 되는 반면 View와 통신하는 DTO 클래스(Request/ Response 클래스)는 자주 변경되므로 분리해야 한다.
@Id
해당 테이블의 PK 필드를 나타낸다.
@GeneratedValue
PK의 생성 규칙을 나타낸다.
TIP) 가능한 Entity의 PK는 Long 타입의 Auto_increment를 추천한다.
기본값은 AUTO로, MySQL의 auto_increment와 같이 자동 증가하는 정수형 값이 된다.
스프링 부트 2.0에선 옵션을 추가하셔야만 auto_increment가 된다.
참고
@Column
테이블의 컬럼을 나타내면, 굳이 선언하지 않더라도 해당 클래스의 필드는 모두 컬럼이 된다.
@Column을 생략하면 필드명을 사용해서 컬럼명과 매핑하게 된다.
Ex) @Column(name = "username")
이 Annotation을 사용하는 이유는, 기본값 외에 추가로 변경이 필요한 옵션이 있을 경우 사용한다.
Ex) 문자열의 경우 VARCHAR(255)가 기본값인데, 사이즈를 500으로 늘리고 싶거나(ex: title), 타입을 TEXT로 변경하고 싶거나(ex: content) 등의 경우에 사용된다.
[Lombok Library Annotation]
@NoArgsConstructor
기본생성자를 자동으로 추가한다.
access = AccessLevel.PROTECTED
기본생성자의 접근 권한을 protected로 제한
생성자로 protected Posts() {}와 같은 효과
Entity 클래스를 프로젝트 코드상에서 기본생성자로 생성하는 것은 막되, JPA에서 Entity 클래스를 생성하는것은 허용하기 위해 추가한다.
@AllArgsConstructor
모든 필드 값을 파라미터로 받는 생성자를 추가한다.
@RequiredArgsConstructor
final이나 @NonNull인 필드 값만 파라미터로 받는 생성자를 추가한다.
final: 값이 할당되면 더 이상 변경할 수 없다.
@Getter
클래스 내 모든 필드의 Getter 메소드를 자동으로 생성한다.
@Setter
Controller에서 @RequestBody로 외부에서 데이터를 받는 경우엔 기본생성자 + set메소드를 통해서만 값이 할당된다.
그래서 이때만 setter를 허용한다.
@ToString
@ToString(exclude = "password")
특정 필드를 toString() 결과에서 제외한다.
클래스명(필드1명=필드1값, 필드2명=필드2값, …) 식으로 출력된다.
@EqualsAndHashCode
equals와 hashCode 메소드 오버라이딩
User user1 =newUser(); user1.setId(1L); user1.setUsername("user"); user1.setPassword("pass"); User user2 =newUser(); user1.setId(2L);// 부모 클래스의 필드가 다름 user2.setUsername("user"); user2.setPassword("pass"); user1.equals(user2);// callSuper = true 이면 false, callSuper = false 이면 true
@EqualsAndHashCode(callSuper = true)
callSuper 속성을 통해 equals와 hashCode 메소드 자동 생성 시 부모 클래스의 필드까지 감안할지 안 할지에 대해서 설정할 수 있다.
즉, callSuper = true로 설정하면 부모 클래스 필드 값들도 동일한지 체크하며, callSuper = false로 설정(기본값)하면 자신 클래스의 필드 값들만 고려한다.
@Builder
어느 필드에 어떤 값을 채워야 할지 명확하게 정하여 생성 시점에 값을 채워준다.
TIP) 생성자와 빌더의 차이
생성 시점에 값을 채워주는 역할은 똑같다.
하지만 빌더를 사용하면 어느 필드에 어떤 값을 채워야 할지 명확하게 인지할 수 있다.
해당 클래스의 빌더 패턴 클래스를 생성
생성자 상단에 선언 시 생성자에 포함된 필드만 빌더에 포함된다.
@Data
@Getter @Setter @EqualsAndHashCode @AllArgsConstructor을 포함한 Lombok에서 제공하는 필드와 관련된 모든 코드를 생성한다.
HttpServletRequest 클래스에는 getParameter만 있고 setParameter는 없다.
클라이언트 단에서 날아온 값으로 서블릿에서는 setAttribute 함수밖에 없으며 setAttribute 값은 getAttribute로 밖에 꺼내올 수 없는데, setAttribute와 setParameter에는 서버에서 세팅했는지, 클라이언트에서 세팅했는지에 대한 차이가 있다.
1) PropertyPlaceholderConfigurer를 이용한 properties 파일 읽어오기
2) context:property-placeholder를 이용한 properties 파일 읽어오기
3) <util:properties/> 와 Spring EL을 이용한 properties 파일 읽어오기
1) PropertyPlaceholderConfigurer를 이용한 properties 파일 읽어오기
프로퍼티를 읽어오기 위해 간단한 선행 작업으로 /WEB-INF안에 config 폴더를 생성 후 안에 config.prpoerties라는 프로퍼티 파일을 생성
config.properties의 내용
#### Oracle DB Info #### db.driver=oracle.jdbc.driver.OracleDriver db.url=jdbc:oracle:thin:@localhost:1521:orcl db.username=ktko db.password=ktko1234 #### File Path #### file.path=C:\\
servlet-context.xml
location 프로퍼티의 값에는 콤마나 공백으로구분된 프로퍼티 파일 목록이 오며, 프로퍼티 파일에 포함된 프로퍼티의 값은 '${프로퍼티 이름}' 형식으로 사용할 수 있습니다. 예제를 보면 config.properties 안에 있는 db.driver의 값을 xml 파일에서 '${db.driver}' 형태로 사용할 수 있습니다.
이클립스의 설정은 윈도우 레지스트리에 보관되지 않습니다. 워크스페이스 폴더를 보면 .metadata 폴더가 있습니다. 여기에 이클립스에서 설정했던 내용들이 들어가 있습니다.
.metadata
이 얘기는 workspace를 바꾸면 설정을 다시해 줘야 한다는 뜻입니다. 또한 이클립스를 업그레이드해도 이전에 쓰던 작업환경의 설정을 그대로 가져갈 수 있다는 뜻이기도 합니다.
살짝 .metadata 폴더 내용을 보면 다음과 같습니다.
.metadata 폴더
이 중에 각각의 플러그인 설정값은 .plugins 아래 보관이 됩니다. .log 파일은 이클립스 내부에서 발생하는 오류들의 스택트레이스 로그가 보관됩니다. 플러그인 충돌이나 기타 이클립스가 오작동을 할 경우 이 안에 있는 내용을 토대로 구글링 해보면 운 좋게 해결법을 찾을 수 있습니다.
이클립스가 종료된 상태에서 .metadata 를 지우면 설정은 다시하셔야 됩니다. 이클립스의 검색 인덱스 파일도 여기에 보관이 되기 때문에 혹시나 이클립스 워크스페이스가 무거워졌다고 느껴지면 한 번 지웠다가 다시 설정하는 것도 나쁘지는 않습니다.
이클립스(Eclipse)를 새 PC에 설치해서 구동하려고 했더니, 다음과 같은 오류 메시지가 떴습니다.
이 오류 메시지가 뜨면 이클립스 실행 자체가 되지 않습니다.
회사에서도 그렇고, 이전 PC에서도 그렇고, 별 문제 없이 잘 실행 되었던 것으로 기억하는데..(사실 잘 기억은 안나네요. 처음 설치하고 고생했는지는 너무 오래전 일이라. 보통 한 번 잘 세팅해놓고, 왠만해서는 변경하지 않으니... ㅎㅎㅎ)
Java was started but returned exit code=13 로 시작하는 긴 오류 메시지가 떴습니다. 블라블라~
보통 가장 빈번한 경우는 OS 비트와 이클립스의 지원 비트 버전이 다른 경우입니다.
OS는 64비트인데, 이클립스는 32비트용을 다운로드 받아 설치한 경우이지요.
이 때의 문제는 간단히 이클립스를 OS 버전에 맞는 것으로 다시 다운로드 받아 설치하면 됩니다.
그리고 다른 케이스가 있는데, 이클립스가 실행하면 javaw.exe 파일(JDK 내에 있음)을 찾아 실행시키는데, 해당 파일을 찾지 못한 경우입니다. (제가 겪은 케이스입니다.)
이 때에는 직접 설치한 JDK폴더의 javaw.exe 파일 경로를 eclipse.ini 파일에 지정해주면 됩니다.
참고로 javaw.exe 파일은 java.exe 파일과 그 기능이나 동작은 동일하지만, 단지 Console Window 를 띄우지 않는 다는 차이점만 있습니다. (즉, Java.exe 와 동일하게 동작하지만, 어떠한 상태 정보등을 명령 프롬프트(콘솔 창)에 출력하지 않습니다. 단 오류가 발생하는 경우라면 오류 메시지 박스(대화 상자)를 띄워줍니다.)
그리고 java.exe 파일은 자바 프로그램을 구동시키기 위한 자바 런타임 환경(Java Runtime Environment)을 제공 뿐만 아니라 웹 브라우저에서 Java 기반의 플러그인을 실행할 수 있도록 하기 위한 백그라운드 프로세스로 실행되는 프로그램입니다. 그렇기 때문에 Java 프로그래밍에는 필수 요소입니다.
Eclipse가 설치된 폴더로 가서 eclipse.ini 파일을 메모장 등의 텍스트 편집 도구로 불러옵니다.
그리고 아래와 같이 -vmargs 윗쪽에 javaw.exe 파일 경로를 입력하여 줍니다. 사용자마다 JDK 설치 폴더가 다를테니, 자신의 시스템에 설치된 경로를 확인하여 입력하시면 됩니다.
-vm C:\Java\jdk1.7.0_45\bin\javaw.exe (javaw.exe 파일이 존재하는 경로)
아래 -vmargs 는 -vm (Virtual Machine)으로 구동될 javaw.exe의 인자 정보들을 의미하므로 위의 -vm 코드는 반드시 -vmargs 보다 상단에 작성하여야 합니다.