본문 바로가기
☕Java/Spring

[20210819] Lombok을 이용한 로그인, 게시판 예제

by 캔 2021. 8. 19.

Mapper

//BoardMapper.java
package spring_web16.board.repository;

import java.util.List;

import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;

import spring_web16.board.model.Board;

@Mapper
public interface BoardMapper {
	
	public int insert(Board board);
	public int update(Board board);
	public int delete(long board);
	
	@Select("SELECT COUNT(*) FROM xboard")
	public int count();
	
	@Select("SELECT FROM xboard ORDER BY id DESC")
	public List<Board> selectAll();
	
	public Board selectById(long id);
	public List<Board> selectByLimit(@Param("page") int page, @Param("size") int size);
	public int increment(@Param("id") long id, @Param("requester") String requester);
}
//UserMapper.java
package spring_web16.user.repository;

import java.util.List;

import org.apache.ibatis.annotations.Delete;
import org.apache.ibatis.annotations.Insert;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Result;
import org.apache.ibatis.annotations.ResultType;
import org.apache.ibatis.annotations.Results;
import org.apache.ibatis.annotations.Select;
import org.apache.ibatis.annotations.Update;

import spring_web16.user.model.User;

@Mapper
public interface UserMapper {
	@Insert("INSERT INTO xuser(email, password) "
			+ "VALUES(#{email}, #{password})")
	public int insert(User user);

	@Update("UPDATE xuser SET password = #{password} "
			+ "WHERE email = #{email}")
	public int update(User user);
	
	@Delete("DELETE FROM xuser WHERE email = #{email}")
	public int delete(String email);
	
	@Select("SELECT COUNT(*) FROM xuser")
	public int count();

	@Select("SELECT * FROM xuser ORDER BY email ASC")
	@ResultType(User.class) 
	public List<User> selectAll();
	
	@Select("SELECT * FROM xuser WHERE email = #{email}")	
	@Results(id = "userResultMap", value = { 
			@Result(property = "email", column = "email"),
			@Result(property = "password", column = "password") })
	public User selectByEmail(String email);
}

 

DTO

//Pager.java
package spring_web16.board.dto;

import lombok.Data;

@Data
public class Pager {
	
	private int page; // current page
	private int size; // rows per page
	private int bsize; // pages per block

	private int rows; // total elements
	private int pages; // total pages
	private int blocks; // total blocks

	private int block; // current block
	private int bspage; // current block start page
	private int bepage; // current block end page
	
	public Pager(int page, int size, int bsize, int rows) {
		//현재 페이지
		this.page = page;
		//한 페이지당 게시물 개수
		this.size = size;
		//블럭당 페이지 사이즈(기본 5로 되어 있음)
		//페이지 5개씩 한 블럭에 표시되고 넘어가면 >> 표시가 나옴
		this.bsize = bsize;
		//총 게시물 건수
		this.rows = rows;		
		//총 페이지
		pages = (int) Math.ceil((double) this.rows / this.size);
		//총 블럭
		blocks = (int) Math.ceil((double) pages / this.bsize);
		//현재 블럭
		block = (int) Math.ceil((double) this.page / this.bsize);
		//현재 블럭 종료페이지
		bepage = block * this.bsize;
		//현재 페이지 시작 페이지
		bspage = bepage - this.bsize + 1;
	}
	
	//두 번째 페이지이고 한 페이지에 10개씩이라면 10을 리턴
	public static int seekOffset(int page, int size) {
		
		if(page > 0) {
			return (page - 1) * size;
		}
		return 0;
	}
	
	// 두 번째 페이지이고 한 페이지에 10개씩 이라면 11을 리턴
	public static int seekStart(int page, int size) {
		return ((page - 1) * size) + 1;
	}

	// 두 번째 페이지이고 한페이지에 10개씩이라면 20을 리턴
	public static int seekEnd(int page, int size) {
		return page * size;
	}
}
//Board.java
package spring_web16.board.model;

import java.sql.Date;

import lombok.Data;

@Data
public class Board {

	private long id;
	private String writer;
	private String title;
	private String content;
	private Date regDate;
	private long hitCount;
}
//Login.java
package spring_web16.login.dto;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@NoArgsConstructor
@AllArgsConstructor
public class Login {
	
	private String email;
	private String password;
	private String error; //error메시지 세팅을 위한 것.
}
//User.java
package spring_web16.user.model;

import lombok.AllArgsConstructor; // 모든 멤버변수를 받는 생성자 
import lombok.Data;
import lombok.NoArgsConstructor; // 디폴트 생성자.

@Data
@NoArgsConstructor
@AllArgsConstructor
public class User {
	
	private String email;
	private String password;
	// getter setter 사용하지 않아도 됨.
}

 

Service/DAO

//LoginService.java
package spring_web16.login.service;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import spring_web16.login.dto.Login;
import spring_web16.user.model.User;
import spring_web16.user.repository.UserMapper;

@Service
public class LoginService {
	
	@Autowired
	private UserMapper userMapper;

	public void authenticate(Login login) {
		
		User user = userMapper.selectByEmail(login.getEmail());
		
		if (user == null) {
			login.setError("Email does not exist.");
		} else {
			if (!user.getPassword().equals(login.getPassword())) {
				login.setError("Password is not correct.");
			} else {
				login.setError(null);
			}
		}
	}
}

 

Controller

//BoardController.java
package spring_web16.web.controller;

import javax.servlet.http.HttpSession;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.servlet.ModelAndView;

import spring_web16.board.dto.Pager;
import spring_web16.board.model.Board;
import spring_web16.board.repository.BoardMapper;
import spring_web16.user.model.User;

@Controller
@RequestMapping("/boards")
public class BoardController {

	@Autowired
	private BoardMapper boardMapper;
	//게시판 리스트 보기
	//page: 조회를 원하는 페이지
	//size: 한페이지당 보여지는 게시물 건수
	//bsize: 하나의 페이지 블럭에 포함되는 페이지 수(5개 페이를 보인다.)
	@GetMapping()
	public ModelAndView getBoardsView(
			@RequestParam(name="page", required=false, defaultValue="1") int page,
			@RequestParam(name="size", required=false, defaultValue="10") int size,
			@RequestParam(name="bsize", required=false, defaultValue="10") int bsize) {
		
		ModelAndView mav = new ModelAndView("board_list");
		
		mav.addObject("boards", boardMapper.selectByLimit(page, size));
		mav.addObject("pager", new Pager(page, size, bsize, boardMapper.count()));
		
		return mav;
	}
	
	@GetMapping("/view/{id}")
	public String getBoardView(@PathVariable long id, HttpSession session, Model model) {
		
		User user = (User) session.getAttribute("user");
		if (user == null) {
			return session.getServletContext().getContextPath() + "/login";
		}
		
		boardMapper.increment(id, user.getEmail());
		model.addAttribute("board", boardMapper.selectById(id));
		
		return "board_view";
	}
	
	@GetMapping("/write")
	public String getInsertView(HttpSession session, Model model) {
		
		User user = (User)session.getAttribute("user");
		
		if(user == null) {
			return session.getServletContext().getContextPath() 
					+ "/login";			
		}
		
		model.addAttribute("user", user);
		
		return "board_write";
	}
	
	@PostMapping("/write")
	public String postInsert(Board board, HttpSession session, Model model) {
		
		User user = (User) session.getAttribute("user");
		
		if(user != null && board != null) {
			if(user.getEmail().equals(board.getWriter())) {
				boardMapper.insert(board);
				return "redirect:/boards";
			}
		}
		
		return session.getServletContext().getContextPath() + "/boards";
	}
	
	@GetMapping("/update/{id}")
	public String getUpdateView(@PathVariable long id, HttpSession session, Model model) {
		
		User user = (User) session.getAttribute("user");
		Board board = boardMapper.selectById(id);
		
		if (user != null && board != null) {
			if (user.getEmail().equals(board.getWriter())) {
				model.addAttribute("board", board);
				return "board_update";
			}
		}
		
		return session.getServletContext().getContextPath() + "/boards";
	}
	
	@PostMapping("/update")
	public String postUpdate(Board board, HttpSession session, Model model) {
		
		User user = (User) session.getAttribute("user");
		
		if (user != null && board != null) {
			if (user.getEmail().equals(board.getWriter())) {
				boardMapper.update(board);
				return "redirect:/boards/view/" + board.getId();
			}
		}
		
		return session.getServletContext().getContextPath() + "/boards";
	}
	
	@GetMapping("/delete/{id}")
	public String getDelete(@PathVariable long id, HttpSession session, Model model) {
		
		User user = (User) session.getAttribute("user");
		
		if (user != null) {
			Board board = boardMapper.selectById(id);
			if (user.getEmail().equals(board.getWriter())) {
				boardMapper.delete(id);
				return "redirect:/boards";
			}
		}
		
		return session.getServletContext().getContextPath() + "/boards";
	}
}
//ControllerExceptioinHandeler.java
package spring_web16.web.controller;

import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.servlet.ModelAndView;

@ControllerAdvice
public class ControllerExceptionHandler {
	//컨트롤러에서 오류가 생기면 error.jsp 로딩
	@ExceptionHandler(Exception.class)
	public ModelAndView handleError(Exception e) {
		
		ModelAndView mav = new ModelAndView("error/error");
		
		mav.addObject("errorMsg", e.getMessage());
		
		return mav;
	}
}
//HomeController.java
package spring_web16.web.controller;

import javax.servlet.http.HttpServletRequest;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
@RequestMapping("/")
public class HomeController {
	
	@GetMapping
	public String getHomeView(HttpServletRequest request) {
		return "home";
	}
	
	@GetMapping("/404.html")
	public String get404View() {
		return "error/404";
	}
	
	@GetMapping("/throw")
	public String testControllerAdvice() {
		throw new RuntimeException("Error Test In Controller.");
	}
}
//LoginController.java
package spring_web16.web.controller;

import javax.servlet.http.HttpSession;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PostMapping;

import spring_web16.login.dto.Login;
import spring_web16.login.service.LoginService;
import spring_web16.user.model.User;

@Controller
public class LoginController {
	@Autowired
	private LoginService loginService;
	
	@ModelAttribute("active")
	public String active() {
		return "login";
	}
	
	@GetMapping("/login")
	public String getLoginView() {
		return "login";
	}
	
	@PostMapping("/login")
	public String postLogin(Login login, Model model, HttpSession session) {
		
		loginService.authenticate(login);
		
		if (login.getError() != null) {
			model.addAttribute("error", login.getError());
			model.addAttribute("login", login);
			return "login";
		} else {
			User user = new User(login.getEmail(), login.getPassword());
			session.setAttribute("user", user);
			return "redirect:/boards";
		}
	}
	
	@GetMapping("/logout")
	public String getLogout(HttpSession session) {
		
		session.invalidate();
		
		return "login";
	}
	
}
//UserController.java
package spring_web16.web.controller;

import java.util.List;

import javax.servlet.http.HttpSession;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
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.bind.annotation.ResponseBody;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;

import spring_web16.user.model.User;
import spring_web16.user.repository.UserMapper;

@Controller
@RequestMapping("/users")
public class UserController {
	
	@Autowired
	private UserMapper userMapper;
	
	@GetMapping
	@ResponseBody
	public Object getUsersView() {
		
		List<User> users = userMapper.selectAll();
		
		return users;
	}
	
	@PostMapping("/enroll")
	public String postUser(User user, Model model, HttpSession session, RedirectAttributes redirectAttributes) {
		
		User duplicatedUser = userMapper.selectByEmail(user.getEmail());
		
		if(duplicatedUser == null) {
			userMapper.insert(user);
			redirectAttributes.addFlashAttribute("result", "OK");
		} else {
			redirectAttributes.addFlashAttribute("result", "FAIL");
			redirectAttributes.addFlashAttribute("error", "FAIL: Email is duplicated");
		}
		
		return "redirect:/login";
	}	
}
//LoginInterceptor.java
package spring_web16.web.interceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.springframework.stereotype.Component;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;

import spring_web16.user.model.User;

//보드에 진입 시 로그인이 안 되어 있으면 로그인 화면으로 보냄.
@Component
public class LoginInterceptor extends HandlerInterceptorAdapter {
	
	@Override
	public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
		
		HttpSession session = request.getSession();
		User user = (User) session.getAttribute("user");
		
		if (user == null) {
			String url = session.getServletContext().getContextPath() + "/login";
			response.sendRedirect(url);
			System.out.println("LoginInterceptor # preHandle(): NO PASS");
			return false;
		}
		
		System.out.println("LoginInterceptor # preHandle(): PASS");
		
		return true;
	}
}