[21.10.19] service

yed·2021년 10월 19일
0

MVC 동작순서에 따라 DB->MyBatis->DAO까지 만들었다면 Service를 만들어야함

서비스 계층(Service/Business layer)

  • @Service
    객체를 생성해야하는 어노테이션 필요. DAOImple과 마찬가지로 @Component로 대체가능하다
  • 표현 계층(Presentation layer. Front Controller)과 영속계층(Persistence layer. DAO) 사이를 연결해 두 계층이 직접적으로 통신하지 않게끔 결속력을 낮춘다.

  • 서비스계층이 추가되면 코드복잡도가 증가함

  • 트랜잭션(transaction)을 관리함

  • Service에서는 데이터조작을 CRUD(Create, Read, Update, Delete)라고 부름

  • 구조는 DAO와 거의 유사하다

  • DB와 상관없이 DAO 여러개의 데이터를 처리할 수 있다. DAO처럼 DB와 1:1매칭이 필요없음.

@Override
public int create(BoardVO vo) {
	LOGGER.info("create() 호출 : vo = "+vo.toString());
	return dao.insert(vo);
}//end create()

@Override
public List<BoardVO> read(PageCriteria criteria) {
	LOGGER.info("read() 호출 : PageCriteria = "+criteria);
	return dao.select(criteria);
}//end read()
  • controller는 service 객체를 사용한다.
@Autowired
private BoardService boardService;
	
@GetMapping("/list")
public void list(Model model, Integer page, Integer numsPerPage) {
	LOGGER.info("list() 호출");
	LOGGER.info("page = "+page+", numsPerPage = "+numsPerPage);
		
	//paging 처리. 기존데이터가 남아있으면 문제가 생길수있어서 new 사용
	PageCriteria criteria = new PageCriteria();
	if(page !=null) {
		criteria.setPage(page);
	}
	
	if(numsPerPage!=null) {
		criteria.setNumsPerPage(numsPerPage);
	}
	
	List<BoardVO> list=boardService.read(criteria);
	model.addAttribute("list", list); //list 데이터 보내기
	
	PageMaker pageMaker=new PageMaker();
	pageMaker.setCriteria(criteria);
	pageMaker.setTotalCount(boardService.getTotalNumsOfRecords());
	pageMaker.setPageData();
	model.addAttribute("pageMaker", pageMaker);
}//end list()

특정 게시글에서 목록으로 들어가면 해당 게시글이 존재하던 게시판 페이지번호가 남아있어야한다.
이게 없으면 15페이지에있는 게시글을 읽고 목록으로 갈경우 1페이지로 돌아가게되며 사용자는 다시 15페이지까지 찾아가야하는 불편함이 있다.

넘겨받은 pageMaker를 통해 링크에 게시판번호뿐만아니라 현재 page번호까지 넣어서 넘기기

<td><a href="detail?bno=${vo.bno }&page=${pageMaker.criteria.page}">${vo.title }</a></td>

JUnit으로 Controller 테스트

ControllerTest는 front controller역할을 해야함.

@Autowired
private WebApplicationContext wac;
	
private MockMvc mock; 
  • WebApplicationContext : 웹 어플리케이션 객체
  • MockMvc : MVC패턴의 앱을 테스트하는 mock-up객체

@Before

org.junit.Before

  • 실제 JUnit 테스트를 실행하기전에 공통적으로 사용되는 초기화작업을 수행하는 메소드
  • controller와 FrontController 사이에서 before/after 작업을 수행한다. 스프링이 내부적으로 컨트롤하기때문에 테스트가 필요

테스트할 때 경로와 method 방식이 필요

@Before
public void beforeTest() {
	LOGGER.info("beforeTest() 호출");
	LOGGER.info("wac : "+wac);
	LOGGER.info("mock : "+mock);
		
	//컨트롤러 메소드에게 요청을 보낼 수있는 mockup객체 생성
	mock=MockMvcBuilders.webAppContextSetup(wac).build();
}//end beforeTest()
  • mock.perform() : client와 controller의 데이터 이동이 있어서 데이터 유실될 위험이 있어 에러처리가 필요함

    get(uri) : get 요청에 대한 mock 객체 생성
    post(uri) : post 요청에 대한 mock 객체 생성
    put(uri) : 업데이트. put 요청에 대한 mock 객체 생성
    delete(uri) : 삭제. delete 요청에 대한 mock 객체 생성

