AOP와 트랜잭션 처리 실습 (코드로 테스트)

Back-End/Spring 2019. 6. 26. 17:52
728x90
반응형

-AOP 실습예제-


사용자가 메시지를 남기면 포인트 10 증가


메시지를 읽으면 포인트 5 증가


글쓰기를 하면 포인트 10을 부여


글읽기를 하면 열람시간을 수정하고 포인트 5를 부여


뷰는 따로 만들지 않고 크롬의 확장 프로그램을 이용해서 보냄



  

  com.examplt.spring02.aop

  ㄴMessageAdvice.java


  com.example.spring02.controller.message

  ㄴMessageController.java


  com.example.spring02.model.message.dto

  ㄴUserDTO.java

  ㄴMessageDTO.java


  com.example.spring02.model.message.dao

  ㄴMessageDAO.java

  ㄴMessageDAOImpl.java

  ㄴPointDAO.java

  ㄴPointDAOImpl.java


  com.example.spring02.service.message

  ㄴMessageService.java

  ㄴMessageServiceImpl.java




AOP 용어 정리


아래 용어들은 Spring에서만 사용되는 용어들이 아닌 AOP 프레임워크 전체에서 사용되는 공용어입니다.




 타겟 (Target)


 부가기능을 부여할 대상을 의미한다.


 여기선 핵심기능을 담당하는 getBoards 혹은 getUsers를 하는 Service들을 의미한다.

 

 

 애스팩트 (Aspect)


 객체지향 모듈을 오브젝트라 부르는 것과 비슷하게 부가기능 모듈을 애스펙트라고 부르며, 핵심기능에 부가되어 의미를 갖는 특별한 모듈이라


 생각하면 된다.


 애스팩트는 부가될 기능을 정의한 어드바이스와 어드바이스를 어디에 적용할지를 결정하는 포인트컷을 함께 갖고 있습니다.


 AOP(Aspect Oriented Programiming) 라는 뜻 자체가 어플리케이션의 핵심적인 기능에서 부가적인 기능을 분리해서 애스팩트라는 모듈로 


 만들어서 설계하고 개발하는 방법을 의미한다.

 

 

 어드바이스 (Advice)


 실질적으로 부가기능을 담은 구현체를 의미합니다.


 어드바이스의 경우 타겟 오브젝트에 종속되지 않기 때문에 순수하게 부가기능에만 집중할 수 있습니다.


 어드바이스는 애스펙트가 '무엇' 을 '언제' 할지를 정의하고 있습니다.



 포인트컷 (PointCut)


 부가기능이 적용될 대상 (메소드) 를 선정하는 방법을 얘기합니다.


 즉, 어드바이스를 적용할 조인포인트를 선별하는 기능을 정의한 모듈을 얘기합니다.



 조인포인트 (JoinPoint)


 어드바이스가 적용될 수 있는 위치를 얘기합니다.


 다른 AOP 프레임워크와 달리 Spring에서는 메소드 조인포인트만 제공하고 있습니다.


 따라서 Spring 프레임워크 내에서 조인포인트라 하면 메소드를 가리킨다고 생각해도 된다.


 

 프록시 (Proxy)


 타겟을 감싸서 타겟의 요청을 대신 받아주는 랩핑(Wrapping) 오브젝트 입니다.


 호출자 (클라이언트)에서 타겟을 호출하게 되면 타겟이 아닌 타겟을 감싸고 있는 프록시가 호출되어, 

 

 타겟 메소드 실행전에 선처리, 타겟 메소드 실행 후, 후처리를 실행시키도록 구성되어있습니다.



  

  (AOP에서 프록시는 호출을 가로챈 후, 어드바이스에 등록된 기능을 수행 후 타겟 메소드를 호출합니다.)
















MessageDTO.java (메시지 저장 DTO 클래스)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
.package com.example.spring02.model.message.dto;
 
import java.util.Date;
 
public class MessageDTO {
    
