Spring MVC 4 文件上传下载 Hibernate+MySQL例子 (带源码)

2021-08-27 15:27:13 浏览数 (1)

【本系列其他教程正在陆续翻译中,点击分类:spring 4 mvc 进行查看。源码下载地址在文章末尾。】

【翻译 by 明明如月 QQ 605283073】

下载地址:http://websystique.com/springmvc/spring-mvc-4-fileupload-download-hibernate-example/

上一篇:

Spring MVC 4 RESTFul Web Services CRUD例子(带源码)【这才是restful,超经典】

下一篇:Spring MVC 4 使用常规的fileupload上传文件(带源码)

本文介绍使用Spring MVC 4, Hibernate & MySQL 数据库实现文件上传. Spring MVC 结合Hibernate MySQL文件上传到数据库的例子, 以及下载和删除.

本文要点:

  • 准备数据库 [创建所需的表]
  • 准备Model类, DAO and Service 层[将被控制器用来处理文件upload/download/delete操作]
  • 准备Hibernate 配置
  • 准备 Spring 对文件上传下载删除的配置
  • 运行应用实现文件上传、下载、删除

由于本文比较常,你可以直接跳到你感兴趣的部分开始阅读。 ---------------------------------------- 所需技术和软件

  • Spring 4.2.0.RELEASE
  • Hibernate 4.3.10.Final
  • MySQL Server 5.6
  • validation-api 1.1.0.Final
  • hibernate-validator 5.1.3.Final
  • Bootstrap v3.3.2
  • Maven 3
  • JDK 1.7
  • Tomcat 8.0.21
  • Eclipse JUNO Service Release 2

让我们开始吧。。。

项目目录结构

项目最终的结构如下:

第2步: 在 pom.xml 文件中声明依赖

代码语言:javascript复制
  4.0.0
  com.websystique.springmvc
  Spring4MVCFileUploadDownloadWithHibernate
  war
  1.0.0
  Spring4MVCFileUploadDownloadWithHibernate Maven Webapp
  http://maven.apache.org
   
   
    
        4.2.0.RELEASE
        4.3.10.Final
        5.1.31
    
 
    
        
        
            org.springframework
            spring-core
            ${springframework.version}
        
        
            org.springframework
            spring-web
            ${springframework.version}
        
        
            org.springframework
            spring-webmvc
            ${springframework.version}
        
        
            org.springframework
            spring-tx
            ${springframework.version}
        
        
            org.springframework
            spring-orm
            ${springframework.version}
        
 
        
        
            org.hibernate
            hibernate-core
            ${hibernate.version}
        
 
        
        
            javax.validation
            validation-api
            1.1.0.Final
        
        
            org.hibernate
            hibernate-validator
            5.1.3.Final
        
 
        
        
            mysql
            mysql-connector-java
            ${mysql.connector.version}
        
 
        
        
            javax.servlet
            javax.servlet-api
            3.1.0
        
        
            javax.servlet.jsp
            javax.servlet.jsp-api
            2.3.1
        
        
            javax.servlet
            jstl
            1.2
        
         
    
 
    
        
            
                
                    org.apache.maven.plugins
                    maven-compiler-plugin
                    3.2
                    
                        1.7
                        1.7
                    
                
                
                    org.apache.maven.plugins
                    maven-war-plugin
                    2.4
                    
                        src/main/webapp
                        Spring4MVCFileUploadDownloadWithHibernate
                        false
                    
                
            
        
        Spring4MVCFileUploadDownloadWithHibernate

创建数据库模式

我们将展示用户和问题的关系,一个用户可以又多个文档,用户和文档的关系是一对多( OneToMany )的关系。

代码语言:javascript复制
create table APP_USER (
   id BIGINT NOT NULL AUTO_INCREMENT,
   sso_id VARCHAR(30) NOT NULL,
   first_name VARCHAR(30) NOT NULL,
   last_name  VARCHAR(30) NOT NULL,
   email VARCHAR(30) NOT NULL,
   PRIMARY KEY (id),
   UNIQUE (sso_id)
);
  
  
create table USER_DOCUMENT(
   id BIGINT NOT NULL AUTO_INCREMENT,
   user_id BIGINT NOT NULL,
   name  VARCHAR(100) NOT NULL,
   description VARCHAR(255) ,
   type VARCHAR(100) NOT NULL,
   content longblob NOT NULL,
   PRIMARY KEY (id),
   CONSTRAINT document_user FOREIGN KEY (user_id) REFERENCES APP_USER (id) ON UPDATE CASCADE ON DELETE CASCADE
);

注意:content longblob 。我们将把文件以二进制的形式存入该列。

创建模型类

代码语言:javascript复制
package com.websystique.springmvc.model;
 
import javax.persistence.Basic;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.Lob;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
 
@Entity
@Table(name="USER_DOCUMENT")
public class UserDocument {
 
    @Id @GeneratedValue(strategy=GenerationType.IDENTITY)
    private Integer id; 
     
    @Column(name="name", length=100, nullable=false)
    private String name;
     
    @Column(name="description", length=255)
    private String description;
     
    @Column(name="type", length=100, nullable=false)
    private String type;
     
    @Lob @Basic(fetch = FetchType.LAZY)
    @Column(name="content", nullable=false)
    private byte[] content;
 
    @ManyToOne(optional = false)
    @JoinColumn(name = "USER_ID")
    private User user;
     
     
    public Integer getId() {
        return id;
    }
 
    public void setId(Integer id) {
        this.id = id;
    }
 
    public String getName() {
        return name;
    }
 
    public void setName(String name) {
        this.name = name;
    }
 
    public String getDescription() {
        return description;
    }
 
    public void setDescription(String description) {
        this.description = description;
    }
 
    public String getType() {
        return type;
    }
 
    public void setType(String type) {
        this.type = type;
    }
 
    public byte[] getContent() {
        return content;
    }
 
    public void setContent(byte[] content) {
        this.content = content;
    }
 
    public User getUser() {
        return user;
    }
 
    public void setUser(User user) {
        this.user = user;
    }
 
    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result   ((id == null) ? 0 : id.hashCode());
        result = prime * result   ((name == null) ? 0 : name.hashCode());
        return result;
    }
 
    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (!(obj instanceof UserDocument))
            return false;
        UserDocument other = (UserDocument) obj;
        if (id == null) {
            if (other.id != null)
                return false;
        } else if (!id.equals(other.id))
            return false;
        if (name == null) {
            if (other.name != null)
                return false;
        } else if (!name.equals(other.name))
            return false;
        return true;
    }
 
    @Override
    public String toString() {
        return "UserDocument [id="   id   ", name="   name   ", description="
                  description   ", type="   type   "]";
    }
 
 
     
}

此实体类需要注意的是:

代码语言:javascript复制
@Lob @Basic(fetch = FetchType.LAZY)
    @Column(name="content", nullable=false)
    private byte[] content;

我们选择byte[]来存储文件内容.  @Lob指明 longblob持久化属性将以大对象的形式存入数据库@Basic注解是一个可选注解 , 在这里是告诉hibernate对此二进制内容执行懒加载。

代码语言:javascript复制
package com.websystique.springmvc.model;
 
import java.util.HashSet;
import java.util.Set;
 
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.OneToMany;
import javax.persistence.Table;
 
import org.hibernate.validator.constraints.NotEmpty;
 
@Entity
@Table(name="APP_USER")
public class User {
 
    @Id @GeneratedValue(strategy=GenerationType.IDENTITY)
    private Integer id;
 
    @NotEmpty
    @Column(name="SSO_ID", unique=true, nullable=false)
    private String ssoId;
     
    @NotEmpty
    @Column(name="FIRST_NAME", nullable=false)
    private String firstName;
 
    @NotEmpty
    @Column(name="LAST_NAME", nullable=false)
    private String lastName;
 
    @NotEmpty
    @Column(name="EMAIL", nullable=false)
    private String email;
 
    @OneToMany(mappedBy = "user", cascade = CascadeType.ALL)
    private Set userDocuments = new HashSet();
     
    public Integer getId() {
        return id;
    }
 
    public void setId(Integer id) {
        this.id = id;
    }
 
    public String getSsoId() {
        return ssoId;
    }
 
    public void setSsoId(String ssoId) {
        this.ssoId = ssoId;
    }
 
    public String getFirstName() {
        return firstName;
    }
 
    public void setFirstName(String firstName) {
        this.firstName = firstName;
    }
 
    public String getLastName() {
        return lastName;
    }
 
    public void setLastName(String lastName) {
        this.lastName = lastName;
    }
 
    public String getEmail() {
        return email;
    }
 
    public void setEmail(String email) {
        this.email = email;
    }
 
    public Set getUserDocuments() {
        return userDocuments;
    }
 
