JAVA/HIGH JAVA

6/7 Homework

아잠만_ 2024. 6. 7. 22:56

문제

- 다음 페이지 이후의 진행 사항에 맞게 회원을 관리하는 웹 프로그램을 작성하시오.

sql문

더보기
CREATE TABLE MYMEMBER(
MEM_ID VARCHAR2(20) NOT NULL, -- 회원ID
MEM_ID VARCHAR2(20) NOT NULL, -- 회원ID
MEM_PASS VARCHAR2(30) NOT NULL, -- 비밀번호
MEM_NAME VARCHAR2(30) NOT NULL, -- 회원이름
MEM_TEL VARCHAR2(14), -- 전화번호
MEM_ADDR VARCHAR2(90) NOT NULL, -- 주소
MEM_PHOTO VARCHAR2(70) -- 프로필사진
CONSTRAINT PK_MYMEMBER PRIMARY KEY (MEM_ID)
);

문제 사진

문제풀이

config

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration 
	PUBLIC "-//mybatis.org/DTD Config 3.0//EN"
	 "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
	<!--  DB연결 정보가 있는 Properties파일 설정  -->
	<properties resource="kr/or/ddit/mybatis/config/dbinfo.properties" />
	
	<!-- MyBatis의 기본 설정값 세팅 -->
	<settings>
		<!-- 데이터가 null로 전달되었으면 빈칸으로 인지되지 않고 null로 인식하는 설정 -->
		<!-- value값은 전부 대문자 -->
		<setting name="jdbcTypeForNull" value="NULL"/>
		<setting name="logImpl" value="LOG4J"/>
	</settings>
	
	<typeAliases>
		<!-- MyBatis에서 사용되는 클래스들은 사용할 때 패키지명이 포함된 
			전체 이름을 사용해야되는데 이것을 대신해서 짧은 이름으로 사용하기 위한 별칭을 등록한다.
		형식) <typeAlias type="패키지명을 포함한 전체이름" alias="별칭이름"/>
			-->
			<typeAlias type="kr.or.ddit.vo.MemberVO" alias="memVo"/>
	</typeAliases>

	<!-- DB에 연결 할 정보 설정하기 -->
	<environments default="oracleDB">
		<!-- 다른 DB도 연결할 수 있으므로 env는 여러개 올 수 있다 / id는 구분하기 위한 이름 -->
		<environment id="oracleDB"> 
			<transactionManager type="JDBC"/>
			<dataSource type="POOLED">
				<property name="driver" value="${driver}"/><!-- value값에 프로퍼티스의 키값 작성 -->
				<property name="url" value="${url}"/>
				<property name="username" value="${user}"/>
				<property name="password" value="${pass}"/>
			</dataSource>
		</environment>
	</environments>
	
	<!-- DB에서 사용되는 SQL문이 작성된 mapper파일을 등록하는 부분 -->
	<mappers>
		<!-- 
		형식) <mapper resource="경로명/파일명.xml"/>
		 -->
		 <mapper resource="kr/or/ddit/mybatis/mappers/member-mapper.xml"/>
	</mappers>
	
</configuration>

mapper

<?xml version="1.0" encoding="UTF-8"?>

<!-- 이 문서는 myBatis에서 처리할 SQL문을 작성하는 문서입니다 -->
<!DOCTYPE mapper
	PUBLIC "-//mybatis.org/DTD Mapper 3.0//EN"
	"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
	
<!-- <mapper>태그의 namespace속성에 설정된 값은 Java소스에서 실행할 SQL문을 호출할 때
	 같이 사용되는 이름이다 -->
<mapper namespace="mem">
	<sql id="photo">
    <!-- 해당 mem_photo가 입력된 경우에만 해당 구문이 include된다-->
		<if test="mem_photo!=null">
		,mem_photo=#{mem_photo}
		</if>
	</sql>

	<insert id="sign" parameterType="memVo">
		insert into mymember
		values(#{mem_id},#{mem_pass},#{mem_name},#{mem_tel},#{mem_addr},#{mem_photo})
	</insert>
	
	<select id="list" resultType="memVo">
		select * from mymember
	</select>
	
	<select id="detail" resultType="memVo" parameterType="String">
		select * from mymember where mem_id=#{mem_id}
	</select>
	
	<select id="idChk" resultType="int" parameterType="String">
		select count(*) from mymember where mem_id=#{mem_id}
	</select>
	
	<update id="update" parameterType="memVo">
		update mymember set mem_pass=#{mem_pass}, mem_name=#{mem_name}, mem_tel=#{mem_tel}, mem_addr=#{mem_addr}
		    <include refid="photo"></include>
		    where mem_id=#{mem_id}
	</update>
	
	<delete id="delete" parameterType="String">
		delete from mymember where mem_id=#{mem_id}
	</delete>
</mapper>

MemberVO

package kr.or.ddit.vo;

/**
 * DB테이블에 있는 컬럼을 기준으로 데이터를 객체화할 클래스
 * 
 * DB테이블의 '컬럼명'이 이 클래스의 '멤버변수'가 된다.
 * DB테이블의 컬럼과 클래스의 멤버변수를 매핑하는 역할을 수행한다.
 * 
 * @author PC-13
 *
 */
public class MemberVO {
	private String mem_id;
	private String mem_pass;
	private String mem_name;
	private String mem_tel;
	private String mem_addr;
	private String mem_photo;

	// VO클래스에서 별도의 생성자를 만들 때에는
	// 기본 생성자도 반드시 같이 만들어 준다.
	public MemberVO() {
		
	}

	public String getMem_id() {
		return mem_id;
	}

	public void setMem_id(String mem_id) {
		this.mem_id = mem_id;
	}

	public String getMem_pass() {
		return mem_pass;
	}

	public void setMem_pass(String mem_pass) {
		this.mem_pass = mem_pass;
	}

	public String getMem_name() {
		return mem_name;
	}

	public void setMem_name(String mem_name) {
		this.mem_name = mem_name;
	}

	public String getMem_tel() {
		return mem_tel;
	}

	public void setMem_tel(String mem_tel) {
		this.mem_tel = mem_tel;
	}

	public String getMem_addr() {
		return mem_addr;
	}

	public void setMem_addr(String mem_addr) {
		this.mem_addr = mem_addr;
	}

	public String getMem_photo() {
		return mem_photo;
	}

	public void setMem_photo(String mem_photo) {
		this.mem_photo = mem_photo;
	}
	
}

Dao

더보기
package kr.or.ddit.member.dao;

import java.util.List;
import java.util.Map;

import kr.or.ddit.vo.MemberVO;

/**
 * 실제 DB와 연결해서 SQL문을 수행하여 결과를 작성해서
 * Service에게 전달하는  DAO의 interface
 * 
 * 메서드 하나가 DB와 관련된 작업 1개를 수행하도록 작성한다.
 * 
 * @author PC-13
 *
 */
public interface IMemberDao {
	/**
	 * MemberVO객체에 담겨진 자료를 DB에 insert하는 메서드
	 * 
	 * @param memVo DB에 insert할 자료가 저장된 MemberVO 객체
	 * @return 작업 성공 : 1, 작업 실패 : 0
	 */
	public int insertMember(MemberVO memVo);
	
	/**
	 * 회원ID를 매개변수로 받아서 해당 회원 정보를 삭제하는 메서드
	 * @param mem_id 삭제할 회원ID
	 * @return 작업 성공 : 1, 작업 실패 : 0
	 */
	public int deleteMember(String mem_id);
	
	/**
	 * 매개변수로 받은 MemberVO객체를 이용하여 해당 회원 정보를 수정하는 메서드
	 * @param memVo update할 회원 정보가 저장된  MemberVO객체
	 * @return 작업 성공 : 1, 작업 실패 : 0
	 */
	public int updateMember(MemberVO memVo);
	
	/**
	 * DB의 전체 회원 정보를 가져와 List에 담아서 반환하는 메서드
	 * @return 전체 회원정보 각각을 MemberVO에 담고 있는 List객체
	 */
	public List<MemberVO> getAllMember();
	
	/**
	 * 회원ID를 매개변수로 받아서 해당 회원ID의 개수를 반환하는 메서드
	 * @param mem_id 검색할 회원ID
	 * @return 검색된 회원ID의 갯수
	 */
	public int getMemIdCount(String mem_id);
	
	/**
	 * 회원ID를 매개변수로 받아서 해당 회원의 정보를 반환하는 메서드
	 * @param mem_id 검색할 회원ID
	 * @return 검색된 회원ID 정보
	 */
	public MemberVO getMemInfo(String mem_id);
	
}
package kr.or.ddit.member.dao;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import org.apache.ibatis.session.SqlSession;

import kr.or.ddit.vo.MemberVO;
import kr.or.ddit.util.MyBatisUtil;

public class MemberMybatisDaoImpl implements IMemberDao{
	private static MemberMybatisDaoImpl dao;
	
	private MemberMybatisDaoImpl() {
		// TODO Auto-generated constructor stub
	}
	
	public static MemberMybatisDaoImpl getInstance() {
		if(dao==null) {
			dao = new MemberMybatisDaoImpl();
		}
		return dao;
	}

	@Override
	public int insertMember(MemberVO memVo) {
		SqlSession session = null;
		int cnt = 0; // 반환값이 저장될 변수
		
		try {
			session = MyBatisUtil.getSqlSession();
			cnt = session.insert("mem.sign", memVo);
			if(cnt>0) {
				session.commit();
			}
		} catch (Exception e) {
			// TODO: handle exception
			e.printStackTrace();
		} finally {
			session.close();
		}
		return cnt;
	}

	@Override
	public int deleteMember(String mem_id) {
		SqlSession session = null;
		int cnt = 0; // 반환값이 저장될 변수
		
		try {
			session = MyBatisUtil.getSqlSession();
			cnt = session.delete("mem.delete", mem_id);
			if(cnt>0) {
				session.commit();
			}
		} catch (Exception e) {
			// TODO: handle exception
			e.printStackTrace();
		} finally {
			if(session!=null) try {session.close();}catch(Exception e){}
		}
		return cnt;
	} 

	@Override
	public int updateMember(MemberVO memVo) {
		SqlSession session = null;
		int cnt = 0; // 반환값이 저장될 변수
		try {
			session = MyBatisUtil.getSqlSession();
			cnt = session.update("mem.update", memVo);
			if(cnt>0) {
				session.commit();
			}
		} catch (Exception e) {
			// TODO: handle exception
			e.printStackTrace();
		} finally {
			if(session!=null) try {session.close();}catch(Exception e){}
		}
		return cnt;
	}

	@Override
	public List<MemberVO> getAllMember() {
		List<MemberVO> list = new ArrayList<MemberVO>();
		SqlSession session = null;
		try {
			session = MyBatisUtil.getSqlSession();
			list = session.selectList("mem.list");
		} catch (Exception e) {
			// TODO: handle exception
		} finally {
			if(session!=null) try {session.close();}catch(Exception e){}
		}
		return list;
	}

	@Override
	public int getMemIdCount(String mem_id) {
		SqlSession session = null;
		int count = 0;
		try {
			session = MyBatisUtil.getSqlSession();
			count = session.selectOne("mem.idChk", mem_id);
		} catch (Exception e) {
			// TODO: handle exception
		} finally {
			if(session!=null) try {session.close();}catch(Exception e){}
		}
		
		return count;
	}

	@Override
	public MemberVO getMemInfo(String mem_id) {
		MemberVO memVo = new MemberVO();
		SqlSession session = null;
		try {
			session = MyBatisUtil.getSqlSession();
			memVo = session.selectOne("mem.detail", mem_id);
		} catch (Exception e) {
			// TODO: handle exception
		} finally {
			if(session!=null) try {session.close();}catch(Exception e){}
		}
		return memVo;
	}
}

Service

더보기
package kr.or.ddit.member.service;

import java.util.List;
import java.util.Map;

import kr.or.ddit.vo.MemberVO;

/**
 * Service객체는 DAO에 만들어진 메서드를 원하는 작업에 맞게 호출하여
 * 결과를 받아오고, 받아온 결과를 Controller에게 보내주는 역할을 한다
 * 
 * 보통 DAO의 메서드와 구조가 같다
 * @author PC-13
 *
 */
public interface IMemberService {
	/**
	 * MemberVO객체에 담겨진 자료를 DB에 insert하는 메서드
	 * 
	 * @param memVo DB에 insert할 자료가 저장된 MemberVO 객체
	 * @return 작업 성공 : 1, 작업 실패 : 0
	 */
	public int insertMember(MemberVO memVo);
	
	/**
	 * 회원ID를 매개변수로 받아서 해당 회원 정보를 삭제하는 메서드
	 * @param mem_id 삭제할 회원ID
	 * @return 작업 성공 : 1, 작업 실패 : 0
	 */
	public int deleteMember(String mem_id);
	
	/**
	 * 매개변수로 받은 MemberVO객체를 이용하여 해당 회원 정보를 수정하는 메서드
	 * @param memVo update할 회원 정보가 저장된  MemberVO객체
	 * @return 작업 성공 : 1, 작업 실패 : 0
	 */
	public int updateMember(MemberVO memVo);
	
	/**
	 * DB의 전체 회원 정보를 가져와 List에 담아서 반환하는 메서드
	 * @return 전체 회원정보 각각을 MemberVO에 담고 있는 List객체
	 */
	public List<MemberVO> getAllMember();
	
	/**
	 * 회원ID를 매개변수로 받아서 해당 회원ID의 개수를 반환하는 메서드
	 * @param mem_id 검색할 회원ID
	 * @return 검색된 회원ID의 갯수
	 */
	public int getMemIdCount(String mem_id);
	
	/**
	 * 회원ID를 매개변수로 받아서 해당 회원의 정보를 반환하는 메서드
	 * @param mem_id 검색할 회원ID
	 * @return 검색된 회원ID 정보
	 */
	public MemberVO getMemInfo(String mem_id);
	
}
package kr.or.ddit.member.service;

import java.util.List;
import java.util.Map;

import kr.or.ddit.member.dao.IMemberDao;
import kr.or.ddit.member.dao.MemberMybatisDaoImpl;
import kr.or.ddit.vo.MemberVO;

public class MemberServiceImpl implements IMemberService {
	private static MemberServiceImpl service;
	private IMemberDao dao; // DAO객체가 저장될 변수 선언
	// 생성자
	private MemberServiceImpl() {
		dao = MemberMybatisDaoImpl.getInstance();
	}
	
	public static MemberServiceImpl getInstance() {
		if(service==null) service = new MemberServiceImpl();
		return service;
	}

	@Override
	public int insertMember(MemberVO memVo) {
		return dao.insertMember(memVo);
	}

	@Override
	public int deleteMember(String mem_id) {
		return dao.deleteMember(mem_id);
	}

	@Override
	public int updateMember(MemberVO memVo) {
		return dao.updateMember(memVo);
	}

	@Override
	public List<MemberVO> getAllMember() {
		return dao.getAllMember();
	}

	@Override
	public int getMemIdCount(String mem_id) {
		return dao.getMemIdCount(mem_id);
	}

	@Override
	public MemberVO getMemInfo(String mem_id) {
		return dao.getMemInfo(mem_id);
	}

}

Servlet

memList Servlet

package kr.or.ddit.member.controller;

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.IMemberService;
import kr.or.ddit.member.service.MemberServiceImpl;
import kr.or.ddit.vo.MemberVO;

@WebServlet("/memList.do")
public class MemList extends HttpServlet {
	private static final long serialVersionUID = 1L;
	private IMemberService service = MemberServiceImpl.getInstance();
	
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // 모든 데이터를 받아서 list값에 저장한다		
        List<MemberVO> list = service.getAllMember();
		
		request.setAttribute("list", list);
		request.getRequestDispatcher("/view/memList.jsp").forward(request, response);
	}

	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		// TODO Auto-generated method stub
		doGet(request, response);
	}

}

idChk Servlet

package kr.or.ddit.member.controller;

import java.io.IOException;
import java.io.PrintWriter;

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.IMemberService;
import kr.or.ddit.member.service.MemberServiceImpl;

@WebServlet("/idChk.do")
public class IdChk extends HttpServlet {
	private static final long serialVersionUID = 1L;
	private IMemberService service = MemberServiceImpl.getInstance();
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		String id = request.getParameter("id");
        
		int cnt = service.getMemIdCount(id);
		
		response.setCharacterEncoding("utf-8");
		response.setContentType("text/html; charset=utf-8");
		PrintWriter out = response.getWriter();
		// cnt값을 ajax data로 보낸다
		out.print(cnt);
		response.flushBuffer();
	}

	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		// TODO Auto-generated method stub
		doGet(request, response);
	}

}

memSign Servlet

package kr.or.ddit.member.controller;

import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.UUID;

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

import com.google.gson.Gson;

import kr.or.ddit.member.service.IMemberService;
import kr.or.ddit.member.service.MemberServiceImpl;
import kr.or.ddit.vo.MemberVO;

//파일 저장시 꼭 설정해야될 애노테이션
@MultipartConfig(fileSizeThreshold = 1024 * 1024 * 10, // 10 mb
		maxFileSize = 1024 * 1024 * 30, maxRequestSize = 1024 * 1024 * 200)
