5 minute read

★Spring MVC Project(using STS) sevlet-context.xml파일에 모든 spring설정(bean객체 등)을, web.xml파일에 서블릿 설정(컨트롤러 객체 등)을 pom.xml에 maven(dependency 등)설정을 넣는다.

매핑이 자동으로 되므로
개발자는 controller(.java)와 views(.jsp)만 구현하면 된다.

★참고로 아래 모든 소스는 springframework-version 4.1.0.RELEASE를 기준으로 함

★dependency 참조 https://mvnrepository.com/

★servlet-context.xml 자바 어노테이션 스프링에 적용하기 위해 설정한다.

<default-servlet-handler/>
	?

<resources mapping="/resources/**" location="/resources/theme/" />
	리소스의 실제주소(location)와 요청주소(mapping)를 매핑해준다
	위 처럼 설정해 두면 만약 /resources/image.png를 요청하면
	/resources/theme/image.png파일을 가리키게 된다.

<beans:bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
	<beans:property name ="prefix" value="/WEB-INF/views/" />
	<beans:property name="suffix" value=".jsp" />
</beans:bean>
	ViewResolver객체를 생성하고 설정한다. 여기서 prefix, suffix는
	컨트롤러의 리턴값 String의 앞뒤에 붙여져서 View로 사용된 jsp파일을
	명시하게 된다.

<context:component-scan base-package="com.dh.day08" />
	해당 패키지 아래의 어노테이션을 이용해 bean객체를 자동으로 만들어준다
	설정파일에 bean객체를 명시하지 않아도 됌

★web.xml DispatcherServlet을 로드할 때 init-param으로 contextConfigLocation이름으로 servlet-context.xml(스프링 설정파일)의 경로를 설정해준다. 그러면 해당 파일이 적용된다. 그리고 url-pattern을 “/”를 해줘서 모든 요청을 해당 dispatcher로 전달한다.

모든 요청에 대해 encoding을 UTF-8로 처리할 수 있도록 등록한다.
<filter>
	<filter-name>encodingFilter</filter-name>
	<filter-class>
		org.springframework.web.filter.CharacterEncodingFilter
	</filter-class>
	<init-param>
		<param-name>encoding</param-name>
		<param-value>UTF-8</param-value>
	</init-param>
</filter>

