maxUploadSize: 최대 업로드 가능 파일 크기
maxInMemorySize: 메모리 보관 최대 바이트 크기
defaultEncoding: 매개변수 인코딩
pro28/pom.xml
라이브러리 설정
...
<!-- 파일 업로드 시 필요한 라이브러리 -->
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.2.1</version>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>1.4</version>
</dependency>
<dependencies>
pro28/src/main/webapp/WEB-INF/spring/appServlet/servlet-context.xml
<!-- CommonsMultipartResolver bean -->
<beans:bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<beans:property name="maxUploadSize" value="52428800" />
<beans:property name="maxInMemorySize" value="1000000" />
<beans:property name="defaultEncoding" value="utf-8" />
</beans:bean>
...
pro28/src/main/java/com/myspring/pro28/ex01/FileDownloadController.java
파일 다운로드
package com.myspring.pro28.ex01;
...
@Controller
public class FileDownloadController {
private static String CURR_IMAGE_REPO_PATH = "c:\\spring\\image_repo"; //파일 저장 위치
/* 다운로드 요청 */
@RequestMapping("/download")
public void download( @RequestParam("imageFileName") String imageFileName, HttpServletResponse response ) throws Exception {
OutputStream out = response.getOutputStream();
String downFile = CURR_IMAGE_REPO_PATH + "\\" + imageFileName;
File file = new File(downFile); //다운받을 파일
/* 헤더 설정 */
response.setHeader("Cache-Control", "no-cache");
response.addHeader("Content-disposition", "attachment; fileName=" + imageFileName);
/* 다운로드 */
FileInputStream in = new FileInputStream(file);
byte[] buffer = new byte[1024 * 8];
while (true) {
int count = in.read(buffer);
if (count == -1) break;
out.write(buffer, 0, count);
}
in.close(); out.close();
}
}
pro28/src/main/java/com/myspring/pro28/ex01/FileUploadController.java
파일 업로드
package com.myspring.pro28.ex01;
...
@Controller
public class FileUploadController {
private static final String CURR_IMAGE_REPO_PATH = "c:\\spring\\image_repo";
/* 업로드 창 요청 */
@RequestMapping(value="/form")
public String form() {
return "uploadForm";
}
/* 업로드 요청 */
@RequestMapping(value="/upload", method = RequestMethod.POST)
public ModelAndView upload(MultipartHttpServletRequest multipartRequest, HttpServletResponse response) throws Exception {
multipartRequest.setCharacterEncoding("utf-8");
Map map = new HashMap();
Enumeration enu = multipartRequest.getParameterNames(); //업로드할 파일들
while(enu.hasMoreElements()) {
String name = (String)enu.nextElement();
String value = multipartRequest.getParameter(name);
map.put(name, value);
}
List fileList = fileProcess(multipartRequest); //업로드 호출
/* 결과창 띄우기 */
map.put("fileList", fileList);
ModelAndView mav = new ModelAndView();
mav.addObject("map", map);
mav.setViewName("result");
return mav;
}
/* 업로드 */
private List<String> fileProcess(MultipartHttpServletRequest multipartRequest) throws Exception {
List<String> fileList= new ArrayList<String>(); //실제 파일 이름 목록
Iterator<String> fileNames = multipartRequest.getFileNames(); //파일 목록
while(fileNames.hasNext()) {
String fileName = fileNames.next();
MultipartFile mFile = multipartRequest.getFile(fileName);
String originalFileName = mFile.getOriginalFilename(); //실제 파일 이름
fileList.add(originalFileName);
File file = new File(CURR_IMAGE_REPO_PATH +"\\"+ fileName);
if(mFile.getSize()!=0) {
if(!file.exists() && if(file.getParentFile().mkdirs()) { file.createNewFile(); } //파일 존재 여부 검사 후 파일 생성
mFile.transferTo(new File(CURR_IMAGE_REPO_PATH +"\\"+ originalFileName)); //임시 저장 파일 -> 실제 파일 변환
}
}
return fileList;
}
}
pro28/src/main/webapp/WEB-INF/views/uploadForm.jsp
파일 업로드 창
...
<!DOCTYPE html >
<html>
<head>
<meta "charset=utf-8">
<title>파일 업로드 하기</title>
<script src="http://code.jquery.com/jquery-latest.js"></script>
<script>
/* 업로드할 파일 선택 동적 추가 */
var cnt = 1; //파일 번호
function fn_addFile() {
$("#d_file").append("<br>"+"<input type='file' name='file"+cnt+"' />");
cnt++;
}
</script>
</head>
<body>
<h1>파일 업로드 하기</h1>
<form method="post" action="${contextPath}/upload" enctype="multipart/form-data"> <!-- 파일 업로드 시 multipart/form-data 필수 -->
<label>아이디:</label>
<input type="text" name="id"><br>
<label>이름:</label>
<input type="text" name="name"><br>
<input type="button" value="파일 추가" onClick="fn_addFile()"/><br>
<div id="d_file"> <!-- script를 통해 파일 선택 --> </div>
<input type="submit" value="업로드"/>
</form>
</body>
</html>
pro28/src/main/webapp/WEB-INF/views/result.jsp
업로드 결과창
...
<!DOCTYPE html>
<html>
<head>
<meta "charset=UTF-8">
<title>결과창</title>
</head>
<body>
<h1>업로드가 완료되었습니다.</h1>
<label>아이디:</label>
<input type="text" name="id" value="${map.id}" readonly><br>
<label>이름:</label>
<input type="text" name="name" value="${map.name}" readonly><br>
<!-- 업로드한 이미지 표시 -->
<div class="result-images">
<c:forEach var="imageFileName" items="${map.fileList}" > <!-- FileUploadController > upload 메소드 > map > fileList -->
<img src="${contextPath }/download?imageFileName=${imageFileName }">
<br><br>
</c:forEach>
</div>
<a href='${contextPath }/form'> 다시 업로드 하기 </a>
</body>
</html>
시간 단축을 위해 이미지를 축소하여 표시
pro28/pom.xml
...
<!-- 썸네일 라이브러리 설정 -->
<dependency>
<groupId>net.coobird</groupId>
<artifactId>thumbnailator</artifactId>
<version>0.4.8</version>
</dependency>
<dependencies>
pro28/src/main/java/com/myspring/pro28/ex02/FileDownController.java
package com.myspring.pro28.ex02;
...
import net.coobird.thumbnailator.Thumbnails;
@Controller
public class FileDownloadController {
private static String CURR_IMAGE_REPO_PATH = "c:\\spring\\image_repo";
@RequestMapping("/download")
protected void download(@RequestParam("imageFileName") String imageFileName, HttpServletResponse response) throws Exception {
OutputStream out = response.getOutputStream();
String filePath = CURR_IMAGE_REPO_PATH + "\\" + imageFileName;
File image = new File(filePath);
int lastIndex = imageFileName.lastIndexOf(".");
String fileName = imageFileName.substring(0,lastIndex);
File thumbnail = new File(CURR_IMAGE_REPO_PATH+"\\"+"thumbnail"+"\\"+fileName+".png");
/* 썸네일 생성 */
if (image.exists()) {
thumbnail.getParentFile().mkdirs();
Thumbnails.of(image).size(50,50).outputFormat("png").toFile(thumbnail);
}
/* 썸네일 출력 */
FileInputStream in = new FileInputStream(thumbnail);
byte[] buffer = new byte[1024 * 8];
while (true) {
int count = in.read(buffer);
if (count == -1)
break;
out.write(buffer, 0, count);
}
in.close(); out.close();
}
}
썸네일 이미지 파일 미 생성
pro28/src/main/java/com/myspring/pro28/ex01/FileDownloadController.java
...
@RequestMapping("/download")
protected void download(@RequestParam("imageFileName") String imageFileName, HttpServletResponse response) throws Exception {
OutputStream out = response.getOutputStream();
String filePath = CURR_IMAGE_REPO_PATH + "\\" + imageFileName;
File image = new File(filePath);
int lastIndex = imageFileName.lastIndexOf(".");
String fileName = imageFileName.substring(0,lastIndex);
File thumbnail = new File(CURR_IMAGE_REPO_PATH+"\\"+"thumbnail"+"\\"+fileName+".png");
if(image.exists()) {
Thumbnails.of(image).size(50,50).outputFormat("png").toOutputStream(out);
} else { return; }
byte[] buffer = new byte[1024 * 8];
out.write(buffer);
out.close();
}
}
pro28/pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> <modelVersion>4.0.0</modelVersion>
<groupId>com.myspring</groupId>
<artifactId>pro28</artifactId>
<name>pro28</name>
<packaging>war</packaging>
<version>1.0.0-BUILD-SNAPSHOT</version>
<properties>
<java-version>1.6</java-version>
<org.springframework-version>4.1.1.RELEASE</org.springframework-version> <!-- 스프링 라이브러리 버전 -->
<org.aspectj-version>1.6.10</org.aspectj-version>
<org.slf4j-version>1.6.6</org.slf4j-version>
</properties>
...
<!-- 스프링 4 이상 사용 시 추가 필요 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
<version>${org.springframework-version}</version>
</dependency>
<!-- 자바 메일 라이브러리 -->
<dependency>
<groupId>javax.mail</groupId>
<artifactId>javax.mail-api</artifactId>
<version>1.5.4</version>
</dependency>
<dependency>
<groupId>com.sun.mail</groupId>
<artifactId>javax.mail</artifactId>
<version>1.5.3</version>
</dependency>
...
pro28/src/main/webapp/WB-INF/web.xml
...
<!-- The definition of the Root Spring Container shared by all Servlets and Filters -->
<!-- 설정 파일들 읽어오기 -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spring/*.xml</param-value>
</context-param>
...
pro28/src/main/webapp/WEB-INF/spring/mail-context.xml
...
<bean id="mailSender" class="org.springframework.mail.javamail.JavaMailSenderImpl">
<!-- 구글 SMTP 서버 연동 -->
<property name="host" value="smtp.gmail.com"/>
<property name="port" value="465" />
<!-- 구글 계정 설정 -->
<property name="username" value="****@gmail.com" />
<property name="password" value="메일비밀번호"/>
<property name="javaMailProperties">
<props>
<prop key="mail.transport.protocol">smtp</prop>
<prop key="mail.smtp.auth">true</prop>
<prop key="mail.smtp.starttls.enable">true</prop>
<prop key="mail.smtp.socketFactory.class">javax.net.ssl.SSLSocketFactory</prop>
<prop key="mail.debug">true</prop>
</props>
</property>
</bean>
<!-- 미리 작성 (정기 발송 시 편리) -->
<bean id="preConfiguredMessage" class="org.springframework.mail.SimpleMailMessage">
<property name="to" value="수신메일주소"></property>
<property name="from" value="****@gmail.com"></property>
<property name="subject" value="테스트 메일입니다."/>
</bean>
...
pro28/src/main/java/com/myspring/pro28/ex04/MailController.java
package com.myspring.pro28.ex04;
...
@Controller
@EnableAsync //비동기
public class MailController {
@Autowired
private MailService mailService;
/* 일반 이메일 발송 */
@RequestMapping(value = "/sendMail.do", method = RequestMethod.GET)
public void sendSimpleMail(HttpServletRequest request, HttpServletResponse response) throws Exception {
request.setCharacterEncoding("utf-8");
response.setContentType("text/html;charset=utf-8");
PrintWriter out = response.getWriter();
mailService.sendMail("******@naver.com","테스트 메일", "안녕하세요. 테스트 메일입니다."); //새 메일 작성 후 발송
mailService.sendPreConfiguredMail("테스트 메일입니다."); //미리 작성된 메일 발송
out.print("메일을 보냈습니다!!");
}
/* HTML 이메일 발송 */
@RequestMapping(value = "/sendHtmlMail.do", method = RequestMethod.GET)
public void sendSimpleMail(HttpServletRequest request, HttpServletResponse response) throws Exception {
request.setCharacterEncoding("utf-8");
response.setContentType("text/html;charset=utf-8");
PrintWriter out = response.getWriter();
StringBuffer sb = new StringBuffer();
/* 메일 내용 작성 */
sb.append("<html><body>");
sb.append("<meta http-equiv='Content-Type' content='text/html; charset=euc-kr'>");
sb.append("<h1>"+"제품소개"+"</h1><br>");
sb.append("신간 도서를 소개합니다.<br><br>");
sb.append("<a href='http://www.kyobobook.co.kr/product/detailViewKor.laf?ejkGb=KOR&mallGb=KOR&barcode=9788956746425&orderClick=LAG&Kc=#N'>");
sb.append("<img src='http://image.kyobobook.co.kr/images/book/xlarge/425/x9788956746425.jpg' /> </a><br>");
sb.append("</a>");
sb.append("<a href='http://www.kyobobook.co.kr/product/detailViewKor.laf?ejkGb=KOR&mallGb=KOR&barcode=9788956746425&orderClick=LAG&Kc=#N'>상품보기</a>");
sb.append("</body></html>");
String str = sb.toString();
mailService.sendMail("*******@naver.com", "신상품을 소개합니다.", str);
out.print("메일을 보냈습니다!!");
}
}
pro28/src/main/java/com/myspring/pro28/ex03/MailService.java
package com.myspring.pro28.ex03;
...
@Service("mailService")
public class MailService {
@Autowired
private JavaMailSender mailSender; //자동 주입
@Autowired
private SimpleMailMessage preConfiguredMessage; //자동 주입
/* 새 메일 발송 */
@Async
public void sendMail(String to, String subject, String body) {
MimeMessage message = mailSender.createMimeMessage();
try {
MimeMessageHelper messageHelper = new MimeMessageHelper(message, true, "UTF-8");
messageHelper.setCc("#####@naver.com"); //수신자 주소
messageHelper.setFrom("xxxxxx@naver.com", "홍길동"); //발송자 주소
messageHelper.setSubject(subject);
messageHelper.setTo(to);
messageHelper.setText(body, true); //html 이메일 작성 시
//messageHelper.setText(body); //일반 이메일 작성 시
mailSender.send(message);
} catch(Exception e) { e.printStackTrace(); }
}
/* 미리 작성한 메일 발송 */
@Async
public void sendPreConfiguredMail(String message) {
SimpleMailMessage mailMessage = new SimpleMailMessage(preConfiguredMessage);
mailMessage.setText(message);
mailSender.send(mailMessage);
}
}
스프링 인터셉터
브라우저 요청 시 메소드 호출 전, 후로 특정 작업 수행
애플리케이션 내 자유롭게 적용 범위 설정 가능 (<-> filter: 특정 위치에서만 동작)
쿠키 제어, 파일 업로드 등
preHandle(): 컨트롤러 실행 전 호출
postHandle(): 컨트롤러 실행 후 호출
afterCompletion(): 뷰 수행 후 호출
pro28/src/main/webapp/WEB-INF/spring/appSevlet/servlet-context.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/mvc"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc.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.xsd">
...
<mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path="/test/*.do"/>
<mvc:mapping path="/*/*.do"/>
<beans:bean class="com.myspring.pro28.ex05.LocaleInterceptor" />
</mvc:interceptor>
</mvc:interceptors>
</beans:beans>
pro28/src/main/webapp/WEB-INF/spring/message-context.xml
...
<bean id="localeResolver" class="org.springframework.web.servlet.i18n.SessionLocaleResolver" /> <!-- 세션에 locale 정보 저장 -->
<bean id="messageSource" class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
<property name="basenames">
<list>
<value>classpath:locale/messages</value> <!-- 다국어 파일 읽기 -->
</list>
</property>
<property name="defaultEncoding" value="UTF-8" />
<property name="cacheSeconds" value="60"/> <!-- 새로고침 주기 -->
</bean>
</beans>
pro28/src/main/java/com/myspring/pro28/ex05/LocaleInterceptor.java
package com.myspring.pro28.ex05;
...
public class LocaleInterceptor extends HandlerInterceptorAdapter {
/* 컨트롤러 실행 전 호출 */
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
HttpSession session=request.getSession();
String locale=request.getParameter("locale");
if(locale==null) { locale="ko"; } //최초 요청 시
session.setAttribute("org.springframework.web.servlet.i18n.SessionLocaleResolver.OCALE", new Locale(locale));
return true;
}
/* 컨트롤러 실행 후 호출 */
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { }
/* 뷰 수행 후 호출 */
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { }
}
pro28/src/main/java/com/myspring/pro28/ex05/LocaleController.java
package com.myspring.pro28.ex05;
...
@Controller("localeController")
public class LocaleController {
@RequestMapping(value="/test/locale.do", method={RequestMethod.GET})
public String locale(HttpServletRequest request, HttpServletResponse response) throws Exception {
System.out.println("localeController입니다.");
return "locale"; //뷰 이름 반환
}
}
pro28/src/main/webapp/WEB-INF/views/locale.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"isELIgnored="false" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%-- spring:message 태그 사용 시 필요 --%>
<%@ taglib uri="http://www.springframework.org/tags" prefix="spring" %>
<c:set var="contextPath" value="${pageContext.request.contextPath}" />
<% request.setCharacterEncoding("UTF-8"); %>
<!DOCTYPE html >
<html>
<head>
<meta charset="UTF-8">
<title><spring:message code="site.title" text="Member Info" /></title>
</head>
<body>
<!-- 언어 선택 -->
<a href="${contextPath }/test/locale.do?locale=ko">한국어</a>
<a href="${contextPath }/test/locale.do?locale=en">ENGLISH</a>
<!-- 선택한 언어로 내용 표시 -->
<h1><spring:message code="site.title" text="Member Info" /></h1>
<p><spring:message code="site.name" text="no name" /> :
<spring:message code="name" text="no name" /></p>
<p><spring:message code="site.job" text="no job" /> :
<spring:message code="job" text="no job" /></p>
<input type="button" value="<spring:message code='btn.send'/>" />
<input type="button" value="<spring:message code='btn.cancel' />" />
<input type="button" value="<spring:message code='btn.finish' />" />
</body>
</html>
pro27/src/main/webapp/WEB-INF/spring/appServlet/servlet-context.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/mvc"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:mvc="http://www.springframework.org/schema/mvc" <!-- mvc 태그 사용 시 필요 -->
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc.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.xsd">
...
<mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path="/*/*.do"/> <!-- 모든 요청에 적용 -->
<beans:bean class="com.myspring.pro27.member.interceptor.ViewNameInterceptor" />
</mvc:interceptor>
</mvc:interceptors>
pro27/src/main/java/com/myspring/pro27/member/interceptor/ViewNameInterceptor.java
package com.myspring.pro27.member.interceptor;
...
public class ViewNameInterceptor extends HandlerInterceptorAdapter {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
try {
String viewName = getViewName(request);
request.setAttribute("viewName", viewName); //뷰이름 바인딩
} catch (Exception e) { e.printStackTrace(); }
return true;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { }
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { }
/* 뷰 이름 가져오기 */
private String getViewName(HttpServletRequest request) throws Exception {
String contextPath = request.getContextPath();
String uri = (String) request.getAttribute("javax.servlet.include.request_uri");
if (uri == null || uri.trim().equals("")) {
uri = request.getRequestURI();
}
...
}
}
pro27/src/main/java/com/myspring/pro28/member/controller/MemberControllerImpl.java
package com.myspring.pro27.member.controller;
...
@Controller("memberController")
public class MemberControllerImpl implements MemberController {
@Autowired
private MemberService memberService;
@Autowired
MemberVO memberVO ;
/* 회원 목록 요청 */
@Override
@RequestMapping(value="/member/listMembers.do" ,method = RequestMethod.GET)
public ModelAndView listMembers(HttpServletRequest request, HttpServletResponse response) throws Exception {
String viewName = (String)request.getAttribute("viewName"); //interceptor에서 바인딩 된 뷰이름
List membersList = memberService.listMembers();
ModelAndView mav = new ModelAndView(viewName);
mav.addObject("membersList", membersList);
return mav;
}
...
/* 로그인 창 요청 */
@RequestMapping(value = "/member/*Form.do", method = RequestMethod.GET)
private ModelAndView form(@RequestParam(value= "result", required=false) String result, HttpServletRequest request, HttpServletResponse response) throws Exception {
String viewName = (String)request.getAttribute("viewName"); //interceptor에서 바인딩 된 뷰이름
ModelAndView mav = new ModelAndView();
mav.addObject("result",result);
mav.setViewName(viewName);
return mav;
}
...
*자바 웹을 다루는 기술