본문 바로가기
JSP

[JDBC] MVC나누기 3_게시판+FC,필터,리스너

by amoomar 2022. 3. 11.
반응형

 

해당 게시글은 MVC 나누기 1, MVC나누기 2 포스팅의 작업을 거쳐 완성된 내용물이다. 따라서 추가된 부분에 대하여만 부분적으로 언급 할 예정이며 이전 코드들과 내용은 각각의 포스팅에서 확인 가능하니 참고할 필요가 있다. 목차는 다음과 같다. 추가로 [controller업그레이드] 부분의 내용들을 적용하여 작업하기 때문에 2개의 게시글을 확인하고 오면 이해가 수월할 것이다.

1. view 수정
2. FrontController
3. 인코딩_Filter
4. 샘플데이터_Listener

 

 

해당 프로젝트의 전체 코드를 압축하여 첨부하였다. 설명 생략된 부분과 주석에 대해 더 자세히 확인할 수 있다.

MVC나누기_3.zip
2.10MB

 

 


 

 

1. view 수정

 

view의 모든 경로들을 수정하여 특정 url패턴을 부여하여 Front Controller의 파일로 집합시키거나, 혹은 바로 페이지 이동이 될 수 있도록 작업해야한다.

*.do를 통해 서블릿파일로 이동할 예정

 


 

2. FrontController개념 도입

 

1)  servlet

url패턴을 어노테이션으로 설정하고, 해당 파일을 통해 controller의 작업이 필요한 view페이지가 한 번에 모일 수 있도록 작업한다.

package controller;

import java.io.IOException;

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

/**
 * Servlet implementation class FrontController
 */
@WebServlet("*.do")
public class FrontController extends HttpServlet {
	private static final long serialVersionUID = 1L;
       
    /**
     * @see HttpServlet#HttpServlet()
     */
    public FrontController() {
        super();
        // TODO Auto-generated constructor stub
    }

	/**
	 * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
	 */
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		// TODO Auto-generated method stub
		actionDo(request, response);
	}

	/**
	 * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
	 */
	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		// TODO Auto-generated method stub
		actionDo(request, response);
	}
	
	private void actionDo(HttpServletRequest request, HttpServletResponse response) {
		String uri=request.getRequestURI();
		String cp=request.getContextPath();
		String command=uri.substring(cp.length());
		
		ActionForward forward=null;
		if(command.equals("/main.do")) {
			
			System.out.println("FC로그: 메인페이지 요청");
			try {
				forward=new MainAction().execute(request, response);
			} catch (Exception e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			
		}else if(command.equals("/login.do")) {
			
			System.out.println("FC로그: 로그인페이지 요청");
			try {
				forward=new LoginAction().execute(request, response);
			} catch (Exception e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}

		}else if(command.equals("/logout.do")) {
			
			System.out.println("FC로그: 로그아웃페이지 요청");
			try {
				forward=new LogoutAction().execute(request, response);
			} catch (Exception e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}

		}else if(command.equals("/board.do")) {
			
			System.out.println("FC로그: 상세페이지 요청");
			try {
				forward=new BoardAction().execute(request, response);
			} catch (Exception e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}

		}else if(command.equals("/insert.do")) {
			
			System.out.println("FC로그: 글작성페이지 요청");
			try {
				forward=new InsertAction().execute(request, response);
			} catch (Exception e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}

		}else if(command.equals("/update.do")) {
			
			System.out.println("FC로그: 글 수정 요청");
			try {
				forward=new UpdateAction().execute(request, response);
			} catch (Exception e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}

		}else if(command.equals("/delete.do")) {
			
			System.out.println("FC로그: 글 삭제 요청");
			try {
				forward=new DeleteAction().execute(request, response);
			} catch (Exception e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}

		}else if(command.equals("/signup.do")) {
			
			System.out.println("FC로그: 회원가입 요청");
			try {
				forward=new SignupAction().execute(request, response);
			} catch (Exception e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}

		}else if(command.equals("/mypage.do")) {
			
			System.out.println("FC로그: 마이페이지 요청");
			try {
				forward=new MypageAction().execute(request, response);
			} catch (Exception e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}

		}else if(command.equals("/mupdate.do")) {
			
			System.out.println("FC로그: 회원정보수정 요청");
			try {
				forward=new MupdateAction().execute(request, response);
			} catch (Exception e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}

		}else if(command.equals("/mdelete.do")) {
			
			System.out.println("FC로그: 회원정보삭제 요청");
			try {
				forward=new MdeleteAction().execute(request, response);
			} catch (Exception e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}

		}else {
			
			System.out.println("잘못된 요청");
		}
		
		if(forward==null) {
			forward=new ActionForward();
			forward.setPath("error.jsp");
			forward.setRedirect(false);
		}
		
		RequestDispatcher dispatcher=request.getRequestDispatcher(forward.getPath());
		try {
			dispatcher.forward(request, response);
		} catch (ServletException | IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
}

 


 

2) POJO

 

① interface파일

메서드의 input과 output을 강제한다.

package controller;

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

public interface Action {
	public ActionForward execute(HttpServletRequest req, HttpServletResponse res) throws Exception;
}

 


 

② 자료형대체파일

interface에서 강제한 추상메서드를 통해 반환할 output으로 어디로, 어떻게 갈지 다른 자료형의 두 아웃풋이 필요하게 되는데, 일반적으로는 두개의 결과를 return할 수 없기때문에 자료형 개념으로 class파일을 생성하였다.

package controller;

public class ActionForward {
	//output으로 사용할 멤버변수
	private String path;//어디로
	private boolean redirect;//redirect방식인지
	
	//생성자
	public ActionForward() {
		
	}

	//getter & setter
	public String getPath() {
		return path;
	}

	public boolean getRedirect() {
		return redirect;
	}

	public void setPath(String path) {
		this.path = path;
	}

	public void setRedirect(boolean redirect) {
		this.redirect = redirect;
	}
	
}

 


 

③ implement파일

로그인과 로그아웃에 대한 로직부분의 코드만을 첨부하였다.

 

 

로그인 관련 로직

package controller;

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

import member.MemberDAO;
import member.MemberVO;

public class LoginAction implements Action {

	@Override
	public ActionForward execute(HttpServletRequest req, HttpServletResponse res) throws Exception {

		ActionForward forward=new ActionForward();
		
		MemberDAO dao=new MemberDAO();
		MemberVO vo=new MemberVO();
		//view에서 받은 입력을 vo에 set
		vo.setMid(req.getParameter("mid"));
		vo.setMpw(req.getParameter("mpw"));
		vo=dao.selectOne(vo);
		
		if(vo==null) {//로그인 실패면
			//그냥 로그인페이지로 새로고침
			forward.setPath("/a_login.jsp");
			forward.setRedirect(true);
		}else {//성공이면
			//session에 로그인 정보 저장해서
			HttpSession session= req.getSession();
			session.setAttribute("mname", vo.getMname());
			session.setAttribute("mid", vo.getMid());
			//메인으로 새로고침
			forward.setPath("/main.do");
			forward.setRedirect(true);
		}
		
		return forward;
	}

}

 

로그아웃 관련 로직

package controller;

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

public class LogoutAction implements Action {

	@Override
	public ActionForward execute(HttpServletRequest req, HttpServletResponse res) throws Exception {
		ActionForward forward=new ActionForward();
		forward.setPath("/a_login.jsp");
		forward.setRedirect(true);
		//로그아웃하면 아무것도 가져가지말고 그냥 로그인 페이지로 가
		
		HttpSession session= req.getSession();
		session.invalidate();
		
		return forward;
	}
}

 

* session정보는 request.getSession을 통해 받아올 수 있다. *

 

* ActionForward(output)을 설정할때, 해당 로직의 비정상수행시 오류페이지로 이동인지의 여부에 따라 forward를 null로 표시할 수 있고, 아닐수도 있다. *

 


 

3. 인코딩_Filter

 

① filter파일

package controller;

import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpFilter;

/**
 * Servlet Filter implementation class EncodingFilter
 */
@WebFilter({ "*.do", "*.jsp" })
public class EncodingFilter extends HttpFilter implements Filter {
    
	private String encoding;
	
    public EncodingFilter() {
        super();
        // TODO Auto-generated constructor stub
    }

	/**
	 * @see Filter#destroy()
	 */
	public void destroy() {
		// TODO Auto-generated method stub
	}

	/**
	 * @see Filter#doFilter(ServletRequest, ServletResponse, FilterChain)
	 */
	public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
		
		request.setCharacterEncoding(encoding);
		response.setCharacterEncoding(encoding);
		System.out.println("필터 수행");
		
		chain.doFilter(request, response);
	}

	/**
	 * @see Filter#init(FilterConfig)
	 */
	public void init(FilterConfig fConfig) throws ServletException {
		this.encoding=fConfig.getServletContext().getInitParameter("encoding");
		System.out.println("필터 생성");
	}
}

