Spring 면접&질문 JAVA
스프링 프레임워크
📖 DI(Dependency Injection)
구성요소간의 의존 관계가 소스코드 내부가 아닌 외부의 설정파일 등을 통해 정의하는 것입니다.
과거와 현재의 객체 개념
- 배터리 일체형 : 배터리가 떨어지면 장난감을 새로 구입하는 것은 문제가 발생했을 때 전체를 교체하는 것과 같으므로 유연성이 떨어집니다.
// 일체형 : 생성자에서 객체 주입
public class ElectronicCarToy{
private Battery battery;
public ElectronicCarToy(){
battery = new NormalBatter();
}
}
- 배터리 분리형 : 배터리가 떨어지면 배터리만 교체하는 것은 필요한 부분만 수정이 가능다는 것이므로 재사용성, 이식성, 유연성이 증가됩니다.
// 분리형 1 : setter를 이용한 객체 주입
public class ElectronicRobotToy{
private Battery battery;
public ElectronicRobotToy(){
}
public void setBattery(Battery battery){
this.battery = battery;
}
}
// 분리형 2 : 생성자, setter를 이용한 객체 주입
public class ElectronicRadioToy{
private Battery battery;
public ElectronicRadioToy(Battery battery){
this.battery = battery;
}
public void setBattery(Battery battery){
this.battery = battery;
}
}
따라서 가장 유연한 코드는 생성자, setter를 이용해 객체를 분리하는 분리형 2입니다.
- 배터리를 필요로하는 장난감은 배터리에 의존적이므로, 배터리를 분리하여 개발 후 의존성을 주입합니다.
스프링의 의존 객체 주입방법
- 생성자를 이용한 의존 객체 주입
- service 클래스 생성(java)
public StudentRegisterService(StudentDao studentDao){
this.studentDao = studentDao;
}
-bean 추가(xml)
<bean id="studentDao" class="day1.ems.member.dao.StudentDao" ></bean>
<bean id="registerService" class="day1.ems.member.service.StudentRegisterService">
<!-- // 생성자 파라미터는 studentDao를 참조하라 -->
<constructor-arg ref="studentDao" ></constructor-arg>
</bean>
-선언 방식
private StudentDao studentDao;
private StudentRegisterService registerService = new StudentRegisterService(studentDao);
setter를 이용한 의존 객체 주입
- setter 선언(java)
public void setJdbcUrl(String jdbcUrl){
this.jdbcUrl = jdbcUrl;
}
-bean 추가(xml)
<bean id="dataBaseConnectionInfoDev" class="day1.ems.member.DataBaseConnectionInfo">
<!-- // set을 없애고 그 뒤에오는 대문자를 소문자로 변경하면 프로퍼티의 이름이 됨 -->
<property name="jdbcUrl" value="jdbc:oracle:thin:@localhost:1521:xe" />
<property name="userId" value="scott" />
<property name="userPw" value="tiger" />
</bean>
- List 타입 의존 객체 주입
- setter 선언(java)
public void setDevelopers(List<String> developers){
this.developers = developers;
}
- property 선언(xml)
<property name="developers">
<list>
<value>Cheney.</value>
<value>Eloy.</value>
<value>Jasper.</value>
<value>Dillon.</value>
<value>Kian.</value>
</list>
</property>
- Map 타입 의존 객체 주입
* setter 선언
public void setAdministrators(Map<String, String> administrators){
this.administrators = administrators;
}
- propery 선언
<property name="administrators">
<map>
<entry>
<key>
<value>Cheney</value>
</key>
<value>[email protected]</value>
</entry>
<entry>
<key>
<value>Jasper</value>
</key>
<value>[email protected]</value>
</entry>
</map>
</property>
의존 객체 자동 주입
스프링 설정 파일에서 의존 객체를 주입할 때 또는 태그로 의존 대상 객체를 명시하지 않아도 스프링 컨테이너가 자동으로 필요한 의존 대상 객체를 찾아서 의존 대상 객체가 필요한 객체에 주입해 주는 기능입니다.
- 기존 스프링 컨테이너 설정 (의존 객체를 수동으로 주입)
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="wordDao" class="day2.com.word.dao.WordDao" />
<bean id="registerService" class="day2.com.word.service.WordRegisterService">
<constructor-arg ref="wordDao" />
</bean>
<bean id="searchService" class="day2.com.word.service.WordSearchService">
<constructor-arg ref="wordDao" />
</bean>
</beans>
- 의존 객체 자동 주입 스프링 컨테이너 설정
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans <!-- 추가 -->"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
<!-- 추가 -->
http://www.springframework.org/schema/context
<!-- 추가 -->
http://www.springframework.org/schema/context/spring-context.xsd">
<!-- 추가 -->
<context:annotation-config />
<bean id="wordDao" class="day2.com.word.dao.WordDao" >
<!-- <qualifier value="usedDao"/> -->
</bean>
<bean id="wordDao2" class="day2.com.word.dao.WordDao" />
<bean id="wordDao3" class="day2.com.word.dao.WordDao" />
<bean id="registerService" class="day2.com.word.service.WordRegisterServiceUseAutowired" />
<bean id="searchService" class="day2.com.word.service.WordSearchServiceUseAutowired" />
</beans>
- @Autowired : 주입하려고 하는 객체의 타입이 일치하는 객체를 자동으로 주입합니다.
- 프로퍼티, 생성자, 메소드에 전부 사용할 수 있습니다.
- 스프링 컨테이너에서 @Autowired에 접근하면 어노테이션을 적용한 객체의 데이터 타입을 가진 빈 객체를 찾아 알맞은 데이터를 주입합니다.
- @Resources
- 주입하려고 하는 객체의 이름이 일치하는 객체를 자동으로 주입하므로 프로퍼티, 메소드에만 사용하고 생성자에는 사용할 수 없습니다.
- @Autowired와 거의 동일하나 일치하는 타입이 아닌 일치하는 이름을 찾는다는 것을 확실히 구분해야 합니다.
의존 객체 선택
동일한 타입의 빈 객체가 여러 개 있을 때 @Autowired는 무엇에 의존성을 주입해야하는지 헷갈릴 수 있습니다.
동일한 객체가 2개 이상인 경우 스프링 컨테이너는 자동 주입 대상 객체를 판단하지 못하고 Exception을 발생시키므로 개발자가 의존 객체를 선택할 수 있는 방법을 제시할 수 있어야 합니다.
@Autowired
: 같은 WordDao 객체지만 @Qualifier(우선통과자)를 사용해 의존 객체 선택- 스프링 설정 파일(xml)
<bean id="wordDao" class="day2.com.word.dao.WordDao" >
<qualifier value="usedDao"/>
</bean>
<bean id="wordDao2" class="day2.com.word.dao.WordDao" />
<bean id="wordDao3" class="day2.com.word.dao.WordDao" />
- 의존성을 주입 받을 파일(java)
@Autowired
@Qualifier("usedDao")
private WordDao wordDao;
@Inject
- 스프링 설정 파일(xml)
<bean id="wordDao1" class="day2.com.word.dao.WordDao" />
<bean id="wordDao2" class="day2.com.word.dao.WordDao" />
<bean id="wordDao3" class="day2.com.word.dao.WordDao" />
- 의존성을 주입 받을 파일(java)
@Inject
@Named(value = "wordDao1")
private WordDao wordDao;
의존 객체 자동 주입 체크
의존 객체가 스프링 컨테이너에서 생성되지 않은 경우, @Autowired 어노테이션을 붙이면 Exception이 발생합니다.
@Autowired(requier=false)를 적용하면 의존 객체 자동 주입을 하지 않겠다는 기능이 활성화됩니다. 그러나 어떤 개발자도 빈 객체를 생성하지 않고 객체 주입을 하지 않으므로 이런 기능이 있다는 것만 알아두세요.
@Autowired와 거의 비슷하게 @Inject 어노테이션을 이용해 의존 객체를 자동으로 주입할 수 있습니다. 차이점이라면 @Autowired는 required 속성으로 의존 대상 객체가 없어도 Exception을 피할 수 있지만, @Inject는 required 속성을 지원하지 않습니다.
📖 생명주기(Life Cycle)
스프링 컨테이너의 생명주기
GenericXmlApplicationContext를 이용한 스프링 컨테이너 초기화(생성), getBean()을 이용한 빈(Bean) 객체 이용, close()를 이용한 스프링 컨테이너 종료가 있습니다.
빈(Bean) 객체의 생명주기는 스프링 컨테이너의 생명주기와 같습니다. 아래를 살펴볼까요?
-
스프링 컨테이너 초기화 : 빈(Bean) 객체 생성 및 주입
- 빈 객체 생성시점에 호출 : afterPropertiesSet(InitializingBean 인터페이스에서 구현)
-
스프링 컨테이너 종료 : 빈(Bean) 객체 소멸
- 빈 객체 소멸시점에 호출 : destory(DiposableBean 인터페이스에서 구현)
init-method, destroy-method 속성
빈 객체 선언시 init-method, destory-method 속성을 적용해 생성/소멸 단계를 제어합니다.
지정한 이름과 동일한 메소드를 의존객체 주입한 대상 내부에 메소드로 구현되며 생성/소멸 시 자동으로 호출됩니다.
- 스프링 설정 (xml, java)
<bean id="bookRegisterService" class="day3.com.brms.book.service.BookRegisterService"
init-method="initMethod" destroy-method="destroyMethod"/>
public void initMethod() {
System.out.println("BookRegisterService 빈(Bean)객체 생성 단계");
}
public void destroyMethod() {
System.out.println("BookRegisterService 빈(Bean)객체 소멸 단계");
}
어노테이션을 이용한 스프링 설정
기존 스프링 설정을 .xml 파일로 설정했다면 이제 .java 파일로 설정합니다.
즉, applicationContext.xml을 어노테이션을 활용한 config.java 파일로 대체하는 것이죠. @Configuration 어노테이션으로 설정 파일임을 알리고, @Bean 어노테이션으로 빈 객체를 생성한다고 알립니다.
java 파일로 스프링 설정 분리
*.xml
파일을 분리하여 유지하듯 *.java
파일도 동일하게 분리하여 관리할 수 있습니다.
이는 설정 파일의 내부 코드가 길어지면 직관성이 떨어지고 유지보수에 어려움이 생길 수 있기 때문입니다. 따라서 마음대로 분리해도 상관 없으나, 분류를 나누어 분리하는 것이 좋습니다.
@Import
어노테이션을 이용한 스프링 설정(java) 파일 읽기
// 변경 전
AnnotationConfigApplicationContext ctx
= new AnnotationConfigApplicationContext(MemberConfig1.class,
MemberConfig2.class, MemberConfig3.class);
// 변경 후
@Configuration
@Import({ MemberConfig2.class, MemberConfig3.class})
public class MemberConfig1 {
.........
}
📖 웹 프로그래밍 설계 모델
웹 프로그래밍을 구축하기 위한 설계 모델
-
Model1 : 브라우저(클라이언트) | WAS(JSP ↔ Service & DAO) | 데이터베이스
-
처리과정
-
클라이언트가 WAS(이하 서버)로 요청을 하면 내부에서 작업을 하면서 데이버테이스에 접근해 데이터를 가져옵니다(내부 로직 처리).
-
가져온 데이터로를 UI 작업을 통해 클라이언트에게 응답합니다(HTML 코드로 반환).
-
WAS에서 사용자로부터 받은 요청을 받은 기능(Service)과 데이터베이스와 연결짓는 기능(DAO), 요청받은 내용을 응답하는 기능(JSP)을 통합하여 하나의 파일로 관리합니다.
-
-
장점
- 단순한 흐름으로 개발에 빠릅니다.
- 초보자도 쉽게 적용할 수 있습니다.
- 작은 프로젝트에 적합합니다.
-
단점
- 여러가지 언어를 하나의 문서에 작성하여 유지보수가 어렵습니다.
-
-
Model2 : Model1의 단점을 보완하기 위해 등장, 브라우저(클라이언트) | WAS(Controller( ↔ View) ↔ Service ↔ DAO) | Model | 데이터베이스
-
처리 과정
-
클라이언트가 서버에 요청을 하는 것은 같으나 각각의 기능을 분리시켜 모듈화
-
기능은 Service
-
데이터베이스와 연결하는 것은 DAO
-
사용자에게 보여줄 것은 JSP
-
이들을 통제하는 것이 Controller
-
데이터베이스와 관련된 데이터는 Model
-
-
장점
-
기능별 로직이 분리되어 유지보수 및 분업이 용이합니다.
-
단위가 큰 프로젝트에 적합합니다.
-
-
단점
-
구조 설계 등 개발자가 신경써야 하는 부분이 많아 개발이 느립니다.
-
스프링 MVC프레임워크 설계 구조
-
구분별 설명
-
HandleMapping
: 많은 컨트롤러 중 가장 알맞은 컨트롤러를 찾습니다. -
HandlerAdapter
: 많은 메소드 중 사용자가 요청한 데이터에 가장 적합한 메소드를 찾고, 요청에 대한 작업 후 Model을 통해 데이터를 운반합니다. -
ViewResolver
: 사용자 요청에 대한 작업이 컨트롤러로부터 모두 종료되고 DispatcherServlet은 ViewResolver에 데이터 정보를 보내면 가장 적합한 JSP 페이지(View 페이지)를 찾습니다. -
View
: 페이지를 통해 사용자 요청에 대해 응답합니다.
-
DispatcherServlet 설정
WEB-INF 폴더에 web.xml을 만들어 설정할 내용들을 태그로 묶어 기입하며, 설정이 완료되면 스프링 설정 파일도 같이 만들어집니다.
DispatcherServlet을 등록, 초기 파라미터로 스프링 설정 파일(servlet-context.xml)을 설정하면 컨테이너가 생성되고 디스패쳐 서블릿이 설정됩니다.
- 초기화 파라미터에서 지정한 파일(servlet-context.xml)을 이용해서 스프링 컨테이너를 생성합니다.
- 초기화 파라미터에서 스프링 설정 파일을 지정하지 않은 경우 서블릿 별칭을 이용해 스프링 컨테이너를 생성합니다.
Controller 객체 1 : @Controller
DispatcherServlet ↔ HandlerAdapter ↔ Controller
servlet-context.xml에 선언 후 Controller 객체로 사용할 클래스를 정의합니다.
@Controller 적용 방법
@Controller
public class HomeController{
...
}
Controller 객체 2 : @RequestMapping
DispatcherServlet ↔ HandlerAdapter ↔ Controller
Controller 클래스 내부의 메소드 중 @RequestMapping 어노테이션을 붙이고 값을 입력하고, 사용자로부터 오는 요청을 특정 문자로 매칭합니다.
@RequestMapping 적용 방법
@RequestMapping("/success")
public String success(Model model){
...
}
Controller 객체 3 : Model 타입의 파라미터
개발자는 Model 객체에 데이터를 담아서 DispatcherServlet에 전달할 수 있습니다.
DispatcherServlet에 전달된 Model 데이터는 View 에서 가공되어 클라이언트에게 응답 처리됩니다.
Model 파라미터 적용 방법
@RequestMapping("/success")
public String success(Model model){
...
}
model.setAttribute("model", "model status set!");
View 객체
뷰를 찾는 역할을 View Resolver에게 위임합니다.
스프링 설정파일에 InternalResourceViewResolver를 찾고, HandlerAdapter에서 찾은 메소드의 리턴 값에 따른 파일을 찾아 실제로 사용자에게 응답합니다.
전체적인 웹 프로그래밍 구조
- 구분 별 설명
- DispatcherServlet은 등록과 설정만 해주면 되며, 개발자가 참여할 필요가 전혀 없습니다.
- HandlerMapping, HandlerAdapter는 개발자가 참여할 필요가 전혀 없으며 컨테이너가 자동으로 처리합니다.
- Controller의 @Controller, @RequestMapping 등 개발자가 처리해야 합니다.
- ViewResolver 개발자가 참여할 필요가 전혀 없습니다.
5 .View는 개발자가 처리해야 합니다.
- 진행 프로세스를 볼까요?
- 최초 사용자 요청 : http://localhost:8080/test/success
- DispatcherServlet
- HandlerMapping
- Controller : @Controller 어노테이션이 적용된 클래스 검색
- DispatcherServlet
- HandlerAdapter : 사용자 요청에 해당하는 메소드 검색
- Controller : @RequestMapping("/success") 어노테이션이 적용된 메소드 검색 및 실행
- DispatcherServlet
- ViewResolver : ViewResolver에 의해 검색된 success.jsp 검색 및 실행
- View : 브라우저에 JSP를 이용해 응답
즉, 서버와 뷰에 대한 개발자의 작업을 분할하여 사용합니다.
📖 웹 어플리케이션 구조
사용자 요청(브라우저) → 프론트 컨트롤러(DispatcherServlet) → 뷰(jsp 파일 등) → 컨트롤러 → 서비스 → DAO(Data Access Object) → Database
서비스 객체 구현
- 방법 1 : new 연산자를 이용한 service 객체 생성 및 참조
MemberService service = new MemberService();
- 방법 2 : 스프링 설정파일을 이용한 서비스 객체 생성 및 의존 객체 자동 주입
<beans:bean id="service" class="com.spring.basic.member.service.MemberService" />
@Autowired
MemberService service;
- 방법3 : 어노테이션을 이용한 서비스 객체 생성 및 의존 객체 자동 주입
@Repository("memService")
public class MemberService implements IMemberService{}
@Resource(name="memService")
MemberService service;
DAO 객체 구현
- 어노테이션을 이용한 DAO 객체 생성 및 의존 객체 자동 주입
@Repository
public class MemberDao implements IMemberDao{}
@Autowired
MemberDao dao;
- 한글 처리(web.xml 추가)
<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>
<init-param>
<param-name>forceEncoding</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>encodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
📖 컨트롤러의 기능
@RequestMapping을 이용한 URL 매핑
메소드에 @RquestMapping 적용
컨트롤러 내부의 세부 기능으로 구분합니다.
- http://locatlhost:8080/basic/memJoin → memJoin() 실행
- 기본적인 매핑 방법
@RequestMapping("/memJoin")
public String memJoin(){
...
}
3.전송 방식에 따른 매핑 방법
// 전송 방식이 GET 방식일 경우(속성 생략 가능)
@RequestMapping(value="memJoin")
public String memJoin(){
...
}
// 전송 방식이 POST 방식일 경우(속성 반드시 기입)
@RequestMapping(value="memJoin", method=RequestMethod.POST)
public String memJoin(){
...
}
클래스에 @RequestMapping 적용
기능에 따른 컨트롤러 클래스를 제작하는데 사용합니다. 매핑 URL이 아래인 경우 코드를 확인해볼까요?
@Controller
@RequestMapping("/member")
public class MemberController{
@RequestMapping(value="/memJoin", method=RequestMethod.POST)
...
@RequestMapping(value="/memLogin", method=RequestMethod.POST)
...
}
요청 파라미터
- HttpServletRequest 객체를 이용한 HTTP 전송 정보 얻기
사용 방법
public String memJoin(Model model, HttpServletRequest request){ String memid = request.getParamter("memId"); }
📖 @RequestParam 어노테이션을 이용한 HTTP 전송 정보 얻기
@RequestParam의 속성
public String memJoin(Model model, @RequestParam("memId") String memId,
@RequestParam("memPw") String memPw) {
String memid = request.getParamter("memId");
}
- value : 생략(value="")해도 됩니다.
- required : 생략(required=true||false)해도 됩니다. 입력 여부를 정하는 속성입니다.
- default : 생략해 됩니다. 입력을 하지 않아도 기본적으로 들어가는 값을 지정하는 속성입니다.
받아온 전송정보 사용하기
- 각 파라미터를 설정하여 사용하는 방법
// Controller 코드
@RequestMapping(value="/memJoin", method=RequestMethod.POST)
public String memJoin(Model model, HttpServletRequest request) {
String memId = request.getParameter("memId");
String memPw = request.getParameter("memPw");
String memMail = request.getParameter("memMail");
String memPhone1 = request.getParameter("memPhone1");
String memPhone2 = request.getParameter("memPhone2");
String memPhone3 = request.getParameter("memPhone3");
service.memberRegister(memId, memPw, memMail, memPhone1, memPhone2, memPhone3);
model.addAttribute("memId", memId);
model.addAttribute("memPw", memPw);
model.addAttribute("memMail", memMail);
model.addAttribute("memPhone", memPhone1 + " - " + memPhone2 + " - " + memPhone3);
return "memJoinOk";
}
<!-- View 코드 -->
<h1> memJoinOk </h1>
ID : ${memId}<br />
PW : ${memPw}<br />
Mail : ${memMail} <br />
Phone : ${memPhone} <br />
// 커맨드 객체를 생성하여 사용하는 방법(getter, setter 반드시 필요)
// Controller 코드
@RequestMapping(value="/memJoin", method=RequestMethod.POST)
public String memJoin(Member member) {
service.memberRegister(member.getMemId(), member.getMemPw(),
member.getMemMail(), member.getMemPhone1(), member.getMemPhone2(),
member.getMemPhone3());
return "memJoinOk";
}
<!-- View 코드 -->
<h1> memJoinOk </h1>
ID : ${member.memId}<br />
PW : ${member.memPw}<br />
Mail : ${member.memMail} <br />
Phone : ${member.memPhone1}, ${member.memPhone2}, ${member.memPhone3} <br />
최근엔 개발자의 스트레스를 줄이기 위해 커맨드 객체를 사용하는 방법을 애용합니다.
@ModelAttribute
- 사용 방법 1
// 컨트롤러
public String memJoin(Member member){...}
public String memLogin(Member member){...}
public String memRemove(@ModelAttribute("mem") Member member){...}
<!-- 뷰 -->
${member.memId}<br />
${member.memId}<br />
${mem.memId}<br />
@ModelAttribute를 이용하면 커맨드 객체의 이름을 변경할 수 있고, 변경된 이름은 뷰에서 커맨드 객체를 참조할 때 사용됩니다. 중복된 이름으로 개발 간 스트레스를 받지 않아도 됩니다.
- 사용 방법 2
@ModelAttribute("serverTime")
public String getServerTime(Locale locale) {
Date date = new Date();
DateFormat dateFormat = DateFormat.getDateTimeInstance(DateFormat.LONG, DateFormat.LONG, locale);
return dateFormat.format(date);
}
@ModelAttribute가 적용된 메소드는 다른 메소드가 호출되어질지라도 공통적으로 같이 호출됩니다.
커맨드 객체 프로퍼티 데이터 타입
- 데이터가 기본 타입인 경우 : 필요한 절차 없이 받고 싶은 타입으로 지정하면 스프링이 자동으로 설정합니다.
<!-- memberJoin.html -->
ID : <input type="text" name="memId" ><br />
PW : <input type="password" name="memPw" ><br />
MAIL : <input type="text" name="memMail" ><br />
AGE : <input type="text" name="memAge" size="4" value="0"><br />
// Member.java
private String memId;
private String memPw;
private String memMail;
private int memAge;
- 데이터가 중첩 커맨드 객체를 이용한 List 구조인 경우, 해당하는 이름의 커맨드 객체를 새로 하나 만들어 저장합니다.
<!-- memberJoin.html -->
PHONE1 : <input type="text" name="memPhones[0].memPhone1" size="5"> -
<input type="text" name="memPhones[0].memPhone2" size="5"> -
<input type="text" name="memPhones[0].memPhone3" size="5"><br />
PHONE2 : <input type="text" name="memPhones[1].memPhone1" size="5"> -
<input type="text" name="memPhones[1].memPhone2" size="5"> -
<input type="text" name="memPhones[1].memPhone3" size="5"><br />
// Member.java
private List<MemPhone> memPhones;
Model & ModelAndView
컨트롤러에서 뷰에 데이터를 전달하기 위해 사용되는 객체입니다.
- Model : View에 데이터만 전달하는 객체
@RequestMapping(value = "/memModify", method = RequestMethod.POST)
public String memModify(Model model, Member member) {
Member[] members = service.memberModify(member);
// 데이터 이름, 데이터 값
model.addAttribute("memBef", members[0]);
model.addAttribute("memAft", members[1]);
// 뷰 이름
return "memModifyOk";
}
- ModelAndView : 데이터와 뷰의 이름을 함께 전달하는 객체
@RequestMapping(value = "/memModify", method = RequestMethod.POST)
public ModelAndView memModify(Member member) {
Member[] members = service.memberModify(member);
ModelAndView mav = new ModelAndView();
// 데이터 이름, 데이터 값
mav.addObject("memBef", members[0]);
mav.addObject("memAft", members[1]);
// 뷰 이름
mav.setViewName("memModifyOk");
// 객체 반환
return mav;
}
Author And Source
이 문제에 관하여(Spring 면접&질문 JAVA), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://velog.io/@mingkimk/Spring-면접질문-JAVA저자 귀속: 원작자 정보가 원작자 URL에 포함되어 있으며 저작권은 원작자 소유입니다.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)