반응형
*예외처리
-
Controller에서의 예외처리
-
@ExceptionHandler Annotation사용
-
@Controller
-
class Test {
-
-
@RequestMapping(...)
-
public String method(int..) throws Exception{
-
}
-
-
//RequestMapping은 DispatherServlet이 불러 사용하게 되는데 예외를 처리하려면...
-
///Dispather Servlet이 잡을 예외를 내가 잡아 이쁘게 보기위한것으로
-
-
Controller의 method가 예외를 날리면 Dispather Servlet가 처리
-
순서)
-
1.요청처리하는 method에서 throws로 예외를 날림
-
2.예외처리하는 method위에서 @ExceptionHandler 정의
-
//메소드의 반환형은 반드시 ModelAndView이어야 한다.
-
@ExceptionHandler(예외처리클래스명.class) //아래의 예외처리 클래스와 같아야 한다
-
public ModelAndView method(예외처리 클래스){
-
ModelAndView mav=new ModelAndView();
-
mav.setViewName("뷰명");
-
mav.addObject("이름", 예외처리메세지);
-
return mav;
-
}
-
//한번에 하나의 예외만 처리가능하다.
-
//ExceptionController.java
package kr.co.sist.controller.webparam;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;
import static org.springframework.web.bind.annotation.RequestMethod.GET;
import java.util.Calendar;
import java.util.Random;
@Controller
public class ExceptionController {
@RequestMapping(value="/exception/exception.do",method=GET)
public String exceptionForm() {
return "exception/exception_form";
}//exceptionForm
@RequestMapping(value="/exception/number_format.do",method=GET)
public String numberFormat(int age, Model model) {
model.addAttribute("birth",Calendar.getInstance().get(Calendar.YEAR)-age+1);
return "exception/view_age";
}//numberFormat
@RequestMapping(value="/exception/class_not_found.do",method=GET)
public String classNotFound() throws ClassNotFoundException{
if(new Random().nextBoolean()) {
throw new ClassNotFoundException("클래스가 없는 상황");
}//end if
return "exception/view_class";
}//classNotFound
//현재 Controller내의 method들 중 NumberFormatException이 발생하면 method가 달라도 아래의 예외처리 method가 호출된다.
@ExceptionHandler(NumberFormatException.class)
public ModelAndView numberFormatProcess(NumberFormatException nfe) {
ModelAndView mav=new ModelAndView();
mav.setViewName("exception/error");
mav.addObject("msg",nfe.getMessage()); //간단한 에러메세지 -무엇때문인지 알수는 없다.
mav.addObject("exception",nfe.toString()); //예외처리 객체와 간단한 에러 메세지
return mav;
}//numberFormatProcess
@ExceptionHandler(ClassNotFoundException.class)
public ModelAndView classNotFoundProcess(ClassNotFoundException cnfe) {
ModelAndView mav=new ModelAndView();
mav.setViewName("exception/error");
mav.addObject("msg", cnfe.getMessage());
mav.addObject("exception", cnfe.toString());
return mav;
}//classNotFoundProcess
}//class
//exception_form.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"
info="Controller에서 HttpServletRequest를 사용하여 전달된 값을 처리하는 Page"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<link rel="stylesheet" type="text/css" href="http://localhost:8080/spring_mvc/common/main_v190130.css"/>
<style type="text/css">
#wrap{margin:0px auto;width:800px; height:860px;}
#header{width:800px; height:140px; background:#FFFFFF url(http://localhost:8080/spring_mvc/common/images/header_bg.png) repeat-x;
position: relative; }
#headerTitle{font-family: HY견고딕,고딕; font-size:35px; font-weight:bold; text-align:center;
/* padding-top: 35px */ position:absolute; top:40px; left:290px; }
#container{width:800px; min-height: 600px; }
#footer{width:800px; height:120px; }
#footerTitle{float: right; font-size:15px; padding-top:20px; padding-right:20px; }
</style>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.2.4/jquery.min.js"></script>
<script type="text/javascript">
$(function(){
});//ready
</script>
</head>
<body>
<div id="wrap">
<div id="header">
<div id="headerTitle">SIST Class4</div>
<div style="padding-top:100px; ">
<c:import url="../common/jsp/main_menu.jsp"></c:import>
</div>
</div>
<div id="container">
<form action="number_format.do" method="get">
<label>나이</label>
<input type="text" name="age" class="inputBox"/>
<input type="submit" value="전송" class="btn"/>
</form>
<form action="class_not_found.do" method="get">
<input type="submit" value="전송" class="btn"/>
</form>
<div>
</div>
</div>
<div id="footer">
<div id="footerTitle">copyright© all right reserved. class 4.</div>
</div>
</div>
</body>
</html>
//view_age.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"
info="Controller에서 HttpServletRequest를 사용하여 전달된 값을 처리하는 Page"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<link rel="stylesheet" type="text/css" href="http://localhost:8080/spring_mvc/common/main_v190130.css"/>
<style type="text/css">
#wrap{margin:0px auto;width:800px; height:860px;}
#header{width:800px; height:140px; background:#FFFFFF url(http://localhost:8080/spring_mvc/common/images/header_bg.png) repeat-x;
position: relative; }
#headerTitle{font-family: HY견고딕,고딕; font-size:35px; font-weight:bold; text-align:center;
/* padding-top: 35px */ position:absolute; top:40px; left:290px; }
#container{width:800px; min-height: 600px; }
#footer{width:800px; height:120px; }
#footerTitle{float: right; font-size:15px; padding-top:20px; padding-right:20px; }
</style>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.2.4/jquery.min.js"></script>
<script type="text/javascript">
$(function(){
});//ready
</script>
</head>
<body>
<div id="wrap">
<div id="header">
<div id="headerTitle">SIST Class4</div>
<div style="padding-top:100px; ">
<c:import url="../common/jsp/main_menu.jsp"></c:import>
</div>
</div>
<div id="container">
나이: ${param.age}<br/>
태어난 해 : ${requestScope.birth}<br/>
<a href="javascript:history.back()">뒤로</a>
<div>
</div>
</div>
<div id="footer">
<div id="footerTitle">copyright© all right reserved. class 4.</div>
</div>
</div>
</body>
</html>
//error.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 charset="UTF-8">
<title>Insert title here</title>
<link rel="stylesheet" type="text/css" href="http://localhost:8080/spring_mvc/common/main_v190130.css"/>
<style type="text/css">
#wrap{margin:0px auto;width:800px; height:860px;}
#header{width:800px; height:140px; background:#FFFFFF url(http://localhost:8080/spring_mvc/common/images/header_bg.png) repeat-x;
position: relative; }
#headerTitle{font-family: HY견고딕,고딕; font-size:35px; font-weight:bold; text-align:center;
/* padding-top: 35px */ position:absolute; top:40px; left:290px; }
#container{width:800px; min-height: 600px; }
#footer{width:800px; height:120px; }
#footerTitle{float: right; font-size:15px; padding-top:20px; padding-right:20px; }
</style>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.2.4/jquery.min.js"></script>
<script type="text/javascript">
$(function(){
});//ready
</script>
</head>
<body>
<div id="wrap">
<div id="header">
<div id="headerTitle">SIST Class4</div>
<div style="padding-top:100px; ">
<c:import url="/common/jsp/main_menu.jsp"></c:import>
</div>
</div>
<div id="container">
<img src="http://localhost:8080/spring_mvc/common/images/err.png"/>
<br/>
문제가 발생했습니다.<br/>
간단한 메세지 : ${msg}<br/>
예외처리 객체와 메세지 : ${requestScope.exception}
</div>
<div id="footer">
<div id="footerTitle">copyright© all right reserved. class 4.</div>
</div>
</div>
</body>
</html>
//view_class.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"
info="Controller에서 HttpServletRequest를 사용하여 전달된 값을 처리하는 Page"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<link rel="stylesheet" type="text/css" href="http://localhost:8080/spring_mvc/common/main_v190130.css"/>
<style type="text/css">
#wrap{margin:0px auto;width:800px; height:860px;}
#header{width:800px; height:140px; background:#FFFFFF url(http://localhost:8080/spring_mvc/common/images/header_bg.png) repeat-x;
position: relative; }
#headerTitle{font-family: HY견고딕,고딕; font-size:35px; font-weight:bold; text-align:center;
/* padding-top: 35px */ position:absolute; top:40px; left:290px; }
#container{width:800px; min-height: 600px; }
#footer{width:800px; height:120px; }
#footerTitle{float: right; font-size:15px; padding-top:20px; padding-right:20px; }
</style>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.2.4/jquery.min.js"></script>
<script type="text/javascript">
$(function(){
});//ready
</script>
</head>
<body>
<div id="wrap">
<div id="header">
<div id="headerTitle">SIST Class4</div>
<div style="padding-top:100px; ">
<c:import url="/common/jsp/main_menu.jsp"></c:import>
</div>
</div>
<div id="container">
정상적인 상황일때 제공할 내용<br/>
<a href="javascript:history.back()">뒤로</a>
<div>
</div>
</div>
<div id="footer">
<div id="footerTitle">copyright© all right reserved. class 4.</div>
</div>
</div>
</body>
</html>
*응답시에 JSP가 아닌 다른 do(업무를 처리하는 하나의 URL)를 다시 요청할 때
-
@RequestMapping("a.do")
-
public String methodA(){
-
//작업(을 한다음에 b.do로 가 나머지 작업을 하고 view를 내보내고 싶으면...
-
return "view명"; /////이때 View명은..?
-
}
-
@RequestMappeing("b.do")
-
public String methodB(){
-
//나머지 작업...
-
return "view명";
-
}
-
-
return에 jsp명이 아닌 요청을 처리하는 .do가 나와야 한다.
-
return "forward :do의 이름"; //do를 직접부를 수 있게 된다. ViewResolver를 거치지 않고 forward로
-
=>ViewResolver를 거치지 않고 do를 요청한다. (redirect도 마찬가지-.jsp를 요청하는게 다름.)
-
=>체인(do를 거쳐)
//ChainController.java
package kr.co.sist.controller.webparam;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import static org.springframework.web.bind.annotation.RequestMethod.GET;
@Controller
public class ChainController {
@RequestMapping(value="/chain/chain_a.do", method=GET)
public String chainA(Model model) {
String[] lunch= {"버거킹","KFC","맥날","롯데리아"};
model.addAttribute("lunch",lunch);
return "forward:/chain/chain_b.do";
//return 에 forward가 붙어있으면 ViewResolver를 거치지 않고 정의된 URL을 직접 호출하게 된다.
}//chainA
@RequestMapping(value="/chain/chain_b.do", method=GET)
public String chainB() { //직접 호출될 수도 있고, A를 거쳐서 호출될 수도 있따.
return "chain/chain_b_result";
}//chainB
}//class
//chain_b_result.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"
info="Controller에서 HttpServletRequest를 사용하여 전달된 값을 처리하는 Page"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<link rel="stylesheet" type="text/css" href="http://localhost:8080/spring_mvc/common/main_v190130.css"/>
<style type="text/css">
#wrap{margin:0px auto;width:800px; height:860px;}
#header{width:800px; height:140px; background:#FFFFFF url(http://localhost:8080/spring_mvc/common/images/header_bg.png) repeat-x;
position: relative; }
#headerTitle{font-family: HY견고딕,고딕; font-size:35px; font-weight:bold; text-align:center;
/* padding-top: 35px */ position:absolute; top:40px; left:290px; }
#container{width:800px; min-height: 600px; }
#footer{width:800px; height:120px; }
#footerTitle{float: right; font-size:15px; padding-top:20px; padding-right:20px; }
</style>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.2.4/jquery.min.js"></script>
<script type="text/javascript">
$(function(){
});//ready
</script>
</head>
<body>
<div id="wrap">
<div id="header">
<div id="headerTitle">SIST Class4</div>
<div style="padding-top:100px; ">
<c:import url="/common/jsp/main_menu.jsp"></c:import>
</div>
</div>
<div id="container">
chain_b.do로 응답된 내용<br/>
<c:choose>
<c:when test="${empty lunch}">
햄버거 목록을 받아오세요.<br/>
<a href="javascript:history.back()">뒤로</a>
</c:when>
<c:otherwise>
좋아하는 햄버거 선택<br/>
<c:forEach var="menu" items="${lunch}">
<input type="checkbox" name="menu" value="${menu}"/><!-- 체크하지 않으면 on값이 넘어간다. -->
<c:out value="${menu}" escapeXml="false"/>
</c:forEach>
</c:otherwise>
</c:choose>
</div>
<div id="footer">
<div id="footerTitle">copyright© all right reserved. class 4.</div>
</div>
</div>
</body>
</html>
<<잠깐의 Diary에서 게시물 번호 가져오기>>
//BbsController.java
package kr.co.sist.controller.bbs;
import static org.springframework.web.bind.annotation.RequestMethod.GET;
import java.util.List;
import org.json.simple.JSONObject;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import kr.co.sist.domain.Diary;
import kr.co.sist.domain.DiaryDetail;
import kr.co.sist.domain.DiaryReply;
import kr.co.sist.service.DiaryService;
import kr.co.sist.vo.DiaryVO;
import kr.co.sist.vo.ReplyVO;
@Controller
public class BbsController {
@RequestMapping(value="/diary/list.do", method=GET)
public String diaryList(/*@RequestParam(name="CurentPage", defaultValue="1")*/DiaryVO dv, Model model) {
DiaryService ds=new DiaryService();
int totalCount=ds.totalCount();//총 개시물의 수
int pageScale=ds.pageScale();//한 화면에 보여줄 게시물의 수(이미 해줌)
int totalPage=ds.totalPage(totalCount);//총 게시물을 보여주기 위한 총 페이지 수
if(dv.getCurrentPage()==0) {//web parameter에 값이 없을 때
dv.setCurrentPage(1);//1번 부터 조회 해야 하므로 1로 설정
}//end if
int startNum=ds.startNum(dv.getCurrentPage());//시작 번호
int endNum=ds.endNum(startNum);//끝 번호
dv.setStartNum(startNum);
dv.setEndNum(endNum);
System.out.println("--========================================--"+dv+ "/"+totalCount);
List<Diary> diaryList=ds.searchDiaryList(dv);//리스트 목록 조회
String indexList=ds.indexList(dv.getCurrentPage(), totalPage, "list.do");
model.addAttribute("diaryList",diaryList);
model.addAttribute("indexList",indexList);
model.addAttribute("pageScale",pageScale);
model.addAttribute("totalCount",totalCount);
model.addAttribute("currentPage",dv.getCurrentPage()); //로 게시물의 순서를 올바르게 가져오게 됨
return "diary/list";
}//diaryList
@RequestMapping(value="/diary/bbs_read.do", method=GET)
public String bbsRead(int num, Model model) {
DiaryService ds=new DiaryService();
DiaryDetail dd=ds.searchBbs(num);//원글의 내용을 조회
List<DiaryReply> replyList=ds.searchReplyList(num);//원글의 댓글들을 조회
model.addAttribute("searchData", dd);
model.addAttribute("replyList", replyList);
return "diary/bbs_read";
}//bbsRead
@ResponseBody
@RequestMapping(value="/diary/add_reply.do", method=GET)
public String writeReply(ReplyVO r_vo) {
JSONObject json=null;
DiaryService ds=new DiaryService();
json=ds.writeReply(r_vo);
return json.toJSONString();
}//writeReply
}//class
*DI(Spring Dependuncy I
-
Spring에서 제공하지만 다운은 maven
-
-
-
-
만 필요.
-
-
javadoc.jar가 붙은 파일들을 한번에 del로 지울수 있다. 여러개를 한번에!
*원활한 이동을 위해 링크로 메뉴를 바꾸어줌
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!-- smartmenu 시작 -->
<!-- SmartMenus core CSS (required) -->
<link href="http://localhost:8080/mybatis_prj/common/smartmenu/css/sm-core-css.css" rel="stylesheet" type="text/css" />
<!-- "sm-blue" menu theme (optional, you can use your own CSS, too) -->
<link href="http://localhost:8080/mybatis_prj/common/smartmenu/css/sm-simple/sm-simple.css" rel="stylesheet" type="text/css" />
<!-- jQuery -->
<!-- <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.2.4/jquery.min.js"></script> -->
<!-- SmartMenus jQuery plugin -->
<script type="text/javascript" src="http://localhost:8080/mybatis_prj/common/smartmenu/jquery.smartmenus.js"></script>
<!-- SmartMenus jQuery init -->
<script type="text/javascript">
$(function() {
$('#main-menu').smartmenus({
subMenusSubOffsetX: 1,
subMenusSubOffsetY: -8
});
});
function requestAll(){
var method="";
if(confirm("GET방식으로 요청 하시겠습니까?")){
method="GET";
}else{
alert("POST방식으로 요청합니다.");
method="POST";
}//end else
document.hidFrm.action="http://localhost:8080/spring_mvc/request_all.do"
document.hidFrm.method=method;
document.hidFrm.submit();
}//requestAll
function sendPost(){
//chrome은 javaScript에서 action을 변경하면 form의 actino이 계속 유지된다.
document.hidFrm.action="http://localhost:8080/spring_mvc/request_post.do"
document.hidFrm.submit();
}//sendPost
function requestString(){
var url="request_string.do"
if(confirm("문자열의 매개변수를 전송 하시겠습니까?")){
url+="?name=jungyun";
}//end if
location.href="http://localhost:8080/spring_mvc/"+url;
}//requestString
function requestInt(){
var url="request_int.do"
if(confirm("정수형의 매개변수를 전송 하시겠습니까?")){
url+="?age=20";
}//end if
location.href="http://localhost:8080/spring_mvc/"+url;
}//requestString
</script>
<form action="request_post.do" name="hidFrm" id="hidFrm" method="post"></form>
<!-- smartmenu 끝 -->
<nav id="main-nav">
<!-- Sample menu definition -->
<ul id="main-menu" class="sm sm-simple">
<li><a href="http://localhost:8080/spring_mvc/index.html">홈으로</a></li>
<li><a href="#void">Spring MVC 사용</a>
<ul>
<li><a href="#void">1일차</a>
<ul>
<li><a href="http://localhost:8080/spring_mvc/request_get.do">GET방식 요청</a></li>
<li><a href="#void" onclick="sendPost()">POST방식 요청</a></li>
<li><a href="#void" onclick="requestAll()">GET/POST모두 요청</a></li>
<li><a href="http://localhost:8080/spring_mvc/request_form.do">HttpServletRequest로 파라메터 처리</a></li>
<li><a href="http://localhost:8080/spring_mvc/vo_form.do">VO로 파라메터 처리</a></li>
</ul>
</li>
<li><a href="#void">2일차</a>
<ul>
<li><a href="#void" onclick="requestString()">단일 데이터형 처리(문자열)</a></li>
<li><a href="#void" onclick="requestInt()">단일 데이터형 처리(정수형)</a></li>
<li><a href="http://localhost:8080/spring_mvc/view_request.do">HttpServletRequest사용 데이터 전달</a></li>
<li><a href="http://localhost:8080/spring_mvc/view_model.do">Model을 사용한 데이터 전달</a></li>
<li><a href="http://localhost:8080/spring_mvc/view_modelandview.do">ModelAndView사용 데이터 전달</a></li>
<li><a href="http://localhost:8080/spring_mvc/use_redirect.do">redirect 이동(기존은 forward)</a></li>
</ul>
</li>
<li><a href="#void">3일차</a>
<ul>
<li><a href="http://localhost:8080/spring_mvc/session/use_session.do">HttpSession 사용</a></li>
<li><a href="http://localhost:8080/spring_mvc/session/an_use_session.do">@SessionAttributes 사용</a></li>
</ul>
</li>
<li><a href="#void">4일차</a>
<ul>
<li><a href="http://localhost:8080/spring_mvc/cookie/read_cookie.do">Cookie Class를 사용한 값 얻기</a></li>
<li><a href="http://localhost:8080/spring_mvc/cookie/read_an_cookie.do">@CookieValue 사용한 값 얻기</a></li>
<li><a href="http://localhost:8080/spring_mvc/include/include.do">JSP include</a></li>
<li><a href="http://localhost:8080/spring_mvc/ajax/ajax.do">ajax</a></li>
</ul>
</li>
<li><a href="#void">5일차</a>
<ul>
<li><a href="http://localhost:8080/spring_mvc/diary/list.do">일정 보기</a></li>
</ul>
</li>
<li><a href="#void">6일차</a>
<ul>
<li><a href="http://localhost:8080/spring_mvc/exception/exception.do">Controller에서 예외처리</a></li>
<li><a href="http://localhost:8080/spring_mvc/chain/chain_a.do">chain_a.do 요청</a></li>
<li><a href="http://localhost:8080/spring_mvc/chain/chain_b.do">chain_b.do 요청</a></li>
</ul>
</li>
</ul>
<li><a href="#">동기방식 차량조회</a></li>
</ul>
</nav>
*Spring DI(Dependency Injection) : Spring Core
-
의존성 주입(이전 이름은 IoC (Inversion of Control, 제어의 역행))
-
약결합 : 기능의 조립과 분해가 쉬워지도록 만드는 것
-
Spring Core
-
Spring Container 사용하여 객체가 생성되고, 의존성 주입 설정
-
Spring Container : BeanFactory<-ApplicationContext<-webApplicationContext
-
///라이브러리, 프레임웤의 공통점은 자주 쓰는 것을 만들어 놓은 것,
-
///차이점은 라이브러리는 생명주기를 개발자가, Framework은 생명주기관리를 Framework가 한다.
.png)
-
BeanFactory : Bean(Spring Framework가 객체를 생성해주는 클래스)들의 의존성 주입, 생명주기 관리
-
ApplicationContext : Bean들의 의전송 주입, 생명주기관리, 파일관리, 국제화 기능
-
WebApplicationContext : Bean들의 의전송 주입, 생명주기관리, 파일관리, 국제화 기능, web에서 사용하는 기능, Web Application 당 하나만 생성되고 사용되어져야 한다.
-
설정용 xml이 사용되거나 Annotation으로 설정
-
설정용 xml : 구조복잡(대규모), 객체간의 의존성 주입 상태(관계)를 한눈에 파악하기 쉽다
-
applicationContext.xml에서 설정함 //mybatis는 mapper, xml에서
<beans>
<bean id=" ">
.
.
</beans>
-
Annotation 사용( @Autowired, @Component ) : 구조 간단/ 처리하는 일이 많지 않아서 소규모 Application/ 객체간의 의존성 주입 상태를 한눈에 파악하기 어렵다
-
단점: 어디서 의존성을 주입받는지 확인하기 어렵다.
*강결합
.png)
*약결합
-
분해가 쉽다
-
기능추가, 변경이 쉽다
-
interface를 사용한다.
-
(인터페이스의 장점 : 자바는 단일상속만 되는데 다중상속을 쓰고 싶을 때 쓴다, 약결합의 구현으로 객체 간 유연성을 높일 수 있다.)
-
Assembly에서 Service를 생성할 때 사용할 DAO를 주입, UseAssembly에서는 getBean()을 이용하여 의존성 주입으로 생성된 Service를 반환받아 사용.
*Maven Project 만들기
JAVA Project 생성 -> Configure -> Convert to MavenProjcet
=====>안되서 sharing에서 pom2.xml받아서 덮어씀
버전 맞춰줌
.png)
lombok이 있으면 편하게 쓸 수 있긴 하지만 에러가 있으므로 주석!
.png)
.png)
*사용자 정의 Library만들기
spring framework에 있는 lib들을 다 복사해서
dev>my_libs폴더 만들어서 넣어줌
.png)
.png)
필요한 것들 모아서 UserLibrary
next>userLibrary>new>"spring_framework"로 만듬
Add External JARs에서 아까 만든거 전체 선택해서 열기해서 설정해줌
package kr.co.sist.vo;
public class EmpVO{
private int empno;
private String ename;
...getter,setter
package kr.co.sist.dao;
public interface Dao{
public int insertEmp(EmpVO evo) throws SQLException;
public List<EmpVO> selectEmp() throws SQLException;
}
public classDAOOracleImpl implements Dao{
@Override
public int insertEmp(EmpVO evo) throws SQLException{
//Oracle DB 에 Insert 작업수행
System.out.println("Oracle에 사원정보 추가");
return 1;
}
@Overricde
public List<EmpVO> selectEmp() throws SQLException {
List<EmpVO> list =new ArrayList<EmpVO>();
list.add(new EmpVO(1111,"노진경"));
list.add(new EmpVO(1112,"김희철"));
list.add(new EmpVO(1113,"김정윤"));
list.add(new EmpVO(1114,"이재찬"));
return list;
}
}
public classDAOMySqlImpl implements Dao {
@Override
public int insertEmp(EmpVO evo) throws SQLException{
//MySql DB에 insert 작업수행
System.out.println("MySql에 사원정보 추가");
return 1;
}
@Overricde
public List<EmpVO> selectEmp() throws SQLException {
List<EmpVO> list =new ArrayList<EmpVO>();
list.add(new EmpVO(2111,"오영근"));
list.add(new EmpVO(2112,"공선의"));
list.add(new EmpVO(2113,"이재현"));
list.add(new EmpVO(2114,"이봉현"));
return list;
}
}
public interface Service{
public void addEmp(EmpVO evo);
public List<EmpVO> searchEmp();
}
public class ServiceImpl implements Service {
private Dao dao;
public ServiceImpl(Dao dao) {//의존성 주입(DI)
this.dao=dao;
}
@Override
public void addEmp(EmpVO evo) {
try {
// 업무로직을 처리
System.out.println("추가 작업에 대한 업무로직 처리");
dao.insertEmp(evo);
} catch (SQLException e) {
e.printStackTrace();
}
}
@Override
public List<EmpVO> searchEmp() {
List<EmpVO> list = null;
try {
System.out.println("조회작업에 대한 업무로직 처리");
list = dao.selectEmp();
} catch (SQLException e) {
e.printStackTrace();
}
return list;
}
}
/**
* 의존성 주입 관계를 설정하는 일
*/
public class Assembly {
public Service getBean() {
// 1. 의존성 주입할 객체를 생성
Dao dao = new DAOOracleImpl();
// 2. 의존성 주입받을 객체를 생성하면서 의존성 주입
Service service = new ServiceImpl(dao);
// 3. 의존성 주입받은 객체를 반환
return service;
}
}
/**
* 조립자 클래스(Assembly)를 사용하여 서비스 객체를 얻고
* 서비스를 사용하는 일을 한다
*/
public class UseAssembly {
public static void main(String[] args) {
Assembly as = new Assembly();
Service service = as.getBean();
service.addEmp(new EmpVO(3111, "피카츄"));
System.out.println("-----------------------");
List<EmpVO> list = service.searchEmp();
for(EmpVO emp : list) {
System.out.println(emp.getEmpno()+" / "+emp.getEname());
}
}
}
//약결합이므로 DAO를 변경할 때 Service 내부를 고치는게 아니라 Assembly(조립자 클래스)만 고치면 됨
public class Assembly {
public Service getBean() {
// 1. 의존성 주입할 객체를 생성
Dao dao = new DAOMySqlImpl();
// 2. 의존성 주입받을 객체를 생성하면서 의존성 주입
Service service = new ServiceImpl(dao);
// 3. 의존성 주입받은 객체를 반환
return service;
}
}
*Spring Container
-
(BeanFactory, ApplicationContext, WebApplicationContext가 제공)
-
객체간의 의존성 주입을 쉽게 해준다.
-
org.springframework.context package에서 제공
-
의존성 주입에 대한 정보는 설정용XML에서 정의한다.
-
Spring Container가 생성하고 관리하는 클래스를 Bean이라고 한다.
-
Spring Container : log4j.jar에 의존성이 있다.(또는 commons-logging.jar??)
사용법 )
-
설정용 XML생성 - 정의된 클래스는 사용여부에 상관없이 모두 객체가 생성된 상태에서 실행된다.
- 객체는 Singleton pattern으로 생성된다.
<beans>
-
객체를 생성
<bean id="객체명" class="객체화할 클래스">
-
의존성 주입 : 인터페이스가 없이 객체가 추가된다.
<bean id="객체명" class="객체화할클래스">
<constructor-arg refid="의존성주입할객체명"/>
</bean>
.
.
</beans>
-
Spring Container를 생성
ApplicationContext ac=new ClassPathXmlApplicationContext("설정용xml");
-
의존성 주입 받은 객체를 얻는다.
-
Spring 2.5 이하(캐스팅)
SearviceImp si = (ServiceImpl)ac.getBean("bean id");
-
Sprint 3.0 이상
SearviceImp si = ac.getBean("의존성 주입 받은 클래스.class"); //캐스팅이 필요 없음
혹은
SearviceImp si = ac.getBean("id","의존성 주입 받은 클래스.class");
.png)
///Edit으로 log4j 도 넣어준다.
mvnrepository.com에서 commons Logging도 다운
commons-logging
.png)
*Spring DI
-
약결합을 하기위해 사용
-
Spring Container : ApplicationContext
-
설정 파일 : XML
-
의존성 주입을 받을 객체가 많을 경우(대규모의 복잡한 시스템/파일이 많아서)
-
의존성 주입관계를 파악하기 쉽다는 장점
-
<beans>
-
<bean id="이름" class="패키지명.클래스명"/> ///쓰든 안쓰든 객체 생성
-
<bean id="이름" class="패키지명.클래스명">
-
<constructor-arg ref="이름"/>
-
</bean>
-
</beans>
-
Container 생성
-
객체 생성, 의존성 주입, 객체의 생명주기를 관리 하게됨
-
ApplicationContext ac=new ClassPathXmlApplicationContext("설정파일의 경로");
-
-bean찾기(id 사용)
-
=>파일에 S가 붙어있는게 bean 이고 bean이라는 노드에 들어있는 클래스가 빈이고 Spring Framework에서 생성하는 객체
-
ac.getBean("id"); //Spring 2.5이하.. 권장하지 않는다.
-
ac.getBean("클래스명.class"); //Spring 3.0 권장하나 같은이름의 클래스가 bean으로 등록되면 식별이 되지 않아 Error발생(찾을수 없다)
-
ac.getBean("id", 클래스명.class); //간혹가다 있는상황으로 3.0이상에서 사용하고 같은이름의 클래스가 bean으로 등록되어있어도 식별이 가능하다. (이걸로 서비스를 넣어줄수 있다)
*생성자 의존성 주입
-
1)<constructor-arg ref="id"/>
-
2)<constructor-arg>
-
<ref bean="id"/>
-
</constructor-arg>
-
//로 두가지 방법이 있다.
*Method 의존성 주입
-
생성자가 없거나, 생성자가 여러개인(Overload된) 경우에는 기본생성자가 반드시 나와야 한다. (없으면 못찾음)
-
<bean id="아이디" class="패키지명.class">
-
<property name="setter명" ref="객체명" /> //ref든 value든 둘중 하나가 들어가는데 value는 기본형 데이터형을 넣을때 사용한다.
-
value="기본형 데이터형을 입력하는 경우"
-
</bean>
*기본형데이터형 injection
//PrimitiveTypeInjection.java
package day0423;
public class PrimitiveTypeInjection {
public PrimitiveTypeInjection(int i) {
System.out.println("기본형 데이터형을 매개변수로 Injection i="+i);
}//PrimitiveTypeInjection
public PrimitiveTypeInjection(String s) {
System.out.println("String을 매개변수로 받는 Injection s="+s);
}//PrimitiveTypeInjection
}//class
*JCF Injection
-
///Java Collection Framework
*Annotation 을 사용한 의존성 주입(Injection)
-
설정용 XML의 영향이 줄어든다(간단해짐)
-
@Component, @Autowired 두 개를 사용하게 됨
-
=>@Component : Bean으로 생성되어야할 클래스 위에 선언.
-
=>@Autowired : 의존성 주입받을 객체위에 선언
-
설정용 XML생성시 bean, context가 선택된 상태에서 사용.
-
사용법)
-
<context : annotation-config/> ///context<=prefix 사용해 처리.
-
<context : component-scan base-package="패키지명.*"/>
-
<context : component-scan base-package="패키지명"/>
-
//들이 들어있는 설정파일에는 가급적이면 <bean>으로 의존성 주입을 하지 않는다. 가능하지만 권장하지 않는다.
-
@Autowired(request=true|false)
-
이때 : true - 의존성 주입 받을 객체가 반드시 생성된 후 의존성 주입을 받게 되는 경우(객체 주소)
-
false - 의존성 주입받을 객체가 생성되지 않은 상태에서 의존성 주입이 되는 경우(null 할당)-(.method로 의존성 주입을 받게 되는 경우)
//applicationContext3.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans-4.3.xsd
http://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context-4.3.xsd">
<context:annotation-config/>
<context:component-scan base-package="day0423.*"/>
<context:component-scan base-package="day0423"/>
</beans>
//TestDao3.java
package day0423;
import org.springframework.stereotype.Component;
@Component
public class TestDao3 {
}
//TestService3.java
package day0423;
import org.springframework.beans.factory.annotation.Autowired;
importorg.springframework.stereotype.Component;
@Component
public class TestService3 {
//의존성 주입 받을 객체 위에 annotation 선언
@Autowired
private TestDao3 td; //private TestDao2 td2;가 추가선언 되면 1.위에만 2.아래만 3.둘다x-1번 위에 하나만 된다!각각해주어야함
public TestDao3 getTestDao3() {
return td;
}
}//class
//RunAnnotation.java
package day0423;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class RunAnnotation {
public static void main(String[] args) {
ApplicationContext ac =new ClassPathXmlApplicationContext("day0423/applicationContext3.xml");
TestService3 ts2=ac.getBean(TestService3.class);
System.out.println(ts2);
System.out.println(ts2.getTestDao3());//autowired로 의존성 주입이 되었어요.
}//main
}//class
# Anotation 을 사용한 의존성 주입
- 설립용 XML의 역할이 줄어든다
- @Component: Bean으로 생성되어야 할 클래스 위에 선언
- @Autowired: 의존성 주입받을 객체 위에 선언
- 설정용 XML 생성시, bean, context가 선택된 상태에서 사용
@Autowired(required=true/false)
: 의존성 주입을 받을 객체가 반드시 생성된 후, 의존성 주입을 받게 되는 경우(객체 주소)
: 의존성 주입받을 객체가 생성되지 않은 상태에서 의존성 주입이 되는 경우( null 할당)
method로 의존성 주입을 받게 되는 경우
- 사용법:
<context: annotation-config/> : prefix 사용
<context: component-scan base-package="패키지명.*"/>
- 설정 파일에는 가급적이면 <bean>으로 의존성 주입을 하지 않는다.
- 의존성 주입하는 클래스
@Component
class Test{
}
-------------------------------------------
- 의존성 주입 받는 클래스
@Component
class TestService{
@Autowired
private 의존성 주입 받을 객체
* 생성자를 만들지 않는다.
}
# Spring JDBC
- JDBC를 단순화하여 제공하는 기능
└ JDBC Template 객체 사용
└ insert, update, delete => update( )
select => queryForObject( )
query( )
- Spring JDBC에서 DB 연결 관리한다. (연결얻기, 연결 끊기 자동처리)
- 쿼리문 수행객체(statement, preparedStatement)
- DB연동하게 될 계정정보, 드라이버 정보를 설정 파일에서 설정한다.
- 값은 bind 변수로 처리할 수 있다.
- ResultSet 직접 얻어 사용하지 않고 RowMapper를 통해서 얻고 사용하게 된다.
1. DB 연동설정(DBCP 사용)
<bean>
2. JDBC 객체를 설정(DB 연동설정 정보를 가지고)
-method Injection 방식
<bean>
<property>
< spring API위치>
C:\dev\framework\spring-framework-4.3.9.RELEASE-dist (1)\spring-framework-4.3.9.RELEASE\docs\spring-framework-reference\pdf
.png)
dataException이없다고 해서 붙여넣을 예정
Spring JDBC
* JDBC를 단순화하여 제공하는 기능
* JdbcTemplate 객체사용
* insert, update, delete => update()
* select => queryFarObject()
* => query()
* spring JDBC에서 DB연결관리한다 (연결얻기, 연결끊기 자동처리)
* 쿼리문 수행객체 ( Statement, PreparedStatement ) 도 자동처리
* DB연동하게된 계정정보, 드라이버정보를 설정파일에서 설정한다.
* 설정파일 : MVC - Servlet-context.xml , DI - applicationContext.xml
* 값은 bind 변수로 처리할 수 있다
* 조회시에 ResultSet 직접 얻어서 사용하지 않고 RowMapper를 통해서 얻고 사용하게 된다.
* 1.DB 연동설정 ( DBCP 사용 )
* <benn>
* 2. JDBC 객체를 설정
Spring_mvc불러다 Spring_JDBC로 war로 불러 스프링화&메이븐설정 하고 src튀어나가면 빌드패스로 다시 넣어준다.
src 수업 부분 넣어주고 위에 해당되는 자르파일 넣어주고 POM.xml고쳐/servlet-context.xml DBMS와 연동하는 부분 넣어주고 저장!
alt+f5 업데이트 해준다. 그리고 index.html생성해 실행!!!!
*Spirng JDBC
- JdbcTemplate : 핵심객체로 의존성주입을(@Autowired->객체가 만들어져 있어야 가능하겠져 @component?) 받는다. DAO에서
-
- JdbcTemplate 에서 제공하는 method를 사용할 때에는 throws DataAccessException을 날려야 한다.
-
=>RuntimeException
*insert, update, delete
-
JdbcTemplate.update(sql문, 바인드 변수에 들어갈 값,,,);
-
?-> variable arguments가 되어 몇개든 들어갈 수 있다...
-
=>"insert into 테이블명(컬럼명,,,) values(?,?,?)" | "update..." | "delete..."
.png)
.png)
*Spring JDBC
-
조회 : RowMapper interface 사용
-
=>조회된 결과를 VO(Domain)에 저장하는 일
-
=>interface 사용하려면 구현클래스를 먼저 만들어야 하는데 내가 만들지 않아도 객체화해 사용할 수 있다. Annonymusinnerclass를 사용하면
-
-
-
한행 조회 )
-
Object o=(Object)JdbcTemplate.queryForObject(select sql문 , 값,,,);
-
여러행 조회 )
-
List l=JdbcTemplate.query( sql문, 값,,,);
@Component
class DAO{
@Autowired
JdbcTemplate jt;
public List<DeptDomain> selectAllDept() throw DataAccessException {
List<DeptDoamin> list =null;
//조회결과를 Domain에 저장 설정
RowMapper<DeptDomain> rm=new RowMapper<DeptDomain>() {
public DeptDoamin mapRow(ResultSet rs, int index){
DeptDomain dd=new DeptDomain(rs.getInt("deptno"), rs.getString("dname"), rs.getString("loc")); //한행이든 여러행이든 다해주어야 한다.
return dd;
}
};
//조회결과를 집어넣어준다 Spring이
//쿼리문 생성
String selectDept..;
//실행
list=jt.query(selectQuery);
return list;
}
//MyBatis 보다는 설정이 없고 JDBC보다는 코드가 짧아 사용이 비교적 편리
*Spring JDBC
//MemberUpdateVO.java
package kr.co.sist.vo;
public class MemberUpdateVO {
private int num;
private String name, highschool, loc; //파라메터로 들어오기 때문에 getter,setter만. 내가만드는거 아님
public int getNum() {
return num;
}
public void setNum(int num) {
this.num = num;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getHighschool() {
return highschool;
}
public void setHighschool(String highschool) {
this.highschool = highschool;
}
public String getLoc() {
return loc;
}
public void setLoc(String loc) {
this.loc = loc;
}
}
//update_result.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 charset="UTF-8">
<title>Insert title here</title>
<link rel="stylesheet" type="text/css" href="http://localhost:8080/spring_jdbc/common/css/main_v190130.css" />
<style type="text/css">
#wrap{margin:0px auto; width:1000px; height:860px;}
#header{width:1000px; height:140px; background: url(http://localhost:8080/spring_JDBC/common/images/header_bg.png) repeat-x; position: relative;}
#headerTitle{font-family:HY견고딕, 고딕; font-size:35px; font-weight: bold; text-align:center; position: absolute; top:40px; left: 350px;}
#container{width:1000px; min-height:600px; }
#footer{width:1000px; height:120px;}
#footerTitle{float:right; font-size: 14px; padding-top: 20px; padding-right: 20px}
td{padding: 3px}
</style>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.2.4/jquery.min.js"></script>
<script type="text/javascript">
$(function(){
});//ready
</script>
</head>
<body>
<div id="wrap">
<div id="header">
<div id="headerTitle">SIST Class4</div>
<div style ="padding-top: 100px">
<c:import url="/common/jsp/main_menu.jsp"/>
</div>
</div>
<div id="container">
<div>
<a href="add_form.do">정보추가</a>
<a href="search_member.do">정보조회</a>
</div>
<c:set var="img" value="err.png"/>
<c:if test="${resultFlag}">
<c:set var="img" value="img.png"/>
</c:if>
<img src="http://localhost:8080/spring_JDBC/common/images/${img}"/><br/>
${resultMsg}
</div>
<div id="footer">
<div id="footerTitle">copyright© all right reserved class4</div>
</div>
</div>
</body>
</html>
*Spring ORM(Object Relation Mapping)
-
Spring Framework과 DB Framework를 연동하는것
-
//DB에서 관리하던걸 Spring에서 대신해줌
-
-
MyBatis, Hibernate등의 Framework와 연동할 수 있는데, 연동의 module을 DB Framework에서 지원해줘야 연동이 가능하다.)
-
=>mybatis-Spring.jar를 사용하여 연동.(별도 다운 필요하지만 maven 으로 다운)
-
=>DB연동을 Spring으로 옮겨가서 하게됨
-
=>auto Commit이 가능해 짐
-
=>DB연동이 옮겨가며 설정이 간단해짐(Mapper만 연결해 주면 되게 되면서 하는일이 없어짐)
-
=>Transaction의 처리를 MyBatis에서 Spring으로 옮겨가서 하게 됨.
-
//Autocommit이 안되서 insert, update ,delete했을때 commit과 rollback을 수동으로 해주어야 했음.
-
//각각동작하는것..???
-
사용법)
-
연동할 수 있는 .jar를 다운(MyBatis site에서 다운)
-
mybatis-Spring.jar
-
Mybatis.org에서
-
-
-
-
-
단, Ojdbc는 메이븐으로 사용할 수 없다.!!! 받아지지 않는다. 오라클에 대해서는 수동
-
-
이렇게 두개 필요
-
DB연동 Bean 설정
(root-context.xml에 설정)
-
<bean id="dataSource" class="DriverManagerDataSource"> //MyBatis_config에 들어있던게 옮겨온것
-
<property...url/Driver/id/pass...>
-
</bean>
-
SqlSessionFactoryBean에 의존성 주입
-
=>SqlSessionFactoryBuilder+SqlSessionFactory의 기능을 가진 클래스 //로 DB연동에대한 관리를 하지는 않는다.
-
<bean id="ssfb" class="org.mybatis.Spring.SqlSessionFactoryBean">
-
//DB연동을 내가 안하고 root-context가 하게 됨?
-
<property name="dataSource" ref="dataSource"/> //객체를 받을땐 ref 기본형데이터를 받을땐 value
-
<property name="configLocation" value="MyBatis설정용.xml의 경로"/>
-
//<mappers><typeAliases>를 갖게된다. Mapper정보가 중요..
-
</bean>
-
//MyBatis Handler 는 SqlSession 이었는데...
-
MyBatis Handler (객체생성해서) 의존성 주입 받기 ========>생성자 의존성 주입
-
=>SqlSessionTemplate ///으로 이름이 변경
-
<bean id="객체명" class="org.mybatis.spring.SqlSessionTemplate">
-
<property name="" ref="ssfb"/>
-
</bean>
.png)
*Spring ORM
-
root-context.xml 설정
-
(mybatis의 역할 축소)
-
DB 연결 설정 : DriverManagerDataSource ///스프링에서 생성하는 객체의 이름을 bean이라고 하는데
-
<bean id="" class="">
-
SqlSessionFactoryBean 설정
-
mybatis_spring.jar에 들어있다. (메이븐으로 다운받았음-이때 실행(운용)하기위해 lib에도 넣어주었다.
-
DriverManagerDataSource를 method의존성 주입을 받게 됨.
-
Mybatis_config.xml을 method의존성 주입
-
=>mapper.xml 설정(sql문 작성)
-
//DI로 빼면 applicationcontext에 넣어도 된다(spring에 context에도 가능
-
<bean id="" class="">
-
<property ref=""/>
-
<property value=""/>
-
SqlSessionTemplate설정 (MyBatis Handler)
-
SqlSessionFactoryBean을 생성자 의존성 주입(constructor-arg로 함) 받게 된다.
-
<bean id="" class="">
-
<constructor-arg ref=""/>
-
</bean>
-
Source Code에서 SqlSessionTemplate를 의존성 주입 받아 사용.
-
@Component //<-<<<설정파일로 context로 찾아주는 ...부분
-
public class Test{
-
@Autowired(required=false) //<- <contest:annotation-config/> <context:component-scan />이 되어있어야 사용가능!!
-
private SqlSessionTemplate sst;
.png)
.png)
반응형
'국비지원학원 > Spring Framework' 카테고리의 다른 글
126일차-Spring AOP~127일차-AOP (0) | 2019.08.24 |
---|---|
117일차-Spring Framework_parameter 처리 (0) | 2019.04.30 |
116일차-Spring Framework설명 (0) | 2019.04.30 |