    //메시지 저장 DTO 클래스
    
    private int mid; 
    private String targetid;
    private String sender;
    private String message;
    private Date opendate; //java.util.Date
    private Date senddate;
    
    //getter,setter,toString()
    
    public int getMid() {
        return mid;
    }
    public void setMid(int mid) {
        this.mid = mid;
    }
    public String getTargetid() {
        return targetid;
    }
    public void setTargetid(String targetid) {
        this.targetid = targetid;
    }
    public String getSender() {
        return sender;
    }
    public void setSender(String sender) {
        this.sender = sender;
    }
    public String getMessage() {
        return message;
    }
    public void setMessage(String message) {
        this.message = message;
    }
    public Date getOpendate() {
        return opendate;
    }
    public void setOpendate(Date opendate) {
        this.opendate = opendate;
    }
    public Date getSenddate() {
        return senddate;
    }
    public void setSenddate(Date senddate) {
        this.senddate = senddate;
    }
    @Override
    public String toString() {
        return "MessageDTO [mid=" + mid + ", targetid=" + targetid + ", sender=" + sender + ", message=" + message
                + ", opendate=" + opendate + ", senddate=" + senddate + "]";
    }
    
}
cs




UserDTO (유저 정보 저장 DTO 클래스)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
.package com.example.spring02.model.message.dto;
 
public class UserDTO {
    
    //사용자 정보 저장 DTO 클래스
    
    private String userid; //아이디
    private String upw;    //비밀번호
    private String uname; //이름
    private int upoint; //포인트
    
    //getter,setter,toString()
    public String getUserid() {
        return userid;
    }
    public void setUserid(String userid) {
        this.userid = userid;
    }
    public String getUpw() {
        return upw;
    }
    public void setUpw(String upw) {
        this.upw = upw;
    }
    public String getUname() {
        return uname;
    }
    public void setUname(String uname) {
        this.uname = uname;
    }
    public int getUpoint() {
        return upoint;
    }
    public void setUpoint(int upoint) {
        this.upoint = upoint;
    }
    @Override
    public String toString() {
        return "UserDTO [userid=" + userid + ", upw=" + upw + ", uname=" + uname + ", upoint=" + upoint + "]";
    }
    
}
 
cs




MessageDAO.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
.package com.example.spring02.model.message.dao;
 
import com.example.spring02.model.message.dto.MessageDTO;
 
public interface MessageDAO {
    
    //메시지 쓰기
    public void create(MessageDTO dto);
    
    //메시지 읽기
    public MessageDTO readMessage(int mid);
    
    //상태 변경
    public void updateState(int mid);
}
 
cs




MessageDAOImpl.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
.package com.example.spring02.model.message.dao;
 
import javax.inject.Inject;
 
 
import org.apache.ibatis.session.SqlSession;
import org.springframework.stereotype.Repository;
 
import com.example.spring02.model.message.dto.MessageDTO;
import com.example.spring02.model.shop.dao.CartDAO;
 
@Repository //dao bean으로 등록
 
public class MessageDAOImpl implements MessageDAO {
 
    @Inject //의존관계 주입(Dependency Injection, DI)
    SqlSession sqlSession;
    
    @Override
    public void create(MessageDTO dto) { //메시지를 추가하는 메소드
        sqlSession.insert("message.create", dto);
    }
 
    @Override
    public MessageDTO readMessage(int mid) {
        return null;
    }
 
    @Override
    public void updateState(int mid) {
    }
 
}
 
cs