    public void setUserDocuments(Set userDocuments) {
        this.userDocuments = userDocuments;
    }
 
 
    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result   ((id == null) ? 0 : id.hashCode());
        result = prime * result   ((ssoId == null) ? 0 : ssoId.hashCode());
        return result;
    }
 
    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (!(obj instanceof User))
            return false;
        User other = (User) obj;
        if (id == null) {
            if (other.id != null)
                return false;
        } else if (!id.equals(other.id))
            return false;
        if (ssoId == null) {
            if (other.ssoId != null)
                return false;
        } else if (!ssoId.equals(other.ssoId))
            return false;
        return true;
    }
 
    @Override
    public String toString() {
        return "User [id="   id   ", ssoId="   ssoId   ", firstName="   firstName   ", lastName="   lastName
                  ", email="   email   "]";
    }
 
}

创建DAO层

代码语言:javascript复制
package com.websystique.springmvc.dao;
 
import java.util.List;
 
import com.websystique.springmvc.model.UserDocument;
 
public interface UserDocumentDao {
 
    List findAll();
     
    UserDocument findById(int id);
     
    void save(UserDocument document);
     
    List findAllByUserId(int userId);
     
    void deleteById(int id);
}
代码语言:javascript复制
package com.websystique.springmvc.dao;
 
import java.util.List;
 
import org.hibernate.Criteria;
import org.hibernate.criterion.Restrictions;
import org.springframework.stereotype.Repository;
 
import com.websystique.springmvc.model.UserDocument;
 
@Repository("userDocumentDao")
public class UserDocumentDaoImpl extends AbstractDao implements UserDocumentDao{
 
    @SuppressWarnings("unchecked")
    public List findAll() {
        Criteria crit = createEntityCriteria();
        return (List)crit.list();
    }
 
    public void save(UserDocument document) {
        persist(document);
    }
 
     
    public UserDocument findById(int id) {
        return getByKey(id);
    }
 
    @SuppressWarnings("unchecked")
    public List findAllByUserId(int userId){
        Criteria crit = createEntityCriteria();
        Criteria userCriteria = crit.createCriteria("user");
        userCriteria.add(Restrictions.eq("id", userId));
        return (List)crit.list();
    }
 
     
    public void deleteById(int id) {
        UserDocument document =  getByKey(id);
        delete(document);
    }
 
}
代码语言:javascript复制
package com.websystique.springmvc.dao;
 
import java.util.List;
 
import com.websystique.springmvc.model.User;
 
 
public interface UserDao {
 
    User findById(int id);
     
    User findBySSO(String sso);
     
    void save(User user);
     
    void deleteBySSO(String sso);
     
    List findAllUsers();
 
}

