240109 TodoList 만들기

MINJU KIM·2024년 1월 10일

Spring

목록 보기
4/13


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

TodoDTO.java

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이 아닌 제목과, 빈문자열이 아닌 작성자와, 미래의 날짜만 받도록 처리해줌

TodoVO.java

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;
}

TodoMapper.java

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();


}

TodoService.java

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();

}

TodoServiceImpl.java

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;

    }


}

CommonExceptionAdvice.java

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 애플리케이션에서 전역적으로 예외를 처리하고, 클라이언트에게 적절한 응답을 전송할 수 있도록 도와줍니다.

custom404.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" pageEncoding="UTF-8" %>
<html>
<head>
    <title>404</title>
</head>
<body>

<h2>페이지를 찾을 수 없습니다.</h2>


</body>
</html>

에러페이지. 잘못된 경로로 가면 404로 넘어온다.

Config

ModelMapperConfig.java

https://castleone.tistory.com/2

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 사이의 데이터 전환에 사용.

  • setFieldMatchingEnabled(true): 필드 매칭을 활성화합니다.
  • setFieldAccessLevel(org.modelmapper.config.Configuration.AccessLevel.PRIVATE): private 접근 레벨의 필드에 접근할 수 있도록 설정합니다.
  • setMatchingStrategy(MatchingStrategies.LOOSE): 매핑 전략을 LOOSE로 설정합니다. 이는 느슨한 매칭 전략으로, 필드 이름이 일치하지 않아도 유사한 이름을 찾아 매핑을 시도합니다.

Controller

TodoController.

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";
    }

}


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

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

0개의 댓글