ResponseEntity- TakeCourse
public class TakeCourse {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
Long id;
long courseId;
String userId;
long payPrice;
String status;
LocalDateTime regDt;
}
- TakeCourseRepository
public interface TakeCourseRepository extends JpaRepository<TakeCourse, Long> {
}
- 강좌 상세목록(detail.html)
서버에는 내 정보를 보내는 것이 아닌 어떤 강좌인지 id 값을 보낸다
<form id="submitForm" method="post">
<input type="hidden" name="id" th:value="${detail.id}" />
<button type="submit">수강신청</button>
<a href="/course">강좌목록</a>
</form>
수강신청 버튼을 통해 서버로 데이터가 보내지는 ajax 사용, 서버에서는 api형태로 데이터를 받는다
axios의 post 기능을 이용해 url, id 값을 넣어준다
<script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
<script src="https://code.jquery.com/jquery-3.6.0.min.js" integrity="sha256-/xUj+3OJU5yExlq6GSYGSHk7tPXikynS7ogEvDej/m4=" crossorigin="anonymous"></script>
<script>
$(function (){
$('#submitForm').on('submit', function (){
var $thisForm = $(this);
var url = '/api/course/req.api';
var parameter = {
// 아이디 값은 hidden에 있는 thisForm의 id 값
id: $thisForm.find('input[name=id]').val()
};
axios.post(url, parameter).then(function (response){
}).catch(function (err){
});
return false;
});
});
</script>
- TakeCourseInput
@Data
public class TakeCourseInput {
// courseId
long courseId;
}
- ApiCourseController
@Controller는 String 을 사용하여 view를 리턴하지만 API서버 같은 경우에는 데이터만 바로 리턴한다
@Controller는 기본적으로 view페이지를 파일형태로 리턴
@RestController는 JsonBody로 데이터가 리턴되니 String이 아닌 responseEntity같은 값들이 리턴되어야 한다
이때는 ResponseEntity<?> 라는 값으로 리턴(문자열 리턴이 된다는 뜻)
public class ApiCourseController {
private final CourseService courseService;
private final CategoryService categoryService;
@GetMapping("/api/course/req.api")
public String courseRequest(Model model, TakeCourseInput param){
return "course/index";
}
}
@RequestBody로 보내지 않으면 payload로 값이 넘어가고 스프링부트에서 자동
Principal : 유저정보를 가져올 수 있게 스프링 내부에서 지원하는 값
ResponseEntity로 상태값을 받을 수 있다
@RequiredArgsConstructor
@RestController
public class ApiCourseController extends BaseController{
private final CourseService courseService;
private final CategoryService categoryService;
@PostMapping("/api/course/req.api")
public ResponseEntity<?> courseRequest(Model model,
@RequestBody TakeCourseInput param,
Principal principal){
// 유저정보 가져오는 코드
param.setUserId(principal.getName());
boolean result = courseService.request(param);
if(!result){
return ResponseEntity.badRequest().body("수강신청에 실패하셨습니다");
}
return ResponseEntity.ok().body(param);
}
}
- CourseService
// 수강신청
boolean request(TakeCourseInput param);
- CourseServiceImpl
@Override
public boolean request(TakeCourseInput param) {
// 강좌글 id 가져오기
Optional<Course> optionalCourse = courseRepository.findById(param.getCourseId());
if(!optionalCourse.isPresent()){
return false;
}
Course course = optionalCourse.get();
TakeCourse takeCourse = TakeCourse.builder()
.courseId(course.getId())
.userId(param.getUserId())
.payPrice(course.getSalePrice())
.regDt(LocalDateTime.now())
.build();
takeCourseRepository.save(takeCourse);
return true;
}
+) 트러블 슈팅
디버깅 모드에서 찍어보니 courseId 값이 null 로 들어왔다
이는 dto의 courseId 와 클라이언트 단의 id 객체명이 달라서 null로 들어옴
- detail.html
var parameter = {
// 아이디 값은 hidden에 있는 thisForm의 id 값
id: $thisForm.find('input[name=id]').val()
};
넘겨주는 id값과 dto(courseId )의 필드명이 같아야 한다
이제 상태값을 결정하는 엔티티 생성함
-TakeCourseCode
+ TakeCourse에 implement하기
public interface TakeCourseCode {
String STATUS_REQ = "REQ"; // 수강 신청상태
String STATUS_COM = "COM"; // 결제완료
String STATUS_CANCEL = "CANCEL"; // 수강취소
}
- CourseServiceImpl
status값 저장
TakeCourse takeCourse = TakeCourse.builder()
.courseId(course.getId())
.userId(param.getUserId())
.payPrice(course.getSalePrice())
.regDt(LocalDateTime.now())
.status(TakeCourse.STATUS_REQ)
.build();
takeCourseRepository.save(takeCourse);
이미 신청되어있으면 신청이 안되는 로직 구현
- CourseRepository
public interface TakeCourseRepository extends JpaRepository<TakeCourse, Long> {
// 값이 있는지 없는지 갯수로 판단
long countByCourseIdAndUserIdAndStatusIn(long courseId, String userId, Collection<String> statusList);
}
- TakeCourseRepository
count 값이 있으면 이미 신청했거나 완료된 값이니 false 값을 준다
@Override
public boolean request(TakeCourseInput param) {
...
// 이미 신청한 경우 신청이 안되는 로직
String[] statusList = {TakeCourse.STATUS_REQ, TakeCourse.STATUS_COM};
long count = takeCourseRepository.countByCourseIdAndUserIdAndStatusIn(course.getId(),
param.getUserId(), Arrays.asList(statusList));
if (count > 0){
return false;
}
return true;
}
상태값도 줬으니 각 상태 (수강신청시 Course 자체가 없는건지 데이터가 잘못되었는지에 대한) 에 대한 구체적인 에러값을 명시하는 로직이 필요
수강신청이 잘 되었는지 안되었느지, 실패했다면 어떤 문제때문에 실패하였느지 값처리
현재는 단순하게 boolean으로 true, false값만으로 처리
- ServiceResult
@Data
public class ServiceResult {
boolean result;
String message;
}
- CourseService
ServiceResult request(TakeCourseInput param);
- CourseServiceImpl
@Override
public ServiceResult request(TakeCourseInput param) {
ServiceResult result = new ServiceResult();
// 강좌글 id 가져오기
Optional<Course> optionalCourse = courseRepository.findById(param.getCourseId());
if(!optionalCourse.isPresent()){
// 현재 에러는 강좌정보 자체가 없는것
result.setResult(false);
result.setMessage("강좌정보가 존재하지 않습니다");
return result;
}
Course course = optionalCourse.get();
// 이미 신청한 경우 신청이 안되는 로직
String[] statusList = {TakeCourse.STATUS_REQ, TakeCourse.STATUS_COM};
long count = takeCourseRepository.countByCourseIdAndUserIdAndStatusIn(course.getId(),
param.getUserId(), Arrays.asList(statusList));
if (count > 0){
// 이미 신청한정보가 있을 때
result.setResult(false);
result.setMessage("이미 신청한 강좌정보가 있습니다");
return result;
}
TakeCourse takeCourse = TakeCourse.builder()
.courseId(course.getId())
.userId(param.getUserId())
.payPrice(course.getSalePrice())
.regDt(LocalDateTime.now())
.status(TakeCourse.STATUS_REQ)
.build();
takeCourseRepository.save(takeCourse);
// 성공했을 때
result.setResult(true);
result.setMessage("");
return result;
}
- ApiCourseController
@PostMapping("/api/course/req.api")
public ResponseEntity<?> courseRequest(Model model,
@RequestBody TakeCourseInput param,
Principal principal){
// 유저정보 가져오는 코드
param.setUserId(principal.getName());
ServiceResult result = courseService.request(param);
if (!result.isResult()){
return ResponseEntity.badRequest().body(result.getMessage());
}
return ResponseEntity.ok().body(param);
}
}
- detail.html
<script>
$(function (){
$('#submitForm').on('submit', function (){
if (!confirm("수강신청을 하시겠습니까?")) {
return false;
}
var $thisForm = $(this);
var url = '/api/course/req.api';
var parameter = {
// 아이디 값은 hidden에 있는 thisForm의 id 값
courseId : $thisForm.find('input[name=id]').val()
};
axios.post(url, parameter).then(function (response){
// data를 초기화시키는 자바스크립트 문법
var msg = response.data || '';
if (msg != ''){
alert(msg);
}
}).catch(function (err){
});
return false;
});
});
</script>
현재 에러메세지가 문자열로만 내려지는데 이를 제이슨을 사용하여 데이터 값으로 받아보겠다
- common.model.ResponeResult
@Data
public class ResponseResult {
ResponseResultHeader header;
Object body;
public ResponseResult(boolean result, String message) {
header = new ResponseResultHeader(result, message);
}
public ResponseResult(boolean result) {
header = new ResponseResultHeader(result);
}
}
- common.model.ResponeResultHeader
@Data
public class ResponseResultHeader {
boolean result;
String message;
public ResponseResultHeader(boolean result, String message) {
this.result = result;
this.message = message;
}
public ResponseResultHeader(boolean result) {
this.result = result;
}
}
- ApiCourseController
@PostMapping("/api/course/req.api")
public ResponseEntity<?> courseRequest(Model model,
@RequestBody TakeCourseInput param,
Principal principal){
// 유저정보 가져오는 코드
param.setUserId(principal.getName());
ServiceResult result = courseService.request(param);
if (!result.isResult()){
ResponseResult responseResult = new ResponseResult(false, result.getMessage());
return ResponseEntity.ok().body(responseResult);
}
// 내리는 값자체를 param이 아닌 response 값 자체를 내릴것
ResponseResult responseResult = new ResponseResult(true);
return ResponseEntity.ok().body(responseResult);
}
- 결과값
- detail.html
<script>
$(function (){
$('#submitForm').on('submit', function (){
if (!confirm("수강신청을 하시겠습니까?")) {
return false;
}
var $thisForm = $(this);
var url = '/api/course/req.api';
var parameter = {
// 아이디 값은 hidden에 있는 thisForm의 id 값
courseId : $thisForm.find('input[name=id]').val()
};
axios.post(url, parameter).then(function (response){
// data를 초기화시키는 자바스크립트 문법
var msg = response.data || '';
// 객체로 초기화
response.data = response.data || {};
response.data.header = response.data.header || {};
if(!response.data.header.result){
alert(response.data.header.message);
return false;
}
// 정상적 상황
alert('강좌가 정상적으로 신청되었습니다');
location.href = '/';
}).catch(function (err){
});
return false;
});
});
</script>
'개인프로젝트(수강프로그램)' 카테고리의 다른 글
회원정보 수정 (0) | 2022.05.03 |
---|---|
백오피스 - 강좌신청 처리구현 (0) | 2022.05.02 |
강좌 목록 구현 (0) | 2022.04.25 |
강좌 목록 구현, 강좌 신청 (0) | 2022.04.22 |
강좌목록 (0) | 2022.04.20 |