

일정 작성과 리스트 출력까지 만들어 보았다.

package com.example.springex.dto;
import lombok.*;
import javax.validation.constraints.Future;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;
import java.time.LocalDate;
@ToString
@Builder
@Data
@AllArgsConstructor
@NoArgsConstructor
public class TodoDTO {
private Long tno;
@NotEmpty
private String title;
@Future
private LocalDate dueDate;
private boolean finished;
@NotEmpty
private String writer;
}
@Builder
멤버 필드들에 대해 알아서 빌드를 만들어준다.
@Data
getter, setter, toString과 같은 반복메서드를 자동으로 작성해준다.
@AllArgsConstructor
모든 필드값을 파라미터로 받는 생성자를 만들어줌.
@NoArgsConstructor
파라미터가 없는 기본 생성자를 만들어줌.
어노테이션을 사용해 null이 아닌 제목과, 빈문자열이 아닌 작성자와, 미래의 날짜만 받도록 처리해줌
package com.example.springex.domain;
import lombok.*;
import java.time.LocalDate;
@Getter
@ToString
@AllArgsConstructor
@NoArgsConstructor
@Builder
public class TodoVO {
private Long tno;
private String title;
private LocalDate dueDate;
private boolean finished;
private String writer;
}
package com.example.springex.mapper;
import com.example.springex.domain.TodoVO;
import org.apache.ibatis.annotations.Mapper;
import java.util.List;
@Mapper
public interface TodoMapper {
void insert(TodoVO todoVO);
List<TodoVO> selectAll();
}
package com.example.springex.service;
import com.example.springex.dto.TodoDTO;
import java.util.List;
public interface TodoService {
void register(TodoDTO todoDTO);
List<TodoDTO> getAll();
}
package com.example.springex.service;
import com.example.springex.domain.TodoVO;
import com.example.springex.dto.TodoDTO;
import com.example.springex.mapper.TodoMapper;
import lombok.RequiredArgsConstructor;
import lombok.extern.log4j.Log4j2;
import org.modelmapper.ModelMapper;
import org.springframework.stereotype.Service;
import java.util.List;
import java.util.stream.Collectors;
@Service
@Log4j2
@RequiredArgsConstructor
public class TodoServiceImpl implements TodoService{
private final TodoMapper todoMapper;
private final ModelMapper modelMapper;
@Override
public void register(TodoDTO todoDTO) {
log.info(modelMapper);
TodoVO todoVO = modelMapper.map(todoDTO, TodoVO.class);
log.info(todoVO);
todoMapper.insert(todoVO);
}
@Override
public List<TodoDTO> getAll() {
List<TodoDTO> dtoList = todoMapper.selectAll().stream()
.map(vo -> modelMapper.map(vo, TodoDTO.class))
.collect(Collectors.toList());
return dtoList;
}
}
package com.example.springex.controller.exception;
import lombok.extern.log4j.Log4j2;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.servlet.NoHandlerFoundException;
import java.lang.reflect.Array;
import java.util.Arrays;
@ControllerAdvice
@Log4j2
public class CommonExceptionAdvice {
//스프링에서 예외 처리할 때 일반적으로
//@ControllerAdvice 사용
@ResponseBody
@ExceptionHandler(NumberFormatException.class)
public String exceptNumber(NumberFormatException numberFormatException){
log.error("=================");
log.error(numberFormatException.getMessage());
return "NUMBER FORMAT EXCEPTION";
}
@ResponseBody
@ExceptionHandler(Exception.class)
public String exceptCommon(Exception exception){
log.error("++++++++++++");
log.error(exception.getMessage());
StringBuffer buffer = new StringBuffer("<ul>");
buffer.append("<li>" + exception.getMessage() + "</li>");
Arrays.stream(exception.getStackTrace()).forEach(stackTraceElement -> {
buffer.append("<li>" + stackTraceElement + "</li>");
});
buffer.append("</ul>");
return buffer.toString();
}
@ExceptionHandler(NoHandlerFoundException.class)
@ResponseStatus(HttpStatus.NOT_FOUND)
public String notFound(){
return "custom404";
}
}
@ControllerAdvice: 전역적으로 예외를 처리할 수 있는 어노테이션. 예외가 발생했을 때 클라이언트에게 응답을 전송하는 데 사용
@ExceptionHandler: 특정 예외 타입에 대한 처리를 정의하는 어노테이션입니다. 여러 개의 @ExceptionHandler 메서드를 정의하여 다양한 예외에 대한 처리를 할 수 있습니다.
@ResponseBody: 해당 메서드가 반환하는 값은 HTTP 응답 본문으로 사용됨을 나타냅니다. JSON 형식 등으로 클라이언트에게 예외 정보를 반환할 때 사용됩니다.
@ResponseStatus(HttpStatus.NOT_FOUND): 특정 예외가 발생했을 때 반환되는 HTTP 응답 상태 코드를 지정합니다. 여기서는 NoHandlerFoundException이 발생했을 때 404 상태 코드를 반환하도록 설정하고 있습니다.
이 클래스에는 세 가지 예외 처리 메서드가 있습니다:
exceptNumber: NumberFormatException이 발생했을 때 처리하는 메서드로, 로그를 출력하고 "NUMBER FORMAT EXCEPTION"을 반환합니다.
exceptCommon: 모든 예외(Exception 타입)에 대한 처리를 담당하는 메서드로, 로그를 출력하고 예외 메시지와 스택 트레이스 정보를 HTML 형식으로 가공하여 반환합니다.
notFound: NoHandlerFoundException이 발생했을 때 404 상태 코드와 함께 "custom404"를 반환합니다. 이는 커스텀 404 페이지를 사용하는 예시입니다.
이렇게 정의된 예외 처리 클래스는 Spring MVC 애플리케이션에서 전역적으로 예외를 처리하고, 클라이언트에게 적절한 응답을 전송할 수 있도록 도와줍니다.
<%@ page contentType="text/html;charset=UTF-8" language="java" pageEncoding="UTF-8" %>
<html>
<head>
<title>404</title>
</head>
<body>
<h2>페이지를 찾을 수 없습니다.</h2>
</body>
</html>
에러페이지. 잘못된 경로로 가면 404로 넘어온다.

package com.example.springex.config;
import org.modelmapper.ModelMapper;
import org.modelmapper.convention.MatchingStrategies;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class ModelMapperConfig {
@Bean
public ModelMapper getMapper() {
ModelMapper modelMapper = new ModelMapper();
modelMapper.getConfiguration()
.setFieldMatchingEnabled(true)
.setFieldAccessLevel(org.modelmapper.config.Configuration.AccessLevel.PRIVATE)
.setMatchingStrategy(MatchingStrategies.LOOSE);
return modelMapper;
}
}
ModelMapper: 객체 간의 매핑을 단순화하고 자동화하는 데 사용되는 라이브러리. 주로 DTO(Data Transfer Object)와 Entity 사이의 데이터 전환에 사용.
package com.example.springex.controller;
import com.example.springex.dto.TodoDTO;
import com.example.springex.service.TodoService;
import lombok.RequiredArgsConstructor;
import lombok.extern.log4j.Log4j2;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;
import javax.validation.Valid;
@Controller
@RequestMapping("/todo")
@Log4j2
@RequiredArgsConstructor
public class TodoController {
private final TodoService todoService;
//list
@RequestMapping("/list")
public void list(Model model){
log.info("todo list");
model.addAttribute("dtoList", todoService.getAll());
}
//register get
@GetMapping("/register")
public void registerGet(){
log.info("todo registerGet");
}
//register post
@PostMapping("/register")
public String registerPost(@Valid TodoDTO todoDTO,
BindingResult bindingResult,
RedirectAttributes redirectAttributes){
log.info("todo registerPost");
if(bindingResult.hasErrors()){
log.info("has errors..");
redirectAttributes.addFlashAttribute("errors", bindingResult.getAllErrors());
return "redirect:/todo/register";
}
todoService.register(todoDTO);
return "redirect:/todo/list";
}
}

데이터베이스- 우클릭 - 새로작성- 쿼리콘솔 들어가면

콘솔창이 떠서 사용할 수 있다.