[목차]

8. Controller 처리

    ① Client요청을 Controller로 연결하기
    공유 객체 사용
    패턴을 사용한 경로 매핑
    @annotation을 이용한 Controller호출
    Spring MVC Project를 사용
    @RequestParam 사용(get)
        * Controller 값 처리(기존) : getParameter()
        * Controller 값 처리(어노테이션 사용)
        * get 방식은 한글이 안깨지나 post 방식사용시 한글이 깨진다. Encording을 하여 한글 깨짐을 방지한다.
    FormBean, @ModelAttribute 사용(post)
        * Controller 값 처리(기존) : getParameter()
        * Controller 값 처리(FormBean 사용)
        * Controller 값 처리(@ModelAttribute 사용)

 


[내용]

1) Client요청을 Controller로 연결하기

 

    : implements Controller와 @Controller 사용

 

=sprweb3

 - start.html

<body>
	<a href="hello.do">클릭 1-1(get)</a>
	<form action="hello.do" method="post">
		<input type="submit" value="클릭 1-2(post)"/>
	</form>
	<hr>
	<a href="world.do">클릭 2-1</a>
	<a href="good.do">클릭 2-2</a>
	<a href="hi/nice.do">클릭 2-3</a>
	<form action="korea.do" method="get">
		<input type="submit" value="클릭 2-4(get)"/>
	</form>
	<form action="usa.do" method="post">
		<input type="submit" value="클릭 2-4(post)"/>
	</form>
</body>

 => 클릭 1-1 (요청 : hello.do / get)

      클릭 1-2 (요청 : hello.do / post)

      클릭 2-1 (요청 : world.do / get)

      클릭 2-2 (요청 : good.do / get)

      클릭 2-3 (요청 : hi/nice.do / get)

      클릭 2-4 (요청 : korea.do / get)

      클릭 2-4 (요청 : usa.do / post)

 

 

 - web.xml

<!-- DispatcherServlet는 test-servlet.xml의 설정을 불러온다. -->
<servlet>
	<servlet-name>test</servlet-name>
	<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
	<!-- servlet-name이 아닌 다른  path로 연결할 경우 사용-->
	<init-param>
		<param-name>contextConfigLocation</param-name>
		<param-value>
			<!-- 공백 구분 -->
			/WEB-INF/abc/hello-servlet.xml
			/WEB-INF/def/world-servlet.xml
		</param-value>
	</init-param>
</servlet>
<servlet-mapping>
	<servlet-name>test</servlet-name>
	<url-pattern>*.do</url-pattern>
</servlet-mapping>

=> test-servlet.xml이 아닌 다른 patch로 연결할 경우, <init-param> 태그를 사용한다.

     hello-servlet, world-servlet으로 연결된다.

 

 

- hello-servlet.xml/ world-servlet.xml

 * Controller implemets(상속)을 사용할 경우

<!-- 2. Handler Mapping -->
<bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"/>

<!-- 3. Controller -->
<bean name="/hello.do" class="pack.HelloController"></bean>

<!-- 5. ViewResover -->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
	<property name="prefix" value="/views/"/>
	<property name="suffix" value=".jsp"/>
</bean>

 => hello.do 요청이 올 경우 HelloController가 실행된다.

 

  * @Controller(어노테이션)을 사용할 경우

<!-- 어노테이션 사용시 삭제 -->
<!-- 2. Handler Mapping -->
<!-- 
<bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"/>
 -->
<!-- 3. Controller -->
<!--  
<bean name="/hello.do" class="pack.HelloController"></bean>
-->
<!-- 어노테이션 사용시 추가 -->
<context:component-scan base-package="pack"/>

<!-- 5. ViewResover -->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
	<property name="prefix" value="/views/"/>
	<property name="suffix" value=".jsp"/>
</bean>

 => 어노테이션 사용시 <context:component-scan>를 사용한다. pack package의 어노테이션이 동작하도록 한다.

 

 

 - HelloController
 * Controller implemets(상속)을 사용할 경우

public class HelloController implements Controller{
	
	@Override
	public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response)
									throws Exception {
		ModelAndView modelAndView = new ModelAndView();
		modelAndView.setViewName("veiw1"); // veiw1.jsp에 연결 
		modelAndView.addObject("message", "hello"); // 모델에 다녀왔다 가정. // key-value 전달.
		
		return modelAndView;
	}
}

=> hello-servlet.xml/ world-servlet.xml에서 연결한 hello.do 요청 발생 시 실행된다.

=> handlerRequest() 메소드를 오버라이딩하여 request를 처리한다.

=> setVieName("파일명")으로 view1에 연결된다. .hello-servlet.xml 파일의 ViewResover 처리로 /views/view1.jsp파일이

     연결된다.

 => addObject(key, value)를 이용하여 값을 전달한다.

 

  * @Controller(어노테이션)을 사용할 경우

 

@Controller
@RequestMapping("hello.do") // 모든 메소드가 수행된다.
public class HelloController{
	@RequestMapping(method=RequestMethod.GET)
	//@RequestMapping("hello.do") // 해당 메소드만 실행된다.
	public ModelAndView aaa() {
		ModelAndView modelAndView =  new ModelAndView();
		modelAndView.setViewName("view1");
		modelAndView.addObject("message", "hello aaa");
		return modelAndView;
	}
	
	@RequestMapping(method=RequestMethod.POST)
	//@RequestMapping("hello.do")
	public ModelAndView bbb() {
		ModelAndView modelAndView =  new ModelAndView();
		modelAndView.setViewName("view1");
		modelAndView.addObject("message", "hello bbb");
		return modelAndView;
	}
}

 => hello-servlet.xml의 <context:component-scan>태그로 인해 @Controller가 동작한다.

      @Controller : 클라이언트 요청에 따라 해당 클래스가 Controller동작을 하게된다.

      @RequestMapping("요청명") : 요청명에 해당하는 요청이 들어올 경우 클래스가 실행된다.

      @RequestMapping(method=RequestMethod.GET) : Get방식의 요청이 들어올때만 실행하게 한다.

      @RequestMapping(method=RequestMethod.POST) : Post방식의 요청이 들어올때만 실행하게 한다.

 => ModelAndView객체를 리턴하도록 하여 값을 전달한다. 메소드명을 임의 지정 가능하다.

 

 

 -  WorldController
 * Controller implemets(상속)을 사용할 경우

public class WorldController implements Controller{
	
	@Override
	public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response)
								throws Exception {
		
		ModelAndView modelAndView = new ModelAndView();
		modelAndView.setViewName("view2"); // veiw1.jsp에 연결 
		modelAndView.addObject("message", "hi world"); // 모델에 다녀왔다 가정. // key-value 전달.
		
		return modelAndView;
	}
}

 => HelloController와 동일

 

  * @Controller(어노테이션)을 사용할 경우

 

@Controller
public class WorldController{
	@RequestMapping({"/world.do","/good*.*","/hi/nice.do"}) // 여러개의 요청을 받을 수 있음.
	//@RequestMapping("world.do")
	public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response)
					throws Exception {
		
		ModelAndView modelAndView = new ModelAndView();
		modelAndView.setViewName("view2"); // veiw1.jsp에 연결 
		modelAndView.addObject("message", "hi world"); // 모델에 다녀왔다 가정. key-value 전달.
		
		return modelAndView;
	}
	
	@RequestMapping(value="/korea.do", method=RequestMethod.GET) // GET만 받을 수 있다.
	//@RequestMapping({"/korea.do"})// Get과 Post를 모두 받을 수 있다.
	public ModelAndView handleRequest2(HttpServletRequest request, HttpServletResponse response)
					throws Exception {
		
		ModelAndView modelAndView = new ModelAndView();
		modelAndView.setViewName("view2"); // veiw1.jsp에 연결 
		modelAndView.addObject("message", "hi world korea"); // 모델에 다녀왔다 가정. key-value 전달.
		
		return modelAndView;
	}
    
	@RequestMapping(value="/usa.*", method=RequestMethod.POST) // POST만 받을 수 있다.
	//@RequestMapping(value="/usa.*", method=RequestMethod.GET) // GET만 받을 수 있다.
	//@RequestMapping({"/usa.*"})
	public ModelAndView handleRequest3(HttpServletRequest request, HttpServletResponse response)
					throws Exception {
		
		ModelAndView modelAndView = new ModelAndView();
		modelAndView.setViewName("view2"); // veiw1.jsp에 연결 
		modelAndView.addObject("message", "hi world usa"); // 모델에 다녀왔다 가정. key-value 전달.
		
		return modelAndView;
	}
}

 => @RequestMapping({요청명1, 요청명2,..}) : 배열을 사용하여 여러개의 요청명을 받을 수 있다.

      @RequestMapping(value="요청명", method=RequestMethod.GET) : 요청과 method 방식을 설정할 수 있다.

      요청명에 * 를 사용하여 복수의 요청을 받을 수 있다.

 

 

 - view1.jsp / view2.jsp

<body>
	hello 결과 : ${requestScope.message}
</body>

 => Controller에서 addObject()메소드로 전달한 value를 key를 사용하여 받을 수 있다. (EL 사용 - ${key})

 

 


2) 공유 객체 사용

 = spr4_share

 - index.html

<body>
	클래스 간 자원 공유<br>
	<a href="hello.do">요청 1</a><br>
	<a href="world.kor">요청2</a><br>
</body>

 

 

 - web.xml

<!-- WebApplicationContext보다 먼저 수행 : 공유 자원 설정시 필요 -->
<context-param>
	<param-name>contextConfigLocation</param-name>
	<param-value>/WEB-INF/applicationContext.xml</param-value>
</context-param>

<listener>
	<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>

 => applicationContext.xml에 공유자원을 설정한다.

<!-- WebApplicationContext에 의해 자동 수행 -->
<servlet>
	<servlet-name>hello</servlet-name>
	<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
	<!-- <load-on-startup> init() 메소드 호출 순서 -->
	<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
	<servlet-name>hello</servlet-name>
	<url-pattern>*.do</url-pattern>
</servlet-mapping>

<servlet>
	<servlet-name>world</servlet-name>
	<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
	<load-on-startup>2</load-on-startup>
</servlet>
<servlet-mapping>
	<servlet-name>world</servlet-name>
	<url-pattern>*.kor</url-pattern>
	<!-- <url-pattern>/</url-pattern> 모든 요청사항 -->
</servlet-mapping>

 => *.do 요청과 hello-servlet.xml 연결

 => *.kor요청과 world-servlet.xml 연결

 

 

- applicationContext.xml

<!-- 공유 자원 객체 생성 -->
<bean id="sharedData" class="pack.SharedData">
	<property name = "shared" value="스프링 프로젝트 공유자원입니다."/>
</bean>

 => setter injection을 이용하여 공유자원 객체 shard에 value를 설정한다.

 

 

 - hello-servlet.xml, world-servlet.xml

<!-- 2. Handler Mapping -->
<bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"/>

<!-- 3. Controller -->  
<bean name="/hello.do" class="pack.HelloController">
	<property name="data" ref="sharedData"/>
</bean>

<!-- 5. ViewResover -->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
	<property name="prefix" value="/views/"/>
	<property name="suffix" value=".jsp"/>
</bean>

 => hello.do과 HelloController 연결. HelloController에 공유객체를 setter injection한다.

 

 

 - SharedData

public class SharedData {
	private String shared;
	public void setShared(String shared) {
		this.shared = shared;
	}
	public String getShared() {
		return shared;
	}
}

 => getter, setter를 이용하여 공유객체를 사용한다.

 

 

 - HelloController

public class HelloController implements Controller{
	private SharedData data; // 공유객체 선언.
	// setter injection에 사용
	public void setData(SharedData data) {
		this.data = data;
	}
	
	@Override
	public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response)
					throws Exception {
		// 현재 클래스가 공유자원을 사용
		ModelAndView modelAndView = new ModelAndView("helloworld"); // ViewFile명
		modelAndView.addObject("msg", data.getShared() + "hello");
	
		return modelAndView;
	}
}

 => ModelAndView("ViewFile명") : ModelAndView 생성자에 매개변수로 ViewFile명을 전달하여 ViewFile에 연결.  (setViewName("ViewFile명")과 동일)
 => addObject()메소드 사용하여 공유 객체의 내용 전달.

 

 

 - helloworld.jsp

<body>
	결과 : ${msg}
</body>

 


3) 패턴을 사용한 경로 매핑

 

 =spr5_arrange

 - index.html

<body>
	@MVC 기본정리<p/>
	<a href="hello.do">인사하기 1</a>
</body>

 => hello.do 요청. (get)

 

 

 - web.xml

<!-- WebApplicationContext에 의해 자동 수행 -->
<servlet>
	<servlet-name>test</servlet-name>
	<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
	<!-- <load-on-startup> init() 메소드 호출 순서 -->
	<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
	<servlet-name>test</servlet-name>
	<url-pattern>*.do</url-pattern>
</servlet-mapping>

 => test-servlet.xml과 *.do를 url mapping한다.

 => <servlet-mapping>이 여러개 일 경우 <load-on-startup>로 init() 메소드 호출 순서를 지정할 수 있다.

 

 

 - test-servlet.xml

 * mapping 방법1 : 요청 url과 동일한 이름을 bean과 매핑(basic)

<!-- 2. Handler Mapping -->
<bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"/>

<!-- 3. Controller -->
<bean name="/hello.do" class="pack.controller.HelloController">
	<property name="helloModel" ref="helloModel"></property>
</bean>

<bean id="helloModel" class="pack.model.HelloModel"></bean>

<!-- 5. ViewResover -->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
	<property name="prefix" value="/views/"/>
	<property name="suffix" value=".jsp"/>
</bean>

=> HelloController에 helloModel를 setter injection하여 객체 생성.

=>  hello.do 요청과 HelloController을 mapping

 

* mapping 방법2 : 경로 매핑(패턴 : *, ?)

<!-- 2. Handler Mapping-->
<bean class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
	<property name="alwaysUseFullPath" value="true"/>
	<property name="mappings">
		<props>
			<!-- <prop key="*.do">hi</prop> -->
			<!-- <prop key="h*.do">hi</prop> -->
			<!--<prop key="/**/*.do">hi</prop> -->
			<prop key="/**/?????.do">hi</prop>
		</props>
	</property>
</bean>

<!-- 3. Controller -->
<bean name="hi" class="pack.controller.HelloController">
	<property name="helloModel" ref="helloModel"></property>
</bean>

<bean id="helloModel" class="pack.model.HelloModel"></bean>

<!-- 5. ViewResover -->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
	<property name="prefix" value="/views/"/>
	<property name="suffix" value=".jsp"/>
</bean>

 =>SimSimpleUrlHandlerMapping사용하여 <prop>에 경로 매핑 가능하다.

 => ?는 글자 갯수. * 복수개의 문자를 나타냄.

 => HelloController mapping의 name을 <prop>의 값으로 받아 패턴을 연결한다.

 

 

 - HelloController

public class HelloController implements Controller{
	
	private HelloModel helloModel;
	
	//setter injection
	public void setHelloModel(HelloModel helloModel) {
		this.helloModel = helloModel;
	}
	
	@Override
	public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response)
				throws Exception {
		// 모델 만들고 모델과 통신하기
		String result = helloModel.getGreeting();
        
		ModelAndView modelAndView = new ModelAndView();
		//ModelAndView modelAndView = new ModelAndView("hello"); // ViewFile명
		
		modelAndView.setViewName("hello");
		modelAndView.addObject("result",result); // forword 방식(default)
		
		//modelAndView.setViewName("redirect:/views/hello.jsp?result='d'"); // reditect 방식
	
		return modelAndView;
	}
}

 => Controller를 상속받고 handleRequest 오버라이딩하여 요청사항을 처리한다.
 => 기본 방식을 forward로 하여 /views/hello.jsp에 addObject(key, value)로 값을 전달한다.
 => setViewName("redirect:/views/hello.jsp")으로 redirect 가능하다.

 

 - HelloModel

public class HelloModel {
	public String getGreeting() {
		int hour = Calendar.getInstance().get(Calendar.HOUR_OF_DAY);
		if(hour >= 6 & hour <= 10) {
			return "좋은 아침입니다.";
		}else if(hour >= 12 & hour <= 15) {
			return "점심은 맛있게 드셨나요";
		}else if(hour >= 18 & hour <= 22) {
			return "좋은 저녁되세요";
		}else {
			return "안녕하세요";
		}
	}
}

 => 기능을 담당하는 model 클래스

 

 

 - hello.jsp

<body>
 인사말 : ${result}
</body>

 


4) @annotation을 이용한 Controller호출

 

 = sprwrb6_annotation

 - index.html

<body>
	@MVC 기본정리<p/>
	<a href="hello.do">인사하기 1 - annotation</a><br>
	<a href="abc/world.do">인사하기 2 - annotation</a><br>
	<a href="kbs.do">인사하기 3 - annotation</a><br>
	<a href="hello">인사하기 4 - annotation</a><br>
	<br>
	<a href="kakao.do">인사하기 5 - annotation</a><br>
	<a href="mbc">인사하기 6 - annotation</a><br>
	<a href="sbs">인사하기 7 - annotation</a><br>
</body>

 => 요청 url 설정.

 

 - web.xml

<servlet>
	<servlet-name>test</servlet-name>
	<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
</servlet>
<servlet-mapping>
	<servlet-name>test</servlet-name>
    <!--  <url-pattern>*.do</url-pattern>  확장자가 do인 요청 -->
  	<!-- <url-pattern>/aa.jsp</url-pattern> 단일 파일일 경우 /를 붙인다.-->
	<url-pattern>/</url-pattern><!-- 모든요청 -->
</servlet-mapping>

 => <url-pattern>/</url-pattern> 모든요청.
 => test-servlet 실행.

 

 

 - test-servlet.xml

* web.xml의 <url-pattern>/</url-pattern>를 적용하려면 다음 코드를 test-servlet.xml에 추가한다.

<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter">
	<property name="alwaysMustRevalidate" value="true"/>
</bean>

<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping">
	<property name="alwaysUseFullPath" value="true"/>
</bean>

<mvc:annotation-driven/>
<mvc:default-servlet-handler/>

 => 모든 요청 경로가 연결된다.

 => <mvc:annotation-driven/> : @annotation기반의 Controller호출

 => <mvc:default-servlet-handler/> : 처리하지 못한 요청을 DefaultSerlvet에게 넘겨준다.

<!-- annotation인 경우 -->
<context:component-scan base-package="pack.controller"/>
<context:component-scan base-package="pack.model"/>

<!-- 5. ViewResover -->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
	<property name="prefix" value="/views/"/>
	<property name="suffix" value=".jsp"/>
</bean>

 => <context:component-scan> : 어노테이션 사용시 사용.

 


- HelloController

@Controller // controller implements
@RequestMapping({ "hello.do", "abc/world.do", "k*", "mbc", "sbs", "h*" }) // url mapping
public class HelloController {
	
	@Autowired // setter injection
	private HelloModel helloModel;
	
	@RequestMapping(method=RequestMethod.GET) // GET방식과 mapping 
	public ModelAndView abc() { // 모델 만들고 모델과 통신하기
		String result = helloModel.getGreeting();
		ModelAndView modelAndView = new ModelAndView();
		 
		modelAndView.setViewName("hello");
		modelAndView.addObject("result",result); // forword 방식(default)
		  
		//modelAndView.setViewName("redirect:/views/hello.jsp?result='d'"); // reditect 방식
		 
		return modelAndView; 
	}
}

 => @Controller : 어노테이션을 사용하여 Controller를 호출한다.

 => ModelAndView객체를 리턴값으로 값을 전달한다. result key에 result value를 전달한다.

 

@Controller // controller implements
@RequestMapping({ "hello.do", "abc/world.do", "k*", "mbc", "sbs", "h*" }) // url mapping
public class HelloController {
	
	@Autowired // setter injection
	private HelloModel helloModel;
    
	// Map을 이용할 경우 출력할 View의 ViewName을 명시하지않는다.
	// 요청명을 그대로 ViewName으로 가져간다.
	// 요청명 hello, view명 hello.jsp
	@RequestMapping(method = RequestMethod.GET) // GET방식과 mapping
	public Map<String, Object> abc() {
		String result = helloModel.getGreeting();
		
		HashMap<String, Object> map = new HashMap<String, Object>();
		
		map.put("result", result); // 요청명이 view 파일명이 된다.
		
		return map;
	}
}

 => Map을 이용할 경우 출력할 View의 ViewName을 명시하지않는다.
      요청명을 그대로 ViewName으로 가져간다. (spec에 약속된 사항)
      요청명 hello, view명 hello

=> HashMap를 이용하여 key, value를 전달.

@Controller // controller implements
@RequestMapping({ "hello.do", "abc/world.do", "k*", "mbc", "sbs", "h*" }) // url mapping
public class HelloController {
	
	@Autowired // setter injection
	private HelloModel helloModel;
    
	@RequestMapping(method = RequestMethod.GET) // GET방식과 mapping
	public Model abc(Model model) {
		String result = helloModel.getGreeting();
		
		model.addAttribute("result",result); // 요청명이 view 파일명이 된다.
		
		return model;
	}
}

 => Model 객체를 이용하여 addAttribute()메소드를 이용하여 값을 전달한다.

      요청명을 그대로 ViewName으로 가져간다. (spec에 약속된 사항)

@Controller // controller implements
@RequestMapping({ "hello.do", "abc/world.do", "k*", "mbc", "sbs", "h*" }) // url mapping
public class HelloController {
	@Autowired // setter injection
	private HelloModel helloModel;
	@RequestMapping(method = RequestMethod.GET) // GET방식과 mapping
	public String abc() {
		String result = helloModel.getGreeting();
		
		return "hello";
	}
}

 => String 리턴값을 가져간다.

      요청명을 그대로 ViewName으로 가져간다. (spec에 약속된 사항)

 

 

 - HelloModel

@Component
public class HelloModel {
	public String getGreeting() {
		int hour = Calendar.getInstance().get(Calendar.HOUR_OF_DAY);
		if(hour >= 6 & hour <= 10) {
			return "좋은 아침입니다.";
		}else if(hour >= 12 & hour <= 15) {
			return "점심은 맛있게 드셨나요";
		}else if(hour >= 18 & hour <= 22) {
			return "좋은 저녁되세요";
		}else {
			return "안녕하세요";
		}
	}
}

 

 - hello.jsp

<body>
 - annotation<br>
 인사말 : ${result}
</body>

 

 


5) Spring MVC Project를 사용

 

[New] - [Spring Legacy Project] - project명 입력 - [Spring MVC Project] 선택 - [Next] - aa.bb.cc입력 - [finish]

 

 - pom.xml

<properties>
	<java-version>1.8</java-version>
	<org.springframework-version>5.0.0.RELEASE</org.springframework-version>
	<org.aspectj-version>1.6.10</org.aspectj-version>
	<org.slf4j-version>1.6.6</org.slf4j-version>
</properties>

 => 변경

 

 


6) @RequestParam 사용(get)

 = sprweb8_parameter

 - login.jsp

<form action="login" method="get">
	id : <input type="text" name="id"/><br>
	password : <input type="text" name="pwd"/><br>
	<input type="submit" value="전송(get)">
</form>

 => login url로 name이 id, pwd인 값 전달.(get)

 

 

 - LoginController

* Controller 값 처리(기존) : getParameter()

@Controller
public class LoginController {
	//@RequestMapping("login")
	@RequestMapping(value="login", method=RequestMethod.GET)
	public ModelAndView submit(HttpServletRequest request) {
		String id = request.getParameter("id");
		String pwd = request.getParameter("pwd");
		
		System.out.println("id:"+id);
		System.out.println("pwd:"+pwd);
		
		String data = "";
		if(id.equals("aa") && pwd.equals("11")) {
			data = "로그인 성공";
		}else {
			data = "로그인 실패";
		}
			
		ModelAndView view = new ModelAndView();
		view.setViewName("result");
		view.addObject("data", data);
		
		return view;
	}
}

 => getParameter() 메소드를 사용하여 값을 가져온다.

 => 로직 동작 후 seyViewName()로 result.jsp에 addObject()메소드로 data값을 전달한다.

 

* Controller 값 처리(어노테이션 사용)

@Controller
@RequestMapping("login") // type level mapping
public class LoginController {
	
	@RequestMapping(method=RequestMethod.GET) // method level mapping
	public ModelAndView submit(
			@RequestParam("id") String id,
			@RequestParam("pwd") String pwd) {
		
		String data = "";
		if(id.equals("aa") && pwd.equals("11")) {
			data = "로그인 성공";
		}else {
			data = "로그인 실패";
		}
			
		ModelAndView view = new ModelAndView();
		view.setViewName("result");
		view.addObject("data", data);
		
		return view;
	}
}

 => @RequestParam("name")을 사용하여 getParameter()의 기능을 수행한다.

 

 

 - result.jsp

<body>
	결과 : ${data}
</body>

 


* get 방식은 한글이 안깨지나 post 방식사용시 한글이 깨진다. Encording을 하여 한글 깨짐을 방지한다.

 

 - web.xml

<!-- 한글 깨짐 방지(post) -->
<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>

 => web.xml에 위의 코드를 copy&paste한다.

 


7) FormBean, @ModelAttribute 사용(post)

 

 

 - input.jsp

<h2>* 자료입력</h2>
<form action="sangpum" method="post">
	품명 : <input type="text" name="sang"><br>
	수량 : <input type="text" name="su"><br>
	단가 : <input type="text" name="dan"><br>
	<input type="submit" valus="전송(post)"/>
</form>

 

 - SangpumController

* Controller 값 처리(기존) : getParameter()

@Controller
public class SangpumController {
	@RequestMapping(value="sangpum", method=RequestMethod.POST)
	public ModelAndView submit(HttpServletRequest request) {
		String sang = request.getParameter("sang");
		String su = request.getParameter("su");
		String dan = request.getParameter("dan");
		System.out.println(sang+" "+" "+su+" "+dan);
		
		ModelAndView view = new ModelAndView();
		view.setViewName("result");
		view.addObject("data","good");
		
		return view;
	}
}

* Controller 값 처리(FormBean 사용)

@Controller
public class SangpumController {
	@RequestMapping(value="sangpum", method=RequestMethod.POST)
	public ModelAndView submit(SangpumBean bean) { // 지역 변수
		//클라이언트로 부터 들어오는 데이터 양이 많을 경우 사용(form bean)
		
		System.out.println(bean.getSang()+" "+" "+bean.getSu()+" "+bean.getDan());
		
		ModelAndView view = new ModelAndView();
		view.setViewName("result");
		view.addObject("data","good");
		
		return view;
	}
}

 => 매개변수로 FormBean을 사용하여 값을 전달한다. bean의 범위는 {}안으로 지역변수로 사용된다.

 

* Controller 값 처리(@ModelAttribute 사용)

@Controller
public class SangpumController {
	@Autowired // setter injection
	private SangpumModel sanpumModel;
	
	@RequestMapping(value="sangpum", method=RequestMethod.POST)
	//public ModelAndView submit(SangpumBean bean) { // 지역 변수
	public ModelAndView submit(@ModelAttribute("bean") SangpumBean bean) { // 전역변수
		//클라이언트로 부터 들어오는 데이터 양이 많을 경우 사용(form bean)
		
		System.out.println(bean.getSang()+" "+" "+bean.getSu()+" "+bean.getDan());
		
		ModelAndView view = new ModelAndView();
		view.setViewName("result");
		view.addObject("data",sanpumModel.computeSangpum(bean));
		
		return view;
	}
}

 => 매개변수로 @ModelAttribute을 사용시 bean의 범위는 전역변수로 사용되어 addObject() 메소드를 사용하지않아도

      다른 파일에서 접근이 가능하다.

 

 

 - SangpumBean

@Component
public class SangpumBean { // form bean
	private String sang; // 클라이언트로 부터 전달되어 오는 요청 Parameter값과 변수명을 동일하게 가져간다.
	private int su, dan;
	
	public String getSang() {
		return sang;
	}
	public void setSang(String sang) {
		this.sang = sang;
	}
	public int getSu() {
		return su;
	}
	public void setSu(int su) {
		this.su = su;
	}
	public int getDan() {
		return dan;
	}
	public void setDan(int dan) {
		this.dan = dan;
	}
}

 => Form Bean 정의. Form Bean의 멤버변수는 <form>태그 하위 태그 name의 값과 동일하게 가져간다.

 

 - SangpumModel

@Component // 객체생성
public class SangpumModel { // 비지니스 로직 처리를 하는 모델 영역의 클래스
	public String computeSangpum(SangpumBean bean) {
		int price = bean.getSu() * bean.getDan();
		String data = "품명" + bean.getSang() + " , 금액은 "+price;
		
		return data;
	}
}

 

 

- result.jsp

<body>
post 결과 : ${data}
<br>
${bean.sang}
</body>

 

[목차]

7. Spring MVC Pattern 
1) DispatcherServlet 
2) Servlet을 통한 forward(default) 
3) Annotation 사용

 


[내용]

7. Spring MVC Pattern

1) DispatcherServlet

①Dynamic Web Project 생성 - project 오른쪽 클릭 - Configure - Convert Maven Project - finish

 

② pom.xml에서 </build>아래 추가

<properties>
	<!-- Generic properties -->
	<java.version>14.0.2</java.version>
	<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
	<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
	<!-- Spring -->
	<spring-framework.version>5.0.0.RELEASE</spring-framework.version>
</properties>
<dependencies>
	<!-- Spring MVC -->
	<dependency>
		<groupId>org.springframework</groupId>
		<artifactId>spring-webmvc</artifactId>
		<version>${spring-framework.version}</version>
	</dependency>
	<!-- Other Web dependencies -->
	<dependency>
		<groupId>javax.servlet.jsp</groupId>
		<artifactId>javax.servlet.jsp-api</artifactId>
		<version>2.2.1</version>
	</dependency>
	<dependency>
		<groupId>javax.servlet</groupId>
		<artifactId>jstl</artifactId>
		<version>1.2</version>
	</dependency>
	<dependency>
		<groupId>javax.servlet</groupId>
		<artifactId>javax.servlet-api</artifactId>
		<version>3.1.0</version>
	</dependency>
	<!-- mariadb driver -->
	<dependency>
		<groupId>org.mariadb.jdbc</groupId>
		<artifactId>mariadb-java-client</artifactId>
		<version>2.6.2</version>
	</dependency>
	<dependency>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-jdbc</artifactId>
		<version>2.3.4.RELEASE</version>
	</dependency>
	<dependency>
		<groupId>org.springframework</groupId>
		<artifactId>spring-jdbc</artifactId>
		<version>5.0.0.RELEASE</version>
	</dependency>
	<dependency>
		<groupId>commons-dbcp</groupId>
		<artifactId>commons-dbcp</artifactId>
		<version>1.4</version>
	</dependency>
	<!-- mybatis -->
	<dependency>
		<groupId>org.mybatis</groupId>
		<artifactId>mybatis</artifactId>
		<version>3.5.5</version>
	</dependency>
	<dependency>
		<groupId>org.mybatis</groupId>
		<artifactId>mybatis-spring</artifactId>
		<version>2.0.5</version>
	</dependency>
</dependencies>

 

③ index.html

<a href="index.do">start</a>
<a href="good/nice.do">start2</a>

 => client request시 web.xml 실행

 

④ web.xml

<!-- DispatcherServlet : Spring의 중심이 되는 Servlet -->
<!-- DispatcherServlet는 test-servlet.xml의 설정을 불러온다. -->
<servlet>
	<servlet-name>test</servlet-name>
	<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
</servlet>
<servlet-mapping>
	<servlet-name>test</servlet-name>
	<url-pattern>*.do</url-pattern>
</servlet-mapping>

 => DispatcherServlet가 test-servlet.xml 실행.

 

⑤ test-servlet.xml

Context - WEB_INF에 <servlet-name>의 네임-servlet의 Spring Bean Configuration을 생성.

<!-- 2. Handler Mapping -->
<bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"/>

<!-- 3. Controller -->
<!-- BeanNameUrlHandlerMapping -->
<bean name="/index.do" class="org.springframework.web.servlet.mvc.ParameterizableViewController">
	<property name="viewName" value="list1"/>
	<!-- list1.jsp 실행 -->
</bean>

<bean name="/good/nice.do" class="org.springframework.web.servlet.mvc.ParameterizableViewController">
	<property name="viewName" value="list2"/>
	<!-- list1.jsp 실행 -->
</bean>

<!-- 5. ViewResover -->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
	<property name="prefix" value="/views/"/>
	<property name="suffix" value=".jsp"/>
</bean>

 => context/views/list1.jsp, context/views/list2.jsp 연결

 


2) Servlet을 통한 forward(default)

 - test-servlet.xml

<!-- 2. Handler Mapping -->
<bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"/>

<!-- 3. Controller -->
<bean name="/start.do" class="pack.StartController"></bean>

<!-- 5. ViewResover -->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
	<property name="prefix" value="/views/"/>
	<property name="suffix" value=".jsp"/>
</bean>

 

 - StartController : Controller 상속

public class StartController implements Controller{

	@Override
	public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception {
		// ModelAndView : DB 처리 결과를 기억, 출력을 위한 view 파일명 기억
		System.out.println("StartController handleRequest()수행");
		
		//return new ModelAndView("list"); // 생성자
		
		//모델과 통신하기 생략
		
		ModelAndView modelAndView = new ModelAndView();
		modelAndView.setViewName("list"); // setter. forward 방식으로 파일 요청 처리 (default)
		//request.setAttribute("key", value); // servlet에서 사용하는 방법.
		modelAndView.addObject("say", "messages");//모델과 통신 후 얻어진 결과를 기억했다 가정.(request)
		
		return modelAndView;
	}
}

 

 - list.jsp

기존
<% 
	String str = (String)request.getAttribute("say"); 
	out.println(str);%>

EL
${say} ${requestScope.say}

 


3) Annotation 사용

 - test-servlet.xml

<!-- 2. Handler Mapping -->
<!-- annotation 사용시 삭제 -->
<!-- <bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"/> -->


<!-- 3. Controller -->
<!-- annotation 사용시 삭제 -->
<!-- <bean name="/start.do" class="pack.StartController"></bean> -->
<!-- annotation 사용시 추가 -->
<context:component-scan base-package="pack"/>

<!-- 5. ViewResover -->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
	<property name="prefix" value="/views/"/>
	<property name="suffix" value=".jsp"/>
</bean>

 

 - StartController

@Controller // Conponent와 동일. Cotroller에 사용.
public class StartController{
	@RequestMapping("start.do")
	public ModelAndView handleStart(HttpServletRequest request, HttpServletResponse response) throws Exception {
		// ModelAndView : DB 처리 결과를 기억, 출력을 위한 view 파일명 기억
		System.out.println("StartController handleStart()수행 - annotaion");
		
		//return new ModelAndView("list"); // 생성자
		
		//모델과 통신하기 생략
		
		ModelAndView modelAndView = new ModelAndView();
		modelAndView.setViewName("list"); // setter. forward 방식으로 파일 요청 처리 (default)
		//request.setAttribute("key", value); // servlet에서 사용하는 방법.
		modelAndView.addObject("say", "messages - annotaion");//모델과 통신 후 얻어진 결과를 기억했다 가정.(request)
		
		return modelAndView;
	}
}

 

 

 

[목차]

6. Spring에서 DB 연동 

* Maria DB lib 등록 

① JAVA의 JDBC를 사용  

② DaoSupport 클래스 사용  - spring이 지원 

③ MyBatis 사용

 


 

[내용]

 - Spring api 문서

docs.spring.io/spring/docs/5.0.x/javadoc-api/

* Maria DB lib 등록

① search.maven.org/접속

② Search창에 mariadb-java-client 검색 
③ 버전선택 (2.6.2) 
④ Apache Maven 내용 pom.xml에 copy & paste

<!-- MariaDB driver -->
<dependency>
  <groupId>org.mariadb.jdbc</groupId>
  <artifactId>mariadb-java-client</artifactId>
  <version>2.6.2</version>
</dependency>

⑤ Search창에 spring-boot-starter-jdbc 검색 
⑥ 버전선택 (2.3.6.RELEASE) 
⑦ Apache Maven 내용 pom.xml에 copy & paste

<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-jdbc</artifactId>
  <version>2.3.6.RELEASE</version>
</dependency>

 


① JAVA의 JDBC를 사용 

 

 - SangpumDto

public class SangpumDto {
	
	private String code, sang, su, dan;
	//getter 추가
	//setter 추가
}


 - SangpumInter

public interface SangpumInter {
	ArrayList<SangpumDto> selectList();
}

 

 - SangpumImpl : DB 처리

@Repository // @Componet와 동일. db와 연동할 코드
public class SangpumImpl implements SangpumInter{
	
	private Connection conn;
	private PreparedStatement ptmt;
	private ResultSet rs;
	
	public SangpumImpl() {
		try {
			Class.forName("org.mariadb.jdbc.Driver");
		} catch (Exception e) {
			System.out.println("SangpumImpl err"+e);
		}
	}
	
	public ArrayList<SangpumDto> selectList() {
		ArrayList<SangpumDto> list = new ArrayList<SangpumDto>();
		String sql="select * from sangdata";
		try {
			conn =DriverManager.getConnection("jdbc:mysql://localhost:3306/test","root","123");
			ptmt = conn.prepareStatement(sql);
			rs = ptmt.executeQuery();
			while(rs.next()) {
				SangpumDto dto = new SangpumDto();
				dto.setCode(rs.getString("code"));
				dto.setSang(rs.getString("sang"));
				dto.setSu(rs.getString("su"));
				dto.setDan(rs.getString("dan"));
				list.add(dto);
			}
		} catch (Exception e) {
			System.out.println("selectList err"+e);
		}finally {
			try {
				if(conn != null) conn.close();
				if(ptmt != null) ptmt.close();
				if(rs != null) rs.close();
			} catch (SQLException e) {
				e.printStackTrace();
			}
		}
		return list;
	}

}

    @Repository : @Componet와 동일. db와 연동할 코드

 

 - BusinessInter

public interface BusinessInter {
	public void dataList();
}

 

 - BusinessImpl

@Service // business logic에 사용
public class BusinessImpl implements BusinessInter{
	@Autowired // setter 주입 사용
	private SangpumInter sangpumInter;
	
	/* 생성자 주입 사용가능
	 * @Autowired public BusinessImpl(SangpumInter sangpumInter) {
	 * this.sangpumInter=sangpumInter; }
	 */
	
	public void dataList() {
		ArrayList<SangpumDto> list = sangpumInter.selectList();
		for(SangpumDto s:list) {
			System.out.println(s.getCode()+" "+
		s.getSang()+" "+
		s.getSu()+" "+
		s.getDan());
		}
	}
}

 

 - main

public static void main(String[] args) {
	ApplicationContext context = new ClassPathXmlApplicationContext("dbinit.xml");
	BusinessInter businessInter = (BusinessInter)context.getBean("businessImpl");
	businessInter.dataList();
}

 

 - dbinit.xml

<!-- 어노테이션 사용하도록 설정 -->
<context:component-scan base-package="pack.business"/>
<context:component-scan base-package="pack.model"/>

 

 


② DaoSupport 클래스 사용

 - SangpumDto 
 - BusinessImpl 
 - main 
 동일

 

 - SangpumInter

public interface SangpumInter {
	List<SangpumDto> selectList() throws DataAccessException;
}

 

 - SangpumImpl

// Spring이 제공하는 DB 연결처리. JdbcDaoSupport 상속.
public class SangpumImpl extends JdbcDaoSupport implements SangpumInter {

//	생성자 주입으로 처리 가능.
//	public SangpumImpl(DataSource dataSource) {
//		super.setDataSource(dataSource);
//	}

	public List<SangpumDto> selectList(/* String code */) throws DataAccessException {
		// member : Datasource, JdbcTemplate
		RowMapper rowMapper = new SangRowMapper();
		
		return getJdbcTemplate().query("select * from sangdata", rowMapper);
		// record수 만큼 mapRow() 호출.
		//return getJdbcTemplate().query("select * from sangdata where code=code", rowMapper); 
		// 매개변수 사용시
	}
	
	// 내부 클래스
	class SangRowMapper implements RowMapper{ // RowMapper 상속
		public Object mapRow(ResultSet rs, int rowNum) throws SQLException {
			// mapRow는 레코드 수 만큼 호출. rs.next()가 내부적으로 처리됨.
			System.out.println("rowNum" + rowNum);
			SangpumDto dto = new SangpumDto();
			dto.setCode(rs.getString("code"));
			dto.setSang(rs.getString("sang"));
			dto.setSu(rs.getString("su"));
			dto.setDan(rs.getString("dan"));
			return dto;
		}
	}
}

 

 - BusinessInter

public class BusinessImpl implements BusinessInter{
	private SangpumInter sangpumInter;
	
	public void setSangpumInter(SangpumInter sangpumInter) {
		this.sangpumInter = sangpumInter;
	}
	
	public void dataList() {
		ArrayList<SangpumDto> list = (ArrayList<SangpumDto>)sangpumInter.selectList();
		for(SangpumDto s:list) {
			System.out.println(s.getCode()+" "+
		s.getSang()+" "+
		s.getSu()+" "+
		s.getDan());
		}
	}
}

 

 - dbinit.xml

<!-- db연결 -->
<!-- xml파일이 아니 별도 class로 작성 가능. -->
<bean id="dataSorce" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
	<property name="driverClassName">
		<value>org.mariadb.jdbc.Driver</value>
	</property>
	<property name="url">
		<value>jdbc:mysql://localhost:3306/test</value>
	</property>
	<property name="username">
		<value>root</value>
	</property>
	<property name="password">
		<value>123</value>
	</property>
</bean>
<!-- db연결 클래스 객체 생성 -->
<bean id="sangpumImpl" class="pack.model.SangpumImpl">
<!--JdbcDaoSupport을 상속받았기 때문에 별도로 dataSource setter를 정의하지않아도 setter주입을 할 수 있다.-->
	<property name="dataSource" ref="dataSorce"/>
</bean>
<!-- 객체생성 -->
<bean id="businessImpl" class="pack.business.BusinessImpl">
	<property name="sangpumInter" ref="sangpumImpl"/>
</bean>

 

 - dbinit.xml

<!-- DriverManagerDataSource를 상속받은 db 연결 class 객체 생성. -->
<bean id="dataSource" class="pack.model.DataSourceMaria"></bean>

<!-- db연결 클래스 객체 생성 -->
<bean id="sangpumImpl" class="pack.model.SangpumImpl">
<!-- JdbcDaoSupport을 상속받았기 때문에 별도로 dataSource setter를 정의하지않아도 setter주입을 할 수 있다. -->
	<property name="dataSource" ref="dataSource"/>
</bean>
<!-- 객체생성 -->
<bean id="businessImpl" class="pack.business.BusinessImpl">
	<property name="sangpumInter" ref="sangpumImpl"/>
</bean>

 


③ MyBatis 사용

 

 - db.properties

 

 - DataMapper.xml

<mapper namespace="dev">
 <select id="selectAll" resultType="dto">
  select * from sangdata
 </select>
</mapper>

 

 - Configuration.xml

<configuration>
 <properties resource="pack/mybatis/db.properties" />
 <typeAliases>
 	<typeAlias type="pack.model.SangpumDto" alias="dto"/>
 </typeAliases>
 <environments default="dev">
  <environment id="dev">
   <transactionManager type="JDBC" />
   <dataSource type="POOLED">
    <property name="driver" value="${driver}" />
    <property name="url" value="${url}" />
    <property name="username" value="${username}" />
    <property name="password" value="${password}" />
   </dataSource>
  </environment>
 </environments>
 <mappers>
  <mapper resource="pack/mybatis/DataMapper.xml" />
 </mappers>
</configuration>

 

 - SqlMapConfig

public class SqlMapConfig { // 메뉴얼 확인하여 작성.
	public static SqlSessionFactory sqlSession; // DB의 SQL 명령 실행을 위한 메소드를 가진 객체.
	
	static {
		String resource = "pack/mybatis/Configuration.xml";
		try {
			Reader reader = Resources.getResourceAsReader(resource);
			// Configuration.xml을 읽는다.
			sqlSession = new SqlSessionFactoryBuilder().build(reader);
			// sqlSession 객체를 생성한다.
			reader.close();
		} catch (Exception e) {
			System.out.println("SqlMapConfig err"+e);
		}
	}
	public static SqlSessionFactory getSqlSession() {
		return sqlSession;
	}
}

 

 - SangpumInter

public interface SangpumInter {
	List<SangpumDto> selectDataAll();
}

 

 - SangpumImpl

@Repository
public class SangpumImpl implements SangpumInter{
	
	private SqlSessionFactory factory = SqlMapConfig.getSqlSession();
	
	public List<SangpumDto> selectDataAll() {
		SqlSession sqlSession = factory.openSession();
		List<SangpumDto> list = null;
		
		try {
			list=sqlSession.selectList("selectAll");
		} catch (Exception e) {
			System.out.println("selectDataAll err"+e);
		}finally {
			if(sqlSession!=null) sqlSession.close();
		}
		return list;
	}
}

 

 - BusinessInter

public interface BusinessInter {
	void dataList();
}

 

 - BusinessImpl

@Service
public class BusinessImpl implements BusinessInter{
	
	@Autowired
	private SangpumInter inter;
	
	public void dataList() {
		List<SangpumDto> list =inter.selectDataAll();
		
		for(SangpumDto s: list) {
			System.out.println(s.getCode()+" "+s.getSang()+" "+s.getSu()+" "+s.getDan());
		}
	}
}

 

 - main

public static void main(String[] args) {
	ApplicationContext context = new ClassPathXmlApplicationContext("dbinit.xml");
	BusinessInter businessInter = (BusinessInter)context.getBean("businessImpl");
	businessInter.dataList();
}

 

 - dbinit

<context:component-scan base-package="pack.business"/>
<context:component-scan base-package="pack.model"/>

 

 

 

[목차]

5. AOP (Aspect Oriented Program)

* 스프링 AOP에서 용어
① AOP 구현

 


 

[내용]

5. AOP (Aspect Oriented Program)

 

: 핵심 로직에서 임의의 동작을 진행할 경우 사용. 
: 별도의 클래스로 정의하여 메소드를 탈부착식으로 사용한다.

: ex) 시큐리티, 로그인, 트랜잭션

 

 1) 설정

 ⓛ 사이트 접속 - search.maven.org/

 ② search창에 aspectjweaver 검색

 ③ version 선택

 ④ Apache Maven 내용 copy & paste

 ⑤ search창에 cglib 검색

 ⑥ version 선택

 ⑦ Apache Maven 내용 copy & paste

 ⑧ pom.xml에 Code 추가

<!-- aop -->
<dependencies>
	<dependency>
		<groupId>aspectj</groupId>
		<artifactId>aspectjweaver</artifactId>
		<version>1.5.4</version>
	</dependency>
	<dependency>
		<groupId>cglib</groupId>
		<artifactId>cglib</artifactId>
		<version>3.3.0</version>
	</dependency>
</dependencies>

 ⑨ 경로에 생성됨. C:\Users\wonh\.m2\repository\

 

2) code

- HelloInter

public interface HelloInter {
	void hello();
	void hi();	
}

 - HelloInterImpl

public class HelloInterImpl implements HelloInter{
	
	public HelloInterImpl() {
		System.out.println("HelloInterImpl 생성자");
	}
	
	public void hello() {
		System.out.println("hello 처리");
	}

	public void hi() {
		System.out.println("hi 처리");
	}
}

 - WriteInter

public interface WriteInter {
	void write();
}

 - WriteInterImpl

public class WriteInterImpl implements WriteInter{ // 핵심 로직을 가진 클래스
	
	public WriteInterImpl() {
		System.out.println("WriteInterImpl 생성자");
	}

	public void write() {
		System.out.println("write 수행");
	}
}

 - MyAspect

public class MyAspect { // 관심사항을 가진 클래스
	public void myLogOn() {
		System.out.println("핵심 메소드 수행전 로그온 작업");
	}
	
	public void myLogOut() {
		System.out.println("핵심 메소드 수행후 로그아웃 작업");
	}
	
	public void mySecurity() {
		System.out.println("핵심 메소드 수행전 보안설정");
	}
}

 - AspectProcess

public class AspectProcess { // 여러개의 관심사항들을 모아 처리하는 클래스
	private MyAspect myAspect; // 관심사항 클래스. 여러개 가능
	
	public void setMyAspect(MyAspect myAspect) {
		this.myAspect = myAspect;
	}
	
	public Object logging(ProceedingJoinPoint joinPoint) throws Throwable{
		Object object = null;
		
		myAspect.myLogOn();
		object = joinPoint.proceed(); // 메타파일에서 설정한 핵심 메소드 수행.
		myAspect.myLogOut();
		
		return object;
	}
	
	public Object logging2(ProceedingJoinPoint joinPoint) throws Throwable{
		Object object = null;
		
		myAspect.mySecurity();
		object = joinPoint.proceed(); // 메타파일에서 설정한 핵심 메소드 수행.
		return object;
	}
}

 => logging() 메소드는 myLogOn() -> 핵심로직 -> myLogOut() 순 호출

 => logging2() 메소드는 mySecurity() -> 핵심로직 순 호출

 - main

public static void main(String[] args) {
	//String[] configs = new String[] {"aop1core.xml"}; // 핵심만 수행
	String[] configs = new String[] {"aop1core.xml", "aop1.xml"}; // 핵심 + Aop 수행.
	
	ApplicationContext context = new ClassPathXmlApplicationContext(configs);
	
	WriteInter writeInter = (WriteInter)context.getBean("writeInterImpl");
	writeInter.write();
	System.out.println();
	
	HelloInterImpl helloInter = (HelloInterImpl)context.getBean("helloInterImpl"); // 방법 1
	HelloInter helloInter = context.getBean("helloInterImpl", HelloInter.class); // 방법 2
	helloInter.hi();
	helloInter.hello();
}

 - aop1core.xml

<bean id="writeInterImpl" class="aop1.WriteInterImpl"/>
<bean id="helloInterImpl" class="aop1.HelloInterImpl"/>

 - aop1.xml

<!-- Aspect(Advice) -->
<bean id="aspectProcess" class="aop1.AspectProcess">
	<property name="myAspect" ref="myAspect"/>
</bean>
<bean id="myAspect" class="aop1.MyAspect"/>

<!-- Aop 설정 -->
<aop:config>
	<aop:pointcut expression="execution(public void wri*(..))" id="poi1"/>
	// wri로 시작하고 매개변수가 0개 이상인 메소드
	// <aop:pointcut expression="execution(public void write())" id="poi1"/>
	<aop:aspect ref="aspectProcess">
		<aop:around method="logging" pointcut-ref="poi1"/>
	</aop:aspect>
</aop:config>
<aop:config>
	<aop:pointcut expression="execution(public void hel*(..)) or execution(public void hi*(..))" id="poi2"/>
	// or || and &&
	<aop:aspect ref="aspectProcess">
		<aop:around method="logging2" pointcut-ref="poi2"/>
	</aop:aspect>
</aop:config>

 => 핵심 로직의 wri로 시작하고 메개변수가 0개 이상인 메소드가 호출될때 AspectProcess(Aspect를 처리하는) 클래스의 logging() 메소드가 실행된다.

 => 핵심 로직의 hel로 시작하고 메개변수가 0개 이상인 메소드 또는 hi로 시작하는 메소드가 호출될때 AspectProcess클래스의 logging2() 메소드가 실행된다.

 


 - ArticleInter

public interface ArticleInter {
	void select();
}

 

- ArticleDao

//@Component
//@Repository
@Repository("articleDao")

public class ArticleDao implements ArticleInter{

	public void select() {
		System.out.println("db의 상품 자료를 read");
	}
}

 - LogicInter

public interface LogicInter {
	void selectData_process();
}

 - LogicImpl

public class LogicImpl implements LogicInter{
	private ArticleInter articleInter; 
    
	public LogicImpl() {
	}
	
	public LogicImpl(ArticleInter articleInter) {
		this.articleInter = articleInter; 
	}
	
	public void selectData_process() {
		System.out.println("selectData_proces 수행");
		articleInter.select();
	}
}
@Service
public class LogicImpl implements LogicInter{

	@Autowired
	//@Qualifier("aticleDao")
	private ArticleInter articleInter; 
	
	public void selectData_process() {
		System.out.println("selectData_proces 수행");
		articleInter.select();
	}
}

 

 - ProfileAdvice

public class ProfileAdvice { // Advice, Aspect
	public Object abc(ProceedingJoinPoint joinPoint) throws Throwable{
		//핵심 메소드 이름 얻기
		String methodName = joinPoint.getSignature().toString();
		
		System.out.println(methodName+" 시작 전 작업");
		Object object = joinPoint.proceed(); // 핵심 메소드
		System.out.println(methodName+" 처리 후 작업");
		
		return object;
	}
}
@Aspect
@Component
public class ProfileAdvice { // Advice, Aspect
	@Around("execution(public void selectData_process())")
	public Object abc(ProceedingJoinPoint joinPoint) throws Throwable{
		//핵심 메소드 이름 얻기
		String methodName = joinPoint.getSignature().toString();
		
		System.out.println(methodName+" 시작 전 작업");
		Object object = joinPoint.proceed(); // 핵심 메소드
		System.out.println(methodName+" 처리 후 작업");
		
		return object;
	}
}

 

 - main

public static void main(String[] args) {
	ApplicationContext context = new ClassPathXmlApplicationContext("aop2.xml");
	LogicInter inter = (LogicInter)context.getBean("logicImpl");
	inter.selectData_process();
}

 - aop2.xml

<!-- 핵심 로직 처리용 클래스 -->
<bean id="logicImpl" class="aop2.LogicImpl">
	<constructor-arg>
		<ref bean="articleDao"/>
	</constructor-arg>
</bean>
<bean id="articleDao" class="aop2.ArticleDao"></bean>

<!-- Aop 설정 -->
<bean id="profileAdvice" class="aop2.ProfileAdvice"/>
<aop:config>
	<aop:aspect ref="profileAdvice">
		<aop:pointcut expression="execution(public void selectData_process())" id="poi"/>
		<aop:around method="abc" pointcut-ref="poi"/>
	</aop:aspect>
</aop:config>	

 => 핵심로직의 selectData_process()메소드 호출 시 profileAdvice클래스의 abc()메소드가 호출.

<!-- 객체 생성 : 어노테이션 -->
<context:component-scan base-package="aop3"/>
<!-- Aop 설정 -->
<aop:aspectj-autoproxy/>

 

 

 

* 스프링 AOP에서 용어


 - Joinpoint : ‘클래스의 인스턴스 생성 시점’, ‘메소드 호출 시점’ 및 ‘예외 발생 시점’ 과 같이 어플리케이션을 실행할 때 특정 작업이 시작되는 시점을 의미.

 - Advice : 조인포인트에 삽입되어 동작할 수 있는 코드를 말함.

 - Pointcut : 여러 개의 조인포인트를 하나로 결합한(묶은) 것을 말함.

 - Advisor : 어드바이스와 포인트컷을 하나로 묶어 취급한 것을 말함.

 - Weaving : 어드바이스를 핵심 로직 코드에 삽입하는 것을 말함.

 - Target : 핵심 로직을 구현하는 클레스.

 - Aspect : 여러 객체에 공통으로 적용되는 공통 관점 사항을 말함.

 

 

1) AOP 구현

 - LogicInter

public interface LogicInter {
	void startProcess();
}

 

 - LogicImpl

@Service // @Component와 동일하지만 가독성을 위해 Service기능을 사용하면 @Service를 사용.
public class LogicImpl implements LogicInter{
	
	public LogicImpl() {
	}
	
	public void startProcess() {
		System.out.println("핵심 로직 수행");
	}
}

 

 - aop4.xml

<!-- 어노테이션을 사용하여 객체 생성 -->
<context:component-scan base-package="aop4"/>
<!-- aop를 사용하도록 설정 -->
<aop:aspectj-autoproxy/>

    <context:component-scan base-package="패키지명"/>
    <aop:aspectj-autoproxy/>

 

 - main

public static void main(String[] args) {
	ApplicationContext context = new ClassPathXmlApplicationContext("aop4.xml");
	LogicInter inter = (LogicInter)context.getBean("logicImpl");
	// getBean의 매개변수 : @객체 생성할 클래스명을 첫글자 소문자로 변경하여 생성. 
	inter.startProcess();
}

 

 - RunAspect

// 아이디가 같으면 핵심로직 수행, 다르면 수행하지않도록 구현.
@Component
@Aspect // 독립적으로 동작할 관심 로직 클래스에 사용
public class RunAspect {
	
	@Around("execution(public void startProcess())")
	// 핵심로직의 메소드를 선택. 해당메소드 호출시 관심 메소드 호출.
	//@Around는 핵심로직 실행 전/후 모두 기능을 추가할 수 있다.
	public Object trace(ProceedingJoinPoint joinPoint) throws Throwable{
		
		System.out.println("AOP 시작 : 핵심 로직 처리전 id 검증");
		System.out.print("input id : ");
		Scanner scanner = new Scanner(System.in);
		String id = scanner.nextLine();
		if(! id.equalsIgnoreCase("aa")) { //equalsIgnoreCase() 대소문자 구분하지않고 비교.
			System.out.println("id 불일치하여 작업을 종료합니다.");
			return null;
		}
		
		Object obj = joinPoint.proceed(); // 핵심 로직 수행.
		
		return obj;
	}
}

    @Component

    @Aspect

    @Around("excution(핵심 로직의 메소드)")

    public Object 관심메소드명(ProceedingJoinPoint joinPoint) throws Throwable{ .. }

    Object obj = joinPoint.proceed();

    str1.equalsIgnoreCase(str2)

 

 

 

 

[목차]

2. 생성자 주입(Constructor Injection)

① meta.xml

② 생성자 호출 
③ MVC 패턴 및 다형성 활용한 프로그래밍

④ 생성자 주입(construnctor injection)
⑤생성자 주입방법 2

3. setter 주입(setter injection) 
4. new를 이용한 객체생성과 Spring 객체 생성의 차이 

 


[내용]

2. 생성자 주입(Constructor Injection)

public static void main(String[] args) {
	// new로 객체 생성시 매번 생성된다.
	
	MessageImpl m1 = new MessageImpl("김이상");
	m1.sayHi();
	
	MessageImpl m2 = new MessageImpl("김이상");
	m2.sayHi();
	
	System.out.println("주소 : "+m1);
	System.out.println("주소 : "+m2);
}

 => new를 이용한 객체 생성

 

① meta.xml

<beans>
	<bean id="moneyCalc" name="aa,bb,cc" class="pack.model.MoneyCalc"/>	
	<bean id="myProcess" class="pack.controller.MyProcess">
		<constructor-arg>
			<ref bean="moneyCalc"/>
		</constructor-arg>
	</bean>
</beans>

 => 매개변수가 있는 생성자일 경우 <contructor-arg>와 <ref> 태그를 사용하여 매개변수를 입력한다.

 => 매개변수도 생성자를 생성한다.

<beans>
	<bean id="moneyCalc" name="aa,bb,cc" class="pack.model.MoneyCalc"/>	
	<bean id="myProcess" class="pack.controller.MyProcess">
		<constructor-arg>
			<ref bean="aa"/>
		</constructor-arg>
	</bean>
</beans>

 => id나 name 둘중 무엇을 사용해도 상관없으며, <ref bean="name">에서 name을 호출가능.

 

 

② 생성자 호출

public class Main {
	public static void main(String[] args) {
		ApplicationContext context = new ClassPathXmlApplicationContext("money_init.xml");
		MyInter inter = (MyInter)context.getBean("myProcess");
		inter.inputMoney();
		inter.showResult();
	}
}

 => ApplicationContext 객체 생성시 xml에 연결된 모든 생성자가 호출되며, 각 객체가 생성된다.

 => context의 getBean()메소드로 객체를 get하여 메소드를 사용한다.

 => getBean() 메소드의 리턴값은 Object로 다형성을 사용하여 캐스팅하여 객체를 대입한다.

 => getBean() 리턴 객체도 다형성을 사용하여 interface 객체에 대입하여 사용하는 것을 지향한다.

 

 

③ MVC 패턴 및 다형성 활용한 프로그래밍

 

pakage Controller(Servlet) Model(Dto, Dao-sql)
Interface BusinessInterface ModelInterface
 
Class BusinessClass ModelClass

 => 다형성을 갖춘 MVC Pattern 작성을 지향하여 프로그래밍한다.

 => Controller의 Business Class에서 Model Interface를 호출하여 사용한다.

 => 각 모델은 다형성을 활용하여 테이블에 따른 Sql문을 호출하여 DB와 연결된다.

 => [src.main/java]에 작성한다.

 

- Business Interface

public interface MyInter {
	void inputMoney();
	void showResult();
}

 - Business Class

public class MyProcess implements MyInter{
	private MoneyInter inter;
	private int result[];
	
	public MyProcess(MoneyInter inter) {
		this.inter = inter;
	}
	
	public void inputMoney() {
		//키보드로 금액입력
		try {
			InputStreamReader reader = new InputStreamReader(System.in);
			BufferedReader br = new BufferedReader(reader);
			int myMoney=0;
			System.out.println("금액입력");
			String data = br.readLine();
			myMoney = Integer.parseInt(data);
			result = inter.calcMoney(myMoney);
		} catch (Exception e) {
			System.out.println("inputMoney err "+e);
		}
	}

	public void showResult() {
		//계산이 끝난 배열 자료 출력.
		System.out.println("만원 : "+result[0]+"개");
		System.out.println("천원 : "+result[1]+"개");
		System.out.println("백원 : "+result[2]+"개");
		System.out.println("십원 : "+result[3]+"개");
		System.out.println("일원 : "+result[4]+"개");
	}

}

 => 생성자에 모델의 interface 객체를 매개변수로 받아 사용.

 

- Model Interface

public interface MoneyInter {
	int[] calcMoney(int money);
}

 

- Model Class

public class MoneyCalc implements MoneyInter{
	public MoneyCalc() {
	}
	public int[] calcMoney(int money) {
		//단위별 금액 건수 계산용
		int result[] = new int[5];
		int temp=0;
		int len = result.length;
		for(int i=0; i<len;i++) {
			if(i == 0) {
				result[i] = money/(int)Math.pow(10, (len-1-i));
				temp=money%(int)Math.pow(10, (len-1-i));
				continue;
			}
			result[i] = temp/(int)Math.pow(10, (len-1-i));
			temp=temp%(int)Math.pow(10, (len-1-i));
		}
		return result;
	}
}

 

③ 생성자 주입(construnctor injection)

 

 - ShowData(Dao)

public class ShowData {
	public String toAlias() {
		return "홍길동";
	}
	
	public String toHobby() {
		return "운동";
	}
}

 - MyProcess(Controller)

public class MyProcess { // 포함으로 약결합 진행
	private int age;
	private String name;
	private ShowData showData; // Class Type
	
	public MyProcess(int age, String name, ShowData showData) {
		this.age = age;
		this.name = name;
		this.showData = showData;
	}
	
	public void printData() {
		System.out.println(name+age+showData.toAlias()+showData.toHobby());
	}
}

 - xml

<beans>
	<bean id="showData" class="pack.model.ShowData"/>	
	<bean id="myProcess" class="pack.controller.MyProcess">
		<constructor-arg>
			<value>13</value>
		</constructor-arg>
		<constructor-arg>
			<value>홍길동</value>
		</constructor-arg>
		<constructor-arg>
			<ref bean="showData"/>
		</constructor-arg>
	</bean>
</beans>

- main

public static void main(String[] args) {
	ApplicationContext context = new ClassPathXmlApplicationContext("init.xml");
	MyProcess myProcess = (MyProcess)context.getBean("myProcess");
	myProcess.printData();
}

④ 생성자 주입방법 2

 - MessageInter

public interface MessageInter {
	void sayHi();
}

 - MessageImpl

public class MessageImpl implements MessageInter{
	private String name1;
	private String name2;
	private int year;
	private MyClass myclass;
	private String spec;
	
	// 생성자 주입
	public MessageImpl(String name1, String name2, int year, MyClass myclass) {
		this.name1=name1;
		this.name2=name2;
		this.year=year;
		this.myclass = myclass;
	}
	
	//setter 주입
	public void setSpec(String spec) {
		this.spec = spec;
	}
	
	// 출력담당 메소드
	public void sayHi() {
		String msg="이름 : "+name1+" / "+name2+"\n";
		msg+="직업 : "+(year+21)+"년 " + myclass.myData();
		msg+="\n보유기술 : "+spec;
		System.out.println(msg);
	}
}

 - arrange.xml

 ① 생성자 주입방법 1

<bean id="mbean" class="pack.MessageImpl" scope="singleton"> 
	<constructor-arg value="홍길동">
		<ref bean="name1"/>
	</constructor-arg>
</bean>
<bean id="mbean" class="pack.MessageImpl" scope="singleton"> 
// <bean> scope의 default는 singleton.
// scope를  prototype 설정 시 getBean()호출시 매번 객체를 생성한다.
// request, session은 web에서 사용.

	<constructor-arg index="1">
		<value>홍길동</value>
	</constructor-arg>
	
	<constructor-arg index="0">
		<value>도둑놈</value>
	</constructor-arg>
	
	<constructor-arg index="2" value="2000"/> // String -> int로 자동 변경된다.
	<constructor-arg index="2" type="int" value="2000"/> // 매개변수가 int일 경우 
	<constructor-arg index="2" type="int" value="이천"/> // error
	<constructor-arg index="3" type="pack2.MyClass" ref="myClass"/>
</bean>
<bean id="myClass" class="pack2.MyClass">
	<property name="data" value="자바"/> // setter injection
</bean>

② 생성자 주입방법 2

 : arrange.xml의 Namespace Tab에서 c, p check

<bean id="mbean" class="pack.MessageImpl"
			c:name1="고길동"
			c:name2="깡패"
			c:year="2000"
			c:myclass-ref="myClass"
			p:spec="sqld">
</bean>

<bean id="myClass" class="pack2.MyClass">
	<property name="data" value="자바"/><!-- setter injection -->
</bean>

 => contruct, setter injection 혼용가능

 

- main

public static void main(String[] args) {
	ApplicationContext context = new ClassPathXmlApplicationContext("arrange.xml");
	ApplicationContext context = new ClassPathXmlApplicationContext("classpath:pack/arrange.xml");
	// src/main/java/pack에 있을경우 
	
	//다형성
	MessageInter inter = (MessageInter)context.getBean("mbean"); // 캐스팅을 interface로 한다.
	// MessageInter inter = (MessageImpl)context.getBean("mbean"); // 지양
	inter.sayHi();
	System.out.println("주소 : "+inter);
}

 


3. setter 주입(setter injection)

 

 - MyProcess

public class MyProcess {
	private int age;
	private String name;
	private ShowData showData;

	// setter를 이용해서 private 멤버에 값을 입력
	public void setAge(int age) {
		this.age = age;
	}
	public void setName(String name) {
		this.name = name;
	}
	public void setShowData(ShowData showData) {
		this.showData = showData;
	}
	
	public void printData() {
		System.out.println(name+age+showData.toAlias()+showData.toHobby());
	}
}

 - init.xml

① 방법 1

<bean id="myProcess" class="pack.MyProcess">
	<property name="age" value="22"/> //MyProcess의 setAge()를 호출한다. 
	<property name="name" value="김이상"/> // setName() 호출
	<property name="showData" ref="showData"/> //객체의 setter 호출시 ref를 사용한다.  
</bean>
 
<bean id="showData" class="pack.ShowData"/> // 다른 <bean>태그에서도 호출 가능

② 방법 2 : 하위 element로 사용

<bean id="myProcess" class="pack.MyProcess">
	<property name="age">
		<value>23</value>
	</property>
	<property name="name">
		<value>김이상</value>
	</property>
	<property name="showData">
		<bean class="pack.ShowData"/> // 해당 <bean>태그에서만 사용가능
	</property>
</bean>

 - main

public static void main(String[] args) {
	ApplicationContext context = new ClassPathXmlApplicationContext("init.xml");
	MyProcess myProcess = (MyProcess)context.getBean("myProcess");
	myProcess.printData();
}

 


 

4. new를 이용한 객체생성과 Spring 객체 생성의 차이

 

 - new

public static void main(String[] args) {
	// new로 객체 생성시 매번 생성된다.
	MessageImpl m1 = new MessageImpl("김이상");
	m1.sayHi();

	MessageImpl m2 = new MessageImpl("김이상");
	m2.sayHi();

	System.out.println("주소 : "+m1); // 주소 : pack.MessageImpl@74e28667
	System.out.println("주소 : "+m2); // 주소 : pack.MessageImpl@1cf6d1be
}

 - xml

public static void main(String[] args) {
	ApplicationContext context = new ClassPathXmlApplicationContext("arrange.xml");
	
	// getBean사용시 singletone으로 객체 생성
	MessageImpl impl1 = (MessageImpl)context.getBean("mbean");
	impl1.sayHi();
	
	MessageImpl impl2 = (MessageImpl)context.getBean("mbean");
	impl2.sayHi();
	
	System.out.println("주소 : "+impl1);
	System.out.println("주소 : "+impl2);
}

 

. 어노테이션 : 객체생성시 xml에 의존적 -> @annotation으로 대체.

① @Require 어노테이션 : setter를 사용하도록 제약을 건다.

 - Abc

 public class Abc {
	private int number;
	
	@Required // setter를 사용하도록 제약을 건다.
	public void setNumber(int number) {
		this.number = number;
	}
	
	public void printData() {
		System.out.println("number : "+number);
	}
}

 - anno1.xml

<beans>
	<context:annotation-config/>
	<bean id="abc" class="anno1.Abc">
		<property name="number" value="100"></property>
	</bean>
</beans>

 - main

public static void main(String[] args) {
	ApplicationContext context = new ClassPathXmlApplicationContext("anno1.xml");
	Abc abc = (Abc)context.getBean("abc");
	abc.printData();
}

② @Component : 객체 생성 

 - SenderInter

public interface SenderInter{
	void show();
}

 - Sender

@Component // 객체 생성 
public class Sender implements SenderInter{
	public void show() {
		System.out.println("show메소드 수행");
	}
}

- Sender2

//@Component = @Component("Sender2")// 객체 생성
@Component("별명")
public class Sender2 implements SenderInter{
	public void show() {
		System.out.println("Sender2의 show메소드 수행");
	}
}

③ @Service : @Component와 동일하나 Business 로직에서 사용한다.

④ @Autowired : setter가 내부적으로 정의되며, type에 의한 mapping 진행.

⑤ @Qualifier("아이디") : type에 대하여 mapping시 동일한 타입(같은 부모를 상속받는 자식) 객체가 복수인 경우 

     Qualifier의 아이디에 명시한 아이디로 mapping한다.

 - SenderProcess

//@Component
//@Service
@Service("SenderProcess") //Component와 동일
public class SenderProcess { // 서비스를 하는 비지니스 로직
	private String name = "tom";
    
	@Autowired  // xml의 type에 대한 mapping.
	//@Qualifier("sender2") // 동일한 타입의 객체(상속받는 자식 객체)가 복수인 경우 id로 mapping
	@Qualifier("별명")
	private SenderInter senderInter;
	
	//public void setSender(Sender sender) { // @Autowired사용시 삭제가능
	//	this.sender = sender;
	//}
    
	public void displayData() {
		System.out.println("displayData의 name : " + name);
		senderInter.show();
	}
}

 - xml

<context:annotation-config/> // @어노테이션을 사용가능하게 한다.
<bean id="senderProcess" class="anno2.SenderProcess"/>
<bean id="sender" class="anno2.Sender"/>
<bean id="sender2" class="anno2.Sender2"/>
 // SenderInter를 상속하는 class가 복수가 되면 type으로 mapping하기 때문에 식별자가 필요하다.
<bean class="anno2.Sender"/>
// type에 대한 mapping으로 id가 없어도 mapping된다.
<context:annotation-config/> // 생략 가능
<context:component-scan base-package="anno2"/> // pakage의 @Component, @Service가 작성된 class의 Bean을 생성.

 - main

public static void main(String[] args) {
	ApplicationContext context = new ClassPathXmlApplicationContext("anno2.xml");
	SenderProcess senderProcess = (SenderProcess)context.getBean("senderProcess");
	senderProcess.displayData();
}

 

