목차는 아래와 같다.
1. 이미지 업로드
1) V
2) C
3) M
2. 예외처리
1) @활용
2) xml활용
1. 이미지 업로드
각 파트별 수행할 행동으로 나누어 설명할 예정이다.
1) V
① form 생성
파일을 업로드할 수 있는 form을 생성하고, 이미지의 경우 인코딩설정이 필요하다. 이때 controller에서 해당 파일을 전달 받을 수 있도록 name설정이 반드시 필요하다. 예시코드는 아래와 같다.
<form action="insert.do" method="POST" enctype="multipart/form-data"><!-- 이미지 인코딩설정 -->
<input type="file" name="img_tattoo"/>
</from
2) C
파일을 받는데에는 총 두가지의 방법이 있다. 포스팅의 경우 두 번째 방법으로 시행한다.
1) @requestParameter을 인자로 추가하기
2) vo내부에 그냥 받아올 수 있도록 쓰기
① VO추가
기존의 데이터들을 String 타입으로 관리하지만, 스프링 프레임 워크에서 제공하는 MultipartFile타입으로 인코딩 된 데이터를 관리해야한다. 임폴트가 필요하다.
package com.ham.app.vo;
import org.springframework.web.multipart.MultipartFile;
public class ArticleVO {
// 멤버변수
private MultipartFile uploadFile; //타투 이미지
// getter & setter
public MultipartFile getUploadFile() {
return uploadFile;
}
public void setUploadFile(MultipartFile uploadFile) {
this.uploadFile = uploadFile;
}
// to string
@Override
public String toString() {
return "ArticleVO [uploadFile=" + uploadFile + "]";
}
}
② 라이브러리 추가
MultipartFile타입의 등장으로 라이브러리가 필요하다. pom.xml에 추가될 코드는 아래와 같다.
<!-- 파일업로드 -->
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.3.1</version>
</dependency>
<!-- ============================================== -->
첨부된 이미지와 같이 라이브러리가 추가되었다면 설정 설공이다.
③ Resolver추가
MultipartFile타입을 다루기 위한 Resolver가 필요해진다. dispatcherServlet-servlet.xml파일에 추가된 설정 코드는 다음과 같다. 주석을 통해 내용 이해가 가능하다.
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.2.xsd">
<context:component-scan base-package="com.ham.app.controller"/>
<!-- 파일업로드 설정 --> <!-- id가 지정되어있기 때문에, 해당 id가 아니라면 설정 등록이 안될지 모른다. -->
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<property name="maxUploadSize" value="-1"/><!-- 무제한! : 디폴트 설정이라 작성하지 않아도 동일한 값을 부여한다. -->
</bean>
</beans>
④ 로직 추가
transferTo메서드를 활용하여 지정한 위치에 파일을 생성해줄 수 있다.
@RequestMapping(value = "/insert.do")
public String insert_article (ArticleVO vo, ArticleDAO dao) throws IllegalStateException, IOException {
//파일 업로드 로직
MultipartFile uploadFile=vo.getUploadFile();
// 비어있지 않다면, 로직 수행
if(!uploadFile.isEmpty()) {// !=null로도 체크 가능하지만, 해당 방법을 더 선호하기도 함
//파일명
String name=uploadFile.getOriginalFilename();
vo.setFilename(name);
uploadFile.transferTo(new File("/Users/hamjeonghui/Desktop/java/workspace_2/tni/src/main/webapp/img_tattoo/"+name)); // 인자로 입력된 위치에 파일을 생성해주는 메서드이다.
}
boolean flag=dao.insert_article(vo);
if(flag==true) { //성공
return "redirect: main.do"; //해당 디테일 페이지로 이동
}else { //실패
return "redirect: main.do";
}
}
3) M
파일명을 가지고 다닐 칼럼을 추가한다. 이때, vo는 String타입으로 별도로 필요하게 되며 기존에 사용되던 dao의 sql문 등에 수정이 필요하다.
① VO
command객체 활용으로 파일 입출력을 용이하게 할 목적으로 생성한 MultipartFile타입의 멤버변수 외에 table로 가지고 다닐 String 타입의 멤버변수를 추가하여 생성한다. (해당 코드 외에 삭제)
package com.ham.app.vo;
import org.springframework.web.multipart.MultipartFile;
public class ArticleVO {
// 멤버변수
private MultipartFile uploadFile; //타투 이미지
private String filename; //타투 이미지 파일 이름
// getter & setter
public MultipartFile getUploadFile() {
return uploadFile;
}
public void setUploadFile(MultipartFile uploadFile) {
this.uploadFile = uploadFile;
}
public String getFilename() {
return filename;
}
public void setFilename(String filename) {
this.filename = filename;
}
// to string
@Override
public String toString() {
return "uploadFile=" + uploadFile + ", filename=" + filename + "]";
}
}
② DAO
sql문의 insert부분과 update부분을 변경하고, select부분의 rs.getString을 추가한다.
package com.ham.app.dao;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import org.springframework.stereotype.Repository;
import com.ham.app.common.JDBCUtil;
import com.ham.app.vo.ArticleSet;
import com.ham.app.vo.ArticleVO;
import com.ham.app.vo.CommentVO;
@Repository("articleDAO")
// comment의 DAO도 함께 수행할 클래스
public class ArticleDAO {
//트랜잭션: executeQuery,executeUpdate()등의 sql문 적용을 하나의 작업처리단위로 수행해야할때 사용
// -> 하나의 dao비즈니스메서드() 안에서 여러번 sql문을 수행해야할때 사용
private Connection conn=null;
private PreparedStatement pstmt=null;
private ResultSet rs= null;
private final String ARTICLE_INSERT="insert into article (uid, uname, title, acontent, part, leadTime, addr, filename) values (?,?,?,?,?,?,?,?)";//댓글 등록
// 게시글 등록
public boolean insert_article(ArticleVO vo) {
boolean flag = false;
conn = JDBCUtil.connect();
try {
pstmt = conn.prepareStatement(ARTICLE_INSERT);
pstmt.setString(1, vo.getUid());
pstmt.setString(2, vo.getUname());
pstmt.setString(3, vo.getTitle());
pstmt.setString(4, vo.getAcontent());
pstmt.setString(5, vo.getPart());
pstmt.setString(6, vo.getLeadTime());
pstmt.setString(7, vo.getAddr());
pstmt.setString(8, vo.getFilename());
// 등록이 성공하면,
if(pstmt.executeUpdate()>0) {
System.out.println("dao: 게시글 등록 성공"+vo.getFilename());
flag = true;
}
} catch (SQLException e) {
e.printStackTrace();
} finally {
JDBCUtil.disconnect(pstmt, conn);
}
return flag;
}
}
package com.ham.app.dao;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import org.springframework.stereotype.Repository;
import com.ham.app.common.JDBCUtil;
import com.ham.app.vo.ArticleSet;
import com.ham.app.vo.ArticleVO;
import com.ham.app.vo.CommentVO;
@Repository("articleDAO")
// comment의 DAO도 함께 수행할 클래스
public class ArticleDAO {
//트랜잭션: executeQuery,executeUpdate()등의 sql문 적용을 하나의 작업처리단위로 수행해야할때 사용
// -> 하나의 dao비즈니스메서드() 안에서 여러번 sql문을 수행해야할때 사용
private Connection conn=null;
private PreparedStatement pstmt=null;
private ResultSet rs= null;
private final String ARTICLE_SELECTALL_FAV="select * from article where aid=? order by aid desc";//aid에 해당하는 게시글 목록
// aid에 해당하는 게시글 목록 보기
public ArticleVO get_article_fav(ArticleVO vo){
System.out.println("해당하는 게시글");
ArticleVO data = new ArticleVO();
conn = JDBCUtil.connect();
try {
pstmt = conn.prepareStatement(ARTICLE_SELECTALL_FAV);
pstmt.setInt(1, vo.getAid());
rs = pstmt.executeQuery();
if(rs.next()) {
data.setAid(rs.getInt("aid"));
data.setUid(rs.getString("uid"));
data.setUname(rs.getString("uname"));
data.setTitle(rs.getString("title"));
data.setAcontent(rs.getString("acontent"));
data.setPart(rs.getString("part"));
data.setLeadTime(rs.getString("leadTime"));
data.setAddr(rs.getString("addr"));
data.setCnt(rs.getInt("cnt"));
data.setFav(rs.getInt("fav"));
data.setRcnt(rs.getInt("rcnt"));
data.setAdate(rs.getString("adate"));
data.setFilename(rs.getString("filename"));
System.out.println("목록불러오는 중");
}
rs.close();
} catch (SQLException e) {
e.printStackTrace();
} finally {
JDBCUtil.disconnect(pstmt, conn);
}
System.out.println("목록 불러오기 완료");
return data;
}
}
설명 외 부분은 삭제하였다.
view에서는 알맞은 EL식을 통해 해당 이미지를 확인할 수 있다.
2. 예외처리
발생한 예외에 대하여 에러페이지로 이동할 수 있도록 하는데에 있어 방법은 @을 활용한 것과 xml을 활용한 것으로 총 두가지가 있다. 보편적으로 xml을 활용한 방법으로 사용되지만, @으로도 적용할 수 있는 방법도 함께 포스팅 하였다.
1) @활용
① 어노테이션 설정
viewResolver의 관여 아래에서 작업되기 때문에 DispatcherServlet-servlet.xml에서 예외 처리를 위한 어노테이션을 설정할 수 있도록 사전처리가 필요하다.
nameSpace에서 mvc를 선택하여 추가해준다.
주석을 통해 기존 코드외 추가 된 내용을 첨부하였다.
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.2.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.2.xsd">
<context:component-scan base-package="com.test.app.controller" />
<!-- 예외 처리 관련 어노테이션 사용을 위한 코드 -->
<mvc:annotation-driven></mvc:annotation-driven>
</beans>
② 에러페이지를 매핑하는 클래스 추가
어떤 예외에 대해 어떤 처리를 할 것인지를 묶어줄 목적으로 클래스를 생성하여, 해당 클래스의 메서드를 통해 처리가 될 수 있도록 한다. 일단 메서드 수행을 위해서는 아래 클래스가 초기화 되어있어야하므로, 어노테이션을 활용하여 초기화를 진행한다. 이때 @Componenet로도 물론 초기화가 가능하지만, @Component를 상속받아 예외와 관련된 설정을 더 효율적으로 수행할 수 있는 @ControllerAdvice를 사용할 수 있다. 다음 순서로 메서드를 작성해주는데, output을 String으로 하여 예외페이지의 경로만 반환해주어도 되지만, 예외에 대한 내용또한 반환해줄 목적이라면 내용도 함께 전달해주어야하므로 output을 ModelAndView로 대체하여 설정해줄 수 있다. 이때 사용되는 @ExceptionHandler를 메서드 상단에 작성해줌으로써 어떤 예외에 대해 어떤 메서드를 수행할 것인지를 지정해줄 수 있다.
package com.test.app.common;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.servlet.ModelAndView;
@ControllerAdvice("com.test.app") // 메서드 수행을 위해 객체화 되어있어야하므로, 어노테이션으로 객체화 진행
public class ExceptionHandlerCommon {
// 어떤 예외에 대해 어떤 처리를 할 것인지를 작성
@ExceptionHandler(IllegalArgumentException.class)//requestMapping과 유사한 역할을 한다.
public ModelAndView a(Exception e) {
// 어떤 페이지로 전달해줄것인지를 작성
ModelAndView mav=new ModelAndView(); //어떤 예외인지를 전달하고자 mav를 사용 -> String으로 경로만 전달하긴 어렵기 때문이다.
mav.addObject("excep", e);
mav.setViewName("/error/error.jsp");
return mav;
}
@ExceptionHandler(Exception.class)//requestMapping과 유사한 역할을 한다.
public ModelAndView b(Exception e) {
// 어떤 페이지로 전달해줄것인지를 작성
ModelAndView mav=new ModelAndView(); //어떤 예외인지를 전달하고자 mav를 사용 -> String으로 경로만 전달하긴 어렵기 때문이다.
mav.addObject("excep", e);
mav.setViewName("/error/error.jsp");
return mav;
}
}
③ 에러페이지
에러페이지의 경우 이 페이지가 에러페이지인지를 명시해주기 위해 페이지 지시어를 활용하여 설정이 가능하다. 또한 .message메서드를 통해 해당 예외에 대한 문구를 확인할 수 있다.
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8" isErrorPage="true"%> <!-- 에러페이지임을 알려주기 -->
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>에러페이지</title>
</head>
<body>
<!-- 예외페이지들은 모두 .message라는 메서드를 통해 예외에 대한 내용을 확인해볼 수 있다. -->
<h1>${excep.message}</h1>
</body>
</html>
2) xml활용
DispatcherServlet-servlet.xml파일에서 모든 설정을 끝낼 수 있다. 주석을 통해 내용을 이해할 수 있으며, error.jsp페이지에 대한 설정은 위와 동일하다.
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.2.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.2.xsd">
<context:component-scan base-package="com.test.app.controller" />
<!-- 예외 관리를 위한 Spring지원 클래스 -->
<bean id="exceptionResolver" class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
<!-- 기본 설정! 어떤 예외에 대해 어떤 페이지를 매핑할 것인지를 설정함 -->
<property name="exceptionMappings">
<props>
<prop key="java.lang.IllegalArgumentException">
error/error.jsp
</prop>
</props>
</property>
<!-- 디폴트 값 생성 -->
<property name="defaultErrorView" value="error/error2.jsp" />
</bean>
</beans>
단, ModelAndView와 같은 별도 설정이 없으므로 view에서 에러에 대한 메세지를 확인하고 싶다면 아래와 같은 EL식을 사용할 수 있다.
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8" isErrorPage="true"%> <!-- 에러페이지임을 알려주기 -->
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>에러페이지</title>
</head>
<body>
<!-- 예외페이지들은 모두 .message라는 메서드를 통해 예외에 대한 내용을 확인해볼 수 있다. -->
<h1>${exception.message}</h1>
</body>
</html>
'Spring' 카테고리의 다른 글
[Mybatis] Mybatis설치 및 개요_DAO3 (0) | 2022.04.18 |
---|---|
다국어 처리 : 국제화 (0) | 2022.04.13 |
[레이어] 비즈니스 컴포넌트 (0) | 2022.04.11 |
[AOP] 트랜잭션 관리자 (2) | 2022.04.08 |
[AOP] 다양한 어노테이션 : Controller_3 (0) | 2022.04.07 |