Spring MVC Multiple File Upload Example

In this simple tutorial we will see how to implement multiple file upload in a Spring 3 MVC based application.

The requirement is simple. We have a form which displays file input component. User selects a file and upload it. Also its possible to add more file input components using Add button. Once the files are selected and uploaded, the file names are displayed on success page.

1. Maven Dependencies / Required JAR files

If you using Maven in your project for dependency management, you’ll need to add dependencies for Apache Common File upload and Apache Common IO libraries. The spring’sCommonsMultipartResolver class internal uses these library to handle uploaded content.
Add following dependencies in your maven based project to add File upload feature.

<dependencies>
    <!-- Spring 3 MVC  -->
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-webmvc</artifactId>
        <version>3.1.2.RELEASE</version>
    </dependency>
    <!-- Apache Commons file upload  -->
    <dependency>
        <groupId>commons-fileupload</groupId>
        <artifactId>commons-fileupload</artifactId>
        <version>1.2.2</version>
    </dependency>
    <!-- Apache Commons IO -->
    <dependency>
        <groupId>org.apache.commons</groupId>
        <artifactId>commons-io</artifactId>
        <version>1.3.2</version>
    </dependency>
    <!-- JSTL for c: tag -->
    <dependency>
        <groupId>jstl</groupId>
        <artifactId>jstl</artifactId>
        <version>1.2</version>
    </dependency>
</dependencies>

If you have a simple web application, add following JAR files in WEB-INF/lib folder. You can download all these JARs with source code at the end of this tutorial.

2. Model – Form Object

Create a Java bean which acts as Model/Form object for our Spring application. This bean contains aList of org.springframework.web.multipart.MultipartFile objects. Spring framework provides a useful class MultipartFile which can be used to fetch the file content of uploaded file. Apart from its content, the MultipartFile object also gives you other useful information such as filename, file size etc.

FileUploadForm.java

package net.viralpatel.spring3.form;
 
import java.util.List;
 
import org.springframework.web.multipart.MultipartFile;
 
public class FileUploadForm {
 
    private List<MultipartFile> files;
     
    //Getter and setter methods
}

3. Controller – Spring Controller

Create a Spring 3 MVC based controller which handles file upload. There are two methods in this controller:

  1. displayForm – Is a used to show input form to user. It simply forwards to the page file_upload_form.jsp
  2. save – Fetches the form using @ModelAttribute annotation and get the File content from it. It creates a list of filenames of files being uploaded and pass this list to success page.

FileUploadController.java

package net.viralpatel.spring3.controller;
 
import java.util.ArrayList;
import java.util.List;
 
import net.viralpatel.spring3.form.FileUploadForm;
 
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.multipart.MultipartFile;
 
@Controller
public class FileUploadController {
     
    @RequestMapping(value = "/show", method = RequestMethod.GET)
    public String displayForm() {
        return "file_upload_form";
    }
     
    @RequestMapping(value = "/save", method = RequestMethod.POST)
    public String save(
            @ModelAttribute("uploadForm") FileUploadForm uploadForm,
                    Model map) {
         
        List<MultipartFile> files = uploadForm.getFiles();
 
        List<String> fileNames = new ArrayList<String>();
         
        if(null != files && files.size() > 0) {
            for (MultipartFile multipartFile : files) {
 
                String fileName = multipartFile.getOriginalFilename();
                fileNames.add(fileName);
                //Handle file content - multipartFile.getInputStream()
 
            }
        }
         
        map.addAttribute("files", fileNames);
        return "file_upload_success";
    }
}

4. View – JSP views

Now create the view pages for this application. We will need two JSPs, one to display file upload form and another to show result on successful upload.

The file_upload_form.jsp displays a form with file input. Apart from this we have added small jquery snippet onclick of Add button. This will add a new file input component at the end of form. This allows user to upload as many files as they want (subjected to file size limit ofcourse).

Note that we have set enctype=”multipart/form-data” attribute of our <form> tag.

file_upload_form.jsp

<%@taglib uri="http://www.springframework.org/tags/form" prefix="form"%>
<html>
<head>
    <title>Spring MVC Multiple File Upload</title>
<script
src="http://ajax.googleapis.com/ajax/libs/jquery/1.8.2/jquery.min.js"></script>
<script>
$(document).ready(function() {
    //add more file components if Add is clicked
    $('#addFile').click(function() {
        var fileIndex = $('#fileTable tr').children().length - 1;
        $('#fileTable').append(
                '<tr><td>'+
                '   <input type="file" name="files['+ fileIndex +']" />'+
                '</td></tr>');
    });
     
});
</script>
</head>
<body>
<h1>Spring Multiple File Upload example</h1>
 
<form:form method="post" action="save.html"
        modelAttribute="uploadForm" enctype="multipart/form-data">
 
    <p>Select files to upload. Press Add button to add more file inputs.</p>
 
    <input id="addFile" type="button" value="Add File" />
    <table id="fileTable">
        <tr>
            <td><input name="files[0]" type="file" /></td>
        </tr>
        <tr>
            <td><input name="files[1]" type="file" /></td>
        </tr>
    </table>
    <br/><input type="submit" value="Upload" />