[목차]

1. Spring 환경구축
* 이클립스에 연동
* 라이브러리 로딩방법
① maven을 사용하지 않고 spring lib 파일을 직접 다운로드
② Maven, Gradle


 

[내용]

1. Spring 환경구축

* 이클립스에 연동

 

[eclipse] - [help] - [eclipse marketplace] - [find : spring] - [Spring Tools 3 Add-On for Spring Tools 4 3.9.15 RELEASE] download


* 라이브러리 로딩방법

 

① maven을 사용하지 않고 spring lib 파일을 직접 다운로드

 framwork download

maven.springframework.org/release/org/springframework/spring/5.0.5.RELEASE/

 

Index of release/org/springframework/spring/5.0.5.RELEASE

 

maven.springframework.org

 => [spring-framework-5.0.5.RELEASE-dist.zip] Download

 

 라이브러리 등록

[File] - [New] - [New Spring Legacy Project] - [Simple java] check - [next] - [Library] tab - [Add jar] - [spring-framework-5.0.5.RELEASE\libs] 선택

 

③ bean xml 파일에 bean 등록

프로젝트의 [src] 오른쪽 클릭 - [New] - [Spring Bean Configuration file] - xml파일명 입력 - [finish]

<beans>
	<bean id="mes" class="pack.Message1" />
</beans>

④ getBean

ApplicationContext context = new ClassPathXmlApplicationContext("init.xml");
MessageInter inter2 = (MessageInter)context.getBean("mes");
inter2.sayHello("양길동");
// Spring이 객체를 Singletone으로 생성하여 줌.

 

② Maven, Gradle - 주로 사용

 - 외부에서 로딩
 - 프로젝트, 라이브러리 관리

 

① maven 프로젝트 생성

[New] - [Maven Project] - [create a simple project] check - [Group id], [Atifact id] 입력 - [finish]

 

pom.xml파일 수정

<project>
	<properties>
		<!-- Generic properties -->
		<java.version>1.8</java.version>
		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
		<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
		<!-- Spring -->
		<spring-framework.version>5.0.0.RELEASE</spring-framework.version>
		<!-- => 원하는 버전정보 입력 -->
		<!-- Mybatis -->
		<mybatis.version>3.2.3</mybatis.version>
	</properties>
	<dependencies>
		<!-- Spring and Transactions -->
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-context</artifactId>
			<version>${spring-framework.version}</version>
		</dependency>
		<dependency>
			<groupId>javax.annotation</groupId>
			<artifactId>javax.annotation-api</artifactId>
			<version>1.3.2</version>
		</dependency>
		<!-- Spring jdbc -->
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-jdbc</artifactId>
			<version>${spring-framework.version}</version>
		</dependency>
		<!-- oracle jdbc driver -->
		<dependency>
			<groupId>com.oracle</groupId>
			<artifactId>ojdbc6</artifactId>
			<version>11.1.0.7.0</version>
		</dependency>
		<!-- mybatis -->
		<dependency>
			<groupId>org.mybatis</groupId>
			<artifactId>mybatis</artifactId>
			<version>${mybatis.version}</version>
		</dependency>
		<dependency>
			<groupId>org.mybatis</groupId>
			<artifactId>mybatis-spring</artifactId>
			<version>1.0.2</version>
		</dependency>
		<dependency>
			<groupId>commons-dbcp</groupId>
			<artifactId>commons-dbcp</artifactId>
			<version>1.2.2</version>
		</dependency>
	</dependencies>
</project>

 => 다음 경로에 라이브러리가 사이트에서 받아지고 이후 로컬의 라이브러리를 사용한다.

C:\Users\wonh\.m2\repository\org\springframework\spring-core\5.0.0.RELEASE\

 

③ meta.xml 파일 생성

프로젝트의 [src/main/resource] 오른쪽 클릭 - [New] - [Spring Bean Configuration file] - xml파일명 입력 [next] - [beans],[http://www.springframwork.org/schema/beans/spring-beans.xsd] check - [finish] 

<beans>
	<bean id="mes" class="pack.Message1" />
</beans>

12. MVC pattern

Client
(html)
----> Controller
(servlet,
interface, class)
----> Model
(DTO, DAO-sql)
----> DB
----> View
(FormBean, jsp)
   

 

1) Client : html의 <form>,<a>태그로 값을 전달한다.

<form action="path" method="get">
	<input type="text" name="name1" value="value1">
	<input type="submit">
</form>


<a href="sang.do?command=sang">상품</a><br> // Parameter로 값 전달
<a href="sang.do">상품</a> // 요청명으로 값 전달
<a href="buser.do">부서</a>

 

2) Controller

① servlet

@WebServlet("/hobby.do") : 단일
@WebServlet({"/hobby.do","/nicd.do"}) : 배열(복수)
@WebServlet({"*.do","*.kor"}) : 확장자(복수)

 => ( )안 설정한 url pattern을 사용하여 servlet 호출할 수 있다.

 

private HobbyModel model;
public void init() throws ServletException {
	model = new HobbyModel();
}

 => servlet의 service에 구현시 요청마다 new 객체 생성시 메모리를 많이 소모 함으로 init()에 작성한다.

 

protected void service(HttpServletRequest request, HttpServletResponse response)
						throws ServletException, IOException {

 => get/post방식에 상관없이 동작하도록 구현.

 

	try {
		name=request.getParameter("name");
	} catch (Exception e) {
		name=null;
	}  

 => 요청처리 방법 1 : parameter사용. request.getParameter()로 html의 value를 전달받는다.

 

	String str1 = request.getRequestURI();
	// 요청명 : /mvc_ex3_db/sang.do
	int idx = str1.lastIndexOf('/');
	// 11
	String str2 = str1.substring(idx+1); // idx+!부터 끝까지 자름
	// sang.do
	StringTokenizer str3 = new StringTokenizer(str2,"."); // str2를 .을 기준으로 토큰화
	// sang ,  do
	str4 = str3.nextToken();
	// sang
	String command = str4;

 => 요청처리 방법 2 : 요청명을 사용

      "/프로젝트명/uripattern.확장자"로 전달받는다.

 

	CommandInter inter = null;
	String viewName = "views/";
	try {
		if(command.equals("sang")) {
			inter = SangpumImpl.instance();
		}else if(command.equals("buser")) {
			inter = BuserImpl.instance();
		}else if(command.equals("jikwon")) {
			inter = JikwonImpl.instance();			
		}else {
			viewName += "error.html";
			response.sendRedirect(viewName);
            return;
		}
		viewName += inter.showData(request, response);
	} catch (Exception e) {
		System.out.println("service : "+e);
	}

 => interface를 상속받은 클래스의 singletone 객체를 받아온다.

 => 명령에 따른 다른 table의 객체를 받아오도록 오버라이딩을 진행한 메소드를 실행한다.

 

	//HobbyModel model = new HobbyModel();
	ArrayList<String> list = model.getHobby(hobby);
	request.setAttribute("datas", list);

 => 다음의 모델은 interface를 상속받은 클래스에 구현한다.(다형성을 사용)

 

	//response.sendRedirect(viewName+"?result="+result); // 컬렉션 류의 객체는 전달X
		
	request.setAttribute("result", result); // 객체 전달 가능.
	RequestDispatcher rd = request.getRequestDispatcher(viewName);
	rd.forward(request, response);
}

 => request setAttribute(), getAttribute()으로 값 전달.

 => sendRedirect의 경우 객체를 전달할 수 없어 forward로 요청 재지정하여 값 전달.

 

 

 * web.xml를 이용한 url pattern 등록 (경로 : Context/WEB_INF/web.xml)

<welcome-file-list>
	<welcome-file>index.html</welcome-file>
	<welcome-file>index.htm</welcome-file>
	<welcome-file>index.jsp</welcome-file>
	<welcome-file>default.html</welcome-file>
	<welcome-file>default.htm</welcome-file>
	<welcome-file>default.jsp</welcome-file>
</welcome-file-list>

 => <welcom-file>내 파일명을 입력하면, 도메인만 입력시에 해당 파일이 실행된다.

 => 위쪽 부터 우선순위를 가진다.

 

<servlet>
	<servlet-name>hobby</servlet-name>
	<servlet-class>pack.controller.HobbyController</servlet-class>
</servlet>
<servlet-mapping>
	<servlet-name>hobby</servlet-name>
	<url-pattern>*.do</url-pattern>
</servlet-mapping>

=> url pattern 등록

 

 

② Interface

public interface CommandInter {
	String showData(HttpServletRequest request, HttpServletResponse response);
}

 

 

③ class

public class SangpumImpl implements CommandInter{
	//Singleton
	static SangpumImpl impl = new SangpumImpl();
	public static SangpumImpl instance() {
		return impl;
	}

	@Override
	public String showData(HttpServletRequest request, HttpServletResponse response) {
		SangpumModel model = new SangpumModel();//원래는 싱글으로 작성된 클래스를 읽어야함.
		ArrayList<SangpumDto> list = model.getDataAll();
		request.setAttribute("datas", list);
		return "sangpum.jsp";
	}

}

 => 모델에 있는 클래스와 통신을 하는 컨트롤러 영역내의 클래스를 선언한다.

 

* Singletone : 한클래스당 하나의 객체만 사용하도록 하는 인스턴스.

class 클래스명{
	private static 클래스명 singleton명 = new 클래스명();
	static 클래스명 getInstance(){
		return singleton;
	}
}

 

 

3) Model

① DTO

public class SangpumDto {
	private String code;
	private String sang;
	private String su;
	private int dan;
	public String getCode() {
		return code;
	}
	public void setCode(String code) {
		this.code = code;
	}
    ...
}

 => 필드, getter, setter 선언

 

 

② DAO (or Model)

 * JDBC Connection pooling

public class SangpumModel {
	private Connection conn;
	private PreparedStatement ptmt;
	private ResultSet rs;
	private DataSource ds;
	
	
	public SangpumModel() {
		try {
			Context context = new InitialContext();
			ds= (DataSource)context.lookup("java:comp/env/jdbc_maria");
		} catch (Exception e) {
			System.out.println("SangpumModel err"+e);
		}
	}
	
	public ArrayList<SangpumDto> getDataAll(){
		ArrayList<SangpumDto> list = new ArrayList<>();
		try {
			conn=ds.getConnection();
			String sql = "select * from sangdata";
			ptmt = conn.prepareStatement(sql);
			rs= ptmt.executeQuery();
			while(rs.next()) {
				SangpumDto dto = new SangpumDto();
				dto.setCode(rs.getString("code"));
				dto.setSang(rs.getString("sang"));
				dto.setSu(rs.getString("su"));
				dto.setDan(rs.getInt("dan"));
				list.add(dto);
			}
		} catch (Exception e) {
			System.out.println("getDataAll err"+e);
		}finally {
			try {
				if(conn!=null) conn.close();
				if(ptmt!=null) ptmt.close();
				if(rs!=null) rs.close();
			} catch (SQLException e) {
				e.printStackTrace();
			}
		}
		return list;
	}
}

 

 * Mybatis (xml)

  - db.properties : 계정정보

  - Configuration.xml : <alias>, <mapper> 수정

  - DataMapper.xm : xml 형식 sql문 작성

  - SqlMapConfig : SqlSessionFactory 객체 생성

  - DAO(or model)

public class SangpumModel {
	private SqlSessionFactory factory = SqlMapConfig.getSqlSession();
	
	public ArrayList<SangpumDto> getDataAll(){
		ArrayList<SangpumDto> list = null;
		SqlSession sqlSession = factory.openSession();
		list = (ArrayList)sqlSession.selectList("selectDataAll");
		sqlSession.close();
		return list;
	}
}

 

* Mybatis (@어노테이션)

  - db.properties : 계정정보

  - Configuration.xml : <alias>, <mapper> 삭제

  - DataMapper.xm : 삭제

  - SqlMapperInter : 테이블수에 맞게 작성. sql문 작성

public interface SqlMapperInter_Jikwon {
	@Select("select jikwon_no, jikwon_name, buser_num, jikwon_jik from jikwon where buser_num = #{buser_no}")
	public List<JikwonDto> selectPartJikwon(String buser_no);
}

 

  - SqlMapConfig : SqlMapperInter의 class 배열에 연결.

Class[] mappers = {SqlMapperInter_Buser.class, SqlMapperInter_Jikwon.class, SqlMapperInter_Gogek.class};
for(int i=0; i<mappers.length;i++) {
	sqlSession.getConfiguration().addMapper(mappers[i]);
}

 

  - DAO(or model) : SqlSessionFactory객체사용하여 sql 메소드 호출.

public class JikwonDao {
	private SqlSessionFactory factory = SqlMapConfig.getSqlSession();
	
	public ArrayList<JikwonDto> selectPartJikwon(String buser_no){
		ArrayList<JikwonDto> list = new ArrayList<>(); 
		SqlSession sqlSession = factory.openSession();
		
		try {
			SqlMapperInter_Jikwon inter = sqlSession.getMapper(SqlMapperInter_Jikwon.class);
			list = (ArrayList)inter.selectPartJikwon(buser_no);
		} catch (Exception e) {
			System.out.println("selectPartJikwon err"+e);
		}finally {
			if(sqlSession != null) sqlSession.close();
		}
		return list;
	}
	
}

 

 

4) View

① jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<!DOCTYPE html>
<html>
<head>
	<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
	<title>Insert title here</title>
</head>
<body>
	*상품자료(MVC pattern)
	<table border="1">
		<tr>
			<td>코드</td><td>품명</td><td>수량</td><td>단가</td>
		</tr>
		<c:forEach var = "s" items="${datas}">
			<tr>
				<td>${s.code}</td>
				<td>${s.sang}</td>
				<td>${s.su}</td>
				<td>${s.dan}</td>
			</tr>
		</c:forEach>
	</table>
	
</body>
</html>

 

'BACK END > Servlet' 카테고리의 다른 글

[Servlet] Servlet 정리9 - Mybatis2  (0) 2021.01.06
[Servlet] Servlet 정리8 - Mybatis  (0) 2021.01.06
[Servlet] Servlet 정리7 - JDBC  (0) 2021.01.06
[Servlet] Servlet 정리6 - EL, JSTL  (0) 2021.01.04
[Servlet] Servlet 정리5 - Ajax  (0) 2021.01.03

2) @어노테이션을 이용한 Mybatis 사용 : sql문장을 interface의 추상메소드와 연결.

① SqlMapperInter Interface작성 (DataMapper.xml를 대신함 - 삭제)

public interface SqlMapperInter {
	@Select("select * from membertab")
	public List<DataDto> selectDataAllMember();
	
	@Select("select id, name, passwd, reg_date from membertab where id = #{id}")
	public DataDto selectDataPart(String id);
	
	@Insert("insert into membertab values(#{id},#{name},#{passwd},now())")
	public int insertData(DataFormBean bean);
	
	@Update("update membertab set name=#{name} where id=#{id}")
	public int updateData(DataFormBean bean);
	
	@Delete("delete from membertab where id = #{id}")
	public int deleteData(String id);
}

 

② Configuration.xml 내 DataMapper와 연결된 <mapper>태그 및 alias태그 삭제

 

③ SqlMapConfig에서 

public class SqlMapConfig { // 메뉴얼 확인하여 작성.
	public static SqlSessionFactory sqlSession; // DB의 SQL 명령 실행을 위한 메소드를 가진 객체.
	
	static {
		String resource = "pack/mybatis/Configuration.xml";
		try {
			Reader reader = Resources.getResourceAsReader(resource);
			// Configuration.xml을 읽는다.
			sqlSession = new SqlSessionFactoryBuilder().build(reader);
			// sqlSession 객체를 생성한다.
			reader.close();

 - 하기 code 추가 : sqlSession에 @를 연결.

			//Mybatis Annotation을 사용할 경우 추가해야할 코드
			Class[] mappers = {SqlMapperInter.class/*,SqlMapperInter2.class ..*/};
			for(Class m:mappers) {
				//Mapper 등록
				sqlSession.getConfiguration().addMapper(m);
			}
		} catch (Exception e) {
			System.out.println("SqlMapConfig err"+e);
		}
	}
	public static SqlSessionFactory getSqlSession() {
		return sqlSession;
	}
}

④ ProcessDao 수정 : interface의 sql문을 get하도록 수정.

SqlMapperInter inter = sqlSession.getMapper(SqlMapperInter.class); // sql문을 가져온다.
list = inter.selectDataAllMember();

 

public class ProcessDao {
	private SqlSessionFactory factory = SqlMapConfig.getSqlSession();
	
	public List<DataDto> selectDataAllMember(){
		SqlSession sqlSession = factory.openSession();
		List<DataDto> list =null;
		
		try {
			SqlMapperInter inter = sqlSession.getMapper(SqlMapperInter.class); // sql문을 가져온다.
			list = inter.selectDataAllMember();
			//list = sqlSession.selectList("selectDataAll");
		} catch (Exception e) {
			System.out.println("selectDataAllMember err"+e);
		}finally {
			if(sqlSession!=null)sqlSession.close();
		}
		return list;
	}
	public DataDto selectDataPart(String id) {
		SqlSession sqlSession = factory.openSession();
		DataDto dto = null;
		try {
			SqlMapperInter inter = sqlSession.getMapper(SqlMapperInter.class); // sql문을 가져온다.
			dto = inter.selectDataPart(id);
			//dto = sqlSession.selectOne("selectDataPart", id);
		} catch (Exception e) {
			System.out.println("selectDataPart err"+e);
		}finally {
			if(sqlSession!=null)sqlSession.close();
		}
		return dto;
	}
	public boolean insertData(DataFormBean bean) {
		boolean b = false;
		SqlSession sqlSession = factory.openSession();
		try {
			SqlMapperInter inter = sqlSession.getMapper(SqlMapperInter.class); // sql문을 가져온다.
			if(inter.insertData(bean)>0) {
			//if(sqlSession.insert("insertData", bean)>0) {
				b=true;
				sqlSession.commit();
			}
		} catch (Exception e) {
			System.out.println("insertData err"+e);
			sqlSession.rollback();
		}finally {
			if(sqlSession != null) sqlSession.close();
		}
		return b;
	}
	public boolean updateData(DataFormBean bean) {
		boolean b = false;
		SqlSession sqlSession = factory.openSession();
		try {
			SqlMapperInter inter = sqlSession.getMapper(SqlMapperInter.class); // sql문을 가져온다.
			// 비밀번호 비교 후 수정여부 판단.
			DataDto dto = inter.selectDataPart(bean.getId());
			//DataDto dto = selectDataPart(bean.getId());
			if(dto.getPasswd().equals(bean.getPasswd())) {
				if(inter.updateData(bean) >0) {
				//if(sqlSession.update("updateData", bean)>0) {
					b=true;
					sqlSession.commit();
				}
			}
		} catch (Exception e) {
			System.out.println("updateData err"+e);
			sqlSession.rollback();
		}finally {
			if(sqlSession != null) sqlSession.close();
		}
		return b;
	}
	public boolean deleteData(String id) {
		boolean b = false;
		SqlSession sqlSession = factory.openSession();
		try {
			SqlMapperInter inter = sqlSession.getMapper(SqlMapperInter.class); // sql문을 가져온다.
			int cou = inter.deleteData(id);
			//int cou = sqlSession.delete("deleteData", id);
			if(cou>0) {
				b=true;
				sqlSession.commit();
			}
		} catch (Exception e) {
			System.out.println("deleteData err"+e);
			sqlSession.rollback();
		}finally {
			if(sqlSession != null) sqlSession.close();
		}
		return b;
	}

 

'BACK END > Servlet' 카테고리의 다른 글

[Servlet] Servlet 정리 10 - MCV pattern  (0) 2021.01.07
[Servlet] Servlet 정리8 - Mybatis  (0) 2021.01.06
[Servlet] Servlet 정리7 - JDBC  (0) 2021.01.06
[Servlet] Servlet 정리6 - EL, JSTL  (0) 2021.01.04
[Servlet] Servlet 정리5 - Ajax  (0) 2021.01.03

11. Mybatis : ORM 라이브러리

    * ORM(Object-relational mapping) : SQL문을 객체로 만들어 제공.

    * jar의 모임 -> 라이브러리의 모임 -> 프레임워크

     - MyBatis-3-User-Guide_ko 문서 확인.

 

 

    [xml 이용 mybatis 설정하기]

    ① mybatis-3.5.6.jar 추가(하기 사이트에서 다운로드)

     blog.mybatis.org/p/products.html

 

 

    * 보통 Mybatis 파일끼리 package로 묶어서 사용

      - SqlMapConfig.java

      - Configuration.xm

      - DataMapper.xml

      - db.properties

 

    Configuration.xml : 설정파일 작성

    Mapper 파일 추가 <mapper resource="mapper 경로">태그 추가.

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">

<configuration>
 <properties resource="pack/db.properties" />
 <environments default="dev">
  <environment id="dev">
   <transactionManager type="JDBC" />
   <dataSource type="POOLED">
    <property name="driver" value="${driver}" />
    <property name="url" value="${url}" />
    <property name="username" value="${username}" />
    <property name="password" value="${password}" />
   </dataSource>
  </environment>
 </environments>
 <mappers>
  <mapper resource="pack/DataMapper.xml" />
 </mappers>
</configuration>

    * Configuration.xml에 별칭 추가(<configuration>내부)

 <typeAliases>
 	<typeAlias type="pack.business.DataDto" alias="dto"/>
 	<typeAlias type="pack.business.DataFormBean" alias="formBean"/>
 </typeAliases>

 

 

    ③ db.properties : 계정정보 파일

driver=org.mariadb.jdbc.Driver
url=jdbc:mysql://127.0.0.1:3306/test
username=root
password=123

 

    DataMapper.xml 추가

    - SQL문을 작성.

    - value값을 매개변수로 가질 경우 #{code}사용.

    - 칼럼값을 매개변수로 가질 경우${code} 사용.

                                 select : List 리턴.

                                 insert : 0, 1 리턴 - 1개씩만 update 가능.
                                 update : 0, n 리턴.
                                 delete : 0, n 리턴.

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">

<mapper namespace="dev">
 <select id="selectDataAll" resultType="pack.DataDto">
  select * from sangdata order by code asc
 </select>
 
 <select id="selectDataById" parameterType="string" resultType="pack.DataDto">
  select code,sang,su,dan from sangdata where code = #{code}
 </select>
 
 <insert id="insertData" parameterType="pack.DataDto">
  insert into sangdata(code,sang,su,dan) values(#{code},#{sang},#{su},#{dan})
 </insert>
 
 <update id="updateData" parameterType="pack.DataDto">
  update sangdata set sang=#{sang} where code=#{code}
 </update>
 
 <delete id="deleteData" parameterType="int">
  delete from sangdata where code=#{code}
 </delete>
</mapper>

 => Configuration.xml의 별칭을 resultType에 사용가능.

 

    * DataMapper.xml에  재사용 구문 별도 작성하여 재사용성을 높인다.

 <sql id="my1">id, name, passwd, reg_date</sql>
 <sql id="my2">from membertab where id = #{id}</sql>
 
 <select id="selectDataPart" parameterType="string" resultType="dto" statementType="PREPARED">
  select
  <include refid="my1"/>
  <include refid="my2"/>
 </select>

 

    ⑤ SqlMapConfig : 메뉴얼 확인하여 작성.

public class SqlMapConfig {
	public static SqlSessionFactory sqlSession;
	// DB의 SQL 명령 실행 메소드를 가진 객체.
	static {
		String resource = "pack/Configuration.xml";
		try {
			Reader reader = Resources.getResourceAsReader(resource);
			// Configuration.xml을 읽는다.
			sqlSession = new SqlSessionFactoryBuilder().build(reader);
			// sqlSession 객체를 생성한다.
			reader.close();
		} catch (Exception e) {
			System.out.println("SqlMapConfig err"+e);
		}
	}
	public static SqlSessionFactory getSqlSession() {
		return sqlSession;
	}
}

 * 보통 business 파일끼리 package로 묶어서 사용

  - DataDto.java

  - FormBean.java

  - ProcessDao.java

 

* 용도에 따라 FormBean과 Dto 파일로 데이터를 관리한다.

  - FormBean 용도 : 클라이언트의 정보를 레코드 단위로 받아 처리 (update, delete)
  - DataDTO 용도 : DB에서 넘어오는 정보를 레코드 단위로 받아 처리 (select)

 

     DTO작성 - DataDto.java

 

     FormBean작성


    ⑧ ProcessDao : MyBatis와 연결해서 SQL을 실행하고 그 결과를 얻는 역할

public class ProcessDao {
	private SqlSessionFactory factory = SqlMapConfig.getSqlSession();
	
	public List<DataDto> selectDataAll() throws Exception{
		SqlSession sqlSession = factory.openSession(); // 세션 열기(DB처리를 위한 작업단위)
		List<DataDto> list = sqlSession.selectList("selectDataAll"); // DataMapper의 id를 가져온다.
		// selectList() : 여러개 리턴 
		// selectOne() : 1개 리턴
		sqlSession.close();
		return list; // sql의 결과를 가진다.
	}
	
	public DataDto selectDataPart(String code) throws Exception {
		SqlSession sqlSession = factory.openSession();
		DataDto dto = sqlSession.selectOne("selectDataById", code);
		sqlSession.close();
		return dto;
	}
	
	public int insertData(DataDto dto) throws Exception{
		//SqlSession sqlSession = factory.openSession(); // 수동 commit.
		SqlSession sqlSession = factory.openSession(true); // 자동 commit.
		int result = sqlSession.insert("insertData",dto);
		if(result == 0) {
			sqlSession.rollback();
		}else {
			//sqlSession.commit();
		}
		sqlSession.close();
		return result;
	}
	public int upData(DataDto dto) throws Exception{
		SqlSession sqlSession = factory.openSession();
		int result = sqlSession.update("updateData", dto);
		sqlSession.commit();
		sqlSession.close();
		return result;
	}
	public boolean delData(int code){
		boolean result = false; 
		SqlSession sqlSession = factory.openSession();
		try {
			int cou = sqlSession.delete("deleteData", code);
			if(cou>0) {
				result=true;
			}
			sqlSession.commit();
		} catch (Exception e) {
			System.out.println("dlData err"+e);
			sqlSession.rollback();
		}finally {
			if(sqlSession != null) sqlSession.close();
		}		
		return result;
	}
}

 

 * 보통 jsp파일에 작성.

    ⑨-1) java main

ProcessDao dao = new ProcessDao();
try {
	System.out.println("자료 추가");
	DataDto dataDto = new DataDto();
	dataDto.setCode("11");
	dataDto.setSang("초록양말");
	dataDto.setSu("7");
	dataDto.setDan("4000");
	//DataDto dataDto = new DataDto("11","초록양말","7","4000");
	int result = dao.insertData(dataDto);
	System.out.println(result+"개 자료 추가");
	
	System.out.println("자료 수정");
	DataDto dataDto = new DataDto();
	dataDto.setCode("11");
	dataDto.setSang("빨간양말");
	int result = dao.upData(dataDto);
	System.out.println(result+"개 자료 업데이트");
	
	System.out.println("자료삭제");
	boolean result = dao.delData(5);
	if(result) {
		System.out.println("삭제 성공");
	}else {
		System.out.println("삭제 실패");
	}
	
	System.out.println("\n전체자료 출력");
	List<DataDto> list = dao.selectDataAll();
	//ArrayList<DataDto> list = (ArrayList)dao.selectDataAll();
	for(DataDto s:list) {
		 System.out.println(s.getCode() +"\t"+
							s.getSang() +"\t"+
							s.getSu() +"\t"+
							s.getDan());
	}
	System.out.println("전체 건수:" + list.size());
	
	System.out.println("\n부분자료 출력");
	DataDto dto = dao.selectDataPart("3");
	System.out.println(dto.getCode() +"\t"+
						dto.getSang() +"\t"+
						dto.getSu() +"\t"+
						dto.getDan());
} catch (Exception e) {
	System.out.println("Main err "+e);
}

⑨-2) jsp

- main html

<!DOCTYPE html>
<html>
<head>
	<meta charset="UTF-8">
	<title>Insert title here</title>
</head>
<body>
	* 홈페이지<br>
	인사관리 자재관리 영업관리 <a href="list.jsp">회원관리</a>
	<hr>
	<pre>입력값 출력
	</pre>
	<footer>
	꼬리말
	</footer>
</body>
</html>

 - 모든 list 출력 jsp (select all)

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<jsp:useBean id="processDao" class="pack.business.ProcessDao"/>
<%
	ArrayList<DataDto> slist = (ArrayList)processDao.selectDataAll();
%>
<a href="ins.html">상품추가</a><br>
<span style="color:red">코드를 클릭하면 삭제 품명을 클릭하면 수정처리</span>
<table border="1">
	<tr>
		<th>상품명</th><th>품명</th><th>수량</th><th>단가</th>
	</tr>
	
	<c:forEach var ="s" items="<%=slist%>">
	<tr>
		<td><a href="delete.jsp?code=${s.code }">${s.code}</a></td>
		<td><a href="update.jsp?code=${s.code }">${s.sang}</a></td>
		<td>${s.su}</td>
		<td>${s.dan}</td>
	</tr>
	</c:forEach>		
