티스토리 뷰
board >보드 view
member > 멤버 view
net.member.db > 멤버 model
net.board.db > 보드 model
net.board.action> 보드 controller
net.member.action> 멤버 controller
참조한 war파일 출처: cafe.naver.com/siacademybigdata2021
위의 파일들을 전부 설명하려면 글이 너무 길어지기 때문에
가장 쉽게 알 수 있는 흐름과, 가장 복잡한 흐름 두개를 선정해서 설명하도록 하겠습니다.
일단 가장 첫번째로 서블릿과 연동하는 부분을 설명하도록 하겠습니다.
web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd" id="WebApp_ID" version="4.0">
<display-name>Board</display-name>
<welcome-file-list>
<welcome-file>index.html</welcome-file>
<welcome-file>index.htm</welcome-file>
<welcome-file>index.jsp</welcome-file>
<welcome-file>default.html</welcome-file>
<welcome-file>default.htm</welcome-file>
<welcome-file>default.jsp</welcome-file>
</welcome-file-list>
<servlet>
<servlet-name>BoardFrontController</servlet-name>
<servlet-class>
net.board.action.BoardFrontController
</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>BoardFrontController</servlet-name>
<url-pattern>*.bo</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>MemberFrontController</servlet-name>
<servlet-class>
net.member.action.MemberFrontController
</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>MemberFrontController</servlet-name>
<url-pattern>*.me</url-pattern>
</servlet-mapping>
<resource-ref>
<description>Connection</description>
<res-ref-name>jdbc/OracleDB</res-ref-name>
<res-type>javax.sql.DataSource</res-type>
<res-auth>Container</res-auth>
</resource-ref>
</web-app>
web.xml에서
net.member.action.MemberFrontController 를 먼저 서블릿과 연동해줍니다.
<servlet>
<servlet-name>BoardFrontController</servlet-name>
<servlet-class>
net.board.action.BoardFrontController
</servlet-class>
</servlet>
servlet네임을 전해주고
연동한 클래스를 지정해주었죠?
그러면 일단 ok입니다.
그 뒤에 도메인에서 특정 값을 입력했을때 FrontController에 연동하도록 맵핑을 시켜준 부분입니다.
<servlet-mapping>
<servlet-name>BoardFrontController</servlet-name>
<url-pattern>*.bo</url-pattern>
</servlet-mapping>
*.bo라는 부분을 통해 .bo로 끝나는 도메인을 입력할경우 그 값이 어떤 값이더라도 FrontController에 연결 됩니다.
그럼 여기까지 흐름을 통해서
bo라는 도메인을 입력시 Controll부로 연결된다는 점을 알 수 있습니다.
이것이 MVC2패턴의 최초 흐름입니다.
이제 부터 모든흐름은 Controll을 중심으로 흘러간다는 점을 이해하면 좀 더 쉽게 이해 할 수 있습니다.
package net.member.action;
import java.io.IOException;
import java.util.Enumeration;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import javax.servlet.http.HttpSessionContext;
import net.member.action.Action;
import net.member.action.ActionForward;
public class MemberFrontController
extends javax.servlet.http.HttpServlet
implements javax.servlet.Servlet {
protected void doProcess(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
String sessId = null;
String RequestURI=request.getRequestURI();
String contextPath=request.getContextPath();
String command=RequestURI.substring(contextPath.length());
ActionForward forward=null;
Action action=null;
if(command.equals("/MemberJoin.me")){//한글이
forward=new ActionForward();
forward.setRedirect(false);
forward.setPath("./member/joinPageHtml.jsp");
}else if(command.equals("/MemberAddAction.me")){
action = new MemberAddAction();
System.out.println("회원가입 진입");
try{
forward=action.execute(request, response);
}catch(Exception e){
e.printStackTrace();
}
}else if(command.equals("/Login.me")){
forward=new ActionForward();
sessId = null;
forward.setRedirect(false);
forward.setPath("./member/loginForm.jsp");
}else if(command.equals("/MemberLoginAction.me")){
action = new MemberLoginAction();
try{
forward=action.execute(request, response);
}catch(Exception e){
e.printStackTrace();
}
}else if(command.equals("/Main.me")){
forward=new ActionForward();
forward.setRedirect(false);
forward.setPath("./member/Main.jsp");
}else if(command.equals("/MemberList.me")){
action = new MemberListAction();
try{
forward=action.execute(request, response);
}catch(Exception e){
e.printStackTrace();
}
}else if(command.equals("/MemberInfo.me")){
action = new MemberInfoAction();
try{
forward=action.execute(request, response);
}catch(Exception e){
e.printStackTrace();
}
}
if(forward.isRedirect()){
response.setHeader("id", sessId);
response.sendRedirect(forward.getPath());
}else{
RequestDispatcher dispatcher=
request.getRequestDispatcher(forward.getPath());
dispatcher.forward(request, response);
}
}
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doProcess(request,response);
}
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doProcess(request,response);
}
}
그럼 가장 기본적인 흐름인 화면전환 메서드를 살펴보도록 하겠습니다.
if(command.equals("/MemberJoin.me")){//한글이
forward=new ActionForward();
forward.setRedirect(false);
forward.setPath("./member/joinPageHtml.jsp");
}
도메인을 subString을 활용해 저희가 원하는 부분만 자른상태에서
/MemberJoin.me와 일치하면 위 와 같은 if문이 실행됩니다.
foward안에 새로운 ActionForward();라는 생성자를 생성했네요
ActionFoward.java
package net.member.action;
public class ActionForward {
private boolean isRedirect=false;
private String path=null;
public boolean isRedirect(){
return isRedirect;
}
public String getPath(){
return path;
}
public void setRedirect(boolean b){
isRedirect=b;
}
public void setPath(String string){
path=string;
}
}
아래의 클래스가 생성되고 ActionForward안에는 4개의 메서드가 존재합니다.
setRedirect 메서드는 입력받은 Boolean형을 통해 true또는 false값을 입력받아
전송 방식을 Redirect로 할 것인지 아니면 다른 방식으로 사용할지 정하기 위한 값을 받는 공간입니다.
setPath는 말 그대로 어디로 이동 할 것인지 경로는 지정하는 메서드 겠죠??
그럼 다시 if문으로 돌아와 살펴보면 이해가 잘 될것입니다.
if(command.equals("/MemberJoin.me")){//한글이
forward=new ActionForward();
forward.setRedirect(false);
forward.setPath("./member/joinPageHtml.jsp");
}
foward.setRedirect(false); 부분을 보면 false값을 쥐어주었기 때문에 getRedirect부에는 false값이 설정되었고
setPath도 마찬가지로 다음과 같은 경로를 지정해줘서 getRedirect부에 경로가 지정 되었습니다.
여기서 주의할점은 여기서 view로 이동하는게 아닌 값만 쥐어준 상태라는 점을 이해하시면 좋을 것 같네요
if(forward.isRedirect()){
response.setHeader("id", sessId);
response.sendRedirect(forward.getPath());
}else{
RequestDispatcher dispatcher=
request.getRequestDispatcher(forward.getPath());
dispatcher.forward(request, response);
}
그리고 나서 밑으로 내려와 else if문이 끝나는 시점에 if문이 하나가 더 있습니다.
이 부분이 실질적으로 이동하는 부분입니다.
현재 Redirect부는 false값이기 떄문에 if문은 실행되지 않고 else문이 실행됩니다.
이렇게 된 이유는 보낼 데이터가 없는데 굳이 Redirect문을 사용 할 필요가 없기 때문입니다.
그래서 foward방식으로 전송하기 위해 dispatcher를 사용했고
경로는 getPath()가 가지고 있는 경로로
foward방식으로 view에 전송 됩니다.
즉
도메인 > 컨트롤부 연결 > if문 실행(해당하는 도메인을 찾기위해) >if문 실행(실제로 원하는 view 화면을 출력하기 위해) > view
순서대로 진행됩니다. 여기까지는 DB연결이 안되어있으니 그렇게 어렵지 않게 이해할 수 있습니다.
그럼 이제 본격적으로 MVC2패턴의 꽃인 DB가 연결된 연결부를 보도록 하겠습니다.
else if(command.equals("/MemberList.me")){
action = new MemberListAction();
try{
forward=action.execute(request, response);
}catch(Exception e){
e.printStackTrace();
}
Controller에 연결이 되어서 if문이 실행되었고 MemberList.me라는 도메인이 입력되었을 경우
아래와같이 action 값에 new MemberListAction가 생성되고
try문에서 action. 안에 있는 excute라는 메서드가 실행됩니다.
package net.member.action;
import java.util.ArrayList;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import net.member.db.MemberDAO;
public class MemberListAction implements Action {
@Override
public ActionForward execute(HttpServletRequest request, HttpServletResponse response) throws Exception {
request.setCharacterEncoding("UTF-8");
if(request.getSession().getAttribute("id")==null||!request.getSession().getAttribute("id").equals("admin")) {
ActionForward forward = new ActionForward();
forward.setRedirect(false);
forward.setPath("./member/memberList.jsp");
return forward;
}
MemberDAO memberdao = new MemberDAO();
ArrayList<String> result = memberdao.memberList();
request.setAttribute("memberList", result);
ActionForward forward = new ActionForward();
forward.setRedirect(false);
forward.setPath("./member/memberList.jsp");
return forward;
}
}
해당 클래스를 살펴보면 import 부분에
net.member.db.MemberDAO; 이부분이 있는데, 이는 DAO와 이 클래스를 연결해줍니다.
DAO는 데이터 베이스로 저장된 데이터 값을 불러오기 위해 import를 시켜준 상태입니다.
그 뒤에 Action이라는 인터페이스의 메서드를 오버라이딩 해서 아래의 코드들을 전부 실행시킵니다.
if(request.getSession().getAttribute("id")==null||!request.getSession().getAttribute("id").equals("admin")) {
ActionForward forward = new ActionForward();
forward.setRedirect(false);
forward.setPath("./member/memberList.jsp");
return forward;
}
이 곳에 있는 if문을 확인해보면, 세션값에들어있는 id값이 비어있거나
admin이 아니라면 if문이 실행됩니다. 이 문장의 존재이유는 유효하지 않는 유저가 접속하면 아무것도 출력되지 않기 위해서 이런 if문이 존재합니다. 관리자가 아닌데 list에 접속해 데이터를 본다면 난감하기 때문이에용.
if문이 실행되지 않는다면 바로 아래로 내려와 DB를 추출하는 작업이 이루어 집니다.
MemberDAO memberdao = new MemberDAO();
ArrayList<String> result = memberdao.memberList();
request.setAttribute("memberList", result);
ActionForward forward = new ActionForward();
forward.setRedirect(false);
forward.setPath("./member/memberList.jsp");
return forward;
memberdao라는 참조변수를 통해 memberDAO(); 에 접속하도록 하고
ArrayList를 만들어 memberList 메서드의 값들을 순서대로 넣어줬습니다.
이 부분을 살펴볼까요
public ArrayList<String> memberList() {
String sql="select id from member";
ArrayList<String> arr = new ArrayList<String>();
try{
pstmt=con.prepareStatement(sql);
rs = pstmt.executeQuery();
int i=0;
while(rs.next()) {
arr.add(i,rs.getString(1));
i++;
}
return arr;
}catch(Exception e) {
System.out.println("리스트 에러 : "+e);
e.printStackTrace();
} finally {
try {
rs.close();
pstmt.close();
con.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
return null;
}
해당 메서드가 실행되면, 마찬가지로 ArrayList 제네릭 타입의 메서드가 실행되고,
pstmt을 통해 값을 입력 받을 준비를 하고 rs안에 Query를 넣어줬네요 이 Rs안에는 이제 모든 id정보들이 담겨 있습니다.
int i는 순서대로 arrayList에 저장하기 위한 일종의 카운트를 위한 부분이겠죠??
이 부분을 넣어주지 않으면, list에 어떻게 담아야하는지 컴퓨터가 어리버리 하기 때문에 반드시 넣어줘야합니다.
while(rs.next()) 문은 남아있는 데이터가 없을때까지 계속 실행됩니다.
id값이 3개라면 3번 실행되겠죵
실행되면 ArrayList 0번째 배열에 첫번째 id값이 저장이 되고,
i값이 1증가합니다. 이것이 더 이상 담을 데이터가 없을 때 까지 반복이 되고
값을 다 담으면 return arr를 통해 ArrayList값을 보내줍니다. 데이터가 없다면 return null이 되겠죠??
ArrayList<String> result = memberdao.memberList();
그래서 다시 돌아와 result값에 null이 들어가 아무런 정보도 뜨지 않거나 정상적으로 arr가 리턴되어 데이터가 들어가거나 둘중하나인 경우가 될 것입니다.
request.setAttribute("memberList", result);
ActionForward forward = new ActionForward();
forward.setRedirect(false);
forward.setPath("./member/memberList.jsp");
return forward;
request를 위해서 memberList라는 이름에 ,result 값(저희가 입력받았던 arr 값 이 들어가게되고)
밑으로는 아까도 보셨듯 전송 방식입니다.
데이터를 입력받는게 아닌 전송이기 때문에 Redirect방식을 기용할 이유가 없겠죵??
그리고 setPath를 통해 이동할 페이지 값을 설정한뒤 foward에 값을 리턴해줍니다.
그럼 다시 컨트롤러로 돌아와
else if(command.equals("/MemberList.me")){
action = new MemberListAction();
try{
forward=action.execute(request, response);
}catch(Exception e){
e.printStackTrace();
}
try문이 실행되고, forward안에는 저희가 설정한 값들이 전부 들어 갑니다.
이 안에는 이미 전송방식과 전송할 데이터들이 전부 들어있겠죠?
아까와 마찬가지로 마지막에 if문이 실행되면 해당 데이터를 쥐고 있는 채로 List로 이동합니다.
요약해서 흐름은
도메인>컨트롤러>if문실행>해당클래스로 이동>DB와 연결>DB에서 데이터를 가져오는 작업>다이 클래스로 이동>컨트롤러에 값 전송>view로 이동 및 데이터전송
더 요약하자면
도메인>컨트롤러>DB>컨트롤러>view 라고 생각하시면 될 것 같습니다.
나머지 흐름의 이해는 위의 내용들을 이해하셨다면,
DB에 값 전송은 어렵지 않게 이해하실거라 생각합니다.
핵심적으로 요약하면
무조건 DB로 이동하는 것도 아니고, 무조건 View로 이동하는 것도 아닙니다. 하지만
모든 제어권은 Controller가 가지고 있는 방식을 MVC2 방식이라고 이해하면 좋을 것 같습니다.
- Total
- Today
- Yesterday
- MSA
- ACTUATOR
- git
- 운동일기
- config
- 미래의나에게동기부여
- Kafka Connect
- Gateway
- rabbitmq
- springcloud
- elasticSearch
- 오늘저녁 삼겹살
- prometheus
- JWT
- Logstash 활용
- Logstash to ElasticSearch
- docker
- 루틴기록
- 빅-오
- LoadBalancer
- kafka
- MariaDB
- Spring + ELK
- 운동
- UserService
- consumer
- Feign
- zipkin
- producer
- github
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |