[spring] file upload, Interceptor

sang·2024년 4월 23일

다중 파일 업로드

CommonMultipartResolver 클래스 속성

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>
  
  ...

controller

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;
  }
}
  

jsp

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);
  }
}


Interceptor

스프링 인터셉터
브라우저 요청 시 메소드 호출 전, 후로 특정 작업 수행

애플리케이션 내 자유롭게 적용 범위 설정 가능 (<-> filter: 특정 위치에서만 동작)
쿠키 제어, 파일 업로드 등

HandlerInterceptor 클래스 메소드

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;
  }
  
  ...


*자바 웹을 다루는 기술

profile
CS 메모장

0개의 댓글