package com.websystique.springmvc.dao; import java.util.List; import org.hibernate.Criteria; import org.hibernate.criterion.Order; import org.hibernate.criterion.Restrictions; import org.springframework.stereotype.Repository; import com.websystique.springmvc.model.User; @Repository("userDao") public class UserDaoImpl extends AbstractDao implements UserDao { public User findById(int id) { User user = getByKey(id); return user; } public User findBySSO(String sso) { System.out.println("SSO : " sso); Criteria crit = createEntityCriteria(); crit.add(Restrictions.eq("ssoId", sso)); User user = (User)crit.uniqueResult(); return user; } @SuppressWarnings("unchecked") public List findAllUsers() { Criteria criteria = createEntityCriteria().addOrder(Order.asc("firstName")); criteria.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);//To avoid duplicates. List users = (List) criteria.list(); return users; } public void save(User user) { persist(user); } public void deleteBySSO(String sso) { Criteria crit = createEntityCriteria(); crit.add(Restrictions.eq("ssoId", sso)); User user = (User)crit.uniqueResult(); delete(user); } }

代码语言:javascript复制
package com.websystique.springmvc.dao;
 
import java.io.Serializable;
 
import java.lang.reflect.ParameterizedType;
 
import org.hibernate.Criteria;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.springframework.beans.factory.annotation.Autowired;
 
public abstract class AbstractDao {
     
    private final Class persistentClass;
     
    @SuppressWarnings("unchecked")
    public AbstractDao(){
        this.persistentClass =(Class) ((ParameterizedType) this.getClass().getGenericSuperclass()).getActualTypeArguments()[1];
    }
     
    @Autowired
    private SessionFactory sessionFactory;
 
    protected Session getSession(){
        return sessionFactory.getCurrentSession();
    }
 
    @SuppressWarnings("unchecked")
    public T getByKey(PK key) {
        return (T) getSession().get(persistentClass, key);
    }
 
    public void persist(T entity) {
        getSession().persist(entity);
    }
 
    public void delete(T entity) {
        getSession().delete(entity);
    }
     
    protected Criteria createEntityCriteria(){
        return getSession().createCriteria(persistentClass);
    }
 
}

创建Service层

代码语言:javascript复制
package com.websystique.springmvc.service;
 
import java.util.List;
 
import com.websystique.springmvc.model.UserDocument;
 
public interface UserDocumentService {
 
    UserDocument findById(int id);
 
    List findAll();
     
    List findAllByUserId(int id);
     
    void saveDocument(UserDocument document);
     
    void deleteById(int id);
}
代码语言:javascript复制
package com.websystique.springmvc.service;
 
import java.util.List;
 
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
 
import com.websystique.springmvc.dao.UserDocumentDao;
import com.websystique.springmvc.model.UserDocument;
 
@Service("userDocumentService")
@Transactional
public class UserDocumentServiceImpl implements UserDocumentService{
 
    @Autowired
    UserDocumentDao dao;
 
    public UserDocument findById(int id) {
        return dao.findById(id);
    }
 
    public List findAll() {
        return dao.findAll();
    }
 
    public List findAllByUserId(int userId) {
        return dao.findAllByUserId(userId);
    }
     
    public void saveDocument(UserDocument document){
        dao.save(document);
    }
 
    public void deleteById(int id){
        dao.deleteById(id);
    }
     
}
代码语言:javascript复制
package com.websystique.springmvc.service;
 
import java.util.List;
 
import com.websystique.springmvc.model.User;
 
 
public interface UserService {
     
    User findById(int id);
     
    User findBySSO(String sso);
     
    void saveUser(User user);
     
    void updateUser(User user);
     
    void deleteUserBySSO(String sso);
 
    List findAllUsers(); 
     
    boolean isUserSSOUnique(Integer id, String sso);
 
}
代码语言:javascript复制
package com.websystique.springmvc.service;
 
import java.util.List;
 
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
 
import com.websystique.springmvc.dao.UserDao;
import com.websystique.springmvc.model.User;
 
 
@Service("userService")
@Transactional
public class UserServiceImpl implements UserService{
 
    @Autowired
    private UserDao dao;
 
    public User findById(int id) {
        return dao.findById(id);
    }
 
    public User findBySSO(String sso) {
        User user = dao.findBySSO(sso);
        return user;
    }
 
    public void saveUser(User user) {
        dao.save(user);
    }
 
    /*
     * Since the method is running with Transaction, No need to call hibernate update explicitly.
     * Just fetch the entity from db and update it with proper values within transaction.
     * It will be updated in db once transaction ends. 
     */
    public void updateUser(User user) {
        User entity = dao.findById(user.getId());
        if(entity!=null){
            entity.setSsoId(user.getSsoId());
            entity.setFirstName(user.getFirstName());
            entity.setLastName(user.getLastName());
            entity.setEmail(user.getEmail());
            entity.setUserDocuments(user.getUserDocuments());
        }
    }
 
     
    public void deleteUserBySSO(String sso) {
        dao.deleteBySSO(sso);
    }
 
    public List findAllUsers() {
        return dao.findAllUsers();
    }
 
    public boolean isUserSSOUnique(Integer id, String sso) {
        User user = findBySSO(sso);
        return ( user == null || ((id != null) && (user.getId() == id)));
    }
     
}

创建Hibernate配置类

代码语言:javascript复制
package com.websystique.springmvc.configuration;
 
import java.util.Properties;
 
import javax.sql.DataSource;
 
import org.hibernate.SessionFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import org.springframework.core.env.Environment;
import org.springframework.jdbc.datasource.DriverManagerDataSource;
import org.springframework.orm.hibernate4.HibernateTransactionManager;
import org.springframework.orm.hibernate4.LocalSessionFactoryBean;
import org.springframework.transaction.annotation.EnableTransactionManagement;
 
@Configuration
@EnableTransactionManagement
@ComponentScan({ "com.websystique.springmvc.configuration" })
@PropertySource(value = { "classpath:application.properties" })
public class HibernateConfiguration {
 
    @Autowired
    private Environment environment;
 
    @Bean
    public LocalSessionFactoryBean sessionFactory() {
        LocalSessionFactoryBean sessionFactory = new LocalSessionFactoryBean();
        sessionFactory.setDataSource(dataSource());
        sessionFactory.setPackagesToScan(new String[] { "com.websystique.springmvc.model" });
        sessionFactory.setHibernateProperties(hibernateProperties());
        return sessionFactory;
     }
     
    @Bean
    public DataSource dataSource() {
        DriverManagerDataSource dataSource = new DriverManagerDataSource();
        dataSource.setDriverClassName(environment.getRequiredProperty("jdbc.driverClassName"));
        dataSource.setUrl(environment.getRequiredProperty("jdbc.url"));
        dataSource.setUsername(environment.getRequiredProperty("jdbc.username"));
        dataSource.setPassword(environment.getRequiredProperty("jdbc.password"));
        return dataSource;
    }
     
    private Properties hibernateProperties() {
        Properties properties = new Properties();
        properties.put("hibernate.dialect", environment.getRequiredProperty("hibernate.dialect"));
        properties.put("hibernate.show_sql", environment.getRequiredProperty("hibernate.show_sql"));
        properties.put("hibernate.format_sql", environment.getRequiredProperty("hibernate.format_sql"));
        return properties;        
    }
     
    @Bean
    @Autowired
    public HibernateTransactionManager transactionManager(SessionFactory s) {
       HibernateTransactionManager txManager = new HibernateTransactionManager();
       txManager.setSessionFactory(s);
       return txManager;
    }
}

使用下面配置文件 application.properties

代码语言:javascript复制
jdbc.driverClassName = com.mysql.jdbc.Driver
jdbc.url = jdbc:mysql://localhost:3306/websystique
jdbc.username = myuser
jdbc.password = mypassword
hibernate.dialect = org.hibernate.dialect.MySQLDialect
hibernate.show_sql = true
hibernate.format_sql = true

准备文件上传的配置

Spring提供了文件上穿的很多选择. 我们使用其中一种方式, SpringMVC DispatcherServlet的  javax.servlet.MultipartConfigElement  . 这提供了很多可设置的属性如文件最大大小,请求大小,位置和上传过程中文件暂时存在磁盘的入口。

另外, 我们还需要在Spring配置中添加StandardServletMultipartResolver Bean . 它是基于Servlet 3.0javax.servlet.http.Part API 的MultipartResolver 接口的标准实现类。

代码语言:javascript复制
package com.websystique.springmvc.configuration;
 
import javax.servlet.MultipartConfigElement;
import javax.servlet.ServletRegistration;
 
import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;
 
public class HelloWorldInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
 
    @Override
    protected Class[] getRootConfigClasses() {
        return new Class[] { HelloWorldConfiguration.class };
    }
  
    @Override
    protected Class[] getServletConfigClasses() {
        return null;
    }
  
    @Override
    protected String[] getServletMappings() {
        return new String[] { "/" };
    }
 
    @Override
    protected void customizeRegistration(ServletRegistration.Dynamic registration) {
        registration.setMultipartConfig(getMultipartConfigElement());
    }
 
    private MultipartConfigElement getMultipartConfigElement(){
        MultipartConfigElement multipartConfigElement = new MultipartConfigElement(LOCATION, MAX_FILE_SIZE, MAX_REQUEST_SIZE, FILE_SIZE_THRESHOLD);
        return multipartConfigElement;
    }
     
    /*Set these variables for your project needs*/
     
    private static final String LOCATION = "C:/mytemp/";
 
    private static final long MAX_FILE_SIZE = 1024 * 1024 * 25;//25MB
     
    private static final long MAX_REQUEST_SIZE = 1024 * 1024 * 30;//30MB
 
    private static final int FILE_SIZE_THRESHOLD = 0;
}

