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}' 형태로 사용할 수 있습니다.