doFilter( )메서드로 인코딩을 진행하고, init( )메서드로 서블릿 최초 동작시 초기화 매개변수인 encoding의 값을 불러오도록 한다.

 


 

② 초기화매개변수 설정(xml파일)

encoding이라는 이름의 변수에 UTF-8이라는 값을 세팅

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0">

   <context-param>
      <param-name>encoding</param-name>
      <param-value>UTF-8</param-value>
   </context-param>

</web-app>

 


 

4. 샘플데이터_Listener

 

① 크롤링파일

package controller;

import java.io.IOException;
import java.util.Iterator;

import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;

public class Crawling {
	
	public static String admin;
	public static void start() {
		
		final String url="https://www.lyrics.co.kr/?p=472837#gsc.tab=0";
		Document doc=null;
		try {
			doc=Jsoup.connect(url).get();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		Elements eles=doc.select("div.blog-content");
		Iterator<Element> itr=eles.iterator();
		while(itr.hasNext()) {
			admin=itr.next().text();
			
		}
		
	}
}

 

재사용 목적이 없다. static을 통해 외부 파일에서 객체화 없이 즉각적으로 사용이 가능하다.

 


 

② 리스너 파일

package controller;

import javax.servlet.ServletContext;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.annotation.WebListener;

/**
 * Application Lifecycle Listener implementation class CrawlingListener
 *
 */
@WebListener
public class CrawlingListener implements ServletContextListener {

    /**
     * Default constructor. 
     */
    public CrawlingListener() {
        // TODO Auto-generated constructor stub
    }

	/**
     * @see ServletContextListener#contextDestroyed(ServletContextEvent)
     */
    public void contextDestroyed(ServletContextEvent sce)  { 
         // TODO Auto-generated method stub
    }

	/**
     * @see ServletContextListener#contextInitialized(ServletContextEvent)
     */
    public void contextInitialized(ServletContextEvent sce)  { 
        Crawling.start();
        System.out.println("로그: 리스너 클래스: 크롤링 완료");
        ServletContext sc=sce.getServletContext();
        sc.setAttribute("admin", Crawling.admin);
    }
	
}

크롤링 파일의 데이터들을 불러와 admin이라는 이름으로 setAttribute하였다. 사용할 공간에서 ${admin}을 하여 쉽게 데이터를 불러올 수 있게 된다.

 

 


 

반응형