@WebServlet("/memSign.do")
public class MemSign extends HttpServlet {
	private static final long serialVersionUID = 1L;
	private IMemberService service = MemberServiceImpl.getInstance();

	protected void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		doPost(request, response);
	}

	protected void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		// POST 방식으로 요청하면 Upload된 파일을 받아서 처리한다
		request.setCharacterEncoding("utf-8");

		// 업로드된 파일들이 저장될 폴더 설정
		String uploadPath = "d:/d_other/memberImage"; // 서버 위치

		// 저장될 폴더가 없으면 새로 만들어준다
		File file = new File(uploadPath);
		if (!file.exists()) {
			file.mkdirs();
		}

		MemberVO memVo = new MemberVO();
		memVo.setMem_id(request.getParameter("mem_id"));
		memVo.setMem_pass(request.getParameter("mem_pass"));
		memVo.setMem_name(request.getParameter("mem_name"));
		memVo.setMem_addr(request.getParameter("mem_addr"));
		memVo.setMem_tel(request.getParameter("mem_tel"));
		
		// file의 name 값을 Part로 가져온다
		Part part = request.getPart("mem_photo");
		
		// 파일명 가져오기
		String fileName = ""; // 반환값이 저장될 변수
		String dispositionValue = part.getHeader("content-disposition");
		String[] items = dispositionValue.split(";");
		for (String item : items) {
			if (item.trim().startsWith("filename")) { // 파일 정보가 있는지 검사
				fileName = item.substring(item.indexOf("=") + 2, item.length() - 1);
			}
		}
		// 실제 저장되는 파일 이름이 중복되는 것을 방지하기 위해서 UUID를 이용하여 저장할 파일명을 만든다.
		String saveFileName = UUID.randomUUID().toString() + "_" + fileName;
		memVo.setMem_photo(saveFileName);
		try {
			//파일 해당 경로에 저장
			part.write(uploadPath + File.separator + saveFileName);
		} catch (Exception e) {
			// TODO: handle exception
			e.printStackTrace();
		}
		int cnt = service.insertMember(memVo);
		response.setCharacterEncoding("utf-8");
		response.setContentType("text/html; charset=utf-8");
		response.sendRedirect(request.getContextPath() + "/memList.do");

	}
}

memDetail Servlet

해당 서블릿에서는 update시 value값을 입력되게 하여 forward의 경로가 2개이다

그래서 update라는 파라미터 변수를 더 추가하여 list>detail에서 오는건지 detail>update에서 오는 건지 파악하기 위함

package kr.or.ddit.member.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 kr.or.ddit.member.service.IMemberService;
import kr.or.ddit.member.service.MemberServiceImpl;
import kr.or.ddit.vo.MemberVO;

@WebServlet("/memDetail.do")
public class MemDetail extends HttpServlet {
	private static final long serialVersionUID = 1L;
	private IMemberService service = MemberServiceImpl.getInstance();

	protected void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		String id = request.getParameter("id");
		// detail화면과 update화면으로 가는 판별 파라미터
		String update = request.getParameter("update");

		MemberVO memVo = service.getMemInfo(id);

		List<MemberVO> list = new ArrayList<MemberVO>();
		list.add(memVo);
		
		// getAttribute는 String 값으로 전달되어 MemberVO객체로 변환이 안되기 때문에
		// Collection으로 변환 다른 방법이 있는지 공부하기 -----------------------------------<
		request.setAttribute("mem", list);
		if (update.equals("true")) { // true시 update
			request.getRequestDispatcher("/view/memUpdate.jsp").forward(request, response);
		} else {
			request.getRequestDispatcher("/view/memDetail.jsp").forward(request, response);
		}
	}

	protected void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		// TODO Auto-generated method stub
		doGet(request, response);
	}

}

image Servlet

프로젝트 폴더 밖에있는 이미지를 출력하기 위한 서블릿

package kr.or.ddit.member.controller;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
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;


@WebServlet("/image.do")
public class Image extends HttpServlet {
	private static final long serialVersionUID = 1L;
       
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.setCharacterEncoding("utf-8");
		
		// 업로드된 파일들이 저장된 폴더 설정
		String uploadPath = "d:/d_other/memberImage"; // 서버 위치

		File file = new File(uploadPath);
		if(!file.exists()) {
			file.mkdirs();
		}
		
		// 파라미터로 넘어온 파일번호를 받는다
		String photo = request.getParameter("photo");
		
		// 파일번호를 이용하여 DB에서 해당 파일 정보를 가져온다.
		

		response.setCharacterEncoding("utf-8");
		
		// 보여줄 이미지 파일 정보를 갖는 File객체를 생성. ==> 실제 저장된 파일명을 지정하여 생성한다.
		File downFile = new File(file, photo);
		
		if(downFile.exists()) {// 다운 받을 파일이 있을 때
			// 이 이후에 작업은 서버에 저장된 파일을 읽어서 클라이언트에게 보내준다 (일종의 입출력작업)
			BufferedOutputStream bout = null;
			BufferedInputStream bin = null;
			
			try {
				// 출력용 스트림 객체 생성
				bout = new BufferedOutputStream(response.getOutputStream());
				
				// 파일 입력용 스트림 객체 생성
				bin = new BufferedInputStream(new FileInputStream(downFile));
				
				byte[] temp = new byte[1024];
				
				int len = 0;
				while((len = bin.read(temp)) > 0) {
					bout.write(temp, 0, len);
				}
				bout.flush();
			}catch (Exception e) {
				// TODO: handle exception
				System.out.println("입출력 오류 : "+e.getMessage());
			} finally {
				if(bout!=null) try {bout.close();}catch(IOException e) {}
				if(bin!=null) try {bin.close();}catch(IOException e) {}
			}
			
		} else { // 없을 때
		}
		
}

	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		// TODO Auto-generated method stub
		doGet(request, response);
	}

}

memUpdate Servlet

만약 파일이 없을 시 기존의 파일로 그대로 다시 저장

파일이 변경 시엔 기존에 있던 파일 삭제

package kr.or.ddit.member.controller;

import java.io.File;
import java.io.IOException;
import java.util.UUID;

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

import kr.or.ddit.member.service.IMemberService;
import kr.or.ddit.member.service.MemberServiceImpl;
import kr.or.ddit.vo.MemberVO;

@MultipartConfig(fileSizeThreshold = 1024 * 1024 * 10, // 10 mb
maxFileSize = 1024 * 1024 * 30, maxRequestSize = 1024 * 1024 * 200)
@WebServlet("/memUpdate.do")
public class MemUpdate extends HttpServlet {
	private static final long serialVersionUID = 1L;
	private IMemberService service = MemberServiceImpl.getInstance();
       
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
	}

	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		// POST 방식으로 요청하면 Upload된 파일을 받아서 처리한다
		request.setCharacterEncoding("utf-8");

		// 업로드된 파일들이 저장될 폴더 설정
		String uploadPath = "d:/d_other/memberImage"; // 서버 위치

		// 저장될 폴더가 없으면 새로 만들어준다
		File file = new File(uploadPath);
		if (!file.exists()) {
			file.mkdirs();
		}

		MemberVO memVo = new MemberVO();
		memVo.setMem_id(request.getParameter("mem_id"));
		memVo.setMem_pass(request.getParameter("mem_pass"));
		memVo.setMem_name(request.getParameter("mem_name"));
		memVo.setMem_addr(request.getParameter("mem_addr"));
		memVo.setMem_tel(request.getParameter("mem_tel"));
		Part part = request.getPart("mem_photo");
		if (part != null && part.getSize() > 0) {
		    // 파일이 제출시
			
			// 해당 파일명의 이름 찾기
			String fileName = ""; // 반환값이 저장될 변수
			
			String dispositionValue = part.getHeader("content-disposition");
			String[] items = dispositionValue.split(";");
			for(String item : items) {
				if(item.trim().startsWith("filename")) { // 파일 정보가 있는지 검사
					fileName = item.substring(item.indexOf("=") + 2, item.length() - 1);
				}
			}
			// 실제 저장되는 파일 이름이 중복되는 것을 방지하기 위해서 UUID를 이용하여 저장할 파일명을 만든다.
			String saveFileName = UUID.randomUUID().toString() + "_" + fileName;
			System.out.println(fileName);
			memVo.setMem_photo(saveFileName);
			try {
				// 파일 저장
				part.write(uploadPath + File.separator + saveFileName);
			} catch (Exception e) {
				// TODO: handle exception
				e.printStackTrace();
			}
			// 이전파일 삭제
			File oldFile = new File(uploadPath, request.getParameter("backup"));
			oldFile.delete();
		} else {
		    // 파일이 제출X
		}
		
		int cnt = service.updateMember(memVo);
		response.setCharacterEncoding("utf-8");
		response.setContentType("text/html; charset=utf-8");
		response.sendRedirect(request.getContextPath()+"/memList.do");

	}
}

memDelete Servlet

package kr.or.ddit.member.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 kr.or.ddit.member.service.IMemberService;
import kr.or.ddit.member.service.MemberServiceImpl;

@WebServlet("/memDelete.do")
public class MemDelete extends HttpServlet {
	private static final long serialVersionUID = 1L;
	private IMemberService service = MemberServiceImpl.getInstance();
	
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		String id = request.getParameter("id");
		
		// 해당 id 삭제
		int cnt = service.deleteMember(id);
		response.sendRedirect(request.getContextPath()+"/memList.do");
	}

	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		// TODO Auto-generated method stub
		doGet(request, response);
	}

}

JSP

main.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<a href="<%=request.getContextPath()%>/memList.do">회원 목록 보기</a>
</body>
</html>

memList.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"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<script src="<%=request.getContextPath()%>/js/jquery-3.7.1.js"></script>
<script>
$(function(){
	$('#sign').on('click',function(){
		location.href = "<%=request.getContextPath()%>/view/memSign.jsp";
	})
})
</script>
</head>
<body>
<h3>회원 목록 보기</h3>
<br>
<table border="1">
<tr>
<td colspan="5" style="text-align : right">
	<input type="button" id="sign" value="회원추가">
</td>
</tr>
<tr>
	<th>ID</th>
	<th>비밀번호</th>
	<th>이 름</th>
	<th>전 화</th>
	<th>주 소</th>
</tr>
<% 
	List<MemberVO> list = (List<MemberVO>) request.getAttribute("list");
	
	if(list==null || list.size()==0){
	%>
<tr>
	<td colspan="5" style="text-align : center">회원 정보가 없습니다</td>
</tr>
	
	
	<%	
	} else{
	
		for(MemberVO vo : list){
%>
<tr><!-- a태그에 get방식으로 id값과 update(어떤 jsp로 가는지 판단여부)파라미터 추가 -->
	<td><a href="<%=request.getContextPath() %>/memDetail.do?id=<%=vo.getMem_id() %>&update=false"><%=vo.getMem_id() %></a></td>	
	<td><%=vo.getMem_pass() %></td>	
	<td><%=vo.getMem_name() %></td>	
	<td><%=vo.getMem_tel() %></td>	
	<td><%=vo.getMem_addr() %></td>	
</tr>
<% 
		} // for문
	} // if문
%>
</table>
</body>
</html>

memSign.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<script src="<%=request.getContextPath()%>/js/jquery-3.7.1.js"></script>
<script>
// 중복확인 여부 전역변수
let idChk = "false"
$(function(){
	$('#list').on('click',function(){
		location.href = "<%=request.getContextPath()%>/memList.do";
	})
	$('#idChk').on('click',function(){
		let vid = $('#id').val().trim();
		console.log(vid);
		$.ajax({
			url : "<%=request.getContextPath() %>/idChk.do",
			type : "GET",
			data : { id : vid },
			success : function(data){
				if(data>0){
					alert('이미 있는 아이디입니다.')
				} else {
					// 중복확인 후 전역변수 변환
					idChk = "true";
					console.log(idChk);
					$('#id').css("border", "3px solid green");
				}
			},
			error : function(xhr){
				alert("오류 코드 : "+xhr.status);
			},
			dataType : "html"
		})
	})
	$('#insert').on('click',function(){
		let pw1 =$('#pw').val();
		let pw2 =$('#pw2').val();
		if(pw1!=pw2){
			alert('비밀번호가 다릅니다');
			return false;
		} else if(pw1==""||pw2==""){
			alert('비밀번호 입력해주세요');
			return false;
		}
		if(idChk == "false"){ 
			alert('중복검사를 하지않았습니다');
			return false;
		}
	})
	// 중복검사 후에 id값이 변경되었다면 다시 중복검사를 위해 변경
	$('#id').on('change',function(){
		idChk = "false";
		console.log(idChk);
		$('#id').css("border", "3px solid red");
	})
})
</script>
</head>
<body>
<h3>회원 정보 입력 폼</h3>
<br>
<!-- 파일 추가시 꼭 method=post와 enctype설정 필요-->
<form method="post" enctype="multipart/form-data" action="<%=request.getContextPath()%>/memSign.do">
<table border="1">
<tr>
	<td>회원ID</td>
	<td><input id="id" name="mem_id"> <input type="button" id="idChk" value="중복검사"></td>
</tr>
<tr>
	<td>비밀번호</td>
	<td><input id="pw" name="mem_pass" type="password"></td>
</tr>
<tr>
	<td>비밀번호 확인</td>
	<td><input id="pw2" name="mem_pass2" type="password"></td>
</tr>
<tr>
	<td>회원이름</td>
	<td><input id="name" name="mem_name"></td>
</tr>
<tr>
	<td>전화번호</td>
	<td><input id="tel" name="mem_tel"></td>
</tr>
<tr>
	<td>회원주소</td>
	<td><input id="addr" name="mem_addr"></td>
</tr>
<tr>
	<td>프로필 사진</td>
	<td><input id="file" name="mem_photo" type="file"></td>
</tr>
<tr>
<td colspan="2" style="text-align : center">
<input type="submit" value="저장" id="insert">
<input type="button" value="취소" id="cancel">
<input type="button" value="회원목록" id="list">
</td>
</tr>
</table>
</form>
</body>
</html>

memDetail.jsp

<%@page import="java.util.List"%>
<%@page import="kr.or.ddit.vo.MemberVO"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<script src="<%=request.getContextPath()%>/js/jquery-3.7.1.js"></script>
<%
//getAttribute 로  vo객체 불러올수 없어서 list로 설정
List<MemberVO> list = (List<MemberVO>) request.getAttribute("mem");	
for(MemberVO vo : list){
%>
<script>
$(function(){
	$('#list').on('click',function(){
		location.href = "<%=request.getContextPath()%>/memList.do";
	})
	$('#delete').on('click',function(){
		$.ajax({
			url : `<%=request.getContextPath()%>/memDelete.do`,
			data : { id : "<%=vo.getMem_id()%>"},
			type : "post",
			success : function(data){
				// 삭제 성공시 전체 리스트로 이동
				location.href = "<%=request.getContextPath()%>/memList.do";
			},
			error : function(xhr){
				alert(xhr.status);
			}
		})
	})
	$('#update').on('click',function(){
		// update화면으로 이동 (update=true일때)
		location.href = "<%=request.getContextPath()%>/memDetail.do?id=<%=vo.getMem_id()%>&update=true";
	})
})
</script>
</head>
<body>
<h3>회원 정보 상세보기</h3>
<table border="1">
<tr>
<td colspan="2">
	<!-- 해당 이미지를 출력하기 위해서 photo(파일이름) 보내어 사진 출력 -->
	<img src="<%=request.getContextPath() %>/image.do?photo=<%=vo.getMem_photo() %>">
</td>
</tr>
<tr>
	<td>회원ID</td>
	<td><%=vo.getMem_id() %></td>
</tr>
<tr>
	<td>비밀번호</td>
	<td><%=vo.getMem_pass() %></td>
</tr>
<tr>
	<td>회원이름</td>
	<td><%=vo.getMem_name() %></td>
</tr>
<tr>
	<td>전화번호</td>
	<td><%=vo.getMem_tel() %></td>
</tr>
<tr>
	<td>회원주소</td>
	<td><%=vo.getMem_addr() %></td>
</tr>
<td colspan="2" style="text-align : center">
<input type="button" value="수정" id="update">
<input type="button" value="삭제" id="delete" >
<input type="button" value="회원목록" id="list">
</td>
</table>
<% }%>
</body>
</html>

memUpdate.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"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<script src="<%=request.getContextPath()%>/js/jquery-3.7.1.js"></script>
<%
// getAttribute 로  vo객체 불러올수 없어서 list로 설정
List<MemberVO> list = (List<MemberVO>) request.getAttribute("mem");
for(MemberVO vo : list){
%>
<script>
$(function(){
	$('#list').on('click',function(){
		location.href = "<%=request.getContextPath()%>/memList.do";
	})
	$('#cancel').on('click',function(){
		location.href = "<%=request.getContextPath()%>/memDetail.do?id=<%=vo.getMem_id()%>&update=false";
	})
	$('#update').on('click',function(){
		let pass = $('#pw').val().trim();
		if(pass==""){
			alert('비밀번호를 입력하세요');
			return false;
		}
	})
})
</script>
</head>
<body>
<h3>회원 정보 입력 폼</h3>
<br>
<form method="post" enctype="multipart/form-data" action="<%=request.getContextPath()%>/memUpdate.do">
<table border="1">
<td colspan="2">
	<img src="<%=request.getContextPath() %>/image.do?photo=<%=vo.getMem_photo() %>">
</td>
<tr>
	<td>회원ID</td>
	<td><input id="id" name="mem_id" value="<%=vo.getMem_id() %>" readonly="readonly"></td>
</tr>
<tr>
	<td>비밀번호</td>
	<td><input id="pw" name="mem_pass" type="password"></td>
</tr>
<tr>
	<td>회원이름</td>
	<td><input id="name" name="mem_name" value="<%=vo.getMem_name() %>"></td>
</tr>
<tr>
	<td>전화번호</td>
	<td><input id="tel" name="mem_tel" value="<%=vo.getMem_tel() %>"></td>
</tr>
<tr>
	<td>회원주소</td>
	<td><input id="addr" name="mem_addr" value="<%=vo.getMem_addr() %>"></td>
</tr>
<tr>
	<td>프로필 사진</td>
	<td><input id="file" name="mem_photo" type="file"></td>
</tr>
<tr>
<td colspan="2" style="text-align : center">
<input type="submit" value="저장" id="update">
<input type="button" value="취소" id="cancel">
<input type="button" value="회원목록" id="list">
</td>
</tr>
</table>
<!-- 이전 파일 삭제를 위한 hidden으로 백업 -->
<input hidden name="backup"  value="<%=vo.getMem_photo() %>" >
</form>
<% }%>
</body>
</html>