[JAVA] CRUD 토이 프로젝트 - 2

Hyeonseok Jeong·2023년 8월 24일
0

Java

목록 보기
2/5

이전 CRUD 토이 프로젝트에 이어서 작업한결과 이전보다 많은걸 할 수있었다

진행상황

  • BoardDetailController 구현
  • BoardDetailService 구현
  • BoardListController 구현
  • BoardListService 구현
  • SignInController 구현
  • SignInService 구현
  • BoardDao 구현
  • UserDao 추가

SignIn

package com.CRUDp.web.client.controller;

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import com.CRUDp.web.client.service.SignInService;

@WebServlet("/client/signIn")
public class SignInController extends HttpServlet {
	@Override
	protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

		req.getRequestDispatcher("/WEB-INF/view/client/signIn/signIn.jsp").forward(req, resp);
	}

	@Override
	protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

		String email = req.getParameter("email");
		String pwd = req.getParameter("password");

		boolean state = false;
		HttpSession session = req.getSession();

		SignInService service = new SignInService();
		state = service.setUserLogIn(email, pwd);

		if (state) {
			// session 로그인
			session.setAttribute("userId", email);
			resp.sendRedirect("index");
		} else {
			resp.sendRedirect("signIn");
		}

	}
}

로그인 컨트롤 부분이다.
해당 부분은 session을 이용해서 사용자 상태 유지를 구현했다.

  • 다음번에는 토큰을 이용해서 사용자에 대한 상태 관리를 해볼 예정이다.
    지금은 학습을 위해 하는 입장이니 차근차근 해볼 예정

컨트롤 부분에서 사용하는 service단을 보자면

package com.CRUDp.web.client.service;

import java.security.NoSuchAlgorithmException;

import com.CRUDp.web.client.dao.UserDao;
import com.CRUDp.web.client.dto.UserDto;
import com.CRUDp.web.security.Sha256;

public class SignInService {
	public boolean setUserLogIn(String email, String password) {
		System.out.printf("email : %s\n", email);
		System.out.printf("password : %s\n", password);

		UserDto user = new UserDto();
		UserDao userDao = new UserDao();
		Sha256 sha256 = new Sha256();

		String hashingPwd = null;
		boolean state = false;

		try {
			hashingPwd = sha256.encrypt(password);
		} catch (NoSuchAlgorithmException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

		user.setEmail(email);
		user.setPassword(hashingPwd);

		state = userDao.selectUserCheckDao(user);

		return state;
	}
}

사용자에게서 입력받은 패스워드를 해싱하여 DB에 저장되어있는 암호화 패스워드와 비교하여 사용자의 로그인 부분을 처리하였다.

그런데 해당 부분은 솔직히 마음에 들지는 않는다
마음에 안드는 부분은 우선 보안적인 면에서 마음에 들지 않고 (우선 컨트롤 부분에서 들어오는 유저의 정보가 암호화 되지 않고 직접적으로 들어오는 부분 과같은 면)
코드를 보면 Dao단에서 selectUserCheckDao(user) 메소드를 통해 검증하고 있는데 이 검증 부분이 상당히 마음에 안든다 아니 정확하게는 이런식으로 처리하는게 맞는지에 대한 의구심이 든다.

  • selectUserCheckDao(user) 코드 부분

	public boolean selectUserCheckDao(UserDto user) {

		String sql = "select email, password from member where email = ? and password = ?";

		boolean state = false;

		try {

			Class.forName("oracle.jdbc.driver.OracleDriver");
            // 1편에서 언급한 url 부분을 바깥으로 public으로 빼내어 사용
			Connection con = DriverManager.getConnection(url, "crud", "1111");
			PreparedStatement st = con.prepareStatement(sql);

			st.setString(1, user.getEmail());
			st.setString(2, user.getPassword());

			ResultSet rs = st.executeQuery();

			if (rs.next()) {
				if (!rs.getString("email").equals("")) {
					state = true;
				}
			}

			rs.close();
			st.close();
			con.close();

		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		} catch (SQLException e) {
			e.printStackTrace();
		}

		return state;
	}

이처럼 시퀄문을 사용하여 사용자가 맞는지 확인을 하고 있는 상황인데 나중에 단순 해쉬작업이 아닌 솔트를 붙여서 사용하는 암호화 작업시에는 이처럼 될것 같지는 않아 좀더 생각해볼 필요가 있을 것 같다.

BoardList

다음으로는 게시판 리스트 부분이다.
이부분은 그래도 나름 작성한것 같다 물론 실력자분들에게는 부족해 보일 수 있지만 그런 실력자분들을 따라잡을 생각이 다분하기에 지금은 보인다면 피드백 부탁드립니다~~~

아무튼 게시판 리스트 부분의 Controller 부분을 먼저 보자면

package com.CRUDp.web.client.controller;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.CRUDp.web.client.dto.BoardDto;
import com.CRUDp.web.client.service.BoardListService;

@WebServlet("/client/board/list")
public class BoardListController extends HttpServlet {
	@Override
	protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		String field_ = req.getParameter("filed");
		String query_ = req.getParameter("query");
		String page_ = req.getParameter("page");

		String field = field_ != null && !field_.equals("") ? field_ : "title";
		String query = query_ != null && !query_.equals("") ? query_ : "";
		int page = page_ != null && !page_.equals("") ? Integer.parseInt(page_) : 1;

		List<BoardDto> boardList = new ArrayList<>();
		int count = 0;

		BoardListService service = new BoardListService();
		boardList = service.getBoardList(field, query, page);
		count = service.getBoardListCount(field, query);

		req.setAttribute("list", boardList);
		req.setAttribute("count", count);

		req.getRequestDispatcher("/WEB-INF/view/client/board/list/list.jsp").forward(req, resp);
	}
}

parameter를 page 외의 field 와 query를 검색기능도 추가적으로 하기 위해 받아 두었다.
자세한 설명을 위해 Service단을 보자면

package com.CRUDp.web.client.service;

import java.util.ArrayList;
import java.util.List;

import com.CRUDp.web.client.dao.BoardDao;
import com.CRUDp.web.client.dto.BoardDto;

public class BoardListService {
	public List<BoardDto> getBoardList(String field, String query, int page) {

		List<BoardDto> boardList = new ArrayList<>();

		BoardDao boardDao = new BoardDao();

		int start = 1 + (page - 1) * 10;
		int end = page * 10;

		boardList = boardDao.selectBoardListDao(field, query, start, end);

		return boardList;
	}

	public int getBoardListCount(String field, String query) {
		BoardDao boardDao = new BoardDao();
		int result = 0;
		result = boardDao.selectBoardCountDao(field, query);

		return result;
	}

}

page값을 받아 Service단으로 전달하여 start와 end 변수를 만들어 Dao에 전달하였으며,
Dao단에서 해당 변수를

	public List<BoardDto> selectBoardListDao() {

		return selectBoardListDao("title", "", 1, 5);

	}

	public List<BoardDto> selectBoardListDao(int start, int end) {

		return selectBoardListDao("title", "", start, end);
	}

	public List<BoardDto> selectBoardListDao(String field, String query, int start, int end) {
		String url = "jdbc:oracle:thin:@localhost:1521/xepdb1";
		// Board 의 내용을 가지고오는
		String sql = "select * from ( " + "select rownum num, b.* from ( " + "select * from board where " + field
				+ " like ? order by regdate desc ) b " + ") where num between ? and ?";

		List<BoardDto> boardList = new ArrayList<>();

		try {
			Class.forName("oracle.jdbc.driver.OracleDriver");
			Connection con = DriverManager.getConnection(url, "CRUD", "1111");
			PreparedStatement st = con.prepareStatement(sql);

			st.setString(1, "%" + query + "%");
			st.setInt(2, start);
			st.setInt(3, end);

			ResultSet rs = st.executeQuery();

			while (rs.next()) {
				int id = rs.getInt("id");
				String title = rs.getString("title");
				String writerId = rs.getString("writer_id");
				Date regDate = rs.getDate("regdate");
				int hit = rs.getInt("hit");

				BoardDto board = new BoardDto();
				board.setId(id);
				board.setTitle(title);
				board.setWriterId(writerId);
				board.setRegDate(regDate);
				board.setHit(hit);

				boardList.add(board);
			}

			rs.close();
			st.close();
			con.close();

		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		} catch (SQLException e) {
			e.printStackTrace();
		}

		return boardList;
	}
}

위의 코드에서처럼 사용하여 pagenation 부분 처리를 위해 사용하여 쿼리문에 집어넣어 게시판을 10개씩 출력하도록 하였다.

  • 쿼리문 부분
    select * from ( select rownum num, b.* from ( select * from board where field like ? order by regdate desc ) b ) where num between ? and ?
    서브쿼리로 쿼리문 구성

이와같이 게시판 리스트 부분을 작성하고
다음으로는 게시판 디테일 부분을 작성하였다.

BoardDetail

package com.CRUDp.web.client.controller;

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.CRUDp.web.client.dto.BoardDto;
import com.CRUDp.web.client.service.BoardDetailService;

@WebServlet("/client/board/detail")
public class BoardDetailController extends HttpServlet {
	@Override
	protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

		String boardId_ = req.getParameter("board_id");
		int boardId = boardId_ != null && !boardId_.equals("") ? Integer.parseInt(boardId_) : 0;

		BoardDto boardDetail = new BoardDto();

		BoardDetailService service = new BoardDetailService();
		service.setBoardHit(boardId);
		boardDetail = service.getBoardDetailService(boardId);

		req.setAttribute("detailBoard", boardDetail);

		req.getRequestDispatcher("/WEB-INF/view/client/board/detail/detail.jsp").forward(req, resp);
	}
}

사실 Detail 부분은 이렇다할 설명할 구간은 없는것 같다
Dto를 이용해 데이터를 DataBase에서 데이터를 담아 Service단에서 해당 데이터를 가공하여 Controller단에서 request로 뿌려주기만 하면 끝인 부분이라서 그런것같다.
(댓글 부분을 구현하면 좀 복잡할 것 같긴하다)

  • BoardDetailService
package com.CRUDp.web.client.service;

import com.CRUDp.web.client.dao.BoardDao;
import com.CRUDp.web.client.dto.BoardDto;

public class BoardDetailService {
	public BoardDto getBoardDetailService(int boardId) {

		BoardDao boardDao = new BoardDao();
		BoardDto boardDto = new BoardDto();

		boardDto = boardDao.selectBoardDetailDao(boardId);

		return boardDto;
	}

	public int setBoardHit(int boardId) {

		BoardDao boardDao = new BoardDao();

		int result;

		result = boardDao.updateBoardHitDao(boardId);

		return result;
	}
}
  • BoardDao
public BoardDto selectBoardDetailDao(int boardId) {

		String url = "jdbc:oracle:thin:@localhost:1521/xepdb1";
		// Board 의 내용을 가지고오는
		String sql = "select * from board where id = ?";

		BoardDto boardDetail = null;

		try {
			Class.forName("oracle.jdbc.driver.OracleDriver");
			Connection con = DriverManager.getConnection(url, "CRUD", "1111
			PreparedStatement st = con.prepareStatement(sql);

			st.setInt(1, boardId);

			ResultSet rs = st.executeQuery();

			if (rs.next()) {
				int id = rs.getInt("id");
				String title = rs.getString("title");
				String content = rs.getString("content");
				Date regDate = rs.getDate("regdate");
				int hit = rs.getInt("hit");
				String files = rs.getString("files");
				String writerId = rs.getString("writer_id");

				boardDetail = new BoardDto(id, title, content, regDate, hit, files, writerId);
			}

			rs.close();
			st.close();
			con.close();

		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		} catch (SQLException e) {
			e.printStackTrace();
		}

		return boardDetail;
	}
  • BoardHitUpdate
public int updateBoardHitDao(int boardId) {

		String url = "jdbc:oracle:thin:@211.58.105.31:1521/xepdb1";
		// Board 의 내용을 가지고오는
		String sql = "update board set hit = hit + 1 where id = ?";

		int result = 0;

		try {
			Class.forName("oracle.jdbc.driver.OracleDriver");
			Connection con = DriverManager.getConnection(url, "CRUD", "9074");
			PreparedStatement st = con.prepareStatement(sql);

			st.setInt(1, boardId);

			result = st.executeUpdate();

			st.close();
			con.close();

		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		} catch (SQLException e) {
			e.printStackTrace();
		}

		return result;
	}

위의 코드는 설명을 못했지만 단순히 리스트 페이지에서 디테일 페이지로 이동시에 조회수를 증가시키기위해 만든 코드 부분이다.

미구현 기능 - 댓글

마무리

마무리 하자면 오늘은 로그인, Board 리스트 & 디테일 부분을 작성하였고 마음에 들지는 않지만 나는 계속해서 끊임없이 배움을 멈추지않고 나아갈것이다. 이렇게 글을 작성하는건 의지를 부여잡기 위함도 있다 화이팅~~~

끝!

profile
풀스텍 개발자

0개의 댓글