</form:form>
</body>
</html>

Note that we defined the file input name as files[0], files[1] etc. This will map the submitted files to the List object correctly.

I would suggest you to go through this tutorial to understand how Spring maps multiple entries from form to bean: Multiple Row Form Submit using List of Beans

Second view page is to display filename of uploaded file. It simply loops through filename list and display the names.

file_upload_success.jsp

<%@taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<html>
<head>
    <title>Spring MVC Multiple File Upload</title>
</head>
<body>
    <h1>Spring Multiple File Upload example</h1>
    <p>Following files are uploaded successfully.</p>
    <ol>
        <c:forEach items="${files}" var="file">
            <li>${file}</li>
        </c:forEach>
    </ol>
</body>
</html>

5. Spring Configuration

In Spring configuration (spring-servlet.xml) we define several important configurations. Note how we defined bean multipartResolver. This will make sure Spring handles the file upload correctly usingCommonsMultipartResolver class.

spring-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"
    xmlns:mvc="http://www.springframework.org/schema/mvc"
    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.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd">
 
    <context:annotation-config />
    <context:component-scan base-package="net.viralpatel.spring3.controller"/>
  
 <bean id="multipartResolver"
  class="org.springframework.web.multipart.commons.CommonsMultipartResolver"/>
 
  <bean id="jspViewResolver"
    class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="viewClass"
            value="org.springframework.web.servlet.view.JstlView" />
        <property name="prefix" value="/WEB-INF/jsp/" />
        <property name="suffix" value=".jsp" />
  </bean>
</beans>

6. Output

Execute the project in Eclipse. Open following URL in browser to see file upload form.

URL: http://localhost:8080/Spring3MVC_Multiple_File_Upload_example/show.html

spring-mvc-multiple-file-upload-demo

Select files through file dialog and press Upload button to upload. Following page will displayed with list of files being uploaded.

spring-mvc-multi-file-upload-success

We have added a small Javascript snippet for Add button. This will add more file upload components to the page. Use this if you want to upload more files.

Download Source Code

SpringMVC_Multi_File_Upload_example.zip (3.6 MB)



출처 - http://viralpatel.net/blogs/spring-mvc-multiple-file-upload-example/



Posted by linuxism
,


자바 1.2 버전부터 제공되고 있지만 아직 다수의 개발자들이 잘 몰라서 활용을 잘 못하는 기능이 하나 있는데, 그 기능이 바로 쓰레드 단위로 로컬 변수를 할당하는 기능이다. 이 기능은 ThreadLocal 클래스를 통해서 제공되는데, 본 글에서는 ThreadLocal 클래스의 기본적인 사용방법과 활용 방법을 살펴보도록 하겠다.

ThreadLocal이란?

일반 변수의 수명은 특정 코드 블록(예, 메서드 범위, for 블록 범위 등) 범위 내에서만 유효하다.

{
    int a = 10;
    ...
   // 블록 내에서 a 변수 사용 가능
}
// 변수 a는 위 코드 블록이 끝나면 더 이상 유효하지 않다. (즉, 수명을 다한다.)

반면에 ThreadLocal을 이용하면 쓰레드 영역에 변수를 설정할 수 있기 때문에, 특정 쓰레드가 실행하는 모든 코드에서 그 쓰레드에 설정된 변수 값을 사용할 수 있게 된다. 아래 그림은 쓰레드 로컬 변수가 어떻게 동작하는 지를 간단하게 보여주고 있다.


위 그림에서 주목할 점은 동일한 코드를 실행하는 데, 쓰레드1에서 실행할 경우 관련 값이 쓰레드1에 저장되고 쓰레드2에서 실행할 경우 쓰레드2에 저장된다는 점이다.


ThreadLocal의 기본 사용법

ThreadLocal의 사용방법은 너무 쉽다. 단지 다음의 네 가지만 해 주면 된다.
  1. ThreadLocal 객체를 생성한다.
  2. ThreadLocal.set() 메서드를 이용해서 현재 쓰레드의 로컬 변수에 값을 저장한다.
  3. ThreadLocal.get() 메서드를 이용해서 현재 쓰레드의 로컬 변수 값을 읽어온다.
  4. ThreadLocal.remove() 메서드를 이용해서 현재 쓰레드의 로컬 변수 값을 삭제한다.
아래 코드는 ThreadLocal의 기본적인 사용방법을 보여주고 있다.

// 현재 쓰레드와 관련된 로컬 변수를 하나 생성한다.
ThreadLocal<UserInfo> local = new ThreadLocal<UserInfo>();

// 로컬 변수에 값 할당
local.set(currentUser);

// 이후 실행되는 코드는 쓰레드 로컬 변수 값을 사용
UserInfo userInfo = local.get();

위 코드만으로는 ThreadLocal이 어떻게 동작하는 지 잘 이해가 되지 않을테니, 구체적인 예제를 이용해서 ThreadLocal의 동작 방식을 살펴보도록 하겠다. 먼저 ThreadLocal 타입의 static 필드를 갖는 클래스를 하나 작성해보자.

public class Context {
    public static ThreadLocal<Date> local = new ThreadLocal<Date>();
}

이제 Context 클래스를 사용해서 쓰레드 로컬 변수를 설정하고 사용하는 코드를 작성할 차례이다. 아래는 코드의 예이다.

class A {
    public void a() {
        Context.local.set(new Date());
        
        B b = new B();
        b.b();

        Context.local.remove();
    }
}

class B {
    public void b() {
        Date date = Context.local.get();

        C c = new C();
        c.c();
    }
}

class C {
    public void c() {
        Date date = Context.local.get();
    }
}

위 코드를 보면 A, B, C 세 개의 클래스가 존재하는데, A.a() 메서드를 호출하면 다음 그림과 같은 순서로 메서드가 실행된다.


위 그림에서 1~10은 모두 하나의 쓰레드에서 실행된다. ThreadLocal과 관련된 부분을 정리하면 다음과 같다.
  • 2 - A.a() 메서드에서 현재 쓰레드의 로컬 변수에 Date 객체를 저장한다.
  • 4 - B.b() 메서드에서 현재 쓰레드의 로컬 변수에 저장된 Date 객체를 읽어와 사용한다.
  • 6 - C.c() 메서드에서 현재 쓰레드의 로컬 변수에 저장된 Date 객체를 읽어와 사용한다.
  • 9 - A.a() 메서드에서 현재 쓰레드의 로컬 변수를 삭제한다.
위 코드에서 중요한 건 A.a()에서 생성한 Date 객체를 B.b() 메서드나 C.c() 메서드에 파라미터로 전달하지 않는다는 것이다. 즉, 파라미터로 객체를 전달하지 않아도 한 쓰레드로 실행되는 코드가 동일한 객체를 참조할 수 있게 된다.

ThreadLocal의 활용

ThreadLocal은 한 쓰레드에서 실행되는 코드가 동일한 객체를 사용할 수 있도록 해 주기 때문에 쓰레드와 관련된 코드에서 파라미터를 사용하지 않고 객체를 전파하기 위한 용도로 주로 사용되며, 주요 용도는 다음과 같다.

  • 사용자 인증정보 전파 - Spring Security에서는 ThreadLocal을 이용해서 사용자 인증 정보를 전파한다.
  • 트랜잭션 컨텍스트 전파 - 트랜잭션 매니저는 트랜잭션 컨텍스트를 전파하는 데 ThreadLocal을 사용한다.
  • 쓰레드에 안전해야 하는 데이터 보관

이 외에도 쓰레드 기준으로 동작해야 하는 기능을 구현할 때 ThreadLocal을 유용하게 사용할 수 있다.

ThreadLocal 사용시 주의 사항

쓰레드 풀 환경에서 ThreadLocal을 사용하는 경우 ThreadLocal 변수에 보관된 데이터의 사용이 끝나면 반드시 해당 데이터를 삭제해 주어야 한다. 그렇지 않을 경우 재사용되는 쓰레드가 올바르지 않은 데이터를 참조할 수 있다.


출처 - http://javacan.tistory.com/entry/ThreadLocalUsage



'Development > JavaEssential' 카테고리의 다른 글

java - 형변환(casting)  (1) 2014.01.05
java - 숫자, 정수, 실수 범위(integer, long)  (0) 2013.11.25
java - synchronized  (0) 2013.07.08
java - 생성자  (2) 2013.04.08
java - 내부클래스(inner class)  (0) 2012.11.07
Posted by linuxism
,


Is the MongoDB $push operator the way to add an embedded document?


I'm using MongoDB and Spring 3. I have the following domain object:

@Document(collection = "users")
public class User {

    @Id
    private String id;

    private List<Post> posts;
}

I want to add a Post to a User, but what is the best/most efficient way to do that? I can see a way to do this programmatically - find the user, add a new post object to the list and save the user again - but I don't think this is very elegant or efficient.

From the documentation it seems like I need to use the $push operator but I can't seem to find any examples of how to do this with Spring's MongoTemplate. Can anyone provide an example?

share|improve this question

$push would be the correct way to add a new document to the array.

You can see example code in this presentation (slide 22). The relevant line would be:

mongoTemplate.updateFirst(collection, 
... new Query(where("_id").is(...)),
... new Update().push("field", dbo));
share|improve this answer
2 
Thanks this helped. I used the following:mongoTemplate.updateFirst(Query.query(Criteria.where("username").is("username_1‌​")), new Update().push("posts", newPostObject), User.class); I think I got a bit confused because I was trying to user the Update class statically - like i've seen done in many examples - and this did not allow the push method. – chrisjleu Jun 7 '12 at 20:50




출처 - http://stackoverflow.com/questions/10905508/is-the-mongodb-push-operator-the-way-to-add-an-embedded-document



this presentation  slide 22에서 mongoTemplate.getConverter().write()는 생략해도 된다.

중요한건 push()이다.  --> http://docs.mongodb.org/manual/reference/operator/push/



Posted by linuxism
,