messageMapper.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
.<?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와 중복되지 않도록 네임스페이스 기재 -->
<mapper namespace="message">
<!--메시지를 만들때 값을 집어넣는 쿼리문 -->
    <insert id="create">
        insert into tbl_message (mid,targetid,sender,message)
        values ( message_seq.nextval
                        , #{targetid}, #{sender}, #{message} )    
    </insert>
        
</mapper>
cs



메시지를 저장한 후에 포인트를 주기위한 Point 관련 인터페이스와 클래스를 만듦


PointDAO.java

1
2
3
4
5
6
.package com.example.spring02.model.message.dao;
 
public interface PointDAO {
    public void updatePoint(String userid, int point);
}
 
cs



PointDAOImpl.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
.package com.example.spring02.model.message.dao;
 
import java.util.HashMap;
import java.util.Map;
 
import javax.inject.Inject;
 
import org.apache.ibatis.session.SqlSession;
import org.springframework.stereotype.Repository;
 
@Repository //스프링에서 관리하게끔 하기 위해 bean 선언
public class PointDAOImpl implements PointDAO {
    
    @Inject //의존성을 주입
    SqlSession sqlSession;
    
    @Override
    public void updatePoint(String userid, int point) {
        Map<String,Object> map=new HashMap<>(); //두가지 타입의 값을 넣을때는 HashMap()사용
        map.put("userid", userid); //map안에 값들을 저장함
        map.put("point", point);
        //2개 이상의 값을 전달할 경우 - dto, map
        sqlSession.update("point.updatePoint", map); //네임스페이스와 id를 맞춰서 mapper 쿼리 실행
        
    }
 
}
 
 
cs



pointMapper.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<?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">
 
<!-- mappers/message/pointMapper.xml -->
 
<!-- 다른 mapper와 중복되지 않도록 네임스페이스 기재 -->
<mapper namespace="point">
<!-- sqlSession.update("point.updatePoint", map); -->
    <update id="updatePoint">
        update tbl_user
        set upoint=upoint+#{point}
        where userid=#{userid}
    </update>
    <!-- 사용자의 아이디에 맞춰서 포인트를 올려주는 쿼리문 -->
    <!-- 변수 2개가 hashmap<>로 전달되었다. -->
    
</mapper>
cs




MessageSerivce.java

1
2
3
4
5
6
7
8
9
10
package com.example.spring02.service.message;
 
import com.example.spring02.model.message.dto.MessageDTO;
 
public interface MessageService {
    public void addMessage(MessageDTO dto); //메시지를 추가하는 메소드
    public MessageDTO readMessage(String userid, int mid); //메시지를 읽는 메소드
    
}
 
cs




-트랜잭션 처리 (거래 처리 단위)-


트랜잭션이 완료되지 않은 상태에서 에러가 발생할 경우 데이터에 오류가 발생함


트랜잭션의 특징중 일관성에 어긋나기 때문.


예를 들어 메시지는 전달되나 포인트는 안올라가는 문제가 발생할 수 있음.


이러한 문제를 예방하기 위해 @Transactional 어노테이션을 트랜잭션 메소드에 사용한다.


이 어노테이션을 사용하면 메소드 안에 있는 코드가 하나라도 에러가 발생할 시 rollback을 시켜버려서 트랜잭션의 일관성을 유지시켜준다.





-사전 설정-


1. 실습하기 전에 root-context.xml 파일의 네임스페이스의 tx (트랜잭션 처리를 할 수 있는 namespaces) 체크를 확인




2. root-context.xml에 트랜잭션 설정 코드가 있는지 확인


1
2
3
4
5
6
7
    <!-- 트랜잭션 관련 설정 -->
//dataSource에서 트랜잭션 관리자 역할을 할수있는 빈을 만든다.
//<tx:annotation-driven /> 이 태그는 아까 사용한 @Transactional을 인식할 수 있는 태그이다.

    <bean id="transactionManager" //변수명
        class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> //자료형
        <property name="dataSource" ref="dataSource" />
    </bean> //dataSource는 bean을 참조한다. (xml파일의 위쪽에 있음)

    <!-- 트랜잭션 관련 어노테이션을 자동 인식하는 옵션 -->

    <tx:annotation-driven /> //@Transaction 어노테이션을 인식할 수 있게 하는 태그
cs





MessageSerivceImpl.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
.package com.example.spring02.service.message;
 
import javax.inject.Inject;
 
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
 
import com.example.spring02.model.message.dao.MessageDAO;
import com.example.spring02.model.message.dao.PointDAO;
import com.example.spring02.model.message.dto.MessageDTO;
 
@Service //현재 클래스를 스프링에서 관리하는 bean으로 설정
public class MessageServiceImpl implements MessageService {
    
    //서비스는 dao보다 좀 더 큰 단위의 업무를 수행한다.
    //dao에서는 세부 단위 업무를 수행
    
//Inject는 각각 해야 함
//의존성을 주입해야할 DAO클래스가 2개이기때문에 반드시 각각한다.
    
    @Inject
    MessageDAO messageDao;
    
    @Inject
    PointDAO pointDao;
 
    
    //트랜잭션 처리 대상 method
    //이 어노테이션을 사용하는 메소드는 그 메소드안에 있는 명령이 모두다 실행이 되지
    //않으면 rollback을 시켜버린다.
    //트랜잭션의 일관성을 유지하기 위해.
    
    @Transactional //method 내부의 코드를 트랜잭션 (거래처리 단위)로 묶음
    @Override
    public void addMessage(MessageDTO dto) {
        
        //메시지를 테이블에 저장
        messageDao.create(dto);
        //메시지를 보낸 회원에게 10포인트 추가
        pointDao.updatePoint(dto.getSender(), 10); 
    }
 
    @Override
    public MessageDTO readMessage(String userid, int mid) {
        // TODO Auto-generated method stub
        return null;
    }
 
}
 
cs



이 예제를 진행할때는 jsp 페이지를 만들지 않는다.


원래는 만들어야 정상이지만,  이번에는 툴로 처리를 할 것이기 때문에 만들지 않는다.


@RestController을 사용해서 입력되는 데이터와 되돌려주는 데이터를 모두 json으로 처리한다.



MessageController.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
.package com.example.spring02.controller.message;
 
import javax.inject.Inject;
 
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
 
import com.example.spring02.model.message.dto.MessageDTO;
import com.example.spring02.service.message.MessageService;
 
@RestController //jsp파일을 사용하지 않고, 입력되는 데이터와 되돌려주는 데이터를 모두 json으로 처리한다.
@RequestMapping("messages/*"//공통적인 url mapping
public class MessageController {
    
    @Inject
    MessageService messageService;
    
    @RequestMapping(value="/", method=RequestMethod.POST)
    //post방식일때만 이 메소드가 실행되게 만들었다.
    
    public ResponseEntity<String> addMessage(
            @RequestBody MessageDTO dto){
        //json형식으로 자료가 입력될때 RequestBody 어노테이션을 사용한다.
        //RequestBody어노테이션을 DTO를 json형식으로 받는다는 뜻
        //즉 json(String)타입으로 들어오면 dto타입으로 변환해서 되돌려준다.
        
        ResponseEntity<String> entity=null;
        try {
            messageService.addMessage(dto);
            entity=new ResponseEntity<>("success",HttpStatus.OK);
            //ResponseEntiry<>는 메시지 (성공 or 실패)와 에러코드를 함께 출력하고 싶을때 사용하는 타입
        } catch (Exception e) { 
            //메시지 처리가 실패하면 실행되는 코드, 메시지와 에러코드를 출력
            e.printStackTrace();
            entity=new ResponseEntity<>(e.getMessage()
                    ,HttpStatus.BAD_REQUEST); //메시지 처리가 실패하면 메시지와 400에러를 출력시킨다.
        }
        return entity; //메시지와 에러코드를 같이 리턴한다. 그리고 되돌려주는 값도 json형식 으로 보낸다.
    }
}
cs



 서비스 쪽에 AOP 설정을 해서 전, 후에 처리가 어떻게 되는지 확인



 

 @Bean과 @Component의 차이


 @Bean의 경우 개발자가 컨트롤이 불가능한 외부 라이브러리들을 Bean으로 등록하고 싶은 경우에 사용된다.


 ( 예를 들면 ObjectMapper의 경우 ObjectMapper Class에 @Component를 선언할 수는 없으니 ObjectMapper의 인스턴스를 생성하는 메소드를


 만들고 해당 메소드에 @Bean을 선언하여 Bean으로 등록한다.)


 반대로 개발자가 직접 컨트롤이 가능한 Class들의 경우엔 @Component를 사용한다.





MessageAdvice.java


@Before 어노테이션으로 MessageService.java 시작 전에는 로그 수집을 하고, 


@Around 어노테이션으로 MessageService.java 시작 전, 후에 실행시간을 체크한다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
package com.example.spring02.aop;
 
import java.util.Arrays;
 
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
 
@Component // 기타 bean, 개발자가 직접 컨트롤이 가능한 class의 경우에 사용하는 어노테이션
 
@Aspect // aop bean - 공통 업무를 지원하는 코드
 
public class MessageAdvice {
 
    private static final Logger logger = LoggerFactory.getLogger(MessageAdvice.class);
    //MessageAdvice.class의 로그를 출력
    
    @Before( //핵심업무 수행전에 실행이 되는 어노테이션
            "execution(* "
            
//================================================================            
            
            + " com.example.spring02.service.message"
            + ".MessageService*.*(..))")
    
    // MessageSerivce로 시작하는 모든 클래스의 모든 메소드들, 모든파라미터들에 대해서
    // execution구문이 실행되기 전에 startLog메소드가 먼저 실행된다.
    
//================================================================
    
    //그러니까 메시지 서비스 시작하기 전에는 로그수집을 한다.
    public void startLog(JoinPoint jp) {                            //execution구문이 실행되기 바로 전에 호출됨
                                                                    //joinPoint는 advice를 적용 가능한 지점을 의미한다.
                                                                    //메소드 호출, 필드 값 변경 등이 Joinpoint에 해당한다.
        
        logger.info("핵심 업무 코드의 정보:" +jp.getSignature());             //시그니처의 값을 반환
        
        logger.info("method:" +jp.getSignature().getName());        //시그니처의 이름을 반환
        
        logger.info("매개변수:" +Arrays.toString(jp.getArgs()));        //클라이언트가 메소드를 호출할 때 넘겨준 인자 목록을 Object 배열로 리턴함
    }
    
    @Around( //호출 전 후에 실행 되게끔하는 어노테이션
            "execution(* "
            + " com.example.spring02.service.message"
            + ".MessageService*.*(..) )")
    public Object timeLog(ProceedingJoinPoint pjp) throws Throwable {//MessageService 시작 전후로는 시간체크를 한다.
        
        //호출 전(Before)
        long start=System.currentTimeMillis(); //long타입의 값이며, 1/1000초의 값을 리턴한다. 정확한 시간을 측정할때 사용
        
//=========================================================
        
        Object result=pjp.proceed();
        
        //이 구문을 기준으로 위쪽은 호출 전이고, 아래쪽은 호출 후 이다.
        
//=========================================================
        
        //호출 후(After)
        long end=System.currentTimeMillis();                          //long타입의 값이며, 1/1000초의 값을 리턴한다. 정확한 시간을 측정할때 사용
        logger.info(pjp.getSignature().getName()+":"+(end-start));    //시그니처의 이름과 실제 실행한 시간을 로그로 찍는다.
        logger.info("=================");                             //
        return result;                                                
    }
}
cs



(실습 방법)


이번 실습에서는 뷰 (view)를 별도로 만들지 않고 Advanced REST client 확장 프로그램으로만 테스트를 수행합니다.


method : POST


Request URL : http://localhost/spring02/messages/


Body > Body content type > application/json


     Editor view > Raw input





  

  Advanced REST client 확장 프로그램 설치


  (파라미터를 사용해서 컨트롤러로 값을 보낼 수 있음)


  구글 검색창에 Advanced REST client 검색


  




  




일단 입력 데이터를 json으로 보내기 위해 사용해보기


put : 전체 수정


delete : 삭제


patch : 일부분 수정


Method : POST


Request URL : http://localhost/spring02/message/Body


Body content type : application/json


Editor view : Raw input


다음 처럼 설정하고 json 코드를 작성




json 코드 작성하고 send버튼을 누른다.


1
2
3
4
5
{
"targetid" : "user01", //"변수" : "값" 형식이다, 즉, "targetid" 변수의 값은 "user01" 이다.
"sender" : "user02",
"message" : "Good morning"
} // 해석 : user02가 user01에게 "Good morning" 메시지를 보낸다는 뜻.
cs


하단에 200 OK버튼이 뜨면 정상적으로 처리된 것이다.


MessageController.java (메시지 컨트롤러)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
package com.example.spring02.controller.message;
 
import javax.inject.Inject;
 
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
 
import com.example.spring02.model.message.dto.MessageDTO;
import com.example.spring02.service.message.MessageService;
 
@RestController    //json을 리턴하는 method가 있는 경우에는 RestController을 사용
 
@RequestMapping("messages/*"//공통적인 url mapping
 
 
//메시지를 추가할때 맵핑되는 컨트롤러
 
 
public class MessageController {
    
    
    @Inject
    MessageService messageService;    //서비스를 호출하기위해 의존성을 주입한다.
    
    
    @RequestMapping(value="/", method=RequestMethod.POST) //POST방식의 메소드와 맵핑
    
    public ResponseEntity<String> addMessage(
             
            //    크롬 ARC를 사용해서 데이터를 보냈는데 String타입이기때문에 dto에 저장하려면
            //    변환과정이 필요하다.
            //    그 변환과정을 RequestBody라는 어노테이션을 붙이면서 자동적으로 dto타입으로 변환이 되었다.
            

@RequestBody와 ResponseEntity의 차이점

Spring에서는 HttpEntity란 클래스를 제공하는데 이 클래스의 역할은 Http 프로토콜을 이용하는 통신의 header과

body 관련 정보를 저장할 수 있게끔 합니다. 그리고 이를 상속받은 클래스로 RequestEntity와 ResponseEntity가

존재한다.

즉, 통신 메시지 관련 header과 body의 값들을 하나의 객체로 저장하는 것이 HttpEntity 클래스 객체이고,

Request 부분일 경우 HttpEntity를 상속받은 RequestEntity가, Response 부분일 경우 HttpEntity를 상속받은

ResponseEntity가 하게 됩니다.

@ResponseBody나 ResponseEntity를 return 하는거나 결과적으로는 같은 기능이지만.. 그 구현 방법이 틀리다.

예를 들어 header 값을 변경시켜야 할 경우엔 @ResponseBody의 경우 파라미터로 Response 객체를 받아서

이 객체에서 header를 변경시켜야 하고,.. ResponseEntity에서는 이 클래스 객체를 생성한뒤 객체에서

header 값을 변경시키면 된다.

자세한것은 Spring API 문서를 참고하면 된다.
            @RequestBody MessageDTO dto){
        
        ResponseEntity<String> entity=null;
        
        try {
            
            messageService.addMessage(dto);    
            
            entity=new ResponseEntity<>("success",HttpStatus.OK);
            
            //되돌려줄 메시지는 success, 상태메시지는 상태코드는 200이다.
            
        } catch (Exception e) {
            e.printStackTrace();
            
            entity=new ResponseEntity<>(e.getMessage()
                    ,HttpStatus.BAD_REQUEST);
        }
        return entity;
    }
}
cs


데이터베이스에서 데이터를 삭제해보고 크롬브라우저에서 send를 사용해서 컨트롤러로 자료를 보내서 테스트를 해본다.


로그를 확인해보면 dto에 값들이 쌓여있는것을 확인할 수 있다.

728x90
반응형
: