Servlet, JSP 실습.

Jobmania·2023년 3월 6일
0

MVC - JSP, Servlet

목록 보기
3/5

처음 접속시 : 로그인 화면 (로그인 성공시 다음화면, 실패시 로그인화면)
-> 간단한 로직 화면(화면 추가기능시 화면 추가기능 화면으로 이동)

첫화면 구성(Login 화면구성)

  <!--    시작 파일 설정  1 -> 2 -> 3 순위 .. -->
    <welcome-file-list>
        <welcome-file>login.do</welcome-file>
    </welcome-file-list>

web.xml 파일에 위의 코드를 입력하면 시작파일을 설정 가능.
/login.do path로 가게끔 설정.

LoginServlet

@WebServlet(urlPatterns = "/login.do")
public class LoginServlet extends HttpServlet {
    LoginService loginService = new LoginService();
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws 
    ServletException, IOException {
        req.getRequestDispatcher("/WEB-INF/views/login.jsp").forward(req, resp);
    }

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

        String name = req.getParameter("name");
        String password = req.getParameter("pw");

        boolean isValidUser = loginService.isUserValid(name, password);

        if(isValidUser){
            req.getSession().setAttribute("name",name);
            resp.sendRedirect("list-todo.do");
        }else {
            req.setAttribute("error","Invalid Id Or Pw 아이디 or 비번 잘못!");
            req.getRequestDispatcher("/WEB-INF/views/login.jsp").forward(req,resp);
        }

    }
}

처음화면은 Get요청으로 오게되며 view를 담당하는 login.jsp 파일로 이동하게됨.

login.jsp


<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@ include file="../common/header.jspf"%>
<%@ include file="../common/navigation.jspf"%>

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

<div class="container" style="width:50%">
    <form action="login.do" method="post">
        <p>
            <font color="red">${error}</font>
        </p>
        Name: <input class="form-control" type="text" name="name"/> <br>
        Password:<input class="form-control" type="password" name="pw"/>
        <input class="form-control" type="submit" value="로그인">
    </form>
</div>

<%@ include file="../common/footer.jspf"%>

전체적인 html구조가 아닌 이유는 <%@ include>를 통해 중복되는 부분은 추출했기 때문이다.
그래서 아래와 같은 구조로 전체적인 jsp 파일은 구성이 될 것이다.

<header>  
<navigationbar>
코드
코드
코드
<footer>

이후 form-data로 입력된 name 및 pw가 login.do의 post 요청으로 넘어가게 되면 get.Paramter로 값을 꺼내와, 이를 세션에 저장하고 '/list-todo.do' url로 이동하게 된다.
만약 name 및 pw가 맞지 않다면 에러메세지와 다시 로그인 화면으로 이동
여기서는 db를 연동하지 않았기 때문에 아래와 같이 구성.

게시글 작성 로직

로그인 성공후 : 'list-todo.do' url로 이동.

ListTodoServlet


@WebServlet("/list-todo.do")
public class ListTodoServlet extends HttpServlet {
    private TodoService todoService = new TodoService();


    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws IOException, ServletException {
        request.setAttribute("todos", todoService.getTodos());
        request.getRequestDispatcher("/WEB-INF/views/list-todos.jsp").forward(request, response);
    }

    
}

list-todos.jsp


<%@ page language="java" contentType="text/html; charset=UTF-8"
         pageEncoding="UTF-8"%>
<%@ include file="../common/header.jspf"%>
<%@ include file="../common/navigation.jspf"%>

<div class="container">
  <H1>안녕하세요! ${name}</H1>

  <table class="table table-striped">
    <caption>🚀당신의 할일 리스트!🚀</caption>
    <thead>
    <tr>
      <th>할일 설명</th>
      <th>종 류</th>
      <th>삭제하기</th>
    </tr>
    </thead>
    <tbody>
    <c:forEach items="${todos}" var="todo">
      <tr>
        <td>${todo.name}</td>
        <td>${todo.category}</td>
        <td>&nbsp;&nbsp;
        <a class="btn btn-danger" href="delete-todo.do?todo=${todo.name}&category=${todo.category}">Delete</a></td>
      </tr>
    </c:forEach>
    </tbody>
  </table>

  <p>
    <font color="red">${error}</font>
  </p>
  <a class="btn btn-success" href="add-todo.do">할일 추가하기</a>
</div>

<%@ include file="../common/footer.jspf"%>

TodoService


public class TodoService {
    private static List<Todo> todos = new ArrayList<>();


    static {  // 초기값 입력 
        todos.add(new Todo("Learn JSP", "BE"));
        todos.add(new Todo("Learn Spring", "BE"));
        todos.add(new Todo("Learn Spring MVC", "BE"));
    }

    public List<Todo> getTodos() {
        return todos;
    }

    public void addTodo(String todo, String category) {
        todos.add(new Todo(todo , category));
    }

    public void deleteTodo(String name, String category) {
        todos.removeIf(todo -> (todo.getName().equals(name)&&todo.getCategory().equals(category)));
    }

    public boolean sameTodo(String name) {
        return todos.stream().anyMatch(todo -> todo.getName().equals(name));

    }
}

먼저 Todoservice에서 todolist를 들고와 setAttribute를 통해 이름'todos'에 값을 주입 ->이를 list-todo.jsp파일에서 for-each를 통해 하나씩 출력.

화면에 추가하기 삭제하기 버튼이 존재하며 이를 누를시 url로 이동하게 됨.

삭제

<td>&nbsp;&nbsp;<a class="btn btn-danger" href="delete-todo.do?todo=${todo.name}&category=${todo.category}">Delete</a></td>

/delete-todo url로 이동하며 paramter로 todo=todo.getName와 category=todo.getCategory를 들고간다.

@WebServlet("/delete-todo.do")
public class DeleteTodoServlet extends HttpServlet {
    private static final long serialVersionUID = 1L;
    private TodoService todoService = new TodoService();

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

        todoService.deleteTodo(req.getParameter("todo"),req.getParameter("category"));
        resp.sendRedirect("/list-todo.do");


    }
}

Todoservice의 deleteTodo 메소드 수행. (Todo의 이름과 Category의 이름이 같다면 삭제)

 public void deleteTodo(String name, String category) {
        todos.removeIf(todo -> (todo.getName().equals(name)&&todo.getCategory().equals(category)));
    }

추가

 <a class="btn btn-success" href="add-todo.do">할일 추가하기</a>

AddTodoServlet

@WebServlet(name = "addTodoServlet", urlPatterns = "/add-todo.do")
public class AddTodoServlet extends HttpServlet {

    private TodoService todoService = new TodoService();

    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        request.getRequestDispatcher("WEB-INF/views/add-todo.jsp").forward(request, response);
    }


    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        String newTodo = request.getParameter("todo");
        String category = request.getParameter("category");

        if(newTodo.isBlank()||category.isBlank()){
            request.setAttribute("error", "할일을 입력해주세요!!");
            request.getRequestDispatcher("WEB-INF/views/add-todo.jsp").forward(request,response);
        } else if (todoService.sameTodo(newTodo)) {
            request.setAttribute("error", "동일한 작업이 있습니다!!");
            request.getRequestDispatcher("WEB-INF/views/add-todo.jsp").forward(request,response);
        } else {
            todoService.addTodo(newTodo,category);
            request.setAttribute("todos",todoService.getTodos());
            request.getRequestDispatcher("WEB-INF/views/list-todos.jsp").forward(request,response);
        }

    }
}

add-todo.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
         pageEncoding="UTF-8"%>
<%@ include file="../common/header.jspf"%>
<%@ include file="../common/navigation.jspf"%>


<div class="container">
  새로 할일 작성하기: <p>${error}</p>
  <form method="POST" action="add-todo.do">
    <fieldset class="form-group">
      <label>할일 설명</label> <input name="todo" type="text"
                                  class="form-control" /> <BR />
    </fieldset>
    <fieldset class="form-group">
      <label>종 류</label> <input name="category" type="text"
                                class="form-control" /> <BR />
    </fieldset>
    <input name="add" type="submit" class="btn btn-success" value="추가하기" />
  </form>
</div>

<%@ include file="../common/footer.jspf"%>

이름에 대한 중복, 빈칸입력시 error 메세지를 보내주고 다시 입력창으로 가지만
정상적으로 입력한다면 list 조회 화면으로 이동하게됨.

로그아웃 (Filter)

@WebServlet(value = "/logout.do")
public class LogoutServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        request.getSession().invalidate();// 세션 지우기
        response.sendRedirect("login.do");
    }
}

로그아웃시 등록하였던 'name'인 세션 포함 초기화를 한다. 하지만 로그인을 하지 않아도 url로 접속시 todo-list 접속이 가능하다. 이러한 요청을 막기 위해 Filter를 등록하고 요청 및 응답에 관련 로직을 추가한다.

필터란? : HTTP 요청과 응답을 변경할 수 있는 재사용 가능한 클래스

  • 객체 형태로 존재
  • 클라이언트에서 오는 요청(request)과 최종 자원 사이에 위치하여, 클라이언트의 요청 정보를 알맞게 변경 가능
    • 최종 자원과 클라이언트로가는 응답(response) 사이에 위치하여, 최종 자원의 요청 결과를 알맞게 변경 가능

LoginRequiredFitler

@WebFilter("*.do")  // .do로 끝나는 모든 url에 적용
public class LoginRequiredFilter implements Filter {
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain)
            throws IOException, ServletException {

        HttpServletRequest request = (HttpServletRequest) servletRequest;

        // 요청시 로그인 상태가 아니면 login.do로 다시보내버린다.
        if(request.getSession( ).getAttribute("name") != null){
            filterChain.doFilter(servletRequest,servletResponse);
        }else {
            request.getRequestDispatcher("login.do").forward(servletRequest,servletResponse);
        }
    }
}

서블릿 요청, 응답에 필터를 적용, 해당되는 요청과 응답에 name이라는 세션값이 없으면 모든 요청을 login.do의 get요청으로 보낸다.

정리.


MVC를 이해하기 위해 Servlet, JSP를 이용, 요청과 응답이 나가는 부분(Servlet), 로직이 수행되는 부분(Service), 화면을 출력하는부분(View)로 구성.

profile
HelloWorld에서 RealWorld로

0개의 댓글