오늘의 요약!!!!!!!!!
오전만에 수업이 끝남 그리고 CRUD 게시판 만드는거 실습
- AOP
- AOP
- AOP
하루에 요약을 3개씩 쓸라고 했느데 쓸말이 없다.....
AOP(Aspect Oriented Programming) : 관점지향 프로그래밍
=> 프로그램이 실행되는 처리 과정을 바라보는 시점에 따라 분할하여 인식하는것, 해당 시점에 추가적 구현을 하는것
Advice: 관점 지점 (아래 사진의 검정색, 쪼갠 시점)
Joinpoint: 진행중인 흐름 (아래 사진의 주황색 부분)
pointcut: 적용 대상
로그인 했느냐 안했느냐에 따라(필터) 어디로 가고 하는거,
이런 필터를 매번 거는게 번거로움, 또 하나 문제점이 비교대상의 세션유형이 바뀌면 해당하는 곳을 다 바꿔줘야함
이 시점에 뭐 했으면 좋겠다 하고 한번구현하면 나머지 쪽에 다 적용된데
설정과 관련된 부분
요즘에는
https://araikuma.tistory.com/309
AspectJ에 대한 설정이 pom.xml에 있음!
다시 AOPComponent
생각해보니, 서버 실행될때, 콘솔창이 testAOP() 뜨는 거 많이 봄!!!
AOPComponent.java
package com.spring.sample.common.component;
import javax.servlet.http.HttpServletRequest;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.servlet.ModelAndView;
@Aspect // AOP용 클래스
@Component // 객체 생성
@EnableAspectJAutoProxy // AspectJ 기능 활성화
public class AOPComponent {
// Pointcut -> 적용범위
// @Pointcut(범위설정)
/*
* 범위
* execution -> include필터 나 포함할래
* !execution -> exclude필터 나 포함 안할래
* * -> 모든것
* *(..) -> 모든 메소드
* .. -> 모든 경로
* &&, || -> 필터 추가
*
* execution(접근권환 반환타입 범위): 접근권한의 경우 필수가 아님
*/
// com.spring.sample.. 밑에 있는 모든 경로(..)에서 HomeController를 찾고, 모든 메서드인데, 인자도 상관없어
@Pointcut("execution(* com.spring.sample..HomeController.*(..))")
public void testAOP() { // 내용이 없어서 void로 하면 되고, pointcut의 이름과 같은 역활
}
// ProceedingJoinPoint -> 대상 적용 이벤트 필터, 진행중인 현재상태
/*
* Advice
* @Before -> 메소드 실행 전
*
* @After -> 메소드 실행 후
*
* @After-returning -> 메소드 정상실행 후
*
* @After-throwing -> 메소드 예외 발생 후
*
* @Around -> 모든 동작시점
*/
@Around("testAOP()") //"execution(* com.spring.sample..HomeController.*(..))" 한테서 @Around 모든 동작 시점에 체크해볼래
public ModelAndView testAOP(ProceedingJoinPoint joinPoint) throws Throwable {
ModelAndView mav = new ModelAndView();
// Request 객체 취득
// RequestContextHolder
HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.currentRequestAttributes())
.getRequest();
mav = (ModelAndView) joinPoint.proceed(); // 기존 이벤트 처리 행위를 이어서 진행
System.out.println("------- testAOP 실행됨 ------");
return mav;
}
}
https://engkimbs.tistory.com/746
https://sjh836.tistory.com/157
pointcut 추가
근디 우리는 지금 리스트랑 디테일은 로그인 안해도 볼수 있게 해야하기 때문에
그냥
포인트컷 잡을때 범위를 어떻게 찾을지 생각해야함
AOPComponent.java
atAOP 추가 이후 전체코드
package com.spring.sample.common.component;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.servlet.ModelAndView;
@Aspect // AOP용 클래스
@Component // 객체 생성
@EnableAspectJAutoProxy // AspectJ 기능 활성화
public class AOPComponent {
// Pointcut -> 적용범위
// @Pointcut(범위설정)
/*
* 범위 execution -> include필터 나 포함할래
* !execution -> exclude필터 나 포함 안할래
* * -> 모든것
* *(..) -> 모든 메소드
* .. -> 모든 경로
* &&, || -> 필터 추가
*
* execution(접근권환 반환타입 범위): 접근권한의 경우 필수가 아님
*/
// com.spring.sample.. 밑에 있는 모든 경로(..)에서 HomeController를 찾고, 모든 메서드인데, 인자도 상관없어
@Pointcut("execution(* com.spring.sample..HomeController.*(..))")
public void testAOP() { // 내용이 없어서 void로 하면 되고, pointcut의 이름과 같은 역활
}
// ProceedingJoinPoint -> 대상 적용 이벤트 필터, 진행중인 현재상태
/*
* Advice
*
* @Before -> 메소드 실행 전
*
* @After -> 메소드 실행 후
*
* @After-returning -> 메소드 정상실행 후
*
* @After-throwing -> 메소드 예외 발생 후
*
* @Around -> 모든 동작시점
*/
@Around("testAOP()") // "execution(* com.spring.sample..HomeController.*(..))" 한테서 @Around 모든 동작 시점에
// 체크해볼래
public ModelAndView testAOP(ProceedingJoinPoint joinPoint) throws Throwable {
ModelAndView mav = new ModelAndView();
// Request 객체 취득
HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.currentRequestAttributes())
.getRequest();
mav = (ModelAndView) joinPoint.proceed(); // 기존 이벤트 처리 행위를 이어서 진행
System.out.println("------- testAOP 실행됨 ------");
return mav;
}
// pointcut 여러개 써도됨
// 이렇게 했을때 AJAX를 문제, Ajax는 결국 string을 돌려주는데 우리는 지금 ModelAndView로 돌려주게 해놨기 때문에 따로
// 처리해야함
@Pointcut("execution(* com.spring.sample..Controller.ATController.*Insert(..))"
+ "|| execution(* com.spring.sample..Controller.ATController.*Update(..))")
public void atAOP() {
}
@Around("atAOP()") // atAOP()를 가져와서 써
public ModelAndView atAOP(ProceedingJoinPoint joinPoint) throws Throwable {
ModelAndView mav = new ModelAndView();
// Request 객체 취득
HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.currentRequestAttributes())
.getRequest();
HttpSession session = request.getSession();
if (session.getAttribute("sMemNm") != null && session.getAttribute("sMemNm") != "") { // 로그인 중인 경우
mav = (ModelAndView) joinPoint.proceed(); // 기존 이벤트 처리 행위를 이어서 진행
} else { // 비 로그인의 경우
mav.setViewName("redirect:testALogin");
}
return mav;
}
}
aop건 이후
ATController의 insert부분
실행결과
ATinsert, ATUpdate에 들어갈려고 하면
로그인 페이지로 가버림
ATController.java
package com.spring.sample.web.testa.Controller;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.ModelAndView;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.spring.sample.common.service.IPagingService;
import com.spring.sample.web.testa.dao.IACDao;
@Controller
public class ATController {
@Autowired
public IACDao iACDao;
@Autowired
public IPagingService ips;
@RequestMapping(value = "/ATList")
public ModelAndView ATList(@RequestParam HashMap<String, String> params, ModelAndView mav) {
// 비동기가 되면 일단 아무것도 처음에 셋팅 X,
// 페이지만 셋팅
int page = 1;
if (params.get("page") != null && params.get("page") != "") {
page = Integer.parseInt(params.get("page"));
}
mav.addObject("page", page);
mav.setViewName("testa/T/list");
return mav;
}
@RequestMapping(value = "/ATListAjax", method = RequestMethod.POST, produces = "text/json;charset=UTF-8")
@ResponseBody
public String ATListAjax(@RequestParam HashMap<String, String> params) throws Throwable {
ObjectMapper mapper = new ObjectMapper();
Map<String, Object> model = new HashMap<String, Object>();
// 페이지 받아오게 되어있음
int cnt = iACDao.getInt("T.getTCnt", params);
HashMap<String, Integer> pd = ips.getPagingData(Integer.parseInt(params.get("page")), cnt, 10, 5);
params.put("start", Integer.toString(pd.get("start")));
params.put("end", Integer.toString(pd.get("end")));
List<HashMap<String, String>> list = iACDao.getList("T.getTList", params);
model.put("list", list);
model.put("pd", pd);
return mapper.writeValueAsString(model);
}
@RequestMapping(value = "/ATInsert")
public ModelAndView aTInsert(ModelAndView mav) {
mav.setViewName("testa/T/insert");
return mav;
}
@RequestMapping(value = "/ATAction/{gbn}", method = RequestMethod.POST, produces = "text/json;charset=UTF-8")
@ResponseBody
public String ATAction(@PathVariable String gbn, @RequestParam HashMap<String, String> params) throws Throwable {
ObjectMapper mapper = new ObjectMapper();
Map<String, Object> model = new HashMap<String, Object>();
int cnt = 0;
try {
switch (gbn) {
case "insert":
cnt = iACDao.insert("T.insertT", params);
break;
case "update":
cnt = iACDao.update("T.updateT", params);
break;
case "delete":
cnt = iACDao.update("T.deleteT", params);
break;
}
if (cnt > 0) {
model.put("msg", "success");
} else {
model.put("msg", "fail");
}
} catch (Exception e) {
e.printStackTrace();
model.put("msg", "error");
}
return mapper.writeValueAsString(model);
}
// 가져오고 변경되는게 없기 때문에 비동기 처리로 안되도 됨
@RequestMapping(value = "/ATDetail")
public ModelAndView aTDetail(@RequestParam HashMap<String, String> params, ModelAndView mav) throws Throwable {
// 글번호 안 넘어왔을때 처리
if (params.get("no") != null && params.get("no") != "") {
// 조회수
iACDao.update("T.updateTHit", params);
HashMap<String, String> data = iACDao.getMap("T.getT", params);
mav.addObject("data", data);
mav.setViewName("testa/T/detail");
} else {
mav.setViewName("redirect:ATList");
}
return mav;
}
@RequestMapping(value = "/ATUpdate")
public ModelAndView aTUpdate(@RequestParam HashMap<String, String> params, ModelAndView mav) throws Throwable {
// 글번호 안 넘어왔을때 처리
if (params.get("no") != null && params.get("no") != "") {
HashMap<String, String> data = iACDao.getMap("T.getT", params);
mav.addObject("data", data);
mav.setViewName("testa/T/update");
} else {
mav.setViewName("redirect:ATList");
}
return mav;
}
}
내일꺼 미리 셋팅
TBOARD테이블 수정 CATE_NO 컬럼 추가
CATE테이블 만듬
CATE 테이블이랑 TBOARD랑 외래키 설정
시퀀스도 추가해줌
CRUD게시판 만들기 실습(한줄 게시판 느낌으로 만듬, 강사님이랑 같이 한건 아님)
ACateController.java
package com.spring.sample.web.testa.Controller;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.ModelAndView;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.spring.sample.common.service.IPagingService;
import com.spring.sample.web.testa.dao.IACDao;
@Controller
public class ACateController {
@Autowired
public IACDao dao;
@Autowired
public IPagingService ips;
// DB안 붙으니 예외처리 x
@RequestMapping(value = "ACOB")
public ModelAndView aob(ModelAndView mav) {
mav.setViewName("testa/Cate/cob");
return mav;
}
@RequestMapping(value = "/ACOBAction/{gbn}", method = RequestMethod.POST, produces = "text/json;charset=UTF-8")
@ResponseBody
public String AOBAction(@PathVariable String gbn, @RequestParam HashMap<String, String> params) throws Throwable {
ObjectMapper mapper = new ObjectMapper();
Map<String, Object> model = new HashMap<String, Object>();
int cnt = 0;
try {
switch (gbn) {
case "insert":
cnt = dao.insert("cob.insertOb", params);
break;
case "update":
cnt = dao.update("cob.updateOb", params);
break;
case "delete":
cnt = dao.update("cob.deleteOb", params);
break;
}
if (cnt > 0) {
model.put("msg", "success");
} else {
model.put("msg", "fail");
}
} catch (Exception e) {
e.printStackTrace();
model.put("msg", "error");
}
return mapper.writeValueAsString(model);
}
@RequestMapping(value = "/ACOBList", method = RequestMethod.POST, produces = "text/json;charset=UTF-8")
@ResponseBody
public String AOBList(@RequestParam HashMap<String, String> params) throws Throwable {
ObjectMapper mapper = new ObjectMapper();
Map<String, Object> model = new HashMap<String, Object>();
// 페이지 받아오게 되어있음
int cnt = dao.getInt("cob.getObCnt", params);
HashMap<String, Integer> pd = ips.getPagingData(Integer.parseInt(params.get("page")), cnt, 10, 5);
params.put("start", Integer.toString(pd.get("start")));
params.put("end", Integer.toString(pd.get("end")));
List<HashMap<String, String>> list = dao.getList("cob.getObList", params);
model.put("list", list);
model.put("pd", pd);
return mapper.writeValueAsString(model);
}
}
cob.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>
<!-- Common CSS -->
<link rel="stylesheet" type="text/css" href="resources/css/common/cmn.css" />
<!-- Popup CSS -->
<link rel="stylesheet" type="text/css" href="resources/css/common/popup.css" />
<style type="text/css">
.wrap{
width: 600px;
margin: 0 auto;
}
.mtb{
margin: 5px;
}
.login{
vertical-align: baseline;
}
.cateNm{
width: calc(100% - 22px);
height: 40px;
border: 1px solid #d7d7d7;
resize: none;
padding: 10px
}
.update{
display: none;
}
.con_td{
font-size: 0
}
.paging_area{
display: block;
position: relative;
left: 0;
margin-bottom: 10px;
}
.search_area{
text-align: center;
}
body {
overflow: auto;
}
</style>
<script type="text/javascript"
src="resources/script/jquery/jquery-1.12.4.min.js"></script>
<script type="text/javascript"
src="resources/script/common/popup.js"></script>
<!-- Slimscroll -->
<!-- <script type="text/javascript" src="resources/script/jquery/jquery.slimscroll.js"></script> -->
<script type="text/javascript">
$(document).ready(function () {
reloadList();
$("#insertBtn").on("click", function () {
if($.trim($("#cateNm").val()) == ""){
makeAlert("알림","카테고리를 입력하세요." , function () {
$("#cateNm").focus();
});
} else {
action("insert");
}
})
// 페이징 클릭시
$(".paging_area").on("click", "span", function () {
$("#page").val($(this).attr("page"));
//기존 값 유지
$("#searchGbn").val($("#oldGbn").val());
$("#searchText").val($("#oldText").val());
reloadList();
})
// 검색 클릭시
$("#searchBtn").on("click", function () {
$("#page").val("1");
//기존 값 새값으로 변경
$("#oldGbn").val($("#searchGbn").val());
$("#oldText").val($("#searchText").val());
reloadList();
})
// 목록의 삭제버튼 클릭시
$("tbody").on("click", ".delete_btn", function () {
var no = $(this).parent().parent().attr("no");
makePopup({
title : "알림",
contents : "삭제하시겠습니까?",
// draggable : true,
buttons : [{
name : "삭제",
func:function() {
$("#no").val(no);
action("delete");
closePopup(); // 제일 위의 팝업 닫기
}
}, {
name : "취소"
}]
})
})
// 목록 수정버튼 클릭시
$("tbody").on("click", ".update_btn", function () {
var no = $(this).parent().parent().attr("no");
$("#no").val(no);
//eq(인덱스번호) : 자식들 중 인덱스 몇번째 인지 찾아서 취득
var con = $(this).parent().parent().children().eq(1).html();
// 수정 내용 넣기 전 <> 변화
con = con.replace(/</gi, "<");
con = con.replace(/>/gi, ">");
$("#cateNm").val(con);
// 등록버튼 감추기 + 수정, 취소버튼 나타나기
$(".insert").hide();
$(".update").show();
// 작성영역에 포커스
$("#cateNm").focus();
})
// 수정 영역의 취소버튼
$("thead #cancelBtn").on("click", function () {
// 입력내용 초기화
$("#no").val("");
$("#cateNm").val("");
// 등록버튼 나타나기 + 수정, 취소버튼 감추기
$(".insert").show();
$(".update").hide();
})
// 수정 영역의 수정버튼
$("thead #updateBtn").on("click", function () {
action("update");
console.log("1");
})
})
var msg ={
"insert" : "등록",
"update" : "수정",
"delete" : "삭제",
}
function action(flag) {
// con의 <를을 웹문자로 변환
$("#cateNm").val($("#cateNm").val().replace(/</gi, "<"));
// con의 >를을 웹문자로 변환
$("#cateNm").val($("#cateNm").val().replace(/>/gi, ">"));
// Javascript object에서의 [] : 해당 키값으로 내용을 불러오거나 넣을 수있다.
// Java의 Map에서 get, put역활
console.log(msg[flag]);
var params = $("#actionForm").serialize();
$.ajax({
url : "ACOBAction/" + flag,
type : "POST",
dataType: "json",
data: params,
success : function(res) {
switch(res.msg){
case "success" :
// 내용 초기화
$("#cateNm").val("");
$("#no").val("");
// 목록 재조회
switch(flag){
case "insert" :
case "delete" :
// 조회 데이터 초기화
$("#page").val("1");
$("#searchGbn").val("0");
$("#searchText").val("");
$("#oldGbn").val("0");
$("#oldText").val("");
break;
case "update" :
// 기존값 유지
$("#searchGbn").val($("#oldGbn").val());
$("#searchText").val($("#oldText").val());
// 입력내용 초기화
$("#no").val("");
$("#cateNm").val("");
// 등록버튼 나타나기 + 수정, 취소버튼 감추기
$(".insert").show();
$(".update").hide();
break;
}
reloadList();
break;
case "fail" :
makeAlert("알림" , msg[flag] + "에 실패하였습니다.");
break;
case "error" :
makeAlert("알림" , msg[flag] + " 중 문제가 발생하였습니다.");
break;
}
},
error : function(request, status, error) {
console.log(request.responseText);
}
}); //Ajax End
} // action Function End
function reloadList() {
var params = $("#searchForm").serialize();
$.ajax({
url : "ACOBList",
type : "POST",
dataType: "json",
data: params,
success : function(res) {
drawList(res.list);
drawPaging(res.pd);
},
error : function(request, status, error) {
console.log(request.responseText);
}
}); //Ajax End
}
function drawList(list) {
var html = "";
for(var data of list){
html +="<tr no=\"" + data.CATE_NO + "\">";
html +="<td>" + data.CATE_NO + "</td>";
html +="<td>" + data.CATE_NM + "</td>";
html +="<td>";
html +="<div class=\"cmn_btn_ml mtb update_btn\">수정</div><br/>";
html +="<div class=\"cmn_btn_ml mtb delete_btn\">삭제</div>";
html +="</td>";
html +="</tr>";
}
$("tbody").html(html);
}
function drawPaging(pd) {
var html = "";
html += "<span class=\"page_btn page_first\" page=\"1\">처음</span>";
// 이전
if($("#page").val() == "1"){
html += "<span class=\"page_btn page_prev\" page=\"1\">이전</span>";
} else{
// 문자열을 숫자로 바꾸기위해 *1
html += "<span class=\"page_btn page_prev\" page=\"" + ($("#page").val() *1 - 1) + "\">이전</span>";
}
for(var i = pd.startP; i <= pd.endP; i++){
if($("#page").val() * 1 == i){ // 현재 페이지
html += "<span class=\"page_btn_on\" page=\"" + i + "\">" + i + "</span>";
} else { // 다른 페이지
html += "<span class=\"page_btn\" page=\"" + i + "\">" + i + "</span>";
}
}
if($("#page").val() *1 == pd.endP){ // 현재페이지가 마지막 페이지라면
html += "<span class=\"page_btn page_next\" page=\"" +pd.maxP+ "\">다음</span>";
} else {
html += "<span class=\"page_btn page_next\" page=\"" + ($("#page").val() *1 + 1) + "\">다음</span>";
}
html += "<span class=\"page_btn page_last\" page=\"" +pd.maxP+ "\">마지막</span>";
$(".paging_area").html(html);
}
</script>
</head>
<body>
<hr/>
<div class="wrap">
<div class="board_area">
<!-- 작성 또는 로그인 -->
<!-- 목록 -->
<table class="board_table">
<colgroup>
<col width="100"> <!-- 번호 -->
<col width="500"> <!-- 카테고리명 -->
</colgroup>
<thead>
<tr>
<td colspan="3" class="con_td">
<form action="#" id="actionForm">
<input type="hidden" name="no" id="no">
<textarea class="cateNm" name="cateNm" id="cateNm" placeholder="카테고리명을 입력해주세요"></textarea>
</form>
</td>
<td>
<div class="insert">
<div class="cmn_btn_ml" id="insertBtn">등록</div>
</div>
<div class="update">
<div class="cmn_btn_ml mtb" id="updateBtn">수정</div><br/>
<div class="cmn_btn_ml mtb" id="cancelBtn">취소</div>
</div>
</td>
</tr>
<tr>
<th>번호</th>
<th>카테고리명</th>
</tr>
</thead>
<tbody>
</tbody>
</table>
<!-- 페이징 -->
<div class="paging_area"></div>
</div>
<div class="search_area">
<!-- 검색어 유지용 -->
<input type="hidden" id="oldGbn" value="0" />
<input type="hidden" id="oldText" />
<form action="#" id="searchForm">
<input type="hidden" name="page" id="page" value="1" />
<select name="searchGbn" id="searchGbn">
<option value="0">번호</option>
<option value="1">카테고리명</option>
</select>
<input type="text" name="searchText" id="searchText"/>
<div class="cmn_btn_ml" id="searchBtn">검색</div>
</form>
</div>
</div>
</body>
</html>
Cate_SQL.xml
<?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="cob">
<insert id="insertOb" parameterType="hashmap">
INSERT INTO CATE(CATE_NO, CATE_NM) VALUES (CATE_SEQ.NEXTVAL, #{cateNm})
</insert>
<update id="updateOb" parameterType="hashmap">
UPDATE CATE SET CATE_NM = #{cateNm}
WHERE CATE_NO = #{no}
</update>
<update id="deleteOb" parameterType="hashmap">
UPDATE CATE SET DEL = 0
WHERE CATE_NO = #{no}
</update>
<select id="getObCnt" parameterType="hashmap" resultType="Integer">
SELECT COUNT(*) AS CNT
FROM CATE
WHERE DEL = 1
<if test="searchText != null and searchText != ''">
<choose>
<when test="searchGbn eq 0">
AND CATE_NO = #{searchText}
</when>
<when test="searchGbn eq 1">
AND CATE_NM LIKE '%' || #{searchText} || '%'
</when>
</choose>
</if>
</select>
<select id="getObList" parameterType="hashmap" resultType="hashmap">
SELECT S.CATE_NO, S.CATE_NM
FROM(SELECT CATE_NO, CATE_NM,
ROW_NUMBER() OVER(ORDER BY CATE_NO DESC, CATE_NM DESC) AS RNK
FROM CATE
WHERE DEL = 1
<if test="searchText != null and searchText != ''">
<choose>
<when test="searchGbn eq 0">
AND CATE_NO = #{searchText}
</when>
<when test="searchGbn eq 1">
AND CATE_NM LIKE '%' || #{searchText} || '%'
</when>
</choose>
</if>
) S
WHERE S.RNK BETWEEN #{start} AND #{end}
</select>
</mapper>
결과화면
등록, 수정, 삭제, 검색, 페이징 다 잘 됨!
개인적으로 패스트캠퍼스의 강의 들음
AOP
공통 코드의 분리
하나의 메서드의 두개의 관심사
메서드의 핵심기능, 부가기능이 있어
메서드들이 부가기능을 공통적으로 가지고 있어 => 분리
분리
1. 관심사
2. 변하는것, 변하지 않는것
3. 공통코드
분리하고 myAdvice 클래스에서 reflection API 통해서 호출하면, 더 변경에 유리한 코드가 됨
reflection API
https://tecoble.techcourse.co.kr/post/2020-07-16-reflection-api/
강의에서는 reflection API사용했구, 우리는 AspectJ 라이브러리 했고,
뭔가 aop제외하는것도 다름
AspectJ 에서는 !~~~ 이렇게, 강의에서는 pattern으로 정의해서 사용
https://sabarada.tistory.com/97
'TIL > academy' 카테고리의 다른 글
국비 TIL(Today I Learned) 20220902 시험 (0) | 2022.09.02 |
---|---|
국비 TIL(Today I Learned) 20220901 갤러리 실습 (0) | 2022.09.01 |
국비 TIL(Today I Learned) 20220824 시험, CRUD 게시판 만들기, SELL테이블로, 팀별프로젝트 (0) | 2022.08.24 |
국비 TIL(Today I Learned) 20220823 한줄 게시판(댓글) 만들기 (0) | 2022.08.23 |
국비 TIL(Today I Learned) 20220822 ajaxForm으로 파일 첨부, 다운받기 (0) | 2022.08.22 |