前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Spring MVC 4 文件上传下载 Hibernate+MySQL例子 (带源码)

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

作者头像
明明如月学长
发布2021-08-27 15:27:13
6100
发布2021-08-27 15:27:13
举报
文章被收录于专栏:明明如月的技术专栏

【本系列其他教程正在陆续翻译中,点击分类: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

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2016/05/07 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • Spring MVC 4 RESTFul Web Services CRUD例子(带源码)【这才是restful,超经典】
  • 本文介绍使用Spring MVC 4, Hibernate & MySQL 数据库实现文件上传. Spring MVC 结合Hibernate+MySQL文件上传到数据库的例子, 以及下载和删除.
  • 本文要点:
    • 项目目录结构
      • 第2步: 在 pom.xml 文件中声明依赖
        • 创建数据库模式
          • 创建模型类
            • 创建DAO层
            • 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); } }
              • 创建Service层
                • 创建Hibernate配置类
                  • 准备文件上传的配置
                    • Spring配置类
                      • 创建File包装类
                        •  创建Spring MVC控制器类
                          • 创建Validator
                            • 创建视图
                              • 错误处理
                                • 构建, 部署和运行
                                相关产品与服务
                                云数据库 SQL Server
                                腾讯云数据库 SQL Server (TencentDB for SQL Server)是业界最常用的商用数据库之一,对基于 Windows 架构的应用程序具有完美的支持。TencentDB for SQL Server 拥有微软正版授权,可持续为用户提供最新的功能,避免未授权使用软件的风险。具有即开即用、稳定可靠、安全运行、弹性扩缩等特点。
                                领券
                                问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档