注意: 我们重写了customizeRegistration方法将需要的MultiPartConfigElement注入到DispatcherServlet中.下一步是通过注册StandardServletMultipartResolver Bean 激活多文件支持。

Spring配置类

代码语言:javascript复制
package com.websystique.springmvc.configuration;
 
import org.springframework.context.MessageSource;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.support.ResourceBundleMessageSource;
import org.springframework.web.multipart.support.StandardServletMultipartResolver;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.PathMatchConfigurer;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.ViewResolverRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
import org.springframework.web.servlet.view.InternalResourceViewResolver;
import org.springframework.web.servlet.view.JstlView;
 
 
@Configuration
@EnableWebMvc
@ComponentScan(basePackages = "com.websystique.springmvc")
public class HelloWorldConfiguration extends WebMvcConfigurerAdapter{
     
    @Bean(name="multipartResolver")
    public StandardServletMultipartResolver resolver(){
        return new StandardServletMultipartResolver();
    }
 
    /**
     * Configure ViewResolvers to deliver preferred views.
     */
    @Override
    public void configureViewResolvers(ViewResolverRegistry registry) {
 
        InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();
        viewResolver.setViewClass(JstlView.class);
        viewResolver.setPrefix("/WEB-INF/views/");
        viewResolver.setSuffix(".jsp");
        registry.viewResolver(viewResolver);
    }
     
    /**
     * Configure ResourceHandlers to serve static resources like CSS/ Javascript etc...
     */
    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler("/static/**").addResourceLocations("/static/");
    }
     
    /**
     * Configure MessageSource to lookup any validation/error message in internationalized property files
     */
    @Bean
    public MessageSource messageSource() {
        ResourceBundleMessageSource messageSource = new ResourceBundleMessageSource();
        messageSource.setBasename("messages");
        return messageSource;
    }
     
}

创建File包装类

Spring 提供 org.springframework.web.multipart.MultipartFile 代表请求传来的上传文件。它提供了像getName(), getContentType(), getBytes(), getInputStream() 这些方法,使得处理上传的文件非常容易。 

我们写文件的包装类

代码语言:javascript复制
package com.websystique.springmvc.model;
 
import org.springframework.web.multipart.MultipartFile;
 
public class FileBucket {
 
    MultipartFile file;
     
    String description;
 
    public MultipartFile getFile() {
        return file;
    }
 
    public void setFile(MultipartFile file) {
        this.file = file;
    }
 
    public String getDescription() {
        return description;
    }
 
    public void setDescription(String description) {
        this.description = description;
    }
 
}

 创建Spring MVC控制器类

代码语言:javascript复制
package com.websystique.springmvc.controller;
 
import java.io.IOException;
import java.util.List;
import java.util.Locale;
 
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
 
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.MessageSource;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.util.FileCopyUtils;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.InitBinder;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.multipart.MultipartFile;
 
import com.websystique.springmvc.model.FileBucket;
import com.websystique.springmvc.model.User;
import com.websystique.springmvc.model.UserDocument;
import com.websystique.springmvc.service.UserDocumentService;
import com.websystique.springmvc.service.UserService;
import com.websystique.springmvc.util.FileValidator;
 
 
 
@Controller
@RequestMapping("/")
public class AppController {
 
    @Autowired
    UserService userService;
     
    @Autowired
    UserDocumentService userDocumentService;
     
    @Autowired
    MessageSource messageSource;
 
    @Autowired
    FileValidator fileValidator;
     
    @InitBinder("fileBucket")
    protected void initBinder(WebDataBinder binder) {
       binder.setValidator(fileValidator);
    }
     
    /**
     * This method will list all existing users.
     */
    @RequestMapping(value = { "/", "/list" }, method = RequestMethod.GET)
    public String listUsers(ModelMap model) {
 
        List users = userService.findAllUsers();
        model.addAttribute("users", users);
        return "userslist";
    }
 
    /**
     * This method will provide the medium to add a new user.
     */
    @RequestMapping(value = { "/newuser" }, method = RequestMethod.GET)
    public String newUser(ModelMap model) {
        User user = new User();
        model.addAttribute("user", user);
        model.addAttribute("edit", false);
        return "registration";
    }
 
    /**
     * This method will be called on form submission, handling POST request for
     * saving user in database. It also validates the user input
     */
    @RequestMapping(value = { "/newuser" }, method = RequestMethod.POST)
    public String saveUser(@Valid User user, BindingResult result,
            ModelMap model) {
 
        if (result.hasErrors()) {
            return "registration";
        }
 
        /*
         * Preferred way to achieve uniqueness of field [sso] should be implementing custom @Unique annotation 
         * and applying it on field [sso] of Model class [User].
         * 
         * Below mentioned peace of code [if block] is to demonstrate that you can fill custom errors outside the validation
         * framework as well while still using internationalized messages.
         * 
         */
        if(!userService.isUserSSOUnique(user.getId(), user.getSsoId())){
            FieldError ssoError =new FieldError("user","ssoId",messageSource.getMessage("non.unique.ssoId", new String[]{user.getSsoId()}, Locale.getDefault()));
            result.addError(ssoError);
            return "registration";
        }
         
        userService.saveUser(user);
         
        model.addAttribute("user", user);
        model.addAttribute("success", "User "   user.getFirstName()   " "  user.getLastName()   " registered successfully");
        //return "success";
        return "registrationsuccess";
    }
 
 
    /**
     * This method will provide the medium to update an existing user.
     */
    @RequestMapping(value = { "/edit-user-{ssoId}" }, method = RequestMethod.GET)
    public String editUser(@PathVariable String ssoId, ModelMap model) {
        User user = userService.findBySSO(ssoId);
        model.addAttribute("user", user);
        model.addAttribute("edit", true);
        return "registration";
    }
     
    /**
     * This method will be called on form submission, handling POST request for
     * updating user in database. It also validates the user input
     */
    @RequestMapping(value = { "/edit-user-{ssoId}" }, method = RequestMethod.POST)
    public String updateUser(@Valid User user, BindingResult result,
            ModelMap model, @PathVariable String ssoId) {
 
        if (result.hasErrors()) {
            return "registration";
        }
 
        userService.updateUser(user);
 
        model.addAttribute("success", "User "   user.getFirstName()   " "  user.getLastName()   " updated successfully");
        return "registrationsuccess";
    }
 
     
    /**
     * This method will delete an user by it's SSOID value.
     */
    @RequestMapping(value = { "/delete-user-{ssoId}" }, method = RequestMethod.GET)
    public String deleteUser(@PathVariable String ssoId) {
        userService.deleteUserBySSO(ssoId);
        return "redirect:/list";
    }
     
 
     
    @RequestMapping(value = { "/add-document-{userId}" }, method = RequestMethod.GET)
    public String addDocuments(@PathVariable int userId, ModelMap model) {
        User user = userService.findById(userId);
        model.addAttribute("user", user);
 
        FileBucket fileModel = new FileBucket();
        model.addAttribute("fileBucket", fileModel);
 
        List documents = userDocumentService.findAllByUserId(userId);
        model.addAttribute("documents", documents);
         
        return "managedocuments";
    }
     
 
    @RequestMapping(value = { "/download-document-{userId}-{docId}" }, method = RequestMethod.GET)
    public String downloadDocument(@PathVariable int userId, @PathVariable int docId, HttpServletResponse response) throws IOException {
        UserDocument document = userDocumentService.findById(docId);
        response.setContentType(document.getType());
        response.setContentLength(document.getContent().length);
        response.setHeader("Content-Disposition","attachment; filename=""   document.getName()  """);
  
        FileCopyUtils.copy(document.getContent(), response.getOutputStream());
  
        return "redirect:/add-document-" userId;
    }
 
    @RequestMapping(value = { "/delete-document-{userId}-{docId}" }, method = RequestMethod.GET)
    public String deleteDocument(@PathVariable int userId, @PathVariable int docId) {
        userDocumentService.deleteById(docId);
        return "redirect:/add-document-" userId;
    }
 
    @RequestMapping(value = { "/add-document-{userId}" }, method = RequestMethod.POST)
    public String uploadDocument(@Valid FileBucket fileBucket, BindingResult result, ModelMap model, @PathVariable int userId) throws IOException{
         
        if (result.hasErrors()) {
            System.out.println("validation errors");
            User user = userService.findById(userId);
            model.addAttribute("user", user);
 
            List documents = userDocumentService.findAllByUserId(userId);
            model.addAttribute("documents", documents);
             
            return "managedocuments";
        } else {
             
            System.out.println("Fetching file");
             
            User user = userService.findById(userId);
            model.addAttribute("user", user);
 
            saveDocument(fileBucket, user);
 
            return "redirect:/add-document-" userId;
        }
    }
     
    private void saveDocument(FileBucket fileBucket, User user) throws IOException{
         
        UserDocument document = new UserDocument();
         
        MultipartFile multipartFile = fileBucket.getFile();
         
        document.setName(multipartFile.getOriginalFilename());
        document.setDescription(fileBucket.getDescription());
        document.setType(multipartFile.getContentType());
        document.setContent(multipartFile.getBytes());
        document.setUser(user);
        userDocumentService.saveDocument(document);
    }
     
}

创建Validator

创建简单的  validator实现对文件的校验

代码语言:javascript复制
package com.websystique.springmvc.util;
 
import org.springframework.stereotype.Component;
import org.springframework.validation.Errors;
import org.springframework.validation.Validator;
 
import com.websystique.springmvc.model.FileBucket;
 
 
 
@Component
public class FileValidator implements Validator {
         
    public boolean supports(Class clazz) {
        return FileBucket.class.isAssignableFrom(clazz);
    }
 
    public void validate(Object obj, Errors errors) {
        FileBucket file = (FileBucket) obj;
             
        if(file.getFile()!=null){
            if (file.getFile().getSize() == 0) {
                errors.rejectValue("file", "missing.file");
            }
        }
    }
}

messages.properties

代码语言:javascript复制
NotEmpty.user.firstName=First name can not be blank.
NotEmpty.user.lastName=Last name can not be blank.
NotEmpty.user.email=Email can not be blank.
NotEmpty.user.ssoId=SSO ID can not be blank.
non.unique.ssoId=SSO ID {0} already exist. Please fill in different value.
missing.file= Please select a file.

创建视图

managedocuments.jsp

代码语言:javascript复制
<%@ page language="java" contentType="text/html; charset=ISO-8859-1" pageEncoding="ISO-8859-1"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form"%>
 

 

    
    Upload/Download/Delete Documents
    
    

 

    
        
              
            List of Documents 
            
                
                        
                    
                        
                            No.
                            File Name
                            Type
                            Description
                            
                            
                        
                    
                    
                    
                            ${counter.index   1}
                            ${doc.name}
                            ${doc.type}
                            ${doc.description}
                            download
                            delete
                        
                    
                    
                
            
        
        
             
            Upload New Document
            
                
             
                    
                        
                            Upload a document
                            
                                
                                
                                    
                                
                            
                        
                    
                    
                        
                            Description
                            
                                
                            
                             
                        
                    
             
                    
                        
                            
                        
                    
     
                
                
        
        
            Go to Users List

主要部分是 关于文件的enctype="multipart/form-data" 和 input type="file"

registration.jsp

代码语言:javascript复制
<%@ page language="java" contentType="text/html; charset=ISO-8859-1" pageEncoding="ISO-8859-1"%>
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
 

 

    
    User Registration Form
    
    

 

 
    
    User Registration Form
    
        
         
        
            
                First Name
                
                    
                    
                        
                    
                
            
        
 
        
            
                Last Name
                
                    
                    
                        
                    
                
            
        
 
        
            
                SSO ID
                
                    
                        
                            
                        
                        
                            
                            
                                
                            
                        
                    
                
            
        
 
        
            
                Email
                
                    
                    
                        
                    
                
            
        
 
        
            
                
                    
                         or Cancel
                    
                    
                         or Cancel
                    
                
            
        
         
        
            
                Click here to upload/manage your documents   

registrationsuccess.jsp

代码语言:javascript复制
<%@ page language="java" contentType="text/html; charset=ISO-8859-1" pageEncoding="ISO-8859-1"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
 
 


    
    Registration Confirmation Page
    
    


    
        
            ${success}
        
         
        
            Click here to upload/manage your documents   
        
        
            Go to Users List

userslist.jsp

代码语言:javascript复制
<%@ page language="java" contentType="text/html; charset=ISO-8859-1" pageEncoding="ISO-8859-1"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>

 

    
    Users List
    
    

 

    
        
              
            List of Users 
            
                
                        
                    
                        
                            First Name
                            Last Name
                            Email
                            SSO ID
                            
                            
                        
                    
                    
                    
                            ${user.firstName}
                            ${user.lastName}
                            ${user.email}
                            ${user.ssoId}
                            edit
                            delete
                        
                    
                    
                
            
        
        
            Add New User

错误处理

重点:

在文件上传过程中,可能会出现“Packet for query is too large”. 为了避免这个问题,需要设置Mysql 配置文件中的‘max_allowed_packet’值.

  • 在Windows系统中MySQL Server 5.6/my.ini
  • 在Linux在etc/my.cnf

默认是 4M. 你可以根据自己情况配置。

max_allowed_packet=256M

修改配置后不要忘了重启MySQL Server 

你可以通过以下语句进行查询 >show variables like ‘max%’ ;

构建, 部署和运行

在tomcat发布后

浏览器输入   http://localhost:8080/Spring4MVCFileUploadDownloadWithHibernate

创建用户

填充并提交后

点击upload/manage链接

选择文件和填写描述

点击上传(upload)

还可以上传更多文件:

验证数据库:

点击下载  文件也可以被下载下来:

点击 删除,文件将被删除

验证数据库:

不选择文件直接点上传将会显示 请选择文件的提示

项目下载地址:http://websystique.com/?smd_process_download=1&download_id=1789

特别说明:此系列教程有的童鞋下载下来运行 经常404 或者改成xml方式以后

缺少org.springframework.web.context.ContextLoaderServlet等

参见:http://blog.csdn.net/w605283073/article/details/52126347

0 人点赞