ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 로그인처리, 템플릿맛보기-0622
    웹프로그래밍 2022. 6. 22. 20:48
    728x90

    로그인처리 db로 바꿔보자 

     

    1. VO먼저 만들기

    의존관계에 따라 파악해야함 ( 컨트롤러는 서비스 없이 안돼. 서비스는 DAO없음 안돼 , DAO는 VO먼저 만들어져야해

    서비스만들어지기전까지 컨트롤러 안만들 수 없으므로 레이어드 구현체가 아닌 인터페이스먼저 만들고 실 구현체 안나와도 컨트롤러가 서비스 사용할 수 있는 구조가 나옴 )

    DESC MEMBER;
    select *
    from cols;

    스네이크를 카멜로 변환 

    --private String memId;
    SELECT 'private ' ||
            DECODE(DATA_TYPE, 'NUMBER', 'Integer ', 'String ') ||
            LOWER(SUBSTR(COLUMN_NAME,1,1)) ||
            SUBSTR(REPLACE(INITCAP(COLUMN_NAME), '_',''),2) ||
            ';'
    FROM COLS
    WHERE TABLE_NAME ='MEMBER';
    
            --COLUMN_NAME의 첫글자를 추출해서 소문자로 변환
            -- INITCAP: COLUMN_NAME의 각 단어의 첫 글자를 대문자로 나머지는 소문자로 변환
            -- REPLACE로 '_'을 없애고 2번째 글자부터 추출

    여기서 나의 실수 number뒤에는 공백이 있으면 안된다. 그래서 integer안나왔던 것임 !!!

    이제 VO에 할건데

    직렬화 하면 안되니까 넣어주고 이름과 주민번호가 같으면 같은 사람으로 취급 그리고 toString pass랑 주민번호 뺴고 만든다

    직렬화하면 정보 빠져나가니까 안빠져나가도록!!

    package kr.or.ddit.vo;
    
    import java.io.Serializable;
    
    //DTO, marker interface : Serializable - marker annotation
    public class MemberVO implements Serializable {
    	
    	private String memId;
    	private transient String memPass;
    	private String memName;
    	private transient String memRegno1;
    	private transient String memRegno2;
    	private String memBir;
    	private String memZip;
    	private String memAdd1;
    	private String memAdd2;
    	private String memHometel;
    	private String memComtel;
    	private String memHp;
    	private String memMail;
    	private String memJob;
    	private String memLike;
    	private String memMemorial;
    	private String memMemorialday;
    	private String memMileage;
    	private String memDelete;
    	public String getMemId() {
    		return memId;
    	}
    	public void setMemId(String memId) {
    		this.memId = memId;
    	}
    	public String getMemPass() {
    		return memPass;
    	}
    	public void setMemPass(String memPass) {
    		this.memPass = memPass;
    	}
    	public String getMemName() {
    		return memName;
    	}
    	public void setMemName(String memName) {
    		this.memName = memName;
    	}
    	public String getMemRegno1() {
    		return memRegno1;
    	}
    	public void setMemRegno1(String memRegno1) {
    		this.memRegno1 = memRegno1;
    	}
    	public String getMemRegno2() {
    		return memRegno2;
    	}
    	public void setMemRegno2(String memRegno2) {
    		this.memRegno2 = memRegno2;
    	}
    	public String getMemBir() {
    		return memBir;
    	}
    	public void setMemBir(String memBir) {
    		this.memBir = memBir;
    	}
    	public String getMemZip() {
    		return memZip;
    	}
    	public void setMemZip(String memZip) {
    		this.memZip = memZip;
    	}
    	public String getMemAdd1() {
    		return memAdd1;
    	}
    	public void setMemAdd1(String memAdd1) {
    		this.memAdd1 = memAdd1;
    	}
    	public String getMemAdd2() {
    		return memAdd2;
    	}
    	public void setMemAdd2(String memAdd2) {
    		this.memAdd2 = memAdd2;
    	}
    	public String getMemHometel() {
    		return memHometel;
    	}
    	public void setMemHometel(String memHometel) {
    		this.memHometel = memHometel;
    	}
    	public String getMemComtel() {
    		return memComtel;
    	}
    	public void setMemComtel(String memComtel) {
    		this.memComtel = memComtel;
    	}
    	public String getMemHp() {
    		return memHp;
    	}
    	public void setMemHp(String memHp) {
    		this.memHp = memHp;
    	}
    	public String getMemMail() {
    		return memMail;
    	}
    	public void setMemMail(String memMail) {
    		this.memMail = memMail;
    	}
    	public String getMemJob() {
    		return memJob;
    	}
    	public void setMemJob(String memJob) {
    		this.memJob = memJob;
    	}
    	public String getMemLike() {
    		return memLike;
    	}
    	public void setMemLike(String memLike) {
    		this.memLike = memLike;
    	}
    	public String getMemMemorial() {
    		return memMemorial;
    	}
    	public void setMemMemorial(String memMemorial) {
    		this.memMemorial = memMemorial;
    	}
    	public String getMemMemorialday() {
    		return memMemorialday;
    	}
    	public void setMemMemorialday(String memMemorialday) {
    		this.memMemorialday = memMemorialday;
    	}
    	public String getMemMileage() {
    		return memMileage;
    	}
    	public void setMemMileage(String memMileage) {
    		this.memMileage = memMileage;
    	}
    	public String getMemDelete() {
    		return memDelete;
    	}
    	public void setMemDelete(String memDelete) {
    		this.memDelete = memDelete;
    	}
    	@Override
    	public int hashCode() {
    		final int prime = 31;
    		int result = 1;
    		result = prime * result + ((memId == null) ? 0 : memId.hashCode());
    		result = prime * result + ((memRegno1 == null) ? 0 : memRegno1.hashCode());
    		result = prime * result + ((memRegno2 == null) ? 0 : memRegno2.hashCode());
    		return result;
    	}
    	@Override
    	public boolean equals(Object obj) {
    		if (this == obj)
    			return true;
    		if (obj == null)
    			return false;
    		if (getClass() != obj.getClass())
    			return false;
    		MemberVO other = (MemberVO) obj;
    		if (memId == null) {
    			if (other.memId != null)
    				return false;
    		} else if (!memId.equals(other.memId))
    			return false;
    		if (memRegno1 == null) {
    			if (other.memRegno1 != null)
    				return false;
    		} else if (!memRegno1.equals(other.memRegno1))
    			return false;
    		if (memRegno2 == null) {
    			if (other.memRegno2 != null)
    				return false;
    		} else if (!memRegno2.equals(other.memRegno2))
    			return false;
    		return true;
    	}
    	@Override
    	public String toString() {
    		return "MemberVO [memId=" + memId + ", memName=" + memName + ", memBir=" + memBir + ", memZip=" + memZip
    				+ ", memAdd1=" + memAdd1 + ", memAdd2=" + memAdd2 + ", memHometel=" + memHometel + ", memComtel="
    				+ memComtel + ", memHp=" + memHp + ", memMail=" + memMail + ", memJob=" + memJob + ", memLike="
    				+ memLike + ", memMemorial=" + memMemorial + ", memMemorialday=" + memMemorialday + ", memMileage="
    				+ memMileage + ", memDelete=" + memDelete + "]";
    	}
    	
    	
    	
    	
    }

    => 마일리지 넘버이기때문에 integer형으로 바꿔주기

    db 스네이크를 카멜로 변환하는 함수 만들기

    create or replace FUNCTION SNAKETOCAMEL(
        COLUMN_NAME VARCHAR2 
    ) RETURN VARCHAR2 
    IS
    V_TMP VARCHAR2(30);
    BEGIN
        v_TMP := LOWER(SUBSTR(COLUMN_NAME,1,1)) ||
            SUBSTR(REPLACE(INITCAP(COLUMN_NAME), '_',''),2);
        RETURN V_TMP;
    END;

    끌어다 놓으면 사용할 수 있다.


    인터페이스만들고 -> LoginProcessServlet수정

    <LoginProcessServlet.java>

    package kr.or.ddit.login;
    
    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 org.apache.commons.lang3.StringUtils;
    import org.apache.commons.lang3.Validate;
    
    import kr.or.ddit.member.service.AuthenticateService;
    import kr.or.ddit.vo.MemberVO;
    
    
    @WebServlet("/login/loginProcess.do")
    public class LoginProcessServlet extends HttpServlet{
    	
    	AuthenticateService service;
    	
    	private boolean Validate(MemberVO member) {
    		return StringUtils.isNoneBlank(member.getMemId())
    				&&
    				StringUtils.isNoneBlank(member.getMemPass());
    	}
    	@Override
    	protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    		HttpSession session =req.getSession();
    		if(session.isNew()) { //새로운 요청들어온것을 막기 위해(왜? 세션유지되어야하니까)
    			resp.sendError(HttpServletResponse.SC_BAD_REQUEST);
    			return;
    		}
    		req.setCharacterEncoding("UTF-8"); //모든 컨트롤러의 첫번째
    		MemberVO inputData = new MemberVO();
    		inputData.setMemId(req.getParameter("memId"));
    		inputData.setMemPass(req.getParameter("memPass"));
    		
      		//1.검증
    		boolean valid =Validate(inputData);
    		boolean redirect =false;
    		String view =null;
    		if(valid) {
    			
    //			-통과
    //			2. 처리(로그인 여부 판단)
    			MemberVO authMember=service.authenticate(inputData);
    			if(authMember!=null) {
    //			Post-Redirect-Get 패턴
    //			-로그인 성공 : welcome 페이지로 이동(redirect)
    				session.setAttribute("message", "로그인 성공");
    				session.setAttribute("authMember", authMember);
    				redirect=true;
    				view="/";
    			}else {
    				
    //			-실패 : loginForm 으로 이동(forward)
    				session.setAttribute("message", "로그인 실패");
    				redirect=true;
    				view ="/login/loginForm.jsp";
    			}
    			
    		}else {
    			
    //		  -불통 :loginForm 으로 이동(forward / include(UI책임 나눠가짐)) 서블릿이 UI책임 나눠가질 필요 없으므로 forward
    			session.setAttribute("message", "검증실패");
    			redirect=true;
    			view ="/login/loginForm.jsp";
    		}
      		if(redirect) {
      			resp.sendRedirect(req.getContextPath() +view);
      		}else {
      			req.getRequestDispatcher(view).forward(req, resp);
      		}
    		
    	
    		
    	}
    }

     

    <AuthenticateServiceImpl.java>

    package kr.or.ddit.member.service;
    
    import kr.or.ddit.member.dao.MemberDAO;
    import kr.or.ddit.member.dao.MemberDAOImpl;
    import kr.or.ddit.vo.MemberVO;
    
    public class AuthenticateServiceImpl implements AuthenticateService {
    	MemberDAO memberDAO = new MemberDAOImpl();
    	
    	@Override
    	public MemberVO authenticate(MemberVO inputData) {
    
    		return memberDAO.selectMemberForAuth(inputData);
    	}
    
    }

    <MemberDAOImpl.java>

    바꾸기전 statement 사용했을때

    package kr.or.ddit.member.dao;
    
    import java.sql.Connection;
    import java.sql.PreparedStatement;
    import java.sql.ResultSet;
    import java.sql.SQLException;
    import java.sql.Statement;
    
    import kr.or.ddit.db.ConnectionFactory;
    import kr.or.ddit.vo.MemberVO;
    
    public class MemberDAOImple implements MemberDAO {
    
    	@Override
    	public MemberVO selectMemberForAuth(MemberVO inputData) {
    		// 회원의 정보 조회 : id, password. name, hp, address
    		// 해당 조건으로 검색시 존재하지 않으면 null 반환
    		// 쿼리객체 : Statement 객체 사용
    		
    		
    		StringBuffer sql = new StringBuffer();
    		sql.append(" SELECT MEM_ID, MEM_PASS, MEM_NAME, MEM_HP, MEM_ADD1 ");	
    		sql.append(" FROM MEMBER ");	
    		sql.append(" WHERE MEM_ID = '%s' AND MEM_PASS = '%s' ");	
    
    		try (
    			//Connection 수립
    			Connection conn = ConnectionFactory.getConnection();
    			// Query 객체 생성
    			Statement stmt = conn.createStatement();
    		){
    			//Query 실행
    			ResultSet rs = stmt.executeQuery(String.format(sql.toString(), inputData.getMemId(), inputData.getMemPass())); 
    			MemberVO vo = null;
    			
    			if(rs.next()){
    				vo = new MemberVO();
    				vo.setMemId(rs.getString("MEM_ID"));
    				vo.setMemPass(rs.getString("MEM_PASS"));
    				vo.setMemName(rs.getString("MEM_NAME"));
    				vo.setMemHp(rs.getString("MEM_HP"));
    				vo.setMemAdd1(rs.getString("MEM_ADD1"));
    				System.out.println(vo);
    			}
    			return vo;
    			
    		} catch (SQLException e) {
    			throw new RuntimeException(e);
    		}
    	}
    }

     

    NullPointer : 뭔가 주소가 존재하지않는 객체가 메인 어떻게 발생하느냐 Object obj = new Object(); 메모리3개가 잡힘

    클래스 먼저 로딩, 클래스참조 힙메모리에 인스턴스, 인스턴스의 주소  a.member=>  a의 인스턴스 주소찾고 멤버찾음

    a=null 일때 a.member 주소 없어 이때 nullpoint뜸 또다른 멤버를 찾고자 할때 발생 즉 .앞에서 발생 

    존재하지않는 객체의멤버를 참조할때 발생 

    => 그래서 이부분 수정 

     


     

    공격기법 : 1'OR'1'='1

    =>로그인이됨 

    이런식으로 값이 아니라 쿼리문을 입력해서 공격하는 기법.=> Statement의 단점

    해결방법1. 입력 데이터 검증

    해결방법2. 입력 데이터를 쿼리문이 아니라 단순한 값으로 사용(정적쿼리문(PreparedStatement) 사용)

    OR : 단순한키워드로 입력 쿼리문 실행될때는 연산자로 사용됨 그게 가능한 이유 statement 런타임에 쿼리 결정

    런타임때 쿼리문이 바껴도 됨.. 

    MEM_PASS = '1'OR'1'='1'; delete from memebr where '1'='1'

    입력데이터 검증으로 막아야함 

     

    sql.append(" SELECT MEM_ID, MEM_PASS, MEM_NAME, MEM_HP, MEM_ADD1");
          sql.append(" FROM MEMBER");
          sql.append(" WHERE MEM_ID = '%s' AND MEM_PASS ='%s'");
          
        ResultSet rs = stmt.executeQuery(String.format(sql.toString(), inputData.getMemId(), inputData.getMemPass()));

    동적- >정적

    동적쿼리 지양하자! 정적쿼리를 하려면 PreparedStatement사용 

    ibatis도 일종으로

    ibatis에서 #name# (= ?)  :정적 쿼리 / $name$ : 동적 쿼리므로 쓰지 말기!

    mybatis #{name} :정적 쿼리 / ${name} : 동적 쿼리므로 쓰지 말기!

     

    PreparedStatement사용하면 ? 이자리에 값만 포함될 수 있으므로 변경될 수 없음!!!

    <MemberDAOImpl.java>

    package kr.or.ddit.member.dao;
    
    import java.sql.Connection;
    import java.sql.PreparedStatement;
    import java.sql.ResultSet;
    import java.sql.SQLException;
    import java.sql.Statement;
    
    import kr.or.ddit.db.ConnectionFactory;
    import kr.or.ddit.vo.MemberVO;
    
    public class MemberDAOImpl implements MemberDAO {
    
       @Override
       public MemberVO selectMemberForAuth(MemberVO inputData) {
          // 회원의 정보 조회 : id, password, name, hp, address
          // 해당 조건으로 검색시 존재하지 않으면 null 반환
          // 쿼리 객체 : Statement 객체 사용.
          StringBuffer sql = new StringBuffer();
          sql.append(" SELECT MEM_ID, MEM_PASS, MEM_NAME, MEM_HP, MEM_ADD1 ");
          sql.append(" FROM MEMBER ");
          sql.append(" WHERE MEM_ID = ? AND MEM_PASS = ? ");
          try (
             Connection conn = ConnectionFactory.getConnection();
             PreparedStatement stmt = conn.prepareStatement(sql.toString());
          ){
             stmt.setString(1, inputData.getMemId());
             stmt.setString(2, inputData.getMemPass());
             
             ResultSet rs = stmt.executeQuery();
             MemberVO member = null;
             if(rs.next()) {
                member = new MemberVO();
                member.setMemId(rs.getString("MEM_ID"));
                member.setMemPass(rs.getString("MEM_PASS"));
                member.setMemName(rs.getString("MEM_NAME"));
                member.setMemHp(rs.getString("MEM_HP"));
                member.setMemAdd1(rs.getString("MEM_ADD1"));
             }
             return member;
          } catch(SQLException e) {
             throw new RuntimeException(e);
          }
          
       }
    
    }

    비지니스 모델 원래 목적처럼 써보자

    컨트롤러에 작성하게되면 무거워짐!!!

    우리인증은 데이터 보호 하지않고 있음, 비밀번호, 주민번호 조회가 됨...

    1. 제한된 형태로 수집, 인증받은 사용자만 수집가능

    2. 혹시라도 노출되더라도 읽을 수 없게 암호화

     

    DAO는 데이터만 받아오고 인증은 비지니스로직에서..하도록 만들자~

    리펙토링 하고 있어용!!

    <MemberDaoImpl.java>

    package kr.or.ddit.member.dao;
    
    import java.sql.Connection;
    import java.sql.PreparedStatement;
    import java.sql.ResultSet;
    import java.sql.SQLException;
    import java.sql.Statement;
    
    import kr.or.ddit.db.ConnectionFactory;
    import kr.or.ddit.vo.MemberVO;
    
    public class MemberDAOImpl implements MemberDAO {
    
       @Override
       public MemberVO selectMemberForAuth(MemberVO inputData) {
          // 회원의 정보 조회 : id, password, name, hp, address
          // 해당 조건으로 검색시 존재하지 않으면 null 반환
          // 쿼리 객체 : Statement 객체 사용.
          StringBuffer sql = new StringBuffer();
          sql.append(" SELECT MEM_ID, MEM_PASS, MEM_NAME, MEM_HP, MEM_ADD1 ");
          sql.append(" FROM MEMBER "                                        );
          sql.append(" WHERE MEM_ID = ? ");
          try (
             Connection conn = ConnectionFactory.getConnection();
             PreparedStatement stmt = conn.prepareStatement(sql.toString());
          ){
             stmt.setString(1, inputData.getMemId());
             
             
             ResultSet rs = stmt.executeQuery();
             MemberVO member = null;
             if(rs.next()) {
                member = new MemberVO();
                member.setMemId(rs.getString("MEM_ID"));
                member.setMemPass(rs.getString("MEM_PASS"));
                member.setMemName(rs.getString("MEM_NAME"));
                member.setMemHp(rs.getString("MEM_HP"));
                member.setMemAdd1(rs.getString("MEM_ADD1"));
             }
             return member;
          } catch(SQLException e) {
             throw new RuntimeException(e);
          }
          
       }
    
    }

    => ?pass없앰 서비스에서 해줄라고 

    <AuthenticateServiceImpl.java>

    package kr.or.ddit.member.service;
    
    import kr.or.ddit.member.dao.MemberDAO;
    import kr.or.ddit.member.dao.MemberDAOImpl;
    import kr.or.ddit.vo.MemberVO;
    
    public class AuthenticateServiceImpl implements AuthenticateService {
    	MemberDAO memberDAO = new MemberDAOImpl();
    	
    	@Override
    	public MemberVO authenticate(MemberVO inputData) {
    		MemberVO member= memberDAO.selectMemberForAuth(inputData);
    		String inputPass =inputData.getMemPass();
    		String savedPass = member.getMemPass();
    		
    		if(savedPass.equals(inputPass)) {
    			return member;
    		}else {
    			return null;
    		}
    	}
    
    }

    장점 : 이중인증구조로 바꿔라 하면 서비스만 건들일 수 있도록 추가적인 요구사항으로 수정해야한다면 레이어가 책임별로 쪼개져 있다면 변경사항만 연관되어 있는 곳만 고치면된다. 명확하게 어느영역 수정알 수 있음 

     


    번외 : try() 새로나온 문법으로 close안해줘도 됨

    오후: 회원전체목록 조회, 규칙을 코드화 시켜서 프레임워크 만들어보자, 시간 남으면 insert구조까지.. 

    추가된것

    <MemberDAO.java>

    package kr.or.ddit.member.dao;
    
    import java.util.List;
    
    import kr.or.ddit.vo.MemberVO;
    
    /**
     * 회원관리(CRUD) 및 인증구조를 위한 Persistance Layer
     *
     */
    public interface MemberDAO {
    	public MemberVO selectMemberForAuth(MemberVO inputData);
    	
    //	insertMember
    	/**
    	 * 회원목록 조회
    	 * @return 존재하지 않는 경우, size()==0
    	 */
    	public List<MemberVO> selectMemberList();
    //	selectMember
    //	updateMember
    //	deleteMember
    }

    <MemberDAOImpl.java>

    StringBuffer sql = new StringBuffer();
    		
    		try (
    			Connection conn = ConnectionFactory.getConnection();
    			PreparedStatement stmt = conn.prepareStatement(sql.toString());
    		){
    			ResultSet rs = stmt.executeQuery();
    			
    			return null;
    			
    		} catch (SQLException e) {
    			throw new RuntimeException(e);
    		}

    이 구조가 반복되고 있음  template만들자 

    =>insert Variable 누르고 커서 추가 

    @Override
    public List<MemberVO> selectMemberList() {
    	StringBuffer sql = new StringBuffer();
    	sql.append(" SELECT MEM_ID, MEM_NAME, MEM_HP, MEM_ADD1, MEM_MAIL,MEM_MILEAGE ");
        sql.append(" FROM MEMBER "                                        );
        List<MemberVO> memberList = new ArrayList<MemberVO>();
    	try (
    			Connection conn = ConnectionFactory.getConnection();
    			PreparedStatement stmt = conn.prepareStatement(sql.toString());) {
    
    		ResultSet rs = stmt.executeQuery();
    		while(rs.next()) {
    			MemberVO member =new MemberVO();
    			memberList.add(member);
    			member.setMemId(rs.getString("MEM_ID"));
                member.setMemName(rs.getString("MEM_NAME"));
                member.setMemHp(rs.getString("MEM_HP"));
                member.setMemAdd1(rs.getString("MEM_ADD1"));
                member.setMemMail(rs.getString("MEM_MAIL"));
                member.setMemMileage(rs.getInt("MEM_MILEAGE"));
    		}
    		return memberList;
    	} catch (SQLException e) {
    		throw new RuntimeException(e);
    	}
      }

     

    <MemberService.java>

    package kr.or.ddit.member.service;
    
    import java.util.List;
    
    import kr.or.ddit.vo.MemberVO;
    
     /**
     * 회원관리(CRUD)를 위한 Business Logic Layer
     *
     */
    public interface MemberService {
    	//	createMember
    	public List<MemberVO> retrieveMemberList();
    	//	retrienMember
    	//	modifyMember
    	//	removeMember
    }

    <MemberServiceImpl.java>

     

    package kr.or.ddit.member.service;
    
    import java.util.List;
    
    import kr.or.ddit.member.dao.MemberDAO;
    import kr.or.ddit.member.dao.MemberDAOImpl;
    import kr.or.ddit.vo.MemberVO;
    
    public class MemberServiceImpl implements MemberService {
    	MemberDAO memberDao =new MemberDAOImpl();
    	@Override
    	public List<MemberVO> retrieveMemberList() {
    		List<MemberVO> memberList =memberDao.selectMemberList();
    		return memberList;
    	}
    
    }

    <views: member: memberList.jsp>

    <%@page import="kr.or.ddit.vo.MemberVO"%>
    <%@page import="java.util.List"%>
    <%@ page language="java" contentType="text/html; charset=UTF-8"
        pageEncoding="UTF-8"%>
    
    <h4>회원목록 조회</h4>
    
    <table class="table table-bordered">
    	<thead>
    		<tr>
    			<th>회원아이디</th>
    			<th>회원명</th>
    			<th>휴대폰</th>
    			<th>거주지역</th>
    			<th>이메일</th>
    			<th>마일리지</th>
    		</tr>
    	</thead>
    	<tbody>
    	<%
    	List<MemberVO> memberList =(List)request.getAttribute("memberList");
    	if(memberList.size()>0){
    		for(MemberVO member :memberList){
    			%>
    			<tr>
    				<td><%=member.getMemId()%></td>
    				<td><%=member.getMemName()%></td>
    				<td><%=member.getMemHp() %></td>
    				<td><%=member.getMemAdd1()%></td>
    				<td><%=member.getMemMail() %></td>
    				<td><%=member.getMemMileage() %></td>
    			</tr>
    			<% 
    		}
    	}else{
    		%>
    		<tr>
    			<td colspan="6">아직 회원이 없음</td>
    		</tr>
    		<% 
    	}
    	%>
    	
    	
    	</tbody>
    </table>

     

     

    <web : MemberListServlet.java>

    package kr.or.ddit.member.web;
    
    import java.io.IOException;
    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 kr.or.ddit.member.service.MemberService;
    import kr.or.ddit.member.service.MemberServiceImpl;
    import kr.or.ddit.vo.MemberVO;
    /***
     * 회원 목록 조회를 위한 Controller Layer
     *
     */
    
    @WebServlet("/member/memberList.do")
    public class MemberListServlet extends HttpServlet {
    	MemberService service =  new MemberServiceImpl();
    	@Override
    	protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    		
    		List<MemberVO> memberList =service.retrieveMemberList();
    		req.setAttribute("memberList",memberList );
    		
    		
    		req.setAttribute("contents","/WEB-INF/views/member/memberList.jsp" );
    		String view ="/WEB-INF/views/template.jsp";
    		req.getRequestDispatcher(view).forward(req, resp);
    	}
    }


    <a href="<%=request.getContextPath() %>/member/memberInsert.do">회원가입</a> -> 이거 귀찮아

    <a href="${cPath}> 추후 리스너 통해서 리팩토링 해보자

     

     

    <MemberInsertServlet.java> 하고있어요 근데 일단 템플릿부터 만들어보자 

    이 3가지는 변하지 않음 링크만 달라지고 있다. 어느댑스구조안에 있는 jsp이름만 바뀜

    1) 중복해결

    2)바뀌는 데이터 갈아치우는 구조 

            req.setAttribute("contents","/WEB-INF/views/member/memberForm.jsp" );
    		String view ="/WEB-INF/views/template.jsp";
    		req.getRequestDispatcher(view).forward(req, resp);

    얘만 일단 적용해보자 

      ----> : 구현관계

    누구먼저? 인터페이스먼저 만들어야함 

    <ViewResolver.java>

    package kr.or.ddit.mvc;
    
    import java.io.IOException;
    
    import javax.servlet.ServletException;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    
    
    public interface ViewResolver {
    	public void viewResolve(String viewName, HttpServletRequest request,HttpServletResponse response)throws ServletException, IOException;
    }

    <InternalResourceViewResolver.java>

    package kr.or.ddit.mvc;
    
    import java.io.IOException;
    
    import javax.servlet.ServletException;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    /**
     * 하나의 JSP로 응답페이지를 구성하기 위한 전략 객체
     */
    public class InternalResourceViewResolver implements ViewResolver {
       
       private String prefix;
       private String suffix;
       
       public void setPrefix(String prefix) {
          this.prefix = prefix;
       }
    
       public void setSuffix(String suffix) {
          this.suffix = suffix;
       }
    
       @Override
       public void viewResolve(String viewName, HttpServletRequest request, HttpServletResponse response)
             throws ServletException, IOException {
          
          String resolveName = prefix + viewName + suffix;
          request.setAttribute("contents", resolveName);
          String view = "/WEB-INF/views/template.jsp";
          request.getRequestDispatcher(view).forward(request, response);
          
       }
    
    }

    memberlistser

    package kr.or.ddit.member.web;
    
    import java.io.IOException;
    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 kr.or.ddit.member.service.MemberService;
    import kr.or.ddit.member.service.MemberServiceImpl;
    import kr.or.ddit.mvc.InternalResourceViewResolver;
    import kr.or.ddit.vo.MemberVO;
    /***
     * 회원 목록 조회를 위한 Controller Layer
     *
     */
    
    @WebServlet("/member/memberList.do")
    public class MemberListServlet extends HttpServlet {
    	MemberService service =  new MemberServiceImpl();
    	@Override
    	protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    		
    		List<MemberVO> memberList =service.retrieveMemberList();
    		req.setAttribute("memberList",memberList );
    		
    //		
    //		req.setAttribute("contents","/WEB-INF/views/member/memberList.jsp" );
    //		String view ="/WEB-INF/views/template.jsp";
    //		req.getRequestDispatcher(view).forward(req, resp);
    		InternalResourceViewResolver resolver =new InternalResourceViewResolver();
    		resolver.setPrefix("/WEB-INF/views/");
    		resolver.setSuffix(".jsp");
    		
    		String viewName ="member/memberList";
    		resolver.viewResolve(viewName,req,resp);
    		
    	}
    }

    package kr.or.ddit.mvc;
    
    import java.io.IOException;
    
    import javax.servlet.ServletException;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    public class GridTemplateViewResolver implements ViewResolver {
    
    	@Override
    	public void viewResolve(String viewName, HttpServletRequest request, HttpServletResponse response)
    			throws ServletException, IOException {
    	     request.setAttribute("contents", viewName);
    		 String view = "/WEB-INF/views/template.jsp";
    		 request.getRequestDispatcher(view).forward(request, response);
    
    	}
    
    }
    package kr.or.ddit.mvc;
    
    public class ViewResolveUtils {
    	private ViewResolver[] resolvers;
    
    	public ViewResolveUtils(ViewResolver... resolvers) {
    		super();
    		this.resolvers = resolvers;
    	}
    	
    }

    ...:가변파라미터

     

    <DelegatingViewResolver.java>

    package kr.or.ddit.mvc;
    
    import java.io.IOException;
    
    import javax.servlet.ServletException;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    public class DelegatingViewResolver implements ViewResolver {
    	private ViewResolver defaultResolver;
    	private ViewResolver[] resolvers;
    
    	public DelegatingViewResolver() {
    		this(new GridTemplateViewResolver()); //기본을 resolvers에 넣을 수 있다.
    	}
    	
    	public DelegatingViewResolver(ViewResolver... resolvers) {
    		super();
    		this.resolvers = resolvers;
    		this.defaultResolver = new InternalResourceViewResolver();
    		((InternalResourceViewResolver)defaultResolver).setPrefix("/WEB-INF/views/");
    		((InternalResourceViewResolver)defaultResolver).setSuffix(".jsp");
    	}
    	
    	private ViewResolver findViewResolver(String viewName) {
    		ViewResolver findedResolver =defaultResolver;
    		for(ViewResolver tmp :resolvers) {
    			if(viewName.endsWith(".grid") &&(tmp instanceof GridTemplateViewResolver)) {
    				findedResolver =tmp;
    			}
    		}
    		return findedResolver;
    	}
    	
    	@Override
    	public void viewResolve(String viewName, HttpServletRequest request, HttpServletResponse response)
    			throws ServletException, IOException {
    	
    		 ViewResolver finded = findViewResolver(viewName);
    		 finded.viewResolve(viewName, request, response);
    		
    		
    	}
    	
    
    	
    }

    <GridTemplateViewResolver.java>

    package kr.or.ddit.mvc;
    
    import java.io.IOException;
    
    import javax.servlet.ServletException;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    /**
     * logicalViewName 이 ".grid"라는 접미어를 가지고 있을 때 동작
     * @author 306-10
     *
     */
    public class GridTemplateViewResolver implements ViewResolver {
    
    	@Override
    	public void viewResolve(String viewName, HttpServletRequest request, HttpServletResponse response)
    			throws ServletException, IOException {
    		 int idx = viewName.lastIndexOf(".grid");
    		 viewName = viewName.substring(0,idx);
    	     request.setAttribute("contents", viewName);
    		 String view = "/WEB-INF/views/template.jsp";
    		 request.getRequestDispatcher(view).forward(request, response);
    
    	}
    
    }

    <ViewResolver.java>

    package kr.or.ddit.mvc;
    
    import java.io.IOException;
    
    import javax.servlet.ServletException;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    
    
    public interface ViewResolver {
    	public void viewResolve(String viewName, HttpServletRequest request,HttpServletResponse response)throws ServletException, IOException;
    }

    <InternalResourceViewResolver.java> - >이름바꿨었음

    package kr.or.ddit.mvc;
    
    import java.io.IOException;
    
    import javax.servlet.ServletException;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    /**
     * 하나의 JSP로 응답페이지를 구성하기 위한 전략 객체
     */
    public class InternalResourceViewResolver implements ViewResolver {
       
       private String prefix;
       private String suffix;
       
       public void setPrefix(String prefix) {
          this.prefix = prefix;
       }
    
       public void setSuffix(String suffix) {
          this.suffix = suffix;
       }
    
       @Override
       public void viewResolve(String viewName, HttpServletRequest request, HttpServletResponse response)
             throws ServletException, IOException {
          
          String resolveName = prefix + viewName + suffix;
          request.getRequestDispatcher(resolveName).forward(request, response);
          
       }
    
    }

    <MemberListServlet.java> 전체적코드 

    package kr.or.ddit.member.web;
    
    import java.io.IOException;
    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 kr.or.ddit.member.service.MemberService;
    import kr.or.ddit.member.service.MemberServiceImpl;
    import kr.or.ddit.mvc.GridTemplateViewResolver;
    import kr.or.ddit.mvc.InternalResourceViewResolver;
    import kr.or.ddit.mvc.DelegatingViewResolver;
    import kr.or.ddit.vo.MemberVO;
    /***
     * 회원 목록 조회를 위한 Controller Layer
     *
     */
    
    @WebServlet("/member/memberList.do")
    public class MemberListServlet extends HttpServlet {
    	MemberService service =  new MemberServiceImpl();
    	@Override
    	protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    		
    		List<MemberVO> memberList =service.retrieveMemberList();
    		req.setAttribute("memberList",memberList );
    		
    //		
    //		req.setAttribute("contents","/WEB-INF/views/member/memberList.jsp" );
    //		String view ="/WEB-INF/views/template.jsp";
    //		req.getRequestDispatcher(view).forward(req, resp);
    //		InternalResourceViewResolver resolver =new InternalResourceViewResolver();
    //		resolver.setPrefix("/WEB-INF/views/");
    //		resolver.setSuffix(".jsp");
    		
    		
    		DelegatingViewResolver resolver =new DelegatingViewResolver();
    		String viewName ="member/memberList";
    		resolver.viewResolve(viewName,req,resp);
    		
    	}
    }

    그리드 사용하고싶어 

    ViewResolveUtils resolver =new ViewResolveUtils();
    		String viewName ="/WEB-INF/views/member/memberList.jsp.grid";
    		resolver.viewResolve(viewName,req,resp);

     

    그리드 사용안하고싶어

    ViewResolveUtils resolver =new ViewResolveUtils();
    		String viewName ="member/memberList";
    		resolver.viewResolve(viewName,req,resp);


    viewSesolver 내부에서 적용해야지맞음 다시 수정하자

    언제나 반드시 GridTemplateView부터 동작해야함

    package kr.or.ddit.mvc;
    
    import java.io.IOException;
    
    import javax.servlet.ServletException;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    public class DelegatingViewResolver implements ViewResolver {
    	private ViewResolver defaultResolver;
    	private ViewResolver[] resolvers;
    
    	public DelegatingViewResolver() {
    		this(new GridTemplateViewResolver()); //기본을 resolvers에 넣을 수 있다.
            //밑에 public DelegatingViewResolver(ViewResolver... resolvers)에 
            자기자신에 new GridTemplateViewResolver()를 부른것이다.
    	}
    	
    	public DelegatingViewResolver(ViewResolver... resolvers) {
    		super();
    		this.resolvers = resolvers;
    		this.defaultResolver = new InternalResourceViewResolver();
    		((InternalResourceViewResolver)defaultResolver).setPrefix("/WEB-INF/views/");
    		((InternalResourceViewResolver)defaultResolver).setSuffix(".jsp");
    	}
    	//추가됨
    	@Override
    	public boolean suppoerted(String viewName) {
    		
    		return true;
    	}
    	
    	private ViewResolver findViewResolver(String viewName) {
    		ViewResolver findedResolver =defaultResolver;
    		for(ViewResolver tmp :resolvers) {
    			if(tmp.suppoerted(viewName)) {
    				findedResolver =tmp;
    			}
    		}
    		return findedResolver;
    	}
    	
    	@Override
    	public void viewResolve(String viewName, HttpServletRequest request, HttpServletResponse response)
    			throws ServletException, IOException {
    	
    		 ViewResolver finded = findViewResolver(viewName);
    		 finded.viewResolve(viewName, request, response);
    		
    		
    	}
    	
    
    	
    }
    package kr.or.ddit.mvc;
    
    import java.io.IOException;
    
    import javax.servlet.ServletException;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    
    
    public interface ViewResolver {
    	public boolean suppoerted(String viewName);
    	public void viewResolve(String viewName, HttpServletRequest request,HttpServletResponse response)throws ServletException, IOException;
    }
    package kr.or.ddit.mvc;
    
    import java.io.IOException;
    
    import javax.servlet.ServletException;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    /**
     * logicalViewName 이 ".grid"라는 접미어를 가지고 있을 때 동작
     * @author 306-10
     *
     */
    public class GridTemplateViewResolver implements ViewResolver {
    	public static final String GRIDSUFFIX =".grid";
    	@Override
    	public boolean suppoerted(String viewName) {
    		
    		return viewName.endsWith(GRIDSUFFIX);
    	}
    
    	@Override
    	public void viewResolve(String viewName, HttpServletRequest request, HttpServletResponse response)
    			throws ServletException, IOException {
    		 int idx = viewName.lastIndexOf(GRIDSUFFIX);
    		 viewName = viewName.substring(0,idx);
    	     request.setAttribute("contents", viewName);
    		 String view = "/WEB-INF/views/template.jsp";
    		 request.getRequestDispatcher(view).forward(request, response);
    
    	}
    
    
    }
    package kr.or.ddit.mvc;
    
    import java.io.IOException;
    
    import javax.servlet.ServletException;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    /**
     * 하나의 JSP로 응답페이지를 구성하기 위한 전략 객체
     */
    public class InternalResourceViewResolver implements ViewResolver {
       
       private String prefix;
       private String suffix;
       
       public void setPrefix(String prefix) {
          this.prefix = prefix;
       }
    
       public void setSuffix(String suffix) {
          this.suffix = suffix;
       }
    
       @Override
       public boolean suppoerted(String viewName) {
    	  return true;
       }
       
       @Override
       public void viewResolve(String viewName, HttpServletRequest request, HttpServletResponse response)
             throws ServletException, IOException {
          
          String resolveName = prefix + viewName + suffix;
          request.getRequestDispatcher(resolveName).forward(request, response);
          
       }
    
    
    }

     

     

     

     

     

    그리드쓰고싶어

    		DelegatingViewResolver resolver =new DelegatingViewResolver();
    		String viewName ="/WEB-INF/views/member/memberList.jsp"+GridTemplateViewResolver.GRIDSUFFIX;
    		resolver.viewResolve(viewName,req,resp);

     

    예시 또 

    package kr.or.ddit;
    
    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 kr.or.ddit.mvc.DelegatingViewResolver;
    import kr.or.ddit.mvc.GridTemplateViewResolver;
    
    @WebServlet("/index.do")
    public class IndexServlet extends HttpServlet{
    	@Override
    	protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    //		req.setAttribute("contents", "/WEB-INF/views/index.jsp");
    //		String view ="/WEB-INF/views/template.jsp";
    //		req.getRequestDispatcher(view).forward(req, resp);
    		String viewName ="/WEB-INF/views/index.jsp"+GridTemplateViewResolver.GRIDSUFFIX;
    		new DelegatingViewResolver().viewResolve(viewName, req, resp);
    	}
    }

    enum을 사용한 로그인 메세지 세분화

    package kr.or.ddit.enumpkg;
    
    public enum ServiceResult {
    	OK, FAIL, PKDUPLICATED, INVALIDPASSWORD, NOTEXIST
    }

    로그인 경우의 수 3가지 : 존재하지 않을때(NOTEXIST), 비번 오류(INVALIDPASSWORD), 성공(OK)

    AuthenticateServiceImpl 25 call by reference구조 


    회원가입하기 

    --COMMENT 생성 코드조각
    --COMMENT ON COLUMN MEMBER.MEM_ID IS '회원아이디';
    SELECT 'COMMENT ON COLUMN '||
        TABLE_NAME||'.'||COLUMN_NAME||
        ' IS '''';'    
    FROM COLS
    WHERE TABLE_NAME = 'MEMBER';
    
    COMMENT ON COLUMN MEMBER.MEM_ID IS '회원아이디';
    COMMENT ON COLUMN MEMBER.MEM_PASS IS '비밀번호';
    COMMENT ON COLUMN MEMBER.MEM_NAME IS '회원명';
    COMMENT ON COLUMN MEMBER.MEM_REGNO1 IS '주민번호1';
    COMMENT ON COLUMN MEMBER.MEM_REGNO2 IS '주민번호2';
    COMMENT ON COLUMN MEMBER.MEM_BIR IS '생일';
    COMMENT ON COLUMN MEMBER.MEM_ZIP IS '우편번호';
    COMMENT ON COLUMN MEMBER.MEM_ADD1 IS '주소1';
    COMMENT ON COLUMN MEMBER.MEM_ADD2 IS '주소2';
    COMMENT ON COLUMN MEMBER.MEM_HOMETEL IS '집전화번호';
    COMMENT ON COLUMN MEMBER.MEM_COMTEL IS '회사번호';
    COMMENT ON COLUMN MEMBER.MEM_HP IS '휴대폰';
    COMMENT ON COLUMN MEMBER.MEM_MAIL IS '이메일';
    COMMENT ON COLUMN MEMBER.MEM_JOB IS '직업';
    COMMENT ON COLUMN MEMBER.MEM_LIKE IS '취미';
    COMMENT ON COLUMN MEMBER.MEM_MEMORIAL IS '기념일';
    COMMENT ON COLUMN MEMBER.MEM_MEMORIALDAY IS '기념일자';
    COMMENT ON COLUMN MEMBER.MEM_MILEAGE IS '마일리지';
    COMMENT ON COLUMN MEMBER.MEM_MILEAGE IS '탈퇴여부';

    jdbc + ctrl+space누르면 나옴

     

     


    * 메소드 호출시 인자(argument) 전달 방법
     * parameter vs argument
     *  ex) int number =3 ; //기본형 변수 : 상수메모리 공간, 메모리에서 사라지지않음
     *   Object obj = new Object(); 1. 클래스에먼저 적재(가비지안됨), 
     *      2.힙메모리 할당 (레퍼런스 만들어짐) 3.obj들어가는 메모리 공간 
     *   
     * call by value : parameter 타입이 기본형.(copy value)
     * call by reference : parameter 타입이 참조형.(copy reference)

     

     

    =>parameter : 일종의 식별자

     

    argument : 식별자를 통해 전달되는 데이터

    public class MethodParameterPassingDesc {
    	public static void main(String[] args) {
    		int number =10;
    		method1(number);
    		System.out.printf("number: %d",number);
    	}
    	private static void method1(int number) {
    		number = number+1;
    	}
    }

    기본형이며 number는 다른공간일거야 이미 증가해버리고 끝났으며 원래 형태의 10이나옴

    값만 복사했으니

    public class MethodParameterPassingDesc {
    	public static void main(String[] args) {
    		int number =10;
    		method1(number);
    		System.out.printf("number: %d\n",number);
    		
    		StringBuffer sb = new StringBuffer("ORIGINAL");
    		method2(sb);
    		System.out.printf("sb: %s",sb);
    	}
    	private static void method1(int number) {
    		number = number+1;
    	}
    	
    	public static void method2(StringBuffer sb) { //참조형
    		sb.append("APPEND");
    	}
    }

     

    728x90

    '웹프로그래밍' 카테고리의 다른 글

    EL, JSTL 프레임워크 -0624  (0) 2022.06.24
    회원등록, DB -22.06.23  (0) 2022.06.23
    JDBC-22.06.21  (0) 2022.06.22
    기본객체2, scope-0621  (0) 2022.06.21
    ServletContext,File explorer -22.06.20  (0) 2022.06.21
Designed by Tistory.