</table>

 

<%@page import="pack.business.DataDto"%>
<%@page import="java.util.ArrayList"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="func" uri="http://java.sun.com/jsp/jstl/functions" %>
<jsp:useBean id ="processDao" class="pack.business.ProcessDao"/>
<!DOCTYPE html>
<html>
<head>
	<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
	<title>Insert title here</title>
</head>
<body>
	<h2>* 회원정보(Mybatis)</h2>
	<a href="ins.jsp">회원추가</a>
	<table border="1">
		<tr>
			<th>id</th><th>name</th><th>pwd</th><th>date</th>
		</tr>
		<% ArrayList<DataDto> list = (ArrayList)processDao.selectDataAllMember(); %>
		<c:set var="list" value="<%=list %>"/>
		<c:if test="${empty list}">
			<tr>
				<td colspan="4">자료없음</td>
			</tr>
		</c:if>
		<c:forEach var="m" items="<%=list%>">
			<tr>
				<td><a href="del.jsp?id=${m.id}">${m.id}</a></td>
				<td><a href="up.jsp?id=${m.id}">${m.name}</a></td>
				<td>${m.passwd}</td>
				<td>${func:substring(m.reg_date,0,10)}</td>
			</tr>
		</c:forEach>
		<tr>
			<td colspan="4">id클릭은 삭제 name클릭은 수정</td>
		</tr>
	</table>
</body>
</html>

* function 액션태그

<%@ taglib prefix="func" uri="http://java.sun.com/jsp/jstl/functions" %>
${func:substring(m.reg_date,0,10)}

 

 - insert html

<form action="ins.jsp" method="post">
	코드 : <input type="text" name="code"><br>
	품명 : <input type="text" name="sang"><br>
	수량 : <input type="number" name="su"><br>
	단가 : <input type="number" name="dan"><br>
	<input type="submit" value="등록">
</form>

 - insert jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<% request.setCharacterEncoding("utf-8"); %>

<jsp:useBean id="bean" class="pack.business.FormBean"></jsp:useBean>
// java bean객체 생성 액션태그
<jsp:setProperty property="*" name="bean"/>
// 생성 객체에 프로퍼티 값 설정

<jsp:useBean id="processDao" class="pack.business.ProcessDao" />
<%
	processDao.insertData(bean);// Mybatis 호출
	response.sendRedirect("list.jsp");
%>
자바빈 property는 하기와 동일
<%= bean.getCode() %>
<%= bean.getSang() %>

* 수정/ 삭제 후 Redirect 진행해야함(client) forward 진행 시 새로고침시 해당 동작이 중복 수행된다.(수정/삭제에서 실행)

<jsp:forward page="list.jsp" /> insert에선 사용하지않음

* servlet에 하기와 같이 구현가능

// 내부적인 처리만 구현. 비지니스 로직. servlet으로 구현 가능
request.setCharacterEncoding("utf-8");
String code = request.getParameter("code");
String sang = request.getParameter("sang");
...
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
	<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
	<title>Insert title here</title>
</head>
<body>
	<h2>회원가입</h2>
	<form action="insok.jsp" method="post">
	id : <input type="text" name="id"><br>
	name : <input type="text" name="name"><br>
	passwd : <input type="text" name="passwd"><br>
	<br>
	<input type="submit" value="등록">
	</form>
</body>
</html>

 - insert ok jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<% request.setCharacterEncoding("utf-8"); %>
<jsp:useBean id="fbean" class="pack.business.DataFormBean"/>
<jsp:setProperty property="*" name="fbean"/>
<jsp:useBean id="processDao" class="pack.business.ProcessDao"/>
<%
	boolean b = processDao.insertData(fbean);
	if(b){
		response.sendRedirect("list.jsp");
	}else{
		response.sendRedirect("fail.jsp");
	}
%>

 - update jsp

<%@page import="pack.business.DataDto"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
    
<jsp:useBean id="processDao" class="pack.business.ProcessDao"></jsp:useBean>
<%
	String code = request.getParameter("code");
	DataDto dto = processDao.selectDataPart(code);
%>

<!DOCTYPE html>
<html>
<head>
	<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
	<title>Insert title here</title>
	<script type="text/javascript">
	</script>
</head>
<body>

	<form action="updateOk.jsp" method="post">
		코드 : <%= dto.getCode() %><br>
		<input type="hidden" name="code" value="<%=dto.getCode()%>">
		//값은 전달이 필요하지만 변경이 필요하지않는다면 input태그의 hidden type으로 구현한다.
		품명 : <input type="text" name="sang" value="<%= dto.getSang()%>"><br>
		수량 : <input type="number" name="su" value="<%= dto.getSu()%>"><br>
		단가 : <input type="number" name="dan" value="<%= dto.getDan()%>"><br>
		<input type="submit" value="수정">
		<input type="button" onclick="history.back()" value="이전">
	</form>
    
</body>
</html>
<%@page import="pack.business.DataDto"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<jsp:useBean id="processDao" class="pack.business.ProcessDao"></jsp:useBean>
<% request.setCharacterEncoding("utf-8");
String id = request.getParameter("id");
DataDto dto = processDao.selectDataPart(id);
%>
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
	<h2>*회원정보 수정</h2>
	<form action="upok.jsp" method="post">
	id : <%=dto.getId()%><br>
	<input type="hidden" name="id" value="<%=dto.getId()%>"/>
	name : <input type="text" name="name" value="<%=dto.getName()%>"/><br>
	pwd : <input type="text" name="passwd"/><br>
	<input type="submit" value="수정"/>
	</form>
</body>
</html>

 - update ok jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
    
<% request.setCharacterEncoding("utf-8"); %>

<jsp:useBean id="bean" class="pack.business.FormBean"/>
<jsp:setProperty property="*" name="bean"/>
// formbean 값을 가져온다.
<jsp:useBean id="processDao" class="pack.business.ProcessDao"/>
// sql문 사용 객체 선언
<%
	processDao.upData(bean);
	response.sendRedirect("list.jsp");
%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<% request.setCharacterEncoding("utf-8");%>
<jsp:useBean id="fbean" class="pack.business.DataFormBean"></jsp:useBean>
<jsp:setProperty property="*" name="fbean"/>
<jsp:useBean id="processDao" class="pack.business.ProcessDao"></jsp:useBean>
<%
	boolean b = processDao.updateData(fbean);

	if(b){
		response.sendRedirect("list.jsp");
	}else{
		response.sendRedirect("fail.jsp");
	}
%>

 

 - delete jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<jsp:useBean id="processDao" class="pack.business.ProcessDao"></jsp:useBean>
<%
	int code = Integer.parseInt(request.getParameter("code"));
	boolean b = processDao.delData(code);
	
	
	if(b){
		response.sendRedirect("list.jsp");
	}else{%>
		<script >
			alert("삭제를 실패하였습니다.");
			location.href="list.jsp";
			//response.sendRedirect("list.jsp");
		</script>
	<%}%>
<%@page import="pack.business.DataDto"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<% request.setCharacterEncoding("utf-8");
%>
<jsp:useBean id="processDao" class="pack.business.ProcessDao"></jsp:useBean>
<%
	String id = request.getParameter("id");
	boolean b = processDao.deleteData(id);
	
	if(b){
		response.sendRedirect("list.jsp");
	}else{
		response.sendRedirect("fail.jsp");
	}
%>

 - fail jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
	<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
	<title>Insert title here</title>
</head>
<body>
	<h2>작업실패</h2>
	<a href="list.jsp">회원정보 보기</a>
</body>
</html>

 


* log4j를 이용해 java + MyBatis log 작성
    ① Root에 log4j.properties 생성

log4j.rootLogger=DEBUG, console
log4j.appender.console=org.apache.log4j.ConsoleAppender
log4j.appender.console.Encoding=UTF-8
log4j.appender.console.layout=org.apache.log4j.PatternLayout
log4j.appender.console.layout.ConversionPattern=[%d{ISO8601}] [%-12t] %-5p %m%n

 

    ② Context/WEB_INF/lib에 log4j-1.2.17.jar 추가

 

<tip>

* WEB_INF는 외부에서 접근 불가하다.(보안)

* ctrl + 함수명 : 선언부로 이동.

'BACK END > Servlet' 카테고리의 다른 글

[Servlet] Servlet 정리 10 - MCV pattern  (0) 2021.01.07
[Servlet] Servlet 정리9 - Mybatis2  (0) 2021.01.06
[Servlet] Servlet 정리7 - JDBC  (0) 2021.01.06
[Servlet] Servlet 정리6 - EL, JSTL  (0) 2021.01.04
[Servlet] Servlet 정리5 - Ajax  (0) 2021.01.03

* maria JDBC 사용

public class ConnBean {
	private Connection conn;
	private PreparedStatement ptmt;
	private ResultSet rs;
	
	public ConnBean() {
		try {
			Class.forName("org.mariadb.jdbc.Driver");
		} catch (Exception e) {
			System.out.println("ConnBean err : "+e);
		}finally{
			
		}
	}
	public ArrayList<ProductDto> getData(){
		ArrayList<ProductDto> list = new ArrayList<ProductDto>();
		try {
			conn = DriverManager.getConnection("jdbc:mysql//localhost:3306/test","root","123");
			String sql = "select * from product";
			ptmt = conn.prepareStatement(sql);
			rs = ptmt.executeQuery();
			while(rs.next()) {
				ProductDto dto = new ProductDto();
				dto.setCode(rs.getString("code"));
				dto.setSang(rs.getString("sang"));
				dto.setSu(rs.getInt(3));
				dto.setDan(rs.getInt(4));
				list.add(dto);
			}
		} catch (Exception e) {
			System.out.println("getData err : "+e);
		}finally{			
			try {
				if(conn!=null) conn.close();
				if(ptmt!=null) ptmt.close();
				if(rs!=null) rs.close();
			} catch (SQLException e) {
				e.printStackTrace();
			}
		}
		return list;
	}
}

 

 

* JDBC Connection pooling을 위한 방법

    ① context.xml 추가

     - 경로

context/META-INF/context.xml

     - 내용

<Context>
	<Resource name="jdbc_maria" auth="Container" type="javax.sql.DataSource"
		driverClassName="org.mariadb.jdbc.Driver" loginTimeout="10" maxWait="5000"
		username="root" password="123" testOnBorrow="true"
		maxActive="500" maxIdle="100"
		url="jdbc:mysql://localhost:3306/test" />
</Context>

* dbcp 사용 : 아파치에서 지원하는 기능. 자동적으로 객체 제어.

JNDI(Java Naming and Directory Interface)

public class ConnBean {
	private Connection conn;
	private PreparedStatement ptmt;
	private ResultSet rs;
	private DataSource ds;
	public ConnBean() {
		try {
			Context context = new InitialContext(); // ds사용
			ds = (DataSource)context.lookup("java:comp/env/jdbc_maria"); // ds사용
		} catch (Exception e) {
			System.out.println("ConnBean err : "+e);
		}finally{
			
		}
	}
    public ArrayList<SangpumDto> getData(){
		ArrayList<SangpumDto> list = new ArrayList<SangpumDto>();
		try {
			conn = ds.getConnection();  // ds사용
			String sql = "select * from sangdata";
			ptmt = conn.prepareStatement(sql);
			rs = ptmt.executeQuery();
			while(rs.next()) {
				SangpumDto dto = new SangpumDto();
				dto.setCode(rs.getString("code"));
				dto.setSang(rs.getString("sang"));
				dto.setSu(rs.getInt(3));
				dto.setDan(rs.getInt(4));
				list.add(dto);
			}
		} catch (Exception e) {
			System.out.println("getData err : "+e);
		}finally{			
			try {
				if(conn!=null) conn.close();
				if(ptmt!=null) ptmt.close();
				if(rs!=null) rs.close();
			} catch (SQLException e) {
				e.printStackTrace();
			}
		}
		return list;
	}
}

 

[servlet]

protected void service(HttpServletRequest request, HttpServletResponse response) 
					throws ServletException, IOException {
		//jstl은 service메소드를 오버라이딩해야한다.
		//get/post에 따라 나뉘지않는다.
}


* redirect방식

response.sendRedirect("jstlex2.jsp?aa=value");
// 클라이언트를 통해서 서버파일을 호출
// get방식으로 문자열만 전달가능.

* forward방식 

request.getRequestDispatcher("jstlex2.jsp").forward(request, response);
// server에서 server파일을 직접호출.

* String

 -servlet

String irum = "마당쇠";
request.setAttribute("man", irum);


-jsp

<% 
	String str = (String)request.getAttribute("man");
	out.print(str); 
%>

-EL

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
${man}
${requestScope.man}

* 인스턴스

-servlet

Person person = new Person(); // init()에 구현.
person.setName("한국인");
request.setAttribute("person", person);

-jsp

<% 
	Person p = (Person)request.getAttribute("person");
	out.print(p.getName());
%>

-EL

${person.name}

 

* import

- servlet

String[] ani = {"말","고양이","개"};
request.setAttribute("animal", ani);

-EL

<%@page import="pack.Person"%>
${animal[0]}
${animal[1]}
${animal["2"]}

* List

-sevlet

String[] food = {"당근", "고양이밥","개밥"};
List<Object> list = new ArrayList<>();
list.add(ani);
list.add(food);
request.setAttribute("list", list);

- EL

<c:if test="${list != null }">
	<c:forEach var="a" items="${list}">
		${a[0]}, ${a[1]}, ${a[2]}
	</c:forEach>
</c:if>
<c:if test="${list != null }">
	<c:forEach var="a" items="${list}">
		<c:forEach var="b" items="${a}">
			${b}
		</c:forEach>
	</c:forEach>
</c:if>
<c:choose>
	<c:when test="${list eq null}">자료없음</c:when>
	<c:otherwise>자료있음</c:otherwise>
</c:choose>

 

* catch~except처리(예외처리)

<c:catch var ="myErr">
	<%
		int a = 10/0;
		out.print(a);
	%>
</c:catch>
<c:if test="${myErr != null}">
	에러 발생: ${myErr.message}
</c:if>

* 다른 문서 포함

 - include 지시어

<%@ include file="include.jsp"%>

 - jsp action tag

<jsp:include page="include.jsp"/>

 - jstl(문서)

<c:import url="include.jsp"/>

 - jstl(사이트)

<c:import url="https://www.daum.net"/>

 - 내용

<c:set var="url" value="https://www.naver.com"/>
<c:out value="${url}"/>

 - source

<c:import url="${url}" var="u"></c:import>
<c:out value="${u}"/><br> 

 

+ Recent posts

1···567891011