폼 데이터의 유효성 검증
폼의 데이터를 파마리터로 받아 비지니스 로직에 따른 데이터 처리를 하고 모델에 담아 뷰에 보여주는 일련의 과정에서, 파라미터가 데이터로 사용 가능한지 파악하는 것을 의미한다.
폼 데이터의 유효성 검증은 보통 다음 두 단계에서 이루어 진다.
- 클라이언트인 Html 페이지에서 자바스크립트를 통한 검증
- 서버 페이지인 JSP/Servlet에서 파라미터로 받은 후 검증
1번 방식은 데이터의 유효성이 검증되지 않았다면 서버로 데이터를 내보내지 않아 네트워크의 트래픽 낭비를 막을 수 있게 된다.
이는 트래픽이 많은 서버의 경우, 서버의 부하를 줄여주는 역할을 하기도 한다.
하지만 클라이언트에서 자바 스크립트를 통한 데이터 검증을 했더라도, 악의적인 url 호출에 의해 검증되지 않은 데이터가 서버로 올라올 수 있으므로 서버에서 반드시 확인해야 한다.
Validator
스프링의 Validator은 같은 방식으로 만들어지기 때문에 불편함을 덜어준다.
그리고 유효성 검사를 하기 위해 스프링은 org.springframeword.validation.Validator 인터페이스를 제공하고 있다.
이처럼 스프링이 인터페이스를 제공하여 검증 로직을 만들어야 하는 개발자들이 서로 일관된 방식의 코드를 만들 수 있도록 방향을 제시하고 있다.
폼 데이터의 유효성 검증은 Spring Web을 추가하면, 별도의 디펜던시 추가 없이도 사용할 수 있다.
Validator 인터페이스
Validator 인터페이스를 구현하기 위해서는 supports 메서드와 validate 메서드를 반드시 구현해야 한다.
package com.study.springboot;
import org.springframework.validation.Errors;
import org.springframework.validation.Validator;
public class ContentValidator implements Validator {
@Override
public boolean supports(Class<?> arg0) {
return ContentDto.class.isAssignableFrom(arg0); //검증할 객체의 클래스 타입 정보
}
@Override
public void validate(Object obj, Errors errors) {
ContentDto dto = (ContentDto)obj;
String sWriter = dto.getWriter();
if(sWriter == null || sWriter.trim().isEmpty()) {
System.out.println("Writer is null or Empty");
errors.rejectValue("writer", "trouble");
}
String sContent = dto.getContent();
if(sContent == null || sContent.trim().isEmpty()) {
System.out.println("Content is null or empty");
errors.rejectValue("content", "trouble");
}
}
}
validate메서드 안에는 데이터의 유효성을 검증하기 위한 본인의 코드를 작성하면 된다.
ContentDto dto = (ContentDto)obj; 에서 커맨드 객체를 파라미터로 받아들이고여 형변환을 한다.
인터페이스를 만들 당시에는 파라미터로 어떤 것이 들어올지 모르니, Object로 파라미터로 구현한 것이다.
위의 첫번째 if문을 살펴보면
커맨드 객체로부터 작성자 값을 구해와서 그 값이 널인지 공백인지를 체크하는 로직을 구현한다. 그리고 데이터 유효성 검사에서 통과를 못했다면 errors 객체 변수에 에러 내용을 담는다.
메서드에서 별도의 값을 리턴하지는 않지만, 앞의 모델을 사용한 방식과 같이 참조자로 넘어온 변수인 errors에 값을 넣어주면 다른 곳에서도 이 에러 내용을 이용할 수 있게된다.
모든 요소를 검증할 필요는 없고, 필요한 필드만 검증하는 로직을 만들면 된다.
package com.study.springboot;
import org.springframework.stereotype.Controller;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
@Controller
public class MyController {
@RequestMapping("/")
public @ResponseBody String root() throws Exception{
return "Validatory (1)";
}
@RequestMapping("/insertForm")
public String insert1() {
return "createPage";
}
@RequestMapping("/create")
public String insert2(@ModelAttribute("dto") ContentDto contentDto, BindingResult result) {
String page = "createDonePage";
System.out.println(contentDto);
ContentValidator validator = new ContentValidator();
validator.validate(contentDto, result);
if(result.hasErrors()) {
page= "createPage";
}
return page;
}
}
/insertForm 호출에 대해서는 단순히 JSP 페이지를 리턴한다.
JSP로 만든 뷰에서 폼의 액션으로 /create가 호출되면
커맨드 객체 파라미터로 폼 데이터를 받아서 처리하는데,
유효성 검증 객체를 만들고 파라미터로 받은 커맨드 객체의 값을 검증한다.
검증하는 메서드 자체는 리턴값이 없지만 참조변수 result를 함께 보냈기에 메서드 호출이 끝나고 result에 값이 들어있다면 에러가 있다는 말이 되므로 체크를 한다.
에러가 없다면 결과 페에지의 JSP를, 에러가 있다면 입력 페이지의 JSP를 리턴한다.
String conPath = request.getContextPath();
현재 JSP 페이지의 경로를 리턴
ValidationUtils 사용
package com.study.springboot;
import org.springframework.validation.Errors;
import org.springframework.validation.ValidationUtils;
import org.springframework.validation.Validator;
public class ContentValidator implements Validator {
@Override
public boolean supports(Class<?> arg0) {
return ContentDto.class.isAssignableFrom(arg0); //검증할 객체의 클래스 타입 정보
}
@Override
public void validate(Object obj, Errors errors) {
ContentDto dto = (ContentDto)obj;
// String sWriter = dto.getWriter();
// if(sWriter == null || sWriter.trim().isEmpty()) {
// System.out.println("Writer is null or Empty");
// errors.rejectValue("writer", "trouble");
// }
ValidationUtils.rejectIfEmptyOrWhitespace(errors, "writer", "writer is empty");
String sWriter = dto.getWriter();
if(sWriter.length() < 3) {
errors.rejectValue("writer", "writer is too short");
}
//위에서의 반복 작업을 스프링에서 제공하는 유틸 메서드를 사용하여 편리하게 한다.
// String sContent = dto.getContent();
// if(sContent == null || sContent.trim().isEmpty()) {
// System.out.println("Content is null or empty");
// errors.rejectValue("content", "trouble");
// }
ValidationUtils.rejectIfEmptyOrWhitespace(errors, "content", "content is empty.");
}
}
기존처럼 데이터가 값이 널인지 공백인지 비교하는 단순하지만 누구나 만들어야하는 반복접인 작업이라면 새로운 코드러처럼 스프링에서 제공하는 유틸 메서드를 사용할 수 있다.
데이터를 검증하고 에러가 있을 때는 에러를 처리하는 것까지 이 하나의 유틸 메서드에서 다 처리하고 있다.
package com.study.springboot;
import org.springframework.stereotype.Controller;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
@Controller
public class MyController {
@RequestMapping("/")
public @ResponseBody String root() throws Exception{
return "ValidationUtils (2)";
}
@RequestMapping("/insertForm")
public String insert1() {
return "createPage";
}
@RequestMapping("/create")
public String insert2(@ModelAttribute("dto") ContentDto contentDto, BindingResult result) {
String page = "createDonePage";
System.out.println(contentDto);
ContentValidator validator = new ContentValidator();
validator.validate(contentDto, result);
if(result.hasErrors()) {
System.out.println("getAllErrors : "+ result.getAllErrors());
if(result.getFieldError("writer") != null) {
System.out.println("1:"+result.getFieldError("writer").getCode());
}
if(result.getFieldError("content") != null) {
System.out.println("2:"+result.getFieldError("content").getCode());
}
page = "createPage";
}
return page;
}
}
이전 예제에서는 ContentValidator 클래스에서 유효성 검증 에러를 출력하였는데, 이번 예제에서는 스프링에서 제공되는 API를 사용하면서 에러를 담은 결과를 리턴받기 때문에 MyController 클래스에서 에러를 출력하도록 수정하였다.
initBinder 사용
build.gradle에 추가
implementation 'org.springframework.boot:spring-boot-starter-validation'
validation 관련 디펜던시를 추가해야 사용이 가능.
기본적인 유효성 검사는 지금 추가한 디펜던시 없이도 사용 가능했지만, 유효성 검증 관련 어노테이션들은 이 디펜던시를 추가해야 동작한다.
package com.study.springboot;
import javax.validation.Valid;
import org.springframework.stereotype.Controller;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.InitBinder;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
@Controller
public class MyController {
@RequestMapping("/")
public @ResponseBody String root() throws Exception{
return "ValidationUtils (3)";
}
@RequestMapping("/insertForm")
public String insert1() {
return "createPage";
}
@RequestMapping("/create")
public String insert2(@ModelAttribute("dto") @Valid ContentDto contentDto, BindingResult result) {
String page = "createDonePage";
System.out.println(contentDto);
// ContentValidator validator = new ContentValidator();
// validator.validate(contentDto, result);
if(result.hasErrors()) {
System.out.println("getAllErrors : "+ result.getAllErrors());
if(result.getFieldError("writer") != null) {
System.out.println("1:"+result.getFieldError("writer").getCode());
}
if(result.getFieldError("content") != null) {
System.out.println("2:"+result.getFieldError("content").getCode());
}
page = "createPage";
}
return page;
}
@InitBinder
protected void initBinder(WebDataBinder binder) {
binder.setValidator(new ContentValidator());
}
}
@InitBinder
해당 메서드를 프로젝트가 시작할 때 먼저 실행시칸다.
그러면 WebDataBinder 타입 변수에 우리가 사용할 유효성 검증 클래스가 프로젝트가 시작할 때 등록된다.
프로젝트에서 사용할 빈을 등록하는 것과 비슷하지만 관리하는 곳을 다르게 지정한 것이다.
이후론 개별적으로 생성할 필요 없이 유효성 검증이 필요하면 binder 변수에서 꺼내어 사용하면 된다.
다른 곳에서는 필요할 때마다 매번 new로 만들지 않고 한 번 만들어놓은 것을 주입 받아 사용할 수 있게 되었으므로 약한 결합으로 사용할 수 있게 된 것이다.
@Valid
contentDto 객체 변수에 대한 유효성 검증을 한다고 표시
파라미터로 객체 변수가 들어오면 스프링이 binder 변수에 저장된 객체를 통해서 즉시 유효성 검사를 하고 에러가 있다면 result 변수에 담아 둔다.
그러므로 기존 유효성 검사라인은 주석 처리하고, 유효성 검증을 하기 위해서 result는 그대로 사용한다.
if(result.hasErrors()) {
System.out.println("getAllErrors : "+ result.getAllErrors());
if(result.getFieldError("writer") != null) {
System.out.println("1:"+result.getFieldError("writer").getCode());
}
if(result.getFieldError("content") != null) {
System.out.println("2:"+result.getFieldError("content").getCode());
}
page = "createPage";
}
이 부분에서 에러를 체크해서 에러가 없다면 정상적인 것이기 때문에 완료 페이지의 JSP 이름을 리턴한다.
에러가 있다면 내용을 작성하는 페이지로 보내기 위한 JSP의 이름을 리턴한다.
이렇게 유효성 검사가 필요할 때마다 기존 방법 처럼 생성을 하고, 유효성 검사 메서드를 호출하는 것이 아니고, 유효성 검사가 필요한 객체 변수에 @Valid 어노테이션만 붙여주면 간단하게 유효성 검사를 수행하게 된다.
이렇게 내부적으로 강한 결합을 사용하던 것을 약한 결합을 사용하는 것으로 바꾼것이다.
Valid 어노테이션
package com.study.springboot;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
import lombok.Data;
@Data
public class ContentDto {
private int id;
@NotNull(message="writer is null.")
@NotEmpty(message="writer is empty.")
@Size(min=3, max=10, message="writer min 3, max 10")
private String writer;
@NotNull(message="content is null.")
@NotEmpty(message="content is empty.")
private String content;
}
@NotNull
변수 값이 널이 아니면 안된다는 의미이다. 만약 널이면 입력된 에러 메시지가 사용된다.
@NotEmpty
변수 값이 공백이면 안된다는 의미이다. 만약 공백이라면 입력된 에러 메시지가 사용된다.
@Size
변수의 값의 길이의 최소, 최대를 설정이 가능하다.
조건이 충족되지 않으면 에러 메시지가 사용된다.
유효성 검증 처리의 대부분을 어노테이션으로 지정한다.
package com.study.springboot;
import javax.validation.Valid;
import org.springframework.stereotype.Controller;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
@Controller
public class MyController {
@RequestMapping("/")
public @ResponseBody String root() throws Exception{
return "Valid_initBinder (3)";
}
@RequestMapping("/insertForm")
public String insert1() {
return "createPage";
}
@RequestMapping("/create")
public String insert2(@ModelAttribute("dto") @Valid ContentDto contentDto, BindingResult result) {
String page = "createDonePage";
System.out.println(contentDto);
// ContentValidator validator = new ContentValidator();
// validator.validate(contentDto, result);
if(result.hasErrors()) {
// System.out.println("getAllErrors : "+ result.getAllErrors());
//
// if(result.getFieldError("writer") != null) {
// System.out.println("1:"+result.getFieldError("writer").getCode());
// }
// if(result.getFieldError("content") != null) {
// System.out.println("2:"+result.getFieldError("content").getCode());
// }
if(result.getFieldError("writer") != null) {
System.out.println("1:"+result.getFieldError("writer").getDefaultMessage());
}
if(result.getFieldError("content") != null) {
System.out.println("2:"+result.getFieldError("content").getDefaultMessage());
}
page = "createPage";
}
return page;
}
// @InitBinder
// protected void initBinder(WebDataBinder binder) {
// binder.setValidator(new ContentValidator());
// }
}
스프링에서 제공하는 데이터 유효성 검증 모듈을 사용하기 위해 이미 ContentDto에 유효성 검증에 대한 처리를 어노테이션으로 지정했기에, initBinder 메서드를 통해 우리가 개별적으로 작성한 유효성 검증 클래스를 등록할 필요가 없다.
폼 데이터의 유효성 검증을 어노테이션을 지정해서 하게 되면 에러가 있을 경우 에러를 가져오기 위한 처리 부분이 기존과 조금 다르게 된다.
에러가 있는지를 비교하는 부분은 같지만 에러가 있을 때 에러 내용을 가져오는 코드가 getCode() 메서드가 아니고 getDefaultMessage() 메서드를 사용한다.
웹 애플리케이션 개발에서 데이터의 값이 널인지 공백인지 또는 길이를 제한하는 등의 유효성 검증은 매우 빈번하게 사용되므로 스프링의 유효성 검증 모듈을 사용하게 되면 코딩의 양을 대폭 줄일 수 있다.
폼 데이터 유효성 검증 정리
두 가지 방법
- 클라이언트인 Html 페이지에서 자바 스크립트를 통한 검증
- 서버 페이지인 JSP/Servlet에서 파라미터로 받은 후 검증
첫번째 방법은 데이터의 유효성이 검증되지 않았다면 서버로 데이터를 보내지 않아 네트워크의 트래픽 낭비를 막을 수 있게 된다.
이는 트래픽이 많은 서버의 경우, 서버의 부하를 줄여주는 역할을 하기도 한다.
하지만 클라이언트에서 자바스크립트를 통한 데이터 검증을 했더라도, 악의적인 url 호출에 의해 검증되지 않은 데이터가 서버로 올라올 수 있으므로 서버에서도 반드시 확인해야 한다.
스프링의 Validator은 불편함을 덜어준다. 같은 방식으로 만들기 때문에 일관된 방식으로 만든다.
org.springframework.validation.Validator 인터페이스를 제공한다.
Validator 인터페이스를 구현하기 위해서는 supports 메서드와 validate 메서드를 오바라이딩 해야 한다.
validate 메서드 안에는 데이터의 유효성을 검증하기 위한 코드를 작성하면 된다.
스프링에서는 유효성 검증의 부분인 널, 공백 비교해서 처리하는 부분을 API 메서드로 제공한다.
public abstract class ValidationUtils{
public static void rejectIfEmptyOrWhitespace(
Errors errors, String field, String errorCode, @Nullable Object[] errorArgs) {
rejectIfEmptyOrWhitespace(errors, field, errorCode, errorArgs, null);
}
public static void rejectIfEmptyOrWhitespace(
Errors errors, String field, String errorCode, @Nullable Object[] errorArgs, @Nullable String defaultMessage) {
Assert.notNull(errors, "Errors object must not be null");
Object value = errors.getFieldValue(field);
if (value == null ||!StringUtils.hasText(value.toString())) {
errors.rejectValue(field, errorCode, errorArgs, defaultMessage);
}
....
}
위 클래스의 메서드는 스프링에서제공하는 유틸 메서드이다.
데이터를 검증하고 에러가 있을 때는 에러를 처리하는 것 까지 이 하나의 유틸메서드에서 다 처리한다.
위 메서드는 에러를 담은 결과를 리턴받는다.
위 메서드에서는 검증이 필요할 때 마다 검증용 클래스를 new 해서 사용해야하는 강한 결합을 사용하였다.
약한결합으로도 구현이 가능하다.
build.gradle에 추가
implementation 'org.springframework.boot:spring-boot-starter-validation'
위 의존성을 추가하면 유효성 검증 관련 어노테이션들이 동작한다.
Controller에 추가
@InitBinder
protected void initBinder(WebDataBinder binder) {
binder.setValidator(new ContentValidator());
}
기존 검증용 클래스 삭제
ContentValidator validator = new ContentValidator();
validator.validate(contentDto, result);
검증이 필요한 변수에 @Valid 어노테이션 추가
@InitBinder 어노테이션을 추지정하면 해당 메서드를 프로젝트가 시작할 때 먼저 실행시킨다.
그러면 WebDataBinder 타입 변수에 우리가 사용할 유효성 검증 클래스가 프로젝트가 시작할 때 등록된다.
프로젝트에서 사용할 빈을 등록하는 것과 비슷하지만 관리하는 곳을 다르게 지정하는 것이다.
이후론 개별적인 생성할 필요 없이 유효성 검증이 필요하면 binder 변수에서 꺼내서 사용하면 된다.
다른곳에서 필요할 때마다 매번 new로 만들지 않고 만들어 놓을 것을 주입 받아 사용하므로 약한 결합으로 사용하는 것이다.
@Vaild 어노테이션으로 변수에 대한 유효성 검증을 할 수 있다.
파라미터로 객체 변수가 들어오면 스프링이 binder 변수에 저장된 객체를 통해서 즉시 유효성 검사를 하고 에러가 있다면 result 변수에 담아 둔다.
즉 유효성 검사가 필요한 객체 변수에 @Valid 어노테이션만 붙여주면 유효성 검사를 수행할 수 있다.
또 다른 방법으로는 유효성 검증 관련 어노테이션을 사용하는 것이다.
DTO 클래스나 커맨드객체 클래스의 변수들에 어노테이션을 작성하면 된다.
@NotNull
널값 금지이다. 널이면 입력된 에러 메시지가 사용된다.
@NotEmpty
공백 금지이다. 공백이면 입력된 에러 메시지가 사용된다.
@Size
최소 길이(min), 최대길이(max), 에러메시지를 설정할 수 있다.
기존 컨트롤러에서는 에러 내용을 가져오는 코드가 getCode() 이지만 , 어노테이션을 사용했다면 getDefaultMessage() 메서드를 사용한다.
JdbcTemplate 사용
데이터베이스를 사용하기 위해 JCBC를 직접 이용하면 드라이버 로드, 접속, 쿼리 실행 , 종료 등 반복적인 작업과 컨넥션 풀 관리 등의 작업을 개발자가 매번 해야 한다.
스프링은 누구나 해야 하는 이런 반복적인 작업이 있다면 항상 쉬운 사용 모듈을 제공하고 있다.
그리고 데이터베이스를 쉽게 사용할 수 있는 모듈로는 JdbcTemplate을 제공하고 있다.
데이터베이스 의존성 설정
JDBC API는 자바에서 데이터베이스를 사용하기 위한 디펜던시라 필수로 포함시켜야 한다.
Orcale Driver는 오라클용 드라이버이다.
그레읻르에서 라이브러리로 다운 받고 관리해 주는 것이다.
그런데 오라클의 경우 오라클 드라이버를 생성단계에서 체크하고 그래이들이 관리하게 하면 정상적으로 동작하지 않고 에러가 발생하므로 체크하지 않는다.
오라클 사용시
오라클 데이버베이스 JDBC 드라이버를 사용하기 위해 오라클 데이터베이스가 설치된 폴더에서 ojdbc6.jar 파일을 찾아 프로젝트에서 외부 라이브러리로 등록시키든지, 컴퓨터에 클래스패스로 지정되어 있는 폴더에 등록해서 사용해야 한다.
다음 JDBC 설정을 한다.
application.properties에 추가
#JSP
spring.mvc.view.prefix=/WEB-INF/views/
spring.mvc.view.suffix=.jsp
# oracle set
spring.datasource.driver-class-name=oracle.jdbc.OracleDriver
spring.datasource.url=jdbc:oracle:thin:@localhost:1521/db명
spring.datasource.username=user 이름
spring.datasource.password=user 패스워드
D:\app\oracle\product\11.2.0\server\jdbc\lib 폴더에서 ojdbc6.jar 를 환경변수 편집→사용자변수→새로만들기→classpath/경로넣기;.하면 등록이 완료된다.
MySQL 사용시
MySQL Drivaer 디펜던시를 체크하면 자동으로 의존성이 주입된다.
JDBC 세팅 추가
application.properties에 추가
#JSP
spring.mvc.view.prefix=/WEB-INF/views/
spring.mvc.view.suffix=.jsp
# MySQL set
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/db이름
spring.datasource.username=user 이름
spring.datasource.password=user 패스워드
MariaDB 사용시
build.gradle에 추가
compile group: 'org.mariadb.jdbc', name: 'mariadb-java-client', version: '2.7.0'
application.properties에 추가
#JSP
spring.mvc.view.prefix=/WEB-INF/views/
spring.mvc.view.suffix=.jsp
# MySQL set
spring.datasource.driver-class-name=org.mariadb.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/db이름
spring.datasource.username=user 이름
spring.datasource.password=user 패스워드
DTO 클래스를 만든다.
데이터베이스 테이블에서 SQL문의 쿼리로 발생하는 데이터를 처리하기 위한 것이므로 테이블의 컬럼명으로 변수를 만들면 된다.
후에 @Data 어노테이션을 추가해준다.
DAO 클래스를 만든다.
DAO 클래스는 @Repository라는 어노테이션을 사용해 빈으로 등록한다.
@Repository
@Repository 어노테이션은 스테레오 타입(stereo type)의 일종이다.
스테레오 타입이라는 것은 빈을 등록하고 사용할 때 개발자가 내부적으로 의미 파악을 하기 쉽게 하기 위해서 사용하는 별칭이다.
package com.study.springboot.jdbc;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Repository;
@Repository
public class MyUserDAO {
@Autowired
private JdbcTemplate jdbcTemplate;
public List<MyUserDTO> list(){
String query = "select * from myuser";
List<MyUserDTO> list = jdbcTemplate.query(query,
new BeanPropertyRowMapper<MyUserDTO>(MyUserDTO.class));
// for(UserDto my : list) {
// System.out.println(my);
// }
return list;
}
}
리퀘스트 맵핑에서 사용하는 @Controller 어노테이션은 이 클래스를 빈으로 등록하는데 컨트롤러 용도로 사용하겠다는 의미를 갖는 것이고, 여기서 사용한 @Repository어노테이션은 이 클래스를 빈으로 등록하는데 데이터베이스와 관련된 처리 용도로 사용하겠다는 추가적인 의미를 부여하는 것으로 보면 된다.
스프링 내부적으로는 그냥 빈으로 등록된다.
@Autowired (자동 주입) 어노테이션을 사용했으므로 jdbcTemplate 변수에는 우리가 설정한 데이터베이스 정보를 바탕으로 드라이버를 로드하고 데이터 베이스 접속한 후에 커넥션 풀까지 생성한 정보가 들어오게 된다.
데이터베이스를 사용하기 위한 코드는
@Autowired private JdbcTemplate jdbcTemplate;
이 두줄이 전부이다.
jdbcTemplate 객체 변수의 query 메서드를 이용해서 바로 위에 만든 쿼리문을 실행한다.
SQL 쿼리의 결과를 ResultSet의 로우(Row)마다 DTO 객체로 받아서 전체를 리스트 데이터로 만든다.
package com.study.springboot;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import com.study.springboot.jdbc.MyUserDAO;
@Controller
public class MyController {
@Autowired
private MyUserDAO userDao;
@RequestMapping("/")
public @ResponseBody String root() throws Exception{
return "JdbcTemplate 사용하기";
}
//@GetMapping("/user")
@RequestMapping(value="/user", method = RequestMethod.GET)
public String userlistPage(Model model) {
model.addAttribute("users", userDao.list());
return "userList";
}
}
@Autowired로 지정하고 userDao 객체 변수를 만들었다.
이 프로젝트에서는 이 객체 변수에 들어올 수 있는 빈은 앞에서 @Repository로 등록한 빈, 한 가지밖에 없으니 여기서 자동 주입이 가능하다.
@RequestMaping
RequestMapping은 기존에는 url만 적어주었지만, 이번에는 호출방식까지 적어주었다.
기본은 Get방식인데 Post로 호출할 경우 여기서 지정하면 된다.
혹은 @GetMapping 어노테이션을 사용해도 된다.
RequestMethod는 enum(열거형)으로 등록되어 있다.
userDao 객체 변수의 list() 메서드를 호출하여 리스트형 데이터를 리턴받아 model 변수에 담아준다.
그리고 jsp 파일을 호출한다.
'Back-end' 카테고리의 다른 글
Spring 용어정리(3) (0) | 2021.08.16 |
---|---|
JSP 기초 (0) | 2021.08.14 |
Spring 용어정리 (1) (0) | 2021.08.10 |
Spring Concept (0) | 2021.08.09 |
서블릿(Servlet) (0) | 2021.08.08 |