<filter-mapping>
	<filter-name>encodingFilter</filter-name>
	<url-pattern>/*</url-pattern>
</filter-mapping>

★기본 경로 프로젝트명 src main java resources webapp WEB-INF classes spring appServlet [servlet-context.xml] [root-context.xml] views [web.xml] [pom.xml]

★기본 Controller 설정 @Controller Class에 설정해주면 이 Class를 Controller로 사용한다는 의미 @RequestMapping(value=”…”, method=…) 요청(value)을 지정된 method(GET,POST…)로 받는다. @RequestParam(…) request의 요청값을 메소드의 파라메터로 자동 매칭해줌 ex) public String dummy(@RequestParam(value=”name”) String name) dummy메소드로 전달된 요청속의 파라메터 name의 값을 String타입의 name변수로 가져온다.

★원래는 스프링 설정파일에 bean객체로써 컨트롤러 객체를 생성해 줘야 했으나 STS로 만든 프로젝트는 덕분에 클래스에 @Controller만 붙여주면 알아서 생성해 준다.

★요청페이지 »»> Controller의 Method의 파라메터(요청값) 이동 방법 1. HttpServletRequest를 Method의 파라메터로 받는다. 2. @RequestParam(value=”agree”, defaultValue=”false”)Type name 을 Method의 파라메터로 받는다. 3. 커맨드객체를 이용한다(Best) 1. 커맨드객체로 사용할 DTO를 정의한다, 필드별로 setter가 있어야 한다. 2. jsp문서에서 요청파라메터의 name값을 위 DTO의 필드이름과 일치시키면 자동으로 setter메소드가 호출되며 DTO의 인스턴스에 설정된다. 3. Controller의 Method에서 위 DTO타입의 파라메터를 받도록 설정한다. 4. 결과적으로 getParameter(“name”)해서 setName()해주던 작업을 Spring에서 대신 해주는 결과가 된다. 단 DTO의 setter메소드명과 요청 parameter의 name값이 매칭되어야 한다. ※물론 어딘가에서 new키워드를 통해 인스턴스를 만들어서 setAttribute해야 사용할 수 있다. ※리스트의 경우는 파라메터 이름값을 “responses[0]”의 형식으로, 또다른 클래스의 인스턴스인 경우는 “res.location”, “인스턴스이름.인스턴스내부필드이름” 물론 전부 setter가 있어야 한다.

★Controller의 Method »»> View의 파라메터 이동 방법 1. Model을 이용한 경우 Method의 파라메터로 Model을 받도록 정의한 후 이 Model 객체에 attribute를 설정해 주면 그 값이 View에게 HttpServletRequest를 통해 전달 된다. 2. ModelAndView를 이용한 경우 Controller의 Method의 리턴타입을 ModelAndView로 한 후 Method내부에서 ModelAndView객체를 새로 만들고 addObject로 addtribute추가, setViewName으로 View이름 추가한 뒤 바로 리턴해준다. 1과 거의 비슷함 3. Controller에서 커맨드 객체를 이용한 경우 커맨드 객체의 클래스명의 첫 글자만 소문자로 바꾸면 View에서 커맨드객체를 참조하는 이름이 된다. 스프링MVC가 커맨드객체의 이름을 사용해서 뷰에 전달하기 때문이다. 이때 방법 1과 마찬가지로 Model객체에 넣게 된다. Controller에서 View에 커맨드 객체를 넘길 때 이름을 바꾸고 싶다면 파라메터 선언 부분의 커맨드객체 앞에 @ModelAttribute(“newDataName”)를 붙여주면 된다.

★컨트롤러의 메소드는 String값을 반환하는데, 이것은 jsp파일의 이름을 의미한다. servlet-context.xml에 설정된 ViewResolver객체의 prefix와 suffix값을 붙여서 AbsolutePath를 완성하게 된다. return 후 해당 경로로 포워딩

★리다이렉트 하려면 return “redirect:/절대경로”

★스프링에서 제공하는 form, input, password태그를 사용할 수도 있다. <%@ taglib prefix=”form” uri=”http://springframework.org/tags/form” %> 추가 요청->Controller->View까지 커맨드객체가 날라오므로 commandName으로 받아준 커맨드 객체의 필드값을 알아서 세팅하고, 다시 요청할때도 알아서 객체를 생성한다. 이 태그들은 커맨드객체가 존재함이 보장되어야 하므로 Controller에서 빈 객체를 만들어서 Model에 넣어주자

아무 기능없이 단지 url을 view로 연결하기만 하는 Controller 클래스의 무의미한 정의를 대신할 수 있다.

★Oracle DB를 사용하기 위한 dependency들 정리 org.springframework spring-jdbc ${org.springframework-version}

	<dependency>
		<groupId>com.mchange</groupId>
		<artifactId>c3p0</artifactId>
		<version>0.9.2.1</version>
	</dependency>
	
	<dependency>
		<groupId>commons-dbcp</groupId>
		<artifactId>commons-dbcp</artifactId>
		<version>1.4</version>
	</dependency>
	
	<dependency>
		<groupId>oracle</groupId>
		<artifactId>ojdbc6</artifactId>
		<version>11.2.0.3</version>
	</dependency>

★DB를 연결하기 위한 ConnectionPool를 사용하기 위해 c3p0 라이브러리를 사용한다. pom.xml에 다음 dependency를 추가 com.mchange c3p0 0.9.2.1

spring-member.xml에서 다음 bean객체를 등록한다.
<bean 
	id="dataSource"
	class="com.mchange.v2.c3p0.ComboPooledDataSource"
	destroy-method="close">
	<property name="driverClass" value="oracle.jdbc.driver.OracleDriver"/>
	<property name="jdbcUrl" value="jdbc:oracle:thin:@192.168.152.128:1521:orcl"/>
	<property name="user" value="c##dh"/>
	<property name="password" value="1234"/>
	<property name="maxPoolSize" value="100"/>
	<property name="maxIdleTime" value="600"/>
	<property name="idleConnectionTestPeriod" value="300"/>
</bean>
나중에 Dao객체에서 이 dataSource를 주입받아서
jdbcTemplete객체를 만드는데
이 jdbcTemplete객체로 데이터베이스를 조작한다.

★트랜잭션을 사용하기 위한 설정 spring-member.xml에

태그 안드로이드의 string.xml파일 처럼 문자열 리소스를 분리해서 하드코딩을 방지하고 효율적으로 관리할 수 있다.

1. label.properties에 "키워드=값" 형식으로 넣는다
2. bean객체를 설정해준다. 
	<beans:bean id="messageSource"
		class="org.springframework.context.support.ResourceBundleMessageSource">
		<beans:property name="basenames">
			<beans:list>
				<beans:value>message.label</beans:value>
			</beans:list>
		</beans:property>
		<beans:property name="defaultEncoding" value="UTF-8"/>
	</beans:bean>
	list태그의 message.label은 resources/message/label.property파일을
	가리키고, 그 이름을 basenames로 붙여준다. list태그에 value태그를 여러개 가능
	bean의 id는 무조건 messageSource로 해야함

3. jsp파일에서 태그 등록후 사용해준다.
	<%@ taglib prefix="spring" uri="http://www.springframework.org/tags"%>
	<spring:message code="키"/>로 사용

4. 파라메터값 사용 가능 
	키=<strong>{0}님</strong>회원 가입을 축하합니다{1}
	<spring:message code="키"  arguments="${data }", "${data2}"/>
	
5. 이 값들은 Locale에 상관없이 사용 가능한데, Locale을 적용시키려면
	ResourceBundleMessageSource클래스의 getMessage()메소드를 사용하면 된다.

★커맨드 객체의 값 검증하기 및 에러메시지 처리하기(입력값을 검증) 스프링에서는 다음 두 단계를 통해 입력값을 검증하고, 에러메시지를 처리할 수 있다. 1. 커맨드 객체 검증 및 결과를 에러코드로 저장 2. JSP파일에서 에러코드를 이용해 메시지 출력

★커맨드 객체의 값은 Validator, Errors인터페이스로 검증한다. 1. Validator의 support()에서는 검증할 수 있는 타입인지 확인 타입이 맞으면 return true, 아니면 false 2. validate()에서는 첫번째 파라메터로 받은 객체를 검증하고 결과를 Errors에 담는다. 만약 객체의 상태에 문제가 있다면 Errors의 rejectValue()로 에러코드 저장 ValidationUtils의 rejectIfEmptyOrWhitespace()로 공백을 쉽게 걸러낼 수 있음

★@RequestMapping을 적용한 메소드의 파라메터 선언부에서 커맨드 객체 바로 다음에 Errors객체를 받기로 선언할 수 있다. ex) public String doSomething(SomeType inst, Errors errors) {…} 그럼 자동으로 커맨드객체와 연결된 Errors객체를 생성한다. 해당 메소드 내부에서 Validator인터페이스의 validate()메소드를 실행하면 그 결과가 Errors객체에 저장된다. Errors.getFieldValue()로 커맨드 객체 없이도 특정 값을 가져올 수 있음

★커맨드 객체의 특정 값이 아닌 객체 자체를 검증할 때는 Errors.reject()메소드를 사용한다(Global Error Code)

★이렇게 만들어진 Errors객체는 Model과 함께 View로 보내진다. 는 해당 Errors객체가 가진 “속성이름”의 값을 키로 삼은 MessageResource의 값을 출력한다. MessageResource를 label.properties파일을 기반으로 만들었으니 해당 파일에 미리 지정을 해둬야 한다.

태그의 속성 element : 각 에러메시지를 출력할 때 사용한 HTML태그(기본span) delimeter : 각 에러메시지를 구분할 때 사용할 HTML태그(기본
)

★메시지 검색 규칙(참고) [일반적인 메시지] 1. 에러코드.커맨드객체이름.필드이름 2. 에러코드.필드이름 3. 에러코드.필드타입 4. 에러코드

[프로퍼티가 List일 때]
1. 에러코드.커맨드객체이름.필드이름[인덱스].중첩필드이름
2. 에러코드.커맨드객체이름.필드이름.중첩필드이름
3. 에러코드.필드이름[인덱스].중첩필드이름
4. 에러코드.필드이름.중첩필드이름
5. 에러코드.중첩필드이름
6. 에러코드.필드타입
7. 에러코드

[글로벌 에러코드]
1. 에러코드.커맨드객체이름
2. 에러코드

★컨트롤러에서 HttpSession사용법 컨트롤러의 메소드에서 파라메터로 HttpSession 또는 HttpServletRequest객체를 받는다.

★Interceptor인터페이스는 스프링에서 세가지 시점에 공통기능을 넣을수 있도록 해준다 1. 컨트롤러 실행 전 : preHandle() 2. 컨트롤러 실행 후 - 뷰 실행 전 : postHandle() 3. 뷰 실행 후 : afterCompletion() HandlerInterceptorAdapter클래스를 상속한 클래스를 만들어서 오버라이딩 하면 된다.

★스프링 설정파일에 Interceptor등록하기

: 인터셉터를 설정할 컨트롤러의 경로 : 제외할 경로

이 mapping속성의 **어쩌고 하는걸 Ant경로라고 한다.

  • : 0개 이상의 문자 ? : 문자 1개 ** : 0개 이상의 디렉토리 경로(/edit/**는 /edit/하위 모든 경로를 얘기함)

★쿠키 사용하기 @CookieValue(value=”REMEMBER”, required=false)Cookie cookie를 메소드의 파라메터로 받는다.

★쿠키 생성, 삭제하기 메소드에서 HttpServletResponse를 파라메터로 받은 뒤 생성, 삭제 해준다.

★스프링에서는 입력된 String값을 자동으로 커맨드객체의 프로퍼티 타입에 맞춰서 캐스팅 해주는데 Date는 자동으로 되지 않기때문에 메소드에 @DateTimeFormat(pattern=”…“)을 붙여줘야 한다. ex) @DateTimeFormat(pattern=”yyyyMMddHH”) private Date date; 입력값이 “2019062515”일때 2019년 6월 25일 15시로 캐스팅 된다. Date뿐만 아니라 Calendar와 LocalDateTime타입도 사용할 수 있다.

★Date타입 인스턴스를 jsp파일에서 사용하기 <%@ taglib prefix=”fmt” uri=”http://java.sun.com/jsp/jstl/fmt” %>를 추가해준 뒤 를 사용하면 mem.registerDate: Date객체의 값을 이 패턴으로 표현한다.

★try catch문을 대신해 @ExceptionHandler(처리할Exception클래스)를 메소드에 사용하면 해당 메소드가 소속 컨트롤러에서 발생한 오류처리를 대신 하게 된다.

★프로젝트 전역 오류처리 컨트롤러는 @ControllerAdvice(프로젝트명)을 컨트롤러에다 붙이고 @ExceptionHandler(처리할Exception클래스)로 Exception별로 처리하면 된다.

★@PathVariable을 메소드의 파라메터에 사용하면 요청url속의 요청값을 메소드 내부에서 변수로 사용할 수 있다 @RequestMapping(“/member/detail/{id}”) public String doSomething(@PathVariable(“id”)Long id) {…}

Categories:

Updated: