유정잉

55일차 스프링 [ MVC - session, properties, 유효성검사 ] 본문

네이버 클라우드 부트캠프/복습 정리

55일차 스프링 [ MVC - session, properties, 유효성검사 ]

유정♡ 2024. 5. 9. 13:08

1. 추출 / 주입 받기

    - HttpServletRequest 사용 (request.getParameter())

    - WebRequest 사용 

    - 경로로 주입받기(=@PathVariable) 주소/값1/값2/값3/...

    - ** @RequestParam ** 중요 !! : 값을 직접 주입받을 수 있다 (이름이 무조건 같아야함 !! 즉, 변수이름=파라미터이름)

    - @ModelAttribute : 파라미터를 객체로 주입받을 수 있다. 생략도 가능하다. (@RequestParam은 일반변수, 파라미터로 주입 받음)

    - 여기까진 값을 주입받아 값을 콘솔에 출력 !!!

2. viewReslover

     - 값을 주입받아 값을 브라우저에 출력 

      - 값을 담는 setAttribute 사용해서 브라우저에 전달 (pageContext, request, session, ApplicationContext)

3. form 요소들 <form:form> ----> radio, checkbox, input ...

4. redirect / forward

5. request, session Bean 주입 

==============================================

6. session (project 13&14)

7. properties (=중요 !!) (여기서 주석처리는 #)

8. 유효성 검사, messages 등 

9. radio, checkbox ...

 


[ MVC_Basic_13 - project ] - session

     - session : 브라우저가 서버에 요청을 하게 되면 브라우저 당 하나씩 메모리 공간을 서버에서 할당해줌

                       요청을 새롭게 발생해도 같은 메모리 공간을 사용하게 됨 

    - @SessionScope : 최초의 요청 ~ 브라우저 닫을 때 까지 

 

1) views 폴더 안에 index.jsp

[ index.jsp JSP 파일 ]

<%@ page language="java" contentType="text/html; charset=UTF-8"
   pageEncoding="UTF-8"%>

<body>
<!-- session : 브라우저가 서버에 요청을 하게 되면 브라우저 당 하나씩 메모리 공간을 서버에서 할당해줌
			   요청을 새롭게 발생해도 같은 메모리 공간을 사용하게 됨 -->
<!-- @SessionScope : 최초의 요청 ~ 브라우저 닫을 때 까지 -->
<a href="t1">test1</a><br>
<a href="t2">test2</a><br>
<a href="t3">test3</a><br>

<a href="s1">spring1</a><br>

<a href="t4">test4</a><br>
<a href="s4">spring4</a><br>

<a href="t5">test5</a><br>
<a href="s5">spring5</a><br>

</body>
</html>
[ test1.jsp JSP 파일 ]

<%@ page language="java" contentType="text/html; charset=UTF-8"
   pageEncoding="UTF-8"%>

<body>
	<h1>test1</h1>
</body>
</html>
[ test4.jsp JSP 파일 ]

<%@ page language="java" contentType="text/html; charset=UTF-8"
   pageEncoding="UTF-8"%>

<body>
	<h1>test4</h1>
</body>
</html>
[ test5.jsp JSP 파일 ]

<%@ page language="java" contentType="text/html; charset=UTF-8"
   pageEncoding="UTF-8"%>

<body>
	<h1>test5</h1>
</body>
</html>
[ spring1.jsp JSP 파일 ]

<%@ page language="java" contentType="text/html; charset=UTF-8"
   pageEncoding="UTF-8"%>

<body>
	${sessionScope.data1 }
</body>
</html>
[ spring4.jsp JSP 파일 ]

<%@ page language="java" contentType="text/html; charset=UTF-8"
   pageEncoding="UTF-8"%>

<body>
	${sessionScope.bean.str1 } <br>
	${sessionScope.bean.str2 } <br>
</body>
</html>
[ spring5.jsp JSP 파일 ]

<%@ page language="java" contentType="text/html; charset=UTF-8"
   pageEncoding="UTF-8"%>

<body>
	${requestScope.sbean.str1 } <br>
	${requestScope.sbean.str2 } <br>
	
	${sessionScope.sbean2.str1 } <br>
	${sessionScope.sbean2.str2 } <br>
</body>
</html>

 

2) kr.bit.controller package 안에 SpringController.java class 에서 

     t1을 눌렀을때 session 영역에 담아서 test1.jsp로 페이지 이동하는 @GetMapping 작업

     t2를 눌렀을때 s1으로 강제 이동 (="redirect:s1") 그래서 화면과 콘솔에 spring2도 출력 됨 

     s1은 콘솔에 출력하려고 getAttribute해서 System.out.println 한거임

     t3를 눌렀을때 s1으로 강제 이동 (="forward:s1") 그래서 화면과 콘솔에 spring3도 출력 됨

     t4는 Data d 객체를 생성해서 d객체에 setStr1으로 값을 저장 후 session에 setAttribute로 세션에 저장 후 test4.jsp 페이지로 이동

     처음에 s4만 누르면 오류 발생 t4를 눌러야지 session에 경로가 저장 되기 때문에 t4를 누르고 s4를 눌러야지 spring4, spring5 화면에 출력 됨

t5는 @ModelAttribute를 활용(@ModelAttribute는 request영역에 저장됨 그래서 원래는 views에서 출력하려면${requestScope}로 출력해줬어야 함 !
근데  만약에 session으로 저장하고 싶으면 위에 @SessionAttribute({"sbean","sbean2"}) 적어주면
ModelAttribute로 주입해도 Session 영역에 지정 하면 Session으로 바뀜 !!
주의할점 !!! @ModelAttribute를 활용해 객체를 생성해 반환하는 메서드를 작성해줘야지 Session 영역으로 바뀜  

package kr.bit.controller;

import javax.servlet.http.HttpSession;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.SessionAttribute;
import org.springframework.web.bind.annotation.SessionAttributes;

import kr.bit.beans.Data;

//Bean으로 등록함과 동시에 @Controller 작업이 일어나면서 Mapping 하겠다 
@Controller
@SessionAttributes({"sbean","sbean2"})
public class SpringController {
	
	//주의할 점 ! @ModelAttribute를 활용해 객체를 생성해 반환하는 메서드를 작성해줘야지 Session 영역으로 바뀜 !
	@ModelAttribute("sbean")
	public Data dbean() {
		return new Data(); //세션영역으로 주입받을 수 있다
	}
	
	@ModelAttribute("sbean2")
	public Data dbean2() {
		return new Data(); //세션영역으로 주입받을 수 있다
	}

	@GetMapping("/t1")
	public String t1(HttpSession session) {
		session.setAttribute("data1", "spring1");
		
		return "test1";
	}
	
	@GetMapping("/t2") 
	public String t2(HttpSession session) {
		session.setAttribute("data1", "spring2");
		return "redirect:/s1";
	}
	
	@GetMapping("/s1")
	public String s1(HttpSession session) {
		String str = (String)session.getAttribute("data1");
		System.out.println(str);
		return "spring1";
	}
	
	@GetMapping("/t3")
	public String t3(HttpSession session) {
		session.setAttribute("data1", "spring3");
		return "forward:/s1";
	}
	
	@GetMapping("/t4")
	public String t4(HttpSession session) {
		Data d = new Data();
		
		d.setStr1("spring4");
		d.setStr2("spring5"); //객체에 값 저장 후 
		 
		session.setAttribute("bean", d); //세션영역에 저장
		
		return "test4"; //test4.jsp로 페이지 이동
	}
	
	@GetMapping("/s4") //session영역에 저장되어 있는 객체를 사용하고자 할 때 
	public String s4(@SessionAttribute("bean") Data d) { //session영역이기 때문에 브라우저 닫기 전까지 위에서준 Data d 객체가 유지가 됨 ! 그래서 여기서도 사용 가능 ! 
		return "spring4";
	}
	
	@GetMapping("/t5") //@ModelAttribute는 request영역에 저장됨 (=원래는 requestScope로 출력 가능) 
	public String t5(@ModelAttribute("sbean") Data dbean, @ModelAttribute("sbean2") Data dbean2) {
		dbean.setStr1("aa");
		dbean.setStr2("bb");
		
		dbean2.setStr1("cc");
		dbean2.setStr2("dd");
		
		return "test5";
	}
	
	@GetMapping("/s5")
	public String s5(@ModelAttribute("sbean") Data dbean, @ModelAttribute("sbean2") Data dbean2) {
		return "spring5";
	}
	
}

 


[ MVC_Basic_14 - project ] - session

 

1) Data와 Data2는 @Component로 등록하지 않았기 때문에 RootAppContext에 @Bean으로 등록 

    Data3은 Data3 class에서 @Component와 @Sessionscope로 Bean 등록 

   그리고 ServletAppContext에도 @ComponentScan("kr.bit.beans")등록 ! (+@ComponentScan("kr.bit.controller"))

package kr.bit.beans;

public class Data {
   
	private String str1;
	private String str2;
	
	public String getStr1() {
		return str1;
	}
	public void setStr1(String str1) {
		this.str1 = str1;
	}
	public String getStr2() {
		return str2;
	}
	public void setStr2(String str2) {
		this.str2 = str2;
	}

}
package kr.bit.beans;

public class Data2 {
   
	private String str3;
	private String str4;
	
	public String getStr3() {
		return str3;
	}
	public void setStr3(String str3) {
		this.str3 = str3;
	}
	public String getStr4() {
		return str4;
	}
	public void setStr4(String str4) {
		this.str4 = str4;
	}
}
package kr.bit.beans;

import org.springframework.stereotype.Component;
import org.springframework.web.context.annotation.SessionScope;

@Component
@SessionScope
public class Data3 {
   
	private String str5;
	private String str6;
	
	public String getStr5() {
		return str5;
	}
	public void setStr5(String str5) {
		this.str5 = str5;
	}
	public String getStr6() {
		return str6;
	}
	public void setStr6(String str6) {
		this.str6 = str6;
	}
	
}
package kr.bit.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.context.annotation.SessionScope;

import kr.bit.beans.Data;
import kr.bit.beans.Data2;

@Configuration
public class RootAppContext {  //root-context.xml
	
	@Bean
	@SessionScope 
	//브라우저가 서버에 최초로 요청보낼 때 bean 객체가 주입된다 
	public Data bean() {
		return new Data();
	}
	
	@Bean("session2")
	@SessionScope
	public Data2 bean2() {
		return new Data2();
	}
}
package kr.bit.config;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.ViewResolverRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@Configuration
@EnableWebMvc
@ComponentScan("kr.bit.controller")
@ComponentScan("kr.bit.beans")
public class ServletAppContext implements WebMvcConfigurer{
	
	@Override
	public void configureViewResolvers(ViewResolverRegistry registry) {
		WebMvcConfigurer.super.configureViewResolvers(registry);
		registry.jsp("/WEB-INF/views/",".jsp");
	}
	
	@Override
	public void addResourceHandlers(ResourceHandlerRegistry registry) {
		WebMvcConfigurer.super.addResourceHandlers(registry);
		registry.addResourceHandler("/**").addResourceLocations("/resources/");
	}
}

 

2) views 폴더 안에 index.jsp

[ index.jsp JSP 파일 ]

<%@ page language="java" contentType="text/html; charset=UTF-8"
   pageEncoding="UTF-8"%>

<body>
<!-- session : 브라우저가 서버에 요청을 하게 되면 브라우저 당 하나씩 메모리 공간을 서버에서 할당해줌
			   요청을 새롭게 발생해도 같은 메모리 공간을 사용하게 됨 -->
<!-- @SessionScope : 최초의 요청 ~ 브라우저 닫을 때 까지 -->
<a href="t1">test1</a><br>
<a href="s1">spring1</a><br>

												

</body>
</html>
[ spring1.jsp JSP 파일 ]

<%@ page language="java" contentType="text/html; charset=UTF-8"
   pageEncoding="UTF-8"%>

<body>
	${requestScope.data1.str1 }
	${requestScope.data1.str2 } <br>
	
	${requestScope.data2.str3 }
	${requestScope.data2.str4 } <br>
	
	${requestScope.data3.str5 }
	${requestScope.data3.str6 }

</body>
</html>

 

3) kr.bit.controller package 안에 SpringController.java class 에서 

      @Autowired로 자동주입 (=RootAppContext에 Bean으로 등록한 Data 주소값을 자동 주입 받기)

      t1은 @Autowired로 주입받은 값들을 셋팅 (각 주입한 객체들이 SessionScope임=t1 경로 매핑될 때 Bean 객체 주입 됨)

      s1은 Session에 담겨진 값들을 Model(=${requestScope.클래스명소문자.변수명))객체로 가져오기 

      s1부터 누르면 안됨 먼저 t1을 눌러야지 Session에 값이 저장 됨 -> 그리고 s1을 눌려야지 값이 출력 됨 !

package kr.bit.controller;

import javax.annotation.Resource;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;

import kr.bit.beans.Data;
import kr.bit.beans.Data2;
import kr.bit.beans.Data3;

//Bean으로 등록함과 동시에 @Controller 작업이 일어나면서 Mapping 하겠다 
@Controller
public class SpringController {
	
	@Autowired
	Data data1; //RootAppContext에 Bean으로 등록한 Data 주소값을 자동주입 받기 
	 
	@Resource(name="session2") //이름 같을 때 자동 주입 
	Data2 data2;
	
	@Autowired
	Data3 data3;
	
	@GetMapping("/t1") //@Autowired로 주입받은 값을 셋팅 
	public String t1() {
		data1.setStr1("aa");
		data1.setStr2("bb");
		
		data2.setStr3("cc");
		data2.setStr4("dd");
		
		data3.setStr5("ee");
		data3.setStr6("ff"); //각 주입한 객체들이 SessionScope임 => t1경로 매핑될 때 Bean 객체 주입 됨 
		
		return "test1";
	}
	
	@GetMapping("/s1") //Session에 담겨진 값들을 Model(=request)로 가져오기
	public String s1(Model model) { //세션객체들 data1,2,3를 모델객체에 담는다 
		model.addAttribute("data1",data1);
		model.addAttribute("data2",data2);
		model.addAttribute("data3",data3);
		
		return "spring1";
	}
}


 

[ MVC_Basic_15 - project ] - properties

 

1) src -> maom -> WEB-INF -> properties 폴더 생성 -> New File data1.propertie 파일 생성 (확장자명이 properties)

[ data1.properties 파일 ]

aaa.a1=10
aaa.a2=문자열1

bbb.b1=20
bbb.b2=문자열2
[ data2.properties 파일 ]

ccc.c1=30
ccc.c2=문자열3

ddd.d1=40
ddd.d2=문자열4

 

2) views 폴더 안에 index.jsp

[ index.jsp JSP 파일 ]

<%@ page language="java" contentType="text/html; charset=UTF-8"
   pageEncoding="UTF-8"%>

<body>

<a href="t1">test1</a><br>

</body>
</html>

 

3) kr.bit.controller package 안에 SpringController.java class 에서 

     @PropertySources( value={" "} ) (=Sources인 이유 properties파일이 2개 이상이기 때문에)

     @Value("${}")로 properties파일에 작성한 값을 주입 받는다 

      t1 클릭시 콘솔창에 입력된 값들 출력 됨 

      이때 한글이 깨지면 !!! encoding="UTF-8" 추가 해주기 !!

@PropertySources({

@PropertySource(value={"/WEB-INF/properties/data1.properties"},encoding = "UTF-8"),

@PropertySource(value= {"/WEB-INF/properties/data2.properties"},encoding = "UTF-8")

})

package kr.bit.controller;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.PropertySource;
import org.springframework.context.annotation.PropertySources;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;

//Bean으로 등록함과 동시에 @Controller 작업이 일어나면서 Mapping 하겠다 
@Controller
@PropertySources({
	@PropertySource(value={"/WEB-INF/properties/data1.properties"},encoding = "UTF-8"),
	@PropertySource(value= {"/WEB-INF/properties/data2.properties"},encoding = "UTF-8")
})
//properties -> 실행 중 절대 변하지 않는 값들을 properties 파일 안에 넣어줘야 함 
//ex) 유효성 검사, DB정보 (=유효성검사를 properties안에 싹다 넣어 줌)
public class SpringController {
	
	//@Values를 활용하여 properties파일에 작성한 값을 주입받는다
	@Value("${aaa.a1}") 
	private int a1;
	
	@Value("${aaa.a2}")
	private String a2;
	
	@Value("${bbb.b1}")
	private int b1;
	
	@Value("${bbb.b2}")
	private String b2;
	
	@Value("${ccc.c1}")
	private int c1;
	
	@Value("${ccc.c2}")
	private String c2;
	
	@Value("${ddd.d1}")
	private int d1;
	
	@Value("${ddd.d2}")
	private String d2;
	
	@GetMapping("/t1")
	public String t1() {
		System.out.println(a1);
		System.out.println(a2);
		System.out.println(b1);
		System.out.println(b2);
		System.out.println(c1);
		System.out.println(c2);
		System.out.println(d1);
		System.out.println(d2);
		
		return "test1";
	}
	
}

 

 

 

※ 한글 깨지면 kr.bit.config package안에 SpringConfigClass.java에 코드 추가

    encodingFilter.setEncoding("UTF-8");

package kr.bit.config;

import javax.servlet.Filter;

import org.springframework.web.filter.CharacterEncodingFilter;
import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;

public class SpringConfigClass extends AbstractAnnotationConfigDispatcherServletInitializer {
	
	@Override
	protected String[] getServletMappings() {
		// TODO Auto-generated method stub
		return new String[] {"/"};
	}
	
	@Override
	protected Class<?>[] getServletConfigClasses() {
		// TODO Auto-generated method stub
		return new Class[] {ServletAppContext.class};
	}
	
	
	@Override
	protected Class<?>[] getRootConfigClasses() {
		// TODO Auto-generated method stub
		return new Class[] {RootAppContext.class};
	}
	
	
	@Override
	protected Filter[] getServletFilters() {
		// TODO Auto-generated method stub
		CharacterEncodingFilter encodingFilter = new CharacterEncodingFilter();
		encodingFilter.setEncoding("UTF-8");
		return new Filter[] {encodingFilter};
	}
	

}

 

 


[ MVC_Basic_16 - project ] - properties에 설정한 값 JSP에 출력하기 

 

1) src -> maom -> WEB-INF -> properties 폴더 생성 -> New File data1.propertie 파일 생성 (확장자명이 properties)

[ data1.properties 파일 ]

aaa.a1=문자열1
aaa.a2=홍길동은 {0}살이고 {1}에 산다.
[ data2.properties 파일 ]

bbb.b1=문자열2
[ data1_en.properties 파일 ]

aaa.a3 = english
[ data1_en.properties 파일 ]

aaa.a3 = 한글

 

2) views 폴더 안에 index.jsp

[ index.jsp JSP 파일 ]

<%@ page language="java" contentType="text/html; charset=UTF-8"
   pageEncoding="UTF-8"%>

<body>

<a href="t1">test1</a><br>

</body>
</html>

 

3) kr.bit.config package 안에 ServletAppContext에 Properties파일을 JSP 화면에 가져가지 위해 @Bean 등록해야함

     ReloadableResourceBundleMessageSource 활용 ! 2개이상일 경우 .setBasenames 사용 하기 !

     이때 파일경로 적을 때 확장자는 빼고 파일명만 적으면 됨 ! 

package kr.bit.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.support.ReloadableResourceBundleMessageSource;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.ViewResolverRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@Configuration
@EnableWebMvc
@ComponentScan("kr.bit.controller")
@ComponentScan("kr.bit.beans")
public class ServletAppContext implements WebMvcConfigurer{
	
	@Override
	public void configureViewResolvers(ViewResolverRegistry registry) {
		WebMvcConfigurer.super.configureViewResolvers(registry);
		registry.jsp("/WEB-INF/views/",".jsp");
	}
	
	@Override
	public void addResourceHandlers(ResourceHandlerRegistry registry) {
		WebMvcConfigurer.super.addResourceHandlers(registry);
		registry.addResourceHandler("/**").addResourceLocations("/resources/");
	}
	
	//Properties파일을 jsp 화면에 가져가지 위해 등록해야함 
	@Bean
	public ReloadableResourceBundleMessageSource source() {
		ReloadableResourceBundleMessageSource res = new ReloadableResourceBundleMessageSource();
		
		//하나일 경우는 res.setBasename을 사용 / 여기선 복수니까 names ! 
		res.setBasenames("/WEB-INF/properties/data1","/WEB-INF/properties/data2"); //확장자 빼고 파일명만 적으면 됨 
		
		return res;
	}
}

 

4) kr.bit.controller package 안에 SpringController.java class 에서 

    @Autowired는 properties에서 Bean으로 등록한 객체 주소 값을 자동 주입 받음

     .getMessage(String code, @Nullable Object[] args, Locale locale) 

package kr.bit.controller;

import java.util.Locale;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.PropertySource;
import org.springframework.context.annotation.PropertySources;
import org.springframework.context.support.ReloadableResourceBundleMessageSource;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;

//Bean으로 등록함과 동시에 @Controller 작업이 일어나면서 Mapping 하겠다 
@Controller
@PropertySources({
	@PropertySource(value={"/WEB-INF/properties/data1.properties"},encoding = "UTF-8"),
	@PropertySource(value= {"/WEB-INF/properties/data2.properties"},encoding = "UTF-8")
})
//properties -> 실행 중 절대 변하지 않는 값들을 properties 파일 안에 넣어줘야 함 
//ex) 유효성 검사, DB정보 (=유효성검사를 properties안에 싹다 넣어 줌)
public class SpringController {
	
	//properties 빈으로 등록한 객체 주소값 자동 주입 받음 
	@Autowired
	ReloadableResourceBundleMessageSource res;
	
	@GetMapping("/t1")
	public String t1(Model model, Locale locale) {
		
		System.out.println(locale);
		
		String str1 = res.getMessage("aaa.a1", null, null);
		String str2 = res.getMessage("bbb.b1", null, null);
		
		Object []args = {30, "seoul"};
		String str3 = res.getMessage("aaa.a2", args, null);
		
		String str4=res.getMessage("aaa.a3", args, locale);
		
		System.out.println(str1);
		System.out.println(str2);
		System.out.println(str3);
		System.out.println(str4);
		
		model.addAttribute("args",args);
		
		return "test1";
	}
}

 

5) test1.jsp 에서 브라우저 화면에 출력

[ test1.jsp JSP 파일 ]

<%@ page language="java" contentType="text/html; charset=UTF-8"
   pageEncoding="UTF-8"%>
<%@ taglib prefix="spring" uri="http://www.springframework.org/tags" %>
<body>
	aaa.a1 : <spring:message code="aaa.a1"/><br>
	aaa.a2 : <spring:message code="aaa.a2" arguments="${args }"/><br>
	aaa.a3 : <spring:message code="aaa.a3"/><br>
	
	bbb.b1 : <spring:message code="bbb.b1"/><br>
	
</body>
</html>

 

 

 


[ MVC_Basic_17 - project ] - properties 유효성 검사를 Data.java에서 주기 

 

1) pom.xml에 두개 코드 추가 1) validation api 2)hibernate validator 

<project xmlns="http://maven.apache.org/POM/4.0.0"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 
						http://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<groupId>MVC_Basic_01</groupId>
	<artifactId>MVC_Basic_01</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<packaging>war</packaging>
	<build>
		<sourceDirectory>src</sourceDirectory>
		<plugins>
			<plugin>
				<artifactId>maven-compiler-plugin</artifactId>
				<version>3.8.0</version>
				<configuration>
					<source>1.8</source>
					<target>1.8</target>
				</configuration>
			</plugin>
			<plugin>
				<artifactId>maven-war-plugin</artifactId>
				<version>3.2.1</version>
				<configuration>
					<warSourceDirectory>WebContent</warSourceDirectory>
				</configuration>
			</plugin>
		</plugins>
	</build>
	<!-- 라이브러리 버전관리 -->
	<properties>
		<javax.servlet-version>4.0.1</javax.servlet-version>
		<javax.servlet.jsp-version>2.3.3</javax.servlet.jsp-version>
		<javax.servlet.jsp.jstl-version>1.2</javax.servlet.jsp.jstl-version>
		<org.springframework-version>5.2.2.RELEASE</org.springframework-version>
		<!-- <org.springframework-version>4.3.25.RELEASE</org.springframework-version> -->
	</properties>
	<!-- 라이브러리 셋팅 -->
	<dependencies>
		<!-- https://mvnrepository.com/artifact/javax.servlet/javax.servlet-api -->
		<dependency>
			<groupId>javax.servlet</groupId>
			<artifactId>javax.servlet-api</artifactId>
			<version>${javax.servlet-version}</version>
			<scope>provided</scope>
		</dependency>
		<!-- https://mvnrepository.com/artifact/javax.servlet.jsp/javax.servlet.jsp-api -->
		<dependency>
			<groupId>javax.servlet.jsp</groupId>
			<artifactId>javax.servlet.jsp-api</artifactId>
			<version>${javax.servlet.jsp-version}</version>
			<scope>provided</scope>
		</dependency>
		<!-- https://mvnrepository.com/artifact/javax.servlet.jsp.jstl/jstl -->
		<dependency>
			<groupId>javax.servlet</groupId>
			<artifactId>jstl</artifactId>
			<version>${javax.servlet.jsp.jstl-version}</version>
		</dependency>
		<!-- https://mvnrepository.com/artifact/org.springframework/spring-webmvc -->
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-webmvc</artifactId>
			<version>${org.springframework-version}</version>
		</dependency>
		
	<!-- https://mvnrepository.com/artifact/javax.validation/validation-api -->	
	<dependency>
	    <groupId>javax.validation</groupId>
	    <artifactId>validation-api</artifactId>
	    <version>2.0.1.Final</version>
	</dependency>

	<!-- https://mvnrepository.com/artifact/org.hibernate.validator/hibernate-validator -->
	<dependency>
  	  <groupId>org.hibernate.validator</groupId>
  	  <artifactId>hibernate-validator</artifactId>
  	  <version>6.2.0.Final</version>
	</dependency>
	
	</dependencies>
</project>

 

2) views 폴더 안에 index.jsp

[ index.jsp JSP 파일 ]

<%@ page language="java" contentType="text/html; charset=UTF-8"
   pageEncoding="UTF-8"%>

<body>

<a href="t1">test1</a><br>


												

</body>
</html>

 

3) kr.bit.beans package 안에 Data.java

     @Max와 @Size로 조건 설정 

package kr.bit.beans;

import javax.validation.constraints.Max;
import javax.validation.constraints.Size;

public class Data {

	@Max(100)
	private int num1;
	
	@Size(min=4, max=10)
	private String num2;

	public int getNum1() {
		return num1;
	}

	public void setNum1(int num1) {
		this.num1 = num1;
	}

	public String getNum2() {
		return num2;
	}

	public void setNum2(String num2) {
		this.num2 = num2;
	}
	
}

 

4) kr.bit.controller package 안에 SpringController.java class 에서 

    @ModelAttribute 생략 가능 -> public String test1_proc(@Valid @ModelAttribute Data data1, BindingResult result)

package kr.bit.controller;

import javax.validation.Valid;

import org.springframework.stereotype.Controller;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;

import kr.bit.beans.Data;

//properties -> 실행 중 절대 변하지 않는 값들을 properties 파일 안에 넣어줘야 함 
//ex) 유효성 검사, DB정보 (=유효성검사를 properties안에 싹다 넣어 줌)
@Controller
public class SpringController {
	
	@GetMapping("/t1")
	public String t1() {
		return "test1";
	}
	
	//폼에 작성을 한 후 경로 매핑 
	@PostMapping("/test1_proc") //form에 쓴 값이 주입 됨 
	public String test1_proc(@Valid Data data1, BindingResult result) {
		//@Valid : 메서드에 주입받는 빈에 유효성 검사를 실시하겠다라는 선언
		//BindingResult : 유효성 검사를 실행한 결과정보가 저장되어있음 -> JSP 파일로 이동(여기다가 error메세지를 띄우는것)
		System.out.println(data1.getNum1());
		System.out.println(data1.getNum2());
		System.out.println(result);
		
		return "test1";
	}
	
}

 

5) tes1.jsp test2.jsp 작성 

     적은 값이 Data 클래스의 어노테이션 조건과 맞아야한다 (=@Max와 @Size)

     이때 input의 name값은 Data class에서 준 필드명과 똑같이 준다 ! 

      input에 @Max와 @Size 조건에 알맞는 제대로 된 값을 입력하면 -> test2.jsp 파일로 브라우저에 입력한 값 출력하면서 이동한다 

[ test1.jsp JSP 파일 ]

<%@ page language="java" contentType="text/html; charset=UTF-8"
   pageEncoding="UTF-8"%>

<body>
<!-- 적은값이 Data 클래스의 어노테이션 조건에 맞아야함 =@Max와 @Size -->
<form action="test1_proc" method="post">
		<!-- name값과 Data 필드명 같게 주기 -->
		num1 : <input type="text" name="num1"><br> 
		num2 : <input type="text" name="num2"><br>
	<button type="submit">확인</button> 
</form>
	
</body>
</html>
[ test2.jsp JSP 파일 ]

<%@ page language="java" contentType="text/html; charset=UTF-8"
   pageEncoding="UTF-8"%>

<body>
<!-- 적은값이 Data 클래스의 어노테이션 조건에 맞아야함 =@Max와 @Size -->
	${data.num1 }
	${data.num2 }
	
</body>
</html>

 

num1 : 20 / num2 : abcd 입력 결과
num1 : 20 / num2 를 빈칸으로 했을경우 -> 1 errors num2 rejected

 

 

6) kr.bit.controller package 안에 SpringController.java class 에서 

     ObjectError 활용하여 error 관련 메세지 콘솔창에 출력해보기 

package kr.bit.controller;

import javax.validation.Valid;

import org.springframework.stereotype.Controller;
import org.springframework.validation.BindingResult;
import org.springframework.validation.ObjectError;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PostMapping;

import kr.bit.beans.Data;

//properties -> 실행 중 절대 변하지 않는 값들을 properties 파일 안에 넣어줘야 함 
//ex) 유효성 검사, DB정보 (=유효성검사를 properties안에 싹다 넣어 줌)
@Controller
public class SpringController {

	@GetMapping("/t1")
	public String t1() {
		return "test1";
	}

	// 폼에 작성을 한 후 경로 매핑
	@PostMapping("/test1_proc") // form에 쓴 값이 주입 됨
	public String test1_proc(@Valid @ModelAttribute Data data1, BindingResult result) {
		// @Valid : 메서드에 주입받는 빈에 유효성 검사를 실시하겠다라는 선언
		// BindingResult : 유효성 검사를 실행한 결과정보가 저장되어있음 -> JSP 파일로 이동(여기다가 error메세지를 띄우는것)
		System.out.println(data1.getNum1());
		System.out.println(data1.getNum2());
		System.out.println(result);

		if (result.hasErrors()) {
			for (ObjectError obj : result.getAllErrors()) {
				System.out.println("코드: " + obj.getCode()); // 에러코드 어떻게 출력 되는지 확인
				System.out.println("에러이름: " + obj.getObjectName());
				System.out.println("에러메세지: " + obj.getDefaultMessage());

				String[] str = obj.getCodes();
				for (String s : str) {
					System.out.println(s);
				}
				if (str[0].equals("Size.data.num2")) {
					System.out.println("num2 Size(=글자수)를 잘못 입력했다 ! 다시 입력해라 !!");
				} else if (str[0].equals("Max.data.num1")) {
					System.out.println("num1 최대 입력값은 100이다 ! 다시 입력해라 !!");
				}
			}
			return "test1"; //유효성 검사에 위배되면 다시 form 형태로 감 
		} 
		return "test2"; //유효성 검사에 맞으면 test2.jsp로 가서 내가 입력한 값을 띄운다
	}

}

if (result.hasErrors()) {

      for (ObjectError obj : result.getAllErrors()) {

                System.out.println("코드: " + obj.getCode()); //에러코드 어떻게 출력 되는지 확인

                System.out.println("에러이름: " + obj.getObjectName());

                System.out.println("에러메세지: " + obj.getDefaultMessage());

        }

}

num1 과 num2에 아무런 값을 입력하지 않았을 경우

 

if (result.hasErrors()) {

     for (ObjectError obj : result.getAllErrors()) {

          System.out.println("코드: " + obj.getCode()); // 에러코드 어떻게 출력 되는지 확인

          System.out.println("에러이름: " + obj.getObjectName());

          System.out.println("에러메세지: " + obj.getDefaultMessage());

 

          String[] str = obj.getCodes();

          for (String s : str) {

          System.out.println(s);

           }

          if (str[0].equals("Size.data.num2")) {

                 System.out.println("num2 Size(=글자수)를 잘못 입력했다 ! 다시 입력해라 !!");

           } else if (str[0].equals("Max.data.num1")) {

                  System.out.println("num1 최대 입력값은 100이다 ! 다시 입력해라 !!");

            }

       }

       return "test1"; //유효성 검사에 위배되면 다시 form 형태로 감

}

num1 과 num2의 조건에 맞지 않는 값을 입력했을 경우

 

코드: Size

에러이름: data

에러메세지: 크기가 4에서 10 사이여야 합니다

Size.data.num2 -> 인덱스[0]

Size.num2 -> 인덱스[1]

Size.java.lang.String -> 인덱스[2]

Size -> 인덱스[3]

 

 

7) 이번엔 test1.jsp JSP 파일에서 error 관련 메세지 브라우저 화면에 출력해보기 

[ test1.jsp JSP 파일 ]

<%@ page language="java" contentType="text/html; charset=UTF-8"
   pageEncoding="UTF-8"%>
<%@ taglib prefix="spring" uri="http://www.springframework.org/tags" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<body>

<!-- 적은값이 Data 클래스의 어노테이션 조건에 맞아야함 =@Max와 @Size -->
<form action="test1_proc" method="post">

		<!-- name값과 Data 필드명 같게 주기 -->
		num1 : <input type="text" name="num1"><br> 
		<spring:hasBindErrors name="data"> <!-- 에러정보가 -> errors에 담겨져있다 -->
			<c:if test="${errors.hasFieldErrors('num1') }">
				${errors.getFieldError('num1').defaultMessage }<br> <!-- EL언어로 출력 -->
			</c:if>
		</spring:hasBindErrors>
		
		num2 : <input type="text" name="num2"><br>
				<spring:hasBindErrors name="data"> <!-- 에러정보가 -> errors에 담겨져있다 -->
			<c:if test="${errors.hasFieldErrors('num2') }">
				${errors.getFieldError('num2').defaultMessage }<br> <!-- EL언어로 출력 -->
			</c:if>
		</spring:hasBindErrors>
		
	<button type="submit">확인</button> 
</form>
	
</body>
</html>

 

 

 


[ MVC_Basic_18 - project ] - error.properties에 저장된 오류 멘트를 JSP 화면에서 출력하기 

 

1) kr.bit.beans package 안에 Data.java class 생성

package kr.bit.beans;

import javax.validation.constraints.Max;
import javax.validation.constraints.Size;

public class Data {

	@Max(100)
	private int num1;
	
	@Size(min=4, max=10)
	private String num2;

	public int getNum1() {
		return num1;
	}

	public void setNum1(int num1) {
		this.num1 = num1;
	}

	public String getNum2() {
		return num2;
	}

	public void setNum2(String num2) {
		this.num2 = num2;
	}
	
}

 

2) properites 폴더 안에 error.properties파일 생성

     #에러종류.빈이름.프로퍼티명 

     #어노테이션명.클래스명(맨앞 소문자).필드명

[ error.properites 파일 ]

Max.data.num1 = num1값은 100이 넘어가면 안 된다 
Size.data.num2=num2값은 크기가 4에서 10 사이여야 한다 

#에러종류.빈이름.프로퍼티명 
#어노테이션명.클래스명(맨앞 소문자).필드명

 

3) views 폴더 안에 index.jsp, test1.jsp 

[ index.jsp JSP 파일 ]

<%@ page language="java" contentType="text/html; charset=UTF-8"
   pageEncoding="UTF-8"%>

<body>

<a href="t1">test1</a><br>

</body>
</html>
[ test1.jsp JSP 파일 ]

<%@ page language="java" contentType="text/html; charset=UTF-8"
   pageEncoding="UTF-8"%>
<%@ taglib prefix="spring" uri="http://www.springframework.org/tags" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
<body>

<form:form action="test1_proc" modelAttribute="data" method="post">
	num1: <form:input path="num1" type="text"/><br> <!-- name 똑같아야 주입 됨 -->
	num2: <form:input path="num2" type="text"/><br>
	
	<button type="submit">확인</button>
</form:form>

</body>
</html>
[ test2.jsp JSP 파일 ]

<%@ page language="java" contentType="text/html; charset=UTF-8"
   pageEncoding="UTF-8"%>

<body>
<!-- 적은값이 Data 클래스의 어노테이션 조건에 맞아야함 =@Max와 @Size -->
	${data.num1 }
	${data.num2 }
	
</body>
</html>

 

4) kr.bit.controller package 안에 SpringController.java class 에서 

package kr.bit.controller;

import javax.validation.Valid;

import org.springframework.stereotype.Controller;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;

import kr.bit.beans.Data;

//properties -> 실행 중 절대 변하지 않는 값들을 properties 파일 안에 넣어줘야 함 
//ex) 유효성 검사, DB정보 (=유효성검사를 properties안에 싹다 넣어 줌)
@Controller
public class SpringController {

	@GetMapping("/t1")
	public String t1(Data data) {
		return "test1";
	}
	
	@PostMapping("/test1_proc")
	public String test1_proc(@Valid Data data, BindingResult result) {
		if(result.hasErrors()) {
			return "test1"; //error메시지 띄울거임 -> 유효성 검사에 위배되었으므로 
		}
		return "test2"; //입력된 값을 띄운다 
	}

}

 

5) ServletAppContext.java class 

    이부분 파일명 고쳐주기 res.setBasename("/WEB-INF/properties/error"); //확장자 빼고 파일명만 적으면 됨 

package kr.bit.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.support.ReloadableResourceBundleMessageSource;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.ViewResolverRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@Configuration
@EnableWebMvc
@ComponentScan("kr.bit.controller")
@ComponentScan("kr.bit.beans")
public class ServletAppContext implements WebMvcConfigurer{
	
	@Override
	public void configureViewResolvers(ViewResolverRegistry registry) {
		WebMvcConfigurer.super.configureViewResolvers(registry);
		registry.jsp("/WEB-INF/views/",".jsp");
	}
	
	@Override
	public void addResourceHandlers(ResourceHandlerRegistry registry) {
		WebMvcConfigurer.super.addResourceHandlers(registry);
		registry.addResourceHandler("/**").addResourceLocations("/resources/");
	}
	
	//Properties파일을 jsp 화면에 가져가지 위해 등록해야함 
	@Bean
	public ReloadableResourceBundleMessageSource source() {
		ReloadableResourceBundleMessageSource res = new ReloadableResourceBundleMessageSource();
		
		//하나일 경우는 res.setBasename을 사용 / 복수는 names ! 
		res.setBasename("/WEB-INF/properties/error"); //확장자 빼고 파일명만 적으면 됨 
		res.setDefaultEncoding("UTF-8");
		
		return res;
	}
}

 


 

[ MVC_Basic_19 - project ] - checkbox, radio 

 

1) kr.bit.beans package 안에 Data.java, Data2.java class 생성

    checkbox, radio는 배열로 받음 []

package kr.bit.beans;

public class Data {

	private String s1;
	private String s2;
	private String s3;
	private String s4;
	
	private String s5[];
	private String s6[];
	private String s7[];
	private String s8[];
	
	private String s9;
	private String s10;
	private String s11;
	private String s12;
	
	public String getS1() {
		return s1;
	}
	public void setS1(String s1) {
		this.s1 = s1;
	}
	public String getS2() {
		return s2;
	}
	public void setS2(String s2) {
		this.s2 = s2;
	}
	public String getS3() {
		return s3;
	}
	public void setS3(String s3) {
		this.s3 = s3;
	}
	public String getS4() {
		return s4;
	}
	public void setS4(String s4) {
		this.s4 = s4;
	}
	public String[] getS5() {
		return s5;
	}
	public void setS5(String[] s5) {
		this.s5 = s5;
	}
	public String[] getS6() {
		return s6;
	}
	public void setS6(String[] s6) {
		this.s6 = s6;
	}
	public String[] getS7() {
		return s7;
	}
	public void setS7(String[] s7) {
		this.s7 = s7;
	}
	public String[] getS8() {
		return s8;
	}
	public void setS8(String[] s8) {
		this.s8 = s8;
	}
	public String getS9() {
		return s9;
	}
	public void setS9(String s9) {
		this.s9 = s9;
	}
	public String getS10() {
		return s10;
	}
	public void setS10(String s10) {
		this.s10 = s10;
	}
	public String getS11() {
		return s11;
	}
	public void setS11(String s11) {
		this.s11 = s11;
	}
	public String getS12() {
		return s12;
	}
	public void setS12(String s12) {
		this.s12 = s12;
	}
}
package kr.bit.beans;

public class Data2 {

	   private String s1;
	   private String s2;
	   
	   public String getS1() {
	      return s1;
	   }
	   public void setS1(String s1) {
	      this.s1 = s1;
	   }
	   public String getS2() {
	      return s2;
	   }
	   public void setS2(String s2) {
	      this.s2 = s2;
	   }
}

 

2) SpringConfigClass.java 

package kr.bit.config;

import javax.servlet.Filter;

import org.springframework.web.filter.CharacterEncodingFilter;
import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;

public class SpringConfigClass extends AbstractAnnotationConfigDispatcherServletInitializer {
	
	//DispatcherServlet에 매핑할 요청주소를 세팅 
	@Override
	protected String[] getServletMappings() {
		// TODO Auto-generated method stub
		return new String[] {"/"};
	}
	
	//MVC 설정을 위한 클래스 지정 
	@Override
	protected Class<?>[] getServletConfigClasses() {
		// TODO Auto-generated method stub
		return new Class[] {ServletAppContext.class};
	}
	
	//웹에서 사용할 Bean들을 정의하기 위한 클래스 지정 
	@Override
	protected Class<?>[] getRootConfigClasses() {
		// TODO Auto-generated method stub
		return new Class[] {RootAppContext.class};
	}
	
	@Override
	protected Filter[] getServletFilters() {
		// TODO Auto-generated method stub
		CharacterEncodingFilter encodingFilter = new CharacterEncodingFilter();
		encodingFilter.setEncoding("UTF-8");
		return new Filter[] {encodingFilter};
	}
	

}

 

3) views 폴더 안에 index.jsp, test1.jsp 

[ index.jsp JSP 파일 ]

<%@ page language="java" contentType="text/html; charset=UTF-8"
   pageEncoding="UTF-8"%>

<body>

<a href="t1">test1</a><br>

</body>
</html>
[ test1.jsp JSP 파일 ]

<%@ page language="java" contentType="text/html; charset=UTF-8"
   pageEncoding="UTF-8"%>
<%@ taglib prefix="spring" uri="http://www.springframework.org/tags" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
<body>

<form:form modelAttribute="data">
	<form:select path="s1">
		<form:option value="d1">one</form:option>
		<form:option value="d2">two</form:option>
		<form:option value="d3">three</form:option>
	</form:select>

	<form:select path="s2">
		<form:options items="${requestScope.li1 }"/>
	</form:select>
	
	<form:select path="s3">
		<form:options items="${requestScope.li2 }"/>
	</form:select>
	
	<form:select path="s4">
		<form:options items="${requestScope.li3 }" itemLabel="s1" itemValue="s2"/>
	</form:select><br><br>
	
	<!-- -------------------------------------------------------- -->
	체크박스 <br>
	<form:checkbox path="s5" value="d1"/>one
	<form:checkbox path="s5" value="d2"/>two
	<form:checkbox path="s5" value="d3"/>three <br>
	
	<form:checkboxes items="${requestScope.li1 }" path="s6"/> <br>
	<form:checkboxes items="${requestScope.li2 }" path="s7"/> <br>
	<form:checkboxes items="${requestScope.li3 }" path="s8"/> <br><br>
	
	<!-- -------------------------------------------------------- -->
	라디오버튼 <br>
	<form:radiobutton path="s9" value="d1"/>one
	<form:radiobutton path="s9" value="d2"/>two
	<form:radiobutton path="s9" value="d3"/>three<br>
	
	<form:radiobuttons path="s10" items="${requestScope.li1 }"/> <br>
	<form:radiobuttons path="s11" items="${requestScope.li2 }"/> <br>
	<form:radiobuttons path="s12" items="${requestScope.li3 }" itemLabel="s1" itemValue="s2"/> <br>
</form:form>

</body>
</html>

 

4) kr.bit.controller package 안에 SpringController.java class 에서 

    문자배열 model에 저장을 하고 li2에 저장을 함 

package kr.bit.controller;

import java.util.ArrayList;

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;

import kr.bit.beans.Data;
import kr.bit.beans.Data2;

//properties -> 실행 중 절대 변하지 않는 값들을 properties 파일 안에 넣어줘야 함 
//ex) 유효성 검사, DB정보 (=유효성검사를 properties안에 싹다 넣어 줌)
@Controller
public class SpringController {

	@GetMapping("/t1")
	public String t1(Data data, Model model) {
		data.setS1("d2"); //S1에 d2를 줬기 때문에 브라우저에서 select의 기본값이 two로 설정되어있어여 함 
		data.setS2("d3"); //S2에 d3를 줬기 때문에 브라우저에서 select의 기본값이 d3로 설정되어있어여 함 
		data.setS3("d2");
		data.setS4("d2");
		
		String []str = {"d1","d3"};
		data.setS5(str);
		data.setS6(str);
		data.setS7(str);
		data.setS8(str);
		
		data.setS9("d2");
		data.setS10("d2");
		data.setS11("d2");
		data.setS12("d2");
		
		/////////////////////////////////////////////////////////////
		
		String []str2 = {"d1","d2","d3"};
		model.addAttribute("li1",str2); //문자배열을 li1이라는 문자열에 담음
		
		ArrayList<String> li2 = new ArrayList<String>();
		li2.add("d1");
		li2.add("d2");
		li2.add("d3");
		model.addAttribute("li2",li2);
		
		Data2 b1=new Data2();
		Data2 b2=new Data2();
		Data2 b3=new Data2();
		
		b1.setS1("one");
		b1.setS2("d1");
		
		b2.setS1("two");
		b2.setS2("d2");
		
		b3.setS1("three");
		b3.setS2("d3");
		
		ArrayList<Data2> li3 = new ArrayList<Data2>();
		li3.add(b1);
		li3.add(b2);
		li3.add(b3);
		
		model.addAttribute("li3",li3);
		
		return "test1";
	}


}

728x90