private void testList() throws Exception {
	LOGGER.info("testList() 호출");
	mock.perform(get("/board/list").param("page", "1"));  
}

get방식의 param을 전송한다. 데이터가 문자열인 이유는 parameter는 String만 전송하기 때문.

  • 여러개 데이터를 parameter로 보내는 방법
MultiValueMap<String, String> params=new LinkedMultiValueMap<String, String>();
params.add("page", "1");
params.add("numsPerPage", "5");
mock.perform(get("/board/list").params(params));
  • param(key, value) : 파라미터 데이터 전송
  • params(params) : map형식의 파라미터 데이터 전송

@After

JUnit 테스트 수행 후 호출되는 메소드


날짜 포맷 jsp에서 바꾸기

  • 날짜 포맷을 바꾸기 위한 태그 설정
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>     
  • <fmt:formatDate> 으로 날짜 pattern 지정하기
<fmt:formatDate value="${vo.cdate }" pattern="yyyy-MM-dd HH:mm:ss" var="cdate" />
<td>${cdate }</td>

RedirectAttributes

  • 재경로 위치에 속성값을 전송하는 객체
@PostMapping("/register")
public String registerPOST(BoardVO vo, RedirectAttributes reAttr) {

	LOGGER.info("registerPOST() 호출");
	LOGGER.info(vo.toString());
	int result=boardService.create(vo);
	LOGGER.info(result+"행 삽입");
		
	if(result==1) {
		LOGGER.info("result 1");
		reAttr.addFlashAttribute("insert_result", "success"); //데이터 전송
		return "redirect:/board/list"; // /board/list 경로로 이동시키는 get방식
	}else {
		reAttr.addFlashAttribute("insert_result", "fail");
		return "redirect:/board/register"; //create 실패하면 다시 글작성페이지로 이동
	}
}//end registerPOST()

controller에선 jsp관련 태그를 아예 안쓰는게 좋아서 클라이언트가 하도록 경로와 데이터만 전송함

<input type="hidden" id="insertAlert" value="${insert_result }">
<script type="text/javascript">
	$(function() {
		confirmInsertReslut();
		
		function confirmInsertReslut() {
			var result=$('#insertAlert').val();
			if(result=='success'){
				alert('새 글 작성 성공');
			}
		}
	});//end document
</script>

뒤로가기 캐시 삭제 설정

뒤로가기 할때 이전에 이용했던 데이터가 남아있으면 안됨
url 이동 중간에 간섭해서 세션을 관리하는 인터셉션. 뒤로가기 방지

<interceptors>
	<beans:bean id="webContentInterceptor" class="org.springframework.web.servlet.mvc.WebContentInterceptor">
		<beans:property name="cacheSeconds" value="0"></beans:property>
		<beans:property name="useExpiresHeader" value="true"></beans:property>
		<beans:property name="useCacheControlHeader" value="true"></beans:property>
		<beans:property name="useCacheControlNoStore" value="true"></beans:property>
	</beans:bean>
</interceptors>

뒤로가기 설정을 안했을 땐 글작성 성공 후 뒤로가기 눌렀을 때 다시 글작성 성공했다는 alert가 뜸
뒤로가기 캐시 삭제를 설정하면 글작성 성공 후 뒤로가기 눌렀을 때 바로 글작성 페이지로 이동함.


tomcat timeout 오류

pc환경에서 노트북으로 파일을 옮겨서 진행했는데 갑자기 프로젝트가 무거운게 아닌데 계속 timeout이 떠서 1차 해결방법으로 서버의 start, stop시간을 조정해봤지만 무려 450초가 지나도 서버가 timeout되는 현상이 발생했음
그래서 tomcat을 재설치하려던 중 pc에 tomcat 설치폴더가 두개가 존재함을 발견. 혹시나해서 정상 경로에 있는 폴더 제외하고 다 지웠더니 서버 start가 10초도 안걸렸음! 파일을 전부 인식한것같다... 이런경우가 다있네
일시적 효과였다.
반복적인 서버재시작을 하니깐 갑자기 target 폴더의 config.xml을 찾더니 또 timeout에 걸리고 또 잘됐다가 개복치마냥 다시 timeout..
심지어 port8080과 8005가 이미 사용중이라며 이제 서버가 시작조차 안됨. 최종진화같다.
수업도중에 손보기에 어려울것같아 일단은 임시방편으로 port번호를 8006, 9080으로 바꿔놓았음
문제해결ing

profile
6개월 국비과정 기록하기

0개의 댓글