2014년 7월 13일 일요일
토비의 스프링3 용어정리
빈(bean) : 스프링이 제어권을 가지고 직접 만들고 관계를 부여하는 오브젝트
빈 팩토리(bean factory) : 빈의 생성과 관계설정 같은 제어를 담당하는 IoC 오브젝트
애플리케이션 컨텍스트(application context) : 빈 팩토리와 거의 동일하지만 넓은 의미.
@Configuration : 스프링이 오브젝트 설정을 담당하는 클래스라고 인식할 수 있는 애노테이션
@Bean : 오브젝트 생성을 담당하는 IoC용 메소드
JUnit용 테스트 컨텍스트 프레임워크 확장 클래스
public class EnumTest {
private enum ServiceName{
samsung
,apple;
}
public static void main(String[] args) {
printEnumTest("samsung");
}
public static void printEnumTest(String serviceName){
switch (ServiceName.valueOf(serviceName)){
case samsung:
System.out.println("samsung");
break;
case apple:
System.out.println("apple");
break;
}
}
}
2014년 5월 10일 토요일
4장 예외
4.1.2 예외의 종류와 특징
- Error : 애플리케이션 코드에서 catch할 수 없는 에러. 예를 들면, OutOfMemoryError, ThreadDeath.
- 체크예외 : 명시적인 처리가 필요한 예외. catch나 throw를 처리하지 않으면 컴파일에러가 발생한다.
- 언체크예외 : RuntimeException 클래스를 상속한 예외. 명시적인 예외처리를 강제하지 않기 때문에 언체크 예외라 불린다.
4.1.3 예외처리 방법
예외 복구
사용자에게 예외상황을 알리고 다른 방법을 안내해서 예외상황을 해결. 예를 들어, 네트워크가 불안해서 서버접속이 안되는 경우, 재시도를 통해서 예외를 복구할 수 있다.
예외처리 회피
throw를 통한 예외를 넘기는 행위. 근데 DAO단에서 catch한 뒤 throw를 하지 않은 상황에서 예외를 복구할 수 없는 경우는 어떻게 처리하지??? 결국 transaction을 처리하는 Controller단에서 rollback을 처리해야 하는 것 아닌가?
예외 전환
일반적으로 체크 예외를 계속 throws를 사용해 넘기는 건 무의미하다. 어차피 복구가 불가능한 예외라면 가능한 한 빨리 런타임 예외로 포장해 던지게 해서 다른 계층의 메서드를 작성할 때 불필요한 throws 선언이 들어가지 않도록 해줘야 한다.
대부분 서버환경에서는 애플리케이션 코드에서 처리하지 않고 전달된 예외들을 일괄적으로 다룰 수 있는 기능을 제공한다. 어차피 복구하지 못할 예외라면 애플리케이션코드에서는 런타임 예외로 포장해서 던져버리고, 예외처리 서비스 등을 이용해 자세한 로그를 남기고, 관리자에게는 메일 등으로 통보해주고, 사용자에게는 친절한 안내 메시지를 보여주는 식으로 처리하는 게 바람직히다.
4.1.4 예외처리 전략
런타임 예외의 보편화
예외처리를 강제하는 것은 예외가 발생할 가능성이 있는 API메서드를 사용하는 개발자의 실수를 방지하기 위한 배려라고 볼 수도 있겠지만, 실제로는 예외를 제대로 다루고 싶지 않을 만큼 짜증나게 만드는 원인이 되기도 한다.
자바가 처음 만들어질 때 많이 사용되던 애플릿이나 AWT, 스윙을 사용한 독립형 애플리케이션에서는 통제 불가능한 시스템 예외라고 할지라도 애플리케이션의 작업이 중단되지 않게 해주고 상황을 복구해야 했다. 예를 들어 워드의 파일 열기 기능에서 사용자가 입력한 이름에 해당하는 파일을 찾을 수 없다고 애플리케이션이 종료돼버리게 할 수는 없다.
하지만 자바 엔터프라이즈 서버환경은 다르다. 수많은 사용자가 동시에 요청을 보내고 각 요청이 독립적인 작업으로 취급된다. 하나의 요청을 처리하는 중에 예외가 발생하면 해당 작업만 중단시키면 그만이다. 독립형 애플리케이션과 달리 서버의 특정 계층에서 예외가 발생했을 때 작업을 일시 중지하고 사용자와 바로 커뮤니케이션하면서 예외상황을 복구할 수 있는 방법이 없다.
자바의 환경이 서버로 이동하면서 체크 예외의 활용도와 가치는 점점 떨어지고 있다. 자칫하면 throws Exception으로 점철된 아무런 의미도 없는 메서드들을 낳을 뿐이다. 그래서 대응이 불가능한 체크 예외라면 빨리 런타임 예외로 전환해서 던지는 게 낫다.
- Error : 애플리케이션 코드에서 catch할 수 없는 에러. 예를 들면, OutOfMemoryError, ThreadDeath.
- 체크예외 : 명시적인 처리가 필요한 예외. catch나 throw를 처리하지 않으면 컴파일에러가 발생한다.
- 언체크예외 : RuntimeException 클래스를 상속한 예외. 명시적인 예외처리를 강제하지 않기 때문에 언체크 예외라 불린다.
4.1.3 예외처리 방법
예외 복구
사용자에게 예외상황을 알리고 다른 방법을 안내해서 예외상황을 해결. 예를 들어, 네트워크가 불안해서 서버접속이 안되는 경우, 재시도를 통해서 예외를 복구할 수 있다.
예외처리 회피
throw를 통한 예외를 넘기는 행위. 근데 DAO단에서 catch한 뒤 throw를 하지 않은 상황에서 예외를 복구할 수 없는 경우는 어떻게 처리하지??? 결국 transaction을 처리하는 Controller단에서 rollback을 처리해야 하는 것 아닌가?
예외 전환
일반적으로 체크 예외를 계속 throws를 사용해 넘기는 건 무의미하다. 어차피 복구가 불가능한 예외라면 가능한 한 빨리 런타임 예외로 포장해 던지게 해서 다른 계층의 메서드를 작성할 때 불필요한 throws 선언이 들어가지 않도록 해줘야 한다.
대부분 서버환경에서는 애플리케이션 코드에서 처리하지 않고 전달된 예외들을 일괄적으로 다룰 수 있는 기능을 제공한다. 어차피 복구하지 못할 예외라면 애플리케이션코드에서는 런타임 예외로 포장해서 던져버리고, 예외처리 서비스 등을 이용해 자세한 로그를 남기고, 관리자에게는 메일 등으로 통보해주고, 사용자에게는 친절한 안내 메시지를 보여주는 식으로 처리하는 게 바람직히다.
4.1.4 예외처리 전략
런타임 예외의 보편화
예외처리를 강제하는 것은 예외가 발생할 가능성이 있는 API메서드를 사용하는 개발자의 실수를 방지하기 위한 배려라고 볼 수도 있겠지만, 실제로는 예외를 제대로 다루고 싶지 않을 만큼 짜증나게 만드는 원인이 되기도 한다.
자바가 처음 만들어질 때 많이 사용되던 애플릿이나 AWT, 스윙을 사용한 독립형 애플리케이션에서는 통제 불가능한 시스템 예외라고 할지라도 애플리케이션의 작업이 중단되지 않게 해주고 상황을 복구해야 했다. 예를 들어 워드의 파일 열기 기능에서 사용자가 입력한 이름에 해당하는 파일을 찾을 수 없다고 애플리케이션이 종료돼버리게 할 수는 없다.
하지만 자바 엔터프라이즈 서버환경은 다르다. 수많은 사용자가 동시에 요청을 보내고 각 요청이 독립적인 작업으로 취급된다. 하나의 요청을 처리하는 중에 예외가 발생하면 해당 작업만 중단시키면 그만이다. 독립형 애플리케이션과 달리 서버의 특정 계층에서 예외가 발생했을 때 작업을 일시 중지하고 사용자와 바로 커뮤니케이션하면서 예외상황을 복구할 수 있는 방법이 없다.
자바의 환경이 서버로 이동하면서 체크 예외의 활용도와 가치는 점점 떨어지고 있다. 자칫하면 throws Exception으로 점철된 아무런 의미도 없는 메서드들을 낳을 뿐이다. 그래서 대응이 불가능한 체크 예외라면 빨리 런타임 예외로 전환해서 던지는 게 낫다.
public class DuplicateUserIdException extends RuntimeException {
public DuplicateUserIdException(Throwable cause) {
super(cause);
}
}
public void add() throws DuplicateUserIdException{
try{
// JDBC를 이용해 user 정보를 DB에 추가하는 코드 또는
// 그런 기능이 있는 다른 SQLException을 던지는 메서드를 호출하는 코드
}catch(SQLException e){
if(e.getErrorCode() == MysqlErrorNumbers.ER_DUP_ENTRY)
throw new DuplicateUserIdException(e); //예외 전환
else throw new RuntimeException(e); //예외 포장
}
}
2014년 5월 3일 토요일
3장 템플릿/콜백
중첩 클래스의 종류
다른 클래스 내부에 정의되는 클래스를 중첩 클래스(nested class)라고 한다. 중첩 클래스는 독립적으로 오브젝트로 만들어질 수 있는 스태틱 클래스(static class)와 자신이 정의된 클래스의 오브젝트 안에서만 만들어질 수 있는 내부 클래스(inner class)로 구분된다.
내부 클래스는 다시 범위(scope)에 따라 세 가지로 구분된다. 멤버 필드처럼 오브젝트 레벨에 정의되는 멤버 내부 클래스와 메서드 레벨에 정의되는 로컬 클래스, 그리고 이름을 갖지 않는 익명 내부 클래스다. 익명 내부 클래스의 범위는 선언된 위치에 따라서 다르다.
익명 내부클래스
익명 내부 클래스(anonymous inner class)는 이름을 갖지 않는 클래스다. 클래스 선언과 오브젝트 생성이 결합된 형태로 만들어지면, 상속할 클래스나 구현할 인터페이스를 생성자 대신 사용해서 다음과 같은 형태로 만들어 사용한다. 클래스를 재사용할 필요가 없고, 구현한 인터페이스 타입으로만 사용할 경우에 유용하다.
익명 내부클래스를 이용한 UserDao의 개선
...
전략 패턴의 구조로 보자면 UserDao의 메서드가 클라이언트이고, 익명 내부클래스로 만들어지는 것이 개별적인 전략이고, jdbcContextWithStatementStrategy() 메서드는 컨텍스트다.
템플릿/콜백의 동작원리
템플릿은 고정된 작업 흐름을 가진 코드를 재사용한다는 의미에서 붙인 이름이다. 콜백은 템플릿 안에서 호출되는 것을 목적으로 만들어진 오브젝트를 말한다.
템플릿/콜백의 응용
고정된 작업 흐름을 갖고 있으면서 여기저기서 자주 반복되는 코드가 있다면, 중복되는 코드를 분리할 방법을 생각해보는 습관을 기르자. 중복된 코드는 먼저 메서드로 분리하는 간단한 시도를 해본다. 그중 일부 작업을 필요에 따라 바꾸어 사용해야 한다면 인터페이스를 사이에 두고 분리해서 전략 패턴을 적용하고 DI로 의존관계를 관리하도록 만든다. 그런데 바뀌는 부분이 한 애플리케이션 안에서 동시에 여러 종류가 만들어질 수 있다면 이번엔 템플릿/콜백 패턴을 적용하는 것을 고려해볼 수 있다.
다른 클래스 내부에 정의되는 클래스를 중첩 클래스(nested class)라고 한다. 중첩 클래스는 독립적으로 오브젝트로 만들어질 수 있는 스태틱 클래스(static class)와 자신이 정의된 클래스의 오브젝트 안에서만 만들어질 수 있는 내부 클래스(inner class)로 구분된다.
내부 클래스는 다시 범위(scope)에 따라 세 가지로 구분된다. 멤버 필드처럼 오브젝트 레벨에 정의되는 멤버 내부 클래스와 메서드 레벨에 정의되는 로컬 클래스, 그리고 이름을 갖지 않는 익명 내부 클래스다. 익명 내부 클래스의 범위는 선언된 위치에 따라서 다르다.
익명 내부클래스
익명 내부 클래스(anonymous inner class)는 이름을 갖지 않는 클래스다. 클래스 선언과 오브젝트 생성이 결합된 형태로 만들어지면, 상속할 클래스나 구현할 인터페이스를 생성자 대신 사용해서 다음과 같은 형태로 만들어 사용한다. 클래스를 재사용할 필요가 없고, 구현한 인터페이스 타입으로만 사용할 경우에 유용하다.
익명 내부클래스를 이용한 UserDao의 개선
...
전략 패턴의 구조로 보자면 UserDao의 메서드가 클라이언트이고, 익명 내부클래스로 만들어지는 것이 개별적인 전략이고, jdbcContextWithStatementStrategy() 메서드는 컨텍스트다.
템플릿/콜백의 동작원리
템플릿은 고정된 작업 흐름을 가진 코드를 재사용한다는 의미에서 붙인 이름이다. 콜백은 템플릿 안에서 호출되는 것을 목적으로 만들어진 오브젝트를 말한다.
템플릿/콜백의 응용
고정된 작업 흐름을 갖고 있으면서 여기저기서 자주 반복되는 코드가 있다면, 중복되는 코드를 분리할 방법을 생각해보는 습관을 기르자. 중복된 코드는 먼저 메서드로 분리하는 간단한 시도를 해본다. 그중 일부 작업을 필요에 따라 바꾸어 사용해야 한다면 인터페이스를 사이에 두고 분리해서 전략 패턴을 적용하고 DI로 의존관계를 관리하도록 만든다. 그런데 바뀌는 부분이 한 애플리케이션 안에서 동시에 여러 종류가 만들어질 수 있다면 이번엔 템플릿/콜백 패턴을 적용하는 것을 고려해볼 수 있다.
DirtiesContext어노테이션
Junit의 테스트 컨텍스트는 DirtiesContext어노테이션이 붙은 테스트 클래스에는 애플리케이션 컨텍스트 공유를 허용하지 않는다. 테스트 메소드를 수행하고 나면 매번 새로운 애플리케이션 컨텍스트를 만들어서 다음 테스트가 사용하게 해준다.
JUnit 테스트 오브젝트 학습테스트
학습 테스트
- JUnit 테스트 오브젝트 테스트(JUnit은 테스트 메소드를 수행할 때마다 새로운 오브젝트를 만드는지 확인하는 테스트)
먼저 스태틱 변수로 테스트 오브젝트를 저장할 수 있는 컬렉션을 만들어둔다. 테스트마다 현재 테스트 오브젝트가 컬렉션에 이미 등록되어 있는지 확인하고, 없으면 자기자신을 추가한다.
- JUnit 테스트 오브젝트 테스트(JUnit은 테스트 메소드를 수행할 때마다 새로운 오브젝트를 만드는지 확인하는 테스트)
먼저 스태틱 변수로 테스트 오브젝트를 저장할 수 있는 컬렉션을 만들어둔다. 테스트마다 현재 테스트 오브젝트가 컬렉션에 이미 등록되어 있는지 확인하고, 없으면 자기자신을 추가한다.
public class JUnitTest {
static Set<JUnitTest> testObjects = new HashSet<JUnitTest>();
@Test
public void test1(){
assertThat(testObjects, not(hasItem(this)));
testObjects.add(this);
}
@Test
public void test2(){
assertThat(testObjects, not(hasItem(this)));
testObjects.add(this);
}
@Test
public void test3(){
assertThat(testObjects, not(hasItem(this)));
testObjects.add(this);
}
}
2014년 4월 30일 수요일
JUnit용 테스트 컨텍스트 프레임워크 확장 클래스
@RunWith : JUnit 프레임워크의 테스트 실행 방법을 확장할 때 사용하는 애노테이션
SpringJUnit4ClassRunner라는 JUnit용 테스트 컨텍스트 프레임워크 확장 클래스를 지정해주면 JUnit이 테스트를 진행하는 중에 테스트가 사용할 애플리케이션 컨텍스트를 만들고 관리하는 작업을 진행해준다.
@ContextConfiguration은 자동으로 만들어줄 애플리케이션 컨텍스트의 설정파일 위치를 지정한 것
SpringJUnit4ClassRunner라는 JUnit용 테스트 컨텍스트 프레임워크 확장 클래스를 지정해주면 JUnit이 테스트를 진행하는 중에 테스트가 사용할 애플리케이션 컨텍스트를 만들고 관리하는 작업을 진행해준다.
@ContextConfiguration은 자동으로 만들어줄 애플리케이션 컨텍스트의 설정파일 위치를 지정한 것
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations="/resource/applicationContext.xml")
public class UserDaoTest {
@Autowired
private ApplicationContext context;
private UserDao dao;
@Before
public void setUp(){
/**
* fixture : Object or Information for executing test
* Here fixture is UserDao
*/
this.dao = this.context.getBean("userDao", UserDao.class);
...
}
}
2014년 4월 17일 목요일
토비의 스프링 3 용어정리
빈(bean) : 스프링이 제어권을 가지고 직접 만들고 관계를 부여하는 오브젝트, 스프링이 직접 그 생성과 제어를 담당하는 오브젝트
빈 팩토리(bean factory) : 빈을 등록, 생성, 조회하고 돌려주고, 빈을 관리. 보통은 이를 바로 사용하지 않고 이를 확장한 애플리케이션 컨텍스트를 이용한다.
애플리케이션 컨텍스트(application context) : 빈 팩토리와 거의 동일하지만 넓은 의미.
@Configuration : 스프링이 오브젝트 설정을 담당하는 클래스라고 인식할 수 있는 애노테이션
@Bean : 오브젝트 생성을 담당하는 IoC용 메소드
IoC 컨테이너 : 빈 팩토리를 지칭.
컨테이너 : 애플리케이션 컨텍스트를 지칭.
싱글톤레지스트리(SingletonRegistry) : 스프링은 고전적인 싱글톤 패턴을 대신해서 싱글톤을 만들고 관리해주는 싱글톤 레지스트리.
빈 팩토리(bean factory) : 빈을 등록, 생성, 조회하고 돌려주고, 빈을 관리. 보통은 이를 바로 사용하지 않고 이를 확장한 애플리케이션 컨텍스트를 이용한다.
애플리케이션 컨텍스트(application context) : 빈 팩토리와 거의 동일하지만 넓은 의미.
@Configuration : 스프링이 오브젝트 설정을 담당하는 클래스라고 인식할 수 있는 애노테이션
@Bean : 오브젝트 생성을 담당하는 IoC용 메소드
IoC 컨테이너 : 빈 팩토리를 지칭.
컨테이너 : 애플리케이션 컨텍스트를 지칭.
싱글톤레지스트리(SingletonRegistry) : 스프링은 고전적인 싱글톤 패턴을 대신해서 싱글톤을 만들고 관리해주는 싱글톤 레지스트리.
2013년 1월 30일 수요일
DataAccessException API
'쉽게 따라하는 자바 웹개발'에서 SqlMapClient만을 사용해서 코딩하면 나타나는 불편함 중에서 SQLException에 관한 부분이 있다. 그것과 관련한 API인데 해석을 해보니 영 이해가 안된다. 향후 편집이 필요하다.
org.springframework.dao
책 'ExpertOne-On-One J2EE Design and Development' 에서 논의된 데이터접근 예외에 대한 계층의 근원. 책의 9장에 나와있는 이 패키지에 대한 모티브와 관련한 상세한 논쟁을 살펴보길 권한다.
This exception hierarchy aims to let user code find and handle the kind of error encountered without knowing the details of the particular data access API in use (e.g. JDBC). Thus it is possible to react to an optimistic locking failure without knowing that JDBC is being used.
As this class is a runtime exception, there is no need for user code to catch it or subclasses if any error is to be considered fatal (the usual case).
이 예외 계층은 사용자가 코드를 찾도록 그리고 특정 데이터접근 API의 상세정보를 모를 때 맞딱드리는 것과 같은 종류의 에러를 다룰 수 있도록 지원한다. 그래서 사용되는 JDBC에 대한 인지없이 낙관적인 잠금 실패에 반응하는게 가능하다.
이 클래스는 런타임 예외이기때문에, 만일 어떤 에러라도 치명적(일반적인 경우)으로 간주된다면, 에러나 하위 클래스를 잡기위해 사용자가 코딩할 필요가 없다.
org.springframework.dao
Class DataAccessException
java.lang.Objectjava.lang.Throwable
java.lang.Exception
java.lang.RuntimeException
org.springframework.core.NestedRuntimeException
org.springframework.dao.DataAccessException
- All Implemented Interfaces:
- Serializable
- Direct Known Subclasses:
- CleanupFailureDataAccessException, ConcurrencyFailureException, DataAccessResourceFailureException, DataIntegrityViolationException,DataRetrievalFailureException, InvalidDataAccessApiUsageException, InvalidDataAccessResourceUsageException, UncategorizedDataAccessException
public abstract class DataAccessException
- extends NestedRuntimeException
책 'ExpertOne-On-One J2EE Design and Development' 에서 논의된 데이터접근 예외에 대한 계층의 근원. 책의 9장에 나와있는 이 패키지에 대한 모티브와 관련한 상세한 논쟁을 살펴보길 권한다.
This exception hierarchy aims to let user code find and handle the kind of error encountered without knowing the details of the particular data access API in use (e.g. JDBC). Thus it is possible to react to an optimistic locking failure without knowing that JDBC is being used.
As this class is a runtime exception, there is no need for user code to catch it or subclasses if any error is to be considered fatal (the usual case).
이 예외 계층은 사용자가 코드를 찾도록 그리고 특정 데이터접근 API의 상세정보를 모를 때 맞딱드리는 것과 같은 종류의 에러를 다룰 수 있도록 지원한다. 그래서 사용되는 JDBC에 대한 인지없이 낙관적인 잠금 실패에 반응하는게 가능하다.
이 클래스는 런타임 예외이기때문에, 만일 어떤 에러라도 치명적(일반적인 경우)으로 간주된다면, 에러나 하위 클래스를 잡기위해 사용자가 코딩할 필요가 없다.
- Author:
- Rod Johnson
- See Also:
- Serialized Form
@SessionAttribute
@SessionAttribute관련하여 구글링하여 들어간 어느 블로그에 OLC(Open software Learning Cummunity)이 소개되어 있서 거기에 가입하고, 백기선, 이일민씨 등 프레임워크 구루의 강의가 있어 다 들었다. 후에 이들이 전자전부프레임워크 커뮤니티의 커미터라는 얘기에 또 거기 뒤적거리다가 해당 블로그로 돌아왔다. 하여간 관심사가 많은 것도 문제다. 또 여러 개발관련 커뮤니티를 돌아본 뒤 느낀건 나에겐 그런 다양하고 방대한 내용의 개발지식을 다 소화할 수 있는 열정과 능력이 있나. 없다면 유능한 개발자가 될 수 있을까라는 회의가 든다.
'쉽게 따라하는 자바 웹개발'의 p.138을 정리하면, @SessionAttributes의 정의를 이렇게 내릴 수 있다. 빈에서 @SessionAttributes("애트리뷰트명")로 선언하면, 해당 애트리뷰트명으로 Model에 어떤 값이 들어가면 그 값(객체)을 세션에 담아둔다. 언제까지? 그 세션에 담아둔 객체를 비울 때 (complete)때까지.
아래는 스프링 reference에 있는 @SessionAttributes 정의다.
15.3.2.9 Specifying attributes to store in a session with
@SessionAttributes 애노테이션은 하나의 특정 핸들러에 의해 사용되는 세션 어트리뷰트를 선언한다. 이것은 일반적으로 모델 애트리뷰트 또는 모델 애트리뷰트 타입의 이름이다. 그 애트리뷰트는 세션이나 conversational한 저장소에 유연하게 저장된다. 그리고 그 애트리뷰트는 이후 요청들간에 form-backing 빈으로 작동한다.
다음의 코드정보는 이 애노테이션의 사용이 모델 애트리뷰트명을 지칭하는 것을 보여준다.
'쉽게 따라하는 자바 웹개발'의 p.138을 정리하면, @SessionAttributes의 정의를 이렇게 내릴 수 있다. 빈에서 @SessionAttributes("애트리뷰트명")로 선언하면, 해당 애트리뷰트명으로 Model에 어떤 값이 들어가면 그 값(객체)을 세션에 담아둔다. 언제까지? 그 세션에 담아둔 객체를 비울 때 (complete)때까지.
아래는 스프링 reference에 있는 @SessionAttributes 정의다.
15.3.2.9 Specifying attributes to store in a session with @SessionAttributes
The type-level
@SessionAttributes annotation declares session attributes used by a specific handler. This will typically list the names of model attributes or types of model attributes which should be transparently stored in the session or some conversational storage, serving as form-backing beans between subsequent requests.
The following code snippet shows the usage of this annotation, specifying the model attribute name:
다음의 코드정보는 이 애노테이션의 사용이 모델 애트리뷰트명을 지칭하는 것을 보여준다.
@Controller @RequestMapping("/editPet.do") @SessionAttributes("pet") public class EditPetForm { // ... }
| Note | |
|---|---|
When using controller interfaces (e.g. for AOP proxying), make sure to consistently put all your mapping annotations - such as
@RequestMapping and @SessionAttributes - on the controller interface rather than on the implementation class. |
피드 구독하기:
글
(
Atom
)