spring framework 3 파일 업로드 (검색기능 추가)

limchard·2023년 11월 1일
0

spring framework

목록 보기
4/5

초기세팅

pom.xml에 아래 코드 추가

		<!-- fileUpload -->
		<!-- https://mvnrepository.com/artifact/commons-io/commons-io -->
		<dependency>
		    <groupId>commons-io</groupId>
		    <artifactId>commons-io</artifactId>
		    <version>2.4</version>
		</dependency>
		
		<!-- https://mvnrepository.com/artifact/commons-fileupload/commons-fileupload -->
		<dependency>
		    <groupId>commons-fileupload</groupId>
		    <artifactId>commons-fileupload</artifactId>
		    <version>1.3.1</version>
		</dependency>


servlet-context.xml 에 파일 업로드 관련 설정하기

	<!-- 위치 상관 x
		 file_upload setting
		 class multipartresolver 자동완성해서 불러온 후 id 하면 자동완성 -->
	<beans:bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
		<!-- encoding -->
		<beans:property name="defaultEncoding" value="utf-8"/>
		<!-- 파일크기 설정 5000000->3mb.. 1024*1024 이런 수식 사용 불가능 -->
		<beans:property name="maxUploadSize" value="5000000"/>
	</beans:bean>

servlet-context.xml 수정

	<!-- DispatcherServlet Context: defines this servlet's request-processing infrastructure -->
	
	<!-- Enables the Spring MVC @Controller programming model -->
	<annotation-driven />
	
	<!-- file_upload setting -->
	<beans:bean class="org.springframework.web.multipart.commons.CommonsMultipartResolver" id="multipartResolver">
		<beans:property name="defaultEncoding" value="utf-8"/>
		<beans:property name="maxUploadSize" value="5000000"/> <!-- 이게 약 5MB_문자열 안먹혀서 1024*1024 이런거 불가능함. -->
	</beans:bean>

	// 아래는 이미지 파일 경로 지정하기 
	<!-- Handles HTTP GET requests for /resources/** by efficiently serving up static resources in the ${webappRoot}/resources directory -->
	<resources mapping="/res/**" location="/resources/" />
	<resources mapping="/photo/**" location="/resources/image/" />
	<resources mapping="/upload/**" location="/WEB-INF/photo/" />

	// 아래는 기본 mapping 주소 지정하기
	<!-- Resolves views selected for rendering by @Controllers to .jsp resources in the /WEB-INF/views directory -->
	<beans:bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
		<beans:property name="prefix" value="/WEB-INF/" />
		<beans:property name="suffix" value=".jsp" />
	</beans:bean>
	
    // context : 기본 설정 package지정하기. *를 사용하면 일일이 지정이 아니라 겹치는 부분은 한번에 지정해줄 수 있음
	<context:component-scan base-package="spring.mvc.*,board.data.controller" />

</beans:beans>

infoMapper.xml

  • Mapper 에서 if는 <'if test=(조건)'><'/if'> 를 사용한다.
  • <'if'>는 해당시에 발생하고 해당하지 않으면 발생 안하므로 해당 유,무가 갈리는 부분만 지정하여 작성한다.
  • 검색관련 select 에서는 분류해줄 ${title}과 내가 기입한 값인 #{serch}를 넘겨줘야 한다.
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
  PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
  "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
  
  
<mapper namespace="spring.mvc.friday.InfoDao">
	<select id="selectTotalCountOfMyInfo" resultType="int">
		select count(*) from myinfo
	</select>
	<insert id="insertOfMyInfo" parameterType="idto">
		insert into myinfo(name,driver,addr,photo,gaipday) values(#{name},#{driver},#{addr},#{photo},now())
	</insert>
	<!-- <select id="selectAllOfMyInfo" resultType="idto">
		select * from myinfo order by num
	</select> -->
	<select id="selectOneOfMyInfo" resultType="idto" parameterType="String">
		select * from myinfo where num=#{num}
	</select>
	<update id="updateOfMyInfo" parameterType="idto">
		update myinfo set name=#{name},driver=#{driver},addr=#{addr}
		<!-- <if test="photo!='no'"></if> -->
		<if test="photo!=null">
			,photo=#{photo} 	
		</if>
		where num=#{num}
	</update>
	
	<delete id="deleteOfMyInfo" parameterType="String">
		delete from myinfo where num=#{num}
	</delete>
	
	
	<!-- 검색 리스트 -->
	<select id="selectAllOfMyInfo" resultType="idto" parameterType="Map">
	<!-- parameterType의 경우 이름과 serch에서 각각 넘어와 총 2개가 넘어와야하므로 Map을 사용한다. -->
		select * from myinfo
		<if test="serch!=null">
			where ${title} like concat('%',#{serch},'%') <!--  --> 
			<!-- ${title} 이 의미하는 것은 column이다. -->
			<!-- like('*',?,'*') 원래는 이렇게 썼었는데.. 
				검색은 오른쪽처럼 쓴다. where {검색기준이 될 필드명} link concat('%',?,'%')
			-->
		</if>
		order by num asc
	</select>
</mapper>

InfoInter.java

  • Mapper에서 ${title}과 #{serch} 2개의 값을 넘겨받아야 하기 때문에 검색용 List에서 Parameter값을 Map으로 받는다. (2개 받을때는 Map을 사용한다고 생각하면 편할듯 하다.)
package spring.mvc.friday;

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

public interface InfoInter {

	public int getTotalCount();
	
	public void insertMyInfo(InfoDto idto);
	
    // 일반 전체 출력.. 아래 검색용으로 대체함
	// public List<InfoDto> getAllDataOfMyInfo();
	
	public InfoDto getData(String num);
	
	public void updateMyInfo(InfoDto idto);
	
	public void deleteInfo(String num);
	
	// 검색용
	public List<InfoDto> getAllDataOfMyInfo(Map<String, String> map);
	
}

InfoDao.java

package spring.mvc.friday;

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

import org.apache.ibatis.session.SqlSession;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;

@Repository
public class InfoDao implements InfoInter {

	// sql팩토리로부터 만들어지는 sqlSession을 가지고 온다.
	@Autowired
	SqlSession session;
	
	@Override
	public int getTotalCount() {
		// TODO Auto-generated method stub
		return session.selectOne("selectTotalCountOfMyInfo");
	}
	
	@Override
	public void insertMyInfo(InfoDto idto) {
		// TODO Auto-generated method stub
		session.insert("insertOfMyInfo", idto);
	}
	
//	@Override
//	public List<InfoDto> getAllDataOfMyInfo() {
//		// TODO Auto-generated method stub
//		return session.selectList("selectAllOfMyInfo");
//	}
	
	@Override
	public InfoDto getData(String num) {
		// TODO Auto-generated method stub
		return session.selectOne("selectOneOfMyInfo", num);
	}
	
	@Override
	public void updateMyInfo(InfoDto idto) {
		// TODO Auto-generated method stub
		session.update("updateOfMyInfo", idto);
	}
	
	@Override
	public void deleteInfo(String num) {
		// TODO Auto-generated method stub
		session.delete("deleteOfMyInfo", num);
	}
	
    // 검색용 출력..
	@Override
	public List<InfoDto> getAllDataOfMyInfo(Map<String, String> map) {
		// TODO Auto-generated method stub
		return session.selectList("selectAllOfMyInfo", map);
	}
}

InfoController.java

  • @RequestParam(defaultValue="name") String title : 검색기능으로 인해 초기값을 지정해주지 않으면 오류가 발생한다. 이에 초기값을 name으로 지정해 준 것이다.
  • @RequestParam(Required = false) String serch : 검색기능으로 인해 초기값을 지정해주지 않으면 오류가 발생한다. 어쨌든 오류가 안나게 해준다. 약간 예외처리같은 느낌이다.
package spring.mvc.friday;

import java.io.File;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpSession;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.servlet.ModelAndView;

@Controller
public class InfoController {
	
	@Autowired
	InfoDao idao;
	
	@Autowired
	InfoInter inter;
	
	@GetMapping("/info/list")
	public ModelAndView list(@RequestParam(defaultValue = "name")String title, @RequestParam(required = false)String serch) {
		// @RequestParam(defaultValue="name") String title : 검색기능으로 인해 초기값을 지정해주지 않으면 오류가 발생한다. 이에 초기값을 name으로 지정해 준 것이다.
        // @RequestParam(Required = false) String serch : 검색기능으로 인해 초기값을 지정해주지 않으면 오류가 발생한다. 이에 초기값을 false로 지정해 준 것이다.
        
		ModelAndView mview=new ModelAndView();
		int totalCount=idao.getTotalCount();
		
//		List<InfoDto> list=inter.getAllDataOfMyInfo();
		System.out.println(title+","+serch);
		
		Map<String, String> map=new HashMap<String, String>();
		map.put("serch", serch);
		map.put("title", title);
		
		List<InfoDto> list=inter.getAllDataOfMyInfo(map);
		
		mview.addObject("count", totalCount);
		mview.addObject("list",list);
		
		mview.setViewName("/info/infolist");
		
		return mview;
	}
	
	@GetMapping("/info/addform")
	public String addform() {
		
		return "info/addForm";
	}
	
	@PostMapping("/info/insert")
	public String insert(@ModelAttribute InfoDto idto, @RequestParam MultipartFile upload, HttpSession session) {
		
        // HttpServletRequest 에 realPath 를 찾기 위해서 한다.
        
        // 업로드할 실제 경로 구하기
		String path=session.getServletContext().getRealPath("/resources/image/");
		System.out.println(path);
		
        // 사진 여러개 올리기 위해서 (현재 날짜와 시간 이용하여 파일명 겹치는거 방지하기)
		SimpleDateFormat sdf=new SimpleDateFormat("yyyyMMddHHmmss");
		
		String photo="";
		
		// 사진선택을 안했을 경우 no.. 
		if(upload.getOriginalFilename().equals("")) {
//			photo=null;
			photo="no";
		} else {
			
			String fName=upload.getOriginalFilename();
			fName=sdf.format(new Date())+"_"+fName;
			photo=fName;
			
			// 업로드
			try {
				upload.transferTo(new File(path+"/"+photo));
			} catch (IllegalStateException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			
		}
		
		// dto의 Photo에 업로드 한 것을 넣어줘야 한다.
					idto.setPhoto(photo);
					
					// insert
					inter.insertMyInfo(idto);
		
		return "redirect:list";
	}
	
	@GetMapping("/info/uform")
	public String uform(@RequestParam String num,Model model) {
		InfoDto idto=inter.getData(num);
		
		model.addAttribute("idto", idto);
		
		return "info/updateform";
	}
	
	@PostMapping("/info/update")
	public String update(@ModelAttribute InfoDto idto,@RequestParam MultipartFile upload,HttpSession session,String num) {
		String path=session.getServletContext().getRealPath("/resources/image/");
		System.out.println(path);
		
		SimpleDateFormat sdf=new SimpleDateFormat("yyyyMMddHHmmss");
		
		String photoname; // dto에 담을 변수
				
		// 기존사진삭제
		String photo=inter.getData(num).getPhoto();
				
		if(!photo.equals("no")) {
					
			File file=new File(path+"/"+photo); // 이미지중에 내가 고른 사진
			file.delete();
		}
		
		// 사진 선택안할경우 null
		if(upload.getOriginalFilename().equals("")) {
			photoname=null;
		} else {
			photoname=upload.getOriginalFilename();
			photoname=sdf.format(new Date())+"_"+photoname;
			
			// 업로드
			try {
				upload.transferTo(new File(path+"/"+photoname));
			} catch (IllegalStateException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		
	// dto의 Photo에 Upload한 photoname을 넣어준다.
		idto.setPhoto(photoname);
		
		//update
		inter.updateMyInfo(idto);
		
		return "redirect:list";
	}
	
	@GetMapping("/info/delete")
	public String deleteInfo(@RequestParam String num,HttpSession session) {
		
		// 파일삭제
		String photo=inter.getData(num).getPhoto();
		
		if(!photo.equals("no")) {
			String path=session.getServletContext().getRealPath("/resources/image/"); 
			
			File file=new File(path+"/"+photo); // 이미지중에 내가 고른 사진
			file.delete();
		}
		
		// db삭제
		inter.deleteInfo(num);
		
		return "redirect:list";
	}
}

infolist.jsp

<body>

	<h2 class="alert alert-danger" style="margin: 20px 20px;">총 ${count }개의 정보가 있습니다.</h2>
	<button type="button" class="btn btn-outline-info" onclick="location.href='addform'" style="margin: 20px 20px;">글쓰기</button>

	<table class="table table-bordered" style="width: 800px;">
		<tr>
			<th>no.</th>
			<th>이름</th>
			<th>사진</th>
			<th>운전면허</th>
			<th>주소</th>
			<th>작성일</th>
			<th>편집</th>
		</tr>
		<c:forEach var="idto" items="${list }" varStatus="i">
			<tr>
				<td align="center">${i.count }</td>
				<td align="center">${idto.name }</td>
				<td align="center">
					<c:if test="${idto.photo=='no' }">
						<img alt="" src="../photo/noimage.jpg" width="50" class="img-circle">
					</c:if>
					<c:if test="${idto.photo!='no' }">
						<img alt="" src="../photo/${idto.photo }" width="50" class="img-circle">
					</c:if>
				</td>
				<td>${idto.driver }</td>
				<td>${idto.addr }</td>
				<td>
					<fmt:formatDate value="${idto.gaipday }" pattern="yyyy-MM-dd HH:mm"/>
				</td>
				<td>
					<button type="button" class="btn btn-outline-warning btn-sm" onclick="location.href='uform?num=${idto.num}'">수정</button>
					<button type="button" class="btn btn-outline-danger btn-sm" onclick="location.href='delete?num=${idto.num}'">삭제</button>
				</td>
			</tr>
		</c:forEach>
	</table>
	
	<div style="width: 900px; text-align: center;" >
		<form action="list" class="d-inline-flex">
			<select name="title" class="form-control" style="width: 120px;">
				<option value="name" ${title=='name'?"selected":"" }>이름</option>
				<option value="addr" ${title=='addr'?"selected":"" }>주소</option>
				<option value="driver" ${title=='driver'?"selected":"" }>운전면허</option>
			</select>
			<input type="text" name="serch" class="form-control" placeholder="검색단어" style="width: 150px;" value="${serch }">
			<button type="submit" class="btn btn-success">검색</button>
		</form>
	</div>
</body>

addForm.jsp

<body>
	
	<form action="insert" method="post" enctype="multipart/form-data">
		<table class="table table-bordered" style="width: 400px;">
			<caption align="top"><b>개인정보 입력</b></caption>
			<tr>
				<th>이름</th>
				<td>
					<input type="text" name="name" class="form-control" style="width: 120px;" required="required">
				</td>
			</tr>
			<tr>
				<th>운전면허</th>
				<td>
					<input type="radio" name="driver" value="있음">있음&nbsp;&nbsp;
					<input type="radio" name="driver" value="없음" checked="checked">없음
				</td>
			</tr>
			<tr>
				<th>주소</th>
				<td>
					<input type="text" name="addr" class="form-control" style="width: 250px;" required="required">
				</td>
			</tr>
			<tr>
				<th>사진</th>
				<td>
					<input type="file" name="upload" class="form-control" style="width: 200px;">
				</td>
			</tr>
			<tr>
				<td colspan="2" align="center">
					<button type="submit" class="btn btn-outline-info">저장</button>
					<button type="button" class="btn btn-outline-success" onclick="location.href='list'">목록</button>
				</td>
			</tr>
		</table>
	</form>
</body>

updateform.jsp

<body>
	
	<form action="update" method="post" enctype="multipart/form-data">
	<input type="hidden" name="num" value="${idto.num }">
		<table class="table table-bordered" style="width: 400px;">
			<caption align="top"><b>개인정보 수정</b></caption>
			<tr>
				<th>이름</th>
				<td>
					<input type="text" name="name" class="form-control" style="width: 120px;" required="required" value="${idto.name }">
				</td>
			</tr>
			<tr>
				<th>운전면허</th>
				<td>
					<input type="radio" name="driver" value="있음" ${idto.driver=='있음'?"checked":"" }>있음&nbsp;&nbsp;
					<input type="radio" name="driver" value="없음" ${idto.driver=='없음'?"checked":"" }>없음
				</td>
			</tr>
			<tr>
				<th>주소</th>
				<td>
					<input type="text" name="addr" class="form-control" style="width: 250px;" required="required" value="${idto.addr }">
				</td>
			</tr>
			<tr>
				<th>사진</th>
				<td>
					<input type="file" name="upload" class="form-control" style="width: 200px;">
				</td>
			</tr>
			<tr>
				<td colspan="2" align="center">
					<button type="submit" class="btn btn-outline-info">저장</button>
					<button type="button" class="btn btn-outline-success" onclick="location.href='list'">목록</button>
				</td>
			</tr>
			
		</table>
	</form>
	
</body>

profile
java를 잡아...... 하... 이게 맞나...

0개의 댓글