SpringMVC的文件上传下载,异常处理,拦截器的小总结
阅读原文时间:2022年04月25日阅读:1

文件的上传和下载

我们通常在访问网页时会使用到文件的上传与下载的功能,那么他是如何实现的呢?

1 下载:

ResponseEntity :用于控制器方法的返回值类型,该控制器方法的返回值就是响应到浏览器的响应报文

下载,就是从服务器下载一个服务器上的资源,(通过浏览器请求向服务器请求资源,如果服务器上有这个资源就响应给客户端也就是响应到客户端的浏览器)

下载文件的代码如下:

@Controller
public class FileUpAndDownController {

    @RequestMapping("/testDown")
    public ResponseEntity<byte[]> testDown(HttpSession session) {
        ServletContext servletContext = session.getServletContext();
        String realPath = servletContext.getRealPath("/static/img/girl.jpeg");
        InputStream is = null;
        ResponseEntity responseEntity = null;
        try {
            is = new FileInputStream(realPath);
            byte[] bytes = new byte[is.available()];
            is.read(bytes);
            MultiValueMap<String, String> headers = new HttpHeaders();
            headers.add("Content-Disposition", "attachment;filename=girl.jpeg");
            HttpStatus status = HttpStatus.OK;
            responseEntity = new ResponseEntity(bytes, headers, status);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (is != null) {
                is.close();
                try {
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }

        }
        return responseEntity;
    }
}

其实搞懂ResponseEntity的作用,文件下载的问题也就迎刃而解了!

在上面的代码中

MultiValueMap headers = new HttpHeaders();

headers.add("Content-Disposition", "attachment;filename=girl.jpeg");

HttpStatus status = HttpStatus.OK;

responseEntity = new ResponseEntity(bytes, headers, status);

看懂上面部分代码!!!

还有获取文件的真实地址(通过ServletContext)也是需要注意的点!

文件的上传

配置文件上传的解析,首先需要明确文件的上传是需要通过post请求,

需要引入依赖 (在pom.xml中引入下面的依赖)

<!--        文件上传依赖-->
        <dependency>
            <groupId>commons-fileupload</groupId>
            <artifactId>commons-fileupload</artifactId>
            <version>1.3.1</version>
        </dependency>

在springmvc配置文件中配置文件上传解析器:

<!--    配置文件上传解析器-->
    <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver"></bean>

HTML的编写,首先需要明确上传数据是以form 表单,post请求的方式提交,核心的代码如下:

<form th:action="@{/testUp}" method="post" ``enctype``="multipart/form-data">
        文件上传:<input type="file" name="photo"/><br>
        <input type="submit" value="上传">
    </form>

小提示:

enctype:上传数据的编码类型,multipart/form-data 以字节流的方式上传

控制层代码:

import java.io.File;
import java.util.UUID;

class up {
  @RequestMapping(value = "/testUp", method = RequestMethod.POST)
  public String testUp(MultipartFile photo, HttpSession session) throws IOException {
    String originalFilename = photo.getOriginalFilename();//获取原先的文件名
    String suffixName = filename.substring(filename.lastIndexOf("."));
    String fileName = UUID.randomUUID().toString();
    ServletContext servletContext = session.getServletContext();
    String photoPath = servletContext.getRealPath("photoFolder");
    File file = new File(photoPath);
    if(!file.exists()){
        file.mkdir();
    }
    String path = photoPath + File.separator + suffixName;
    photo.transferTo(new File(path));
    return "nice";
  }
}

对上面代码的解读:

photo.getOriginalFilename();//获取原先的文件名
通过对上面的文件名进行字符串的处理,得到文件的后缀,为了防止多次上传时的覆盖问题,名字使用UUID的形式,在服务器的目录下创建一个
目录用于存放数据(没有则新建),然后通过将UUID和文件后缀的添加,在目录下放上传的数据
String path = photoPath + File.separator + suffixName;
photo.transferTo(new File(path));

异常处理

基于配置的异常处理

SpringMVC提供了一个处理控制器方法执行过程中所出现的异常的接口:HandlerExceptionResolver

HandlerExceptionResolver接口的实现类有:DefaultHandlerExceptionResolver和SimpleMappingExceptionResolver

SpringMVC提供了自定义的异常处理器SimpleMappingExceptionResolver

<bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
    <property name="exceptionMappings">
        <props>
            <!--
                properties的键表示处理器方法执行过程中出现的异常
                properties的值表示若出现指定异常时,设置一个新的视图名称,跳转到指定页面
            -->
            <prop key="java.lang.ArithmeticException">error</prop>
        </props>
    </property>
    <!--
        exceptionAttribute属性设置一个属性名,将出现的异常信息在请求域中进行共享
    -->
    <property name="exceptionAttribute" value="exception"></property>
</bean>

基于注解的异常处理

//@ControllerAdvice将当前类标识为异常处理的组件
@ControllerAdvice
public class ExceptionController {

    //@ExceptionHandler用于设置所标识方法处理的异常
    @ExceptionHandler(ArithmeticException.class)
    //ex表示当前请求处理中出现的异常对象
    public String handleArithmeticException(Exception ex, Model model){
        model.addAttribute("ex", ex);
        return "error";
    }

}

注解配置SpringMVC

使用配置类和注解代替web.xml 和 SpringMVC配置文件的功能

WebInit 类继承 AbstractAnnotationConfigDispatcherServletInitializer 用于代替web.xml 初始化web工程

/**
 * 用于web工程的初始化,用于代替web.xml
 */
public class WebInit extends AbstractAnnotationConfigDispatcherServletInitializer {
    /**
     * 指定Spring的配置类
     * @return
     */
    @Override
    protected Class<?>[] getRootConfigClasses() {
        return new Class[]{SpringConfig.class};
    }

    /**
     * 指定SpringMVC的配置类
     * @return
     */
    @Override
    protected Class<?>[] getServletConfigClasses() {
        return new Class[]{WebConfig.class};
    }

    /**
     * 配置过滤器:
     * @return
     */
    @Override
    protected Filter[] getServletFilters() {
        CharacterEncodingFilter characterEncodingFilter = new CharacterEncodingFilter();
        characterEncodingFilter.setEncoding("UTF-8");
        characterEncodingFilter.setForceRequestEncoding(true);
        HiddenHttpMethodFilter hiddenHttpMethodFilter = new HiddenHttpMethodFilter();
        return new Filter[]{characterEncodingFilter,hiddenHttpMethodFilter};
    }

    /**
     * url-parent
     * @return
     */
    @Override
    protected String[] getServletMappings() {
        return new String[]{"/"};

    }
}

SpringConfig 用于代替springmvc的配置

springmvc的配置文件所能提供的一些服务,我们只需在该配置类中实现这些功能即可!
1.扫描组件
2.视图解析器
3.视图控制view-controller
4.default-servlet-handler(静态资源处理)
5.mvc注解驱动
6.文件上传解析器
7.异常处理
8.拦截器



//用于代替springMVC 的配置文件
@Configuration//将当前类标识为配置类
@ComponentScan("com.kobedu.mvc.controller")//扫描组件
@EnableWebMvc//注解驱动
public class WebConfig {

    //配置生成模板解析器
    @Bean
    public ITemplateResolver templateResolver() {
        //ioc 容器在springmvc中的实现
        WebApplicationContext webApplicationContext = ContextLoader.getCurrentWebApplicationContext();
        // ServletContextTemplateResolver需要一个ServletContext作为构造参数,可通过WebApplicationContext 的方法获得
        ServletContextTemplateResolver templateResolver = new ServletContextTemplateResolver(
                webApplicationContext.getServletContext());
        templateResolver.setPrefix("/WEB-INF/templates/");
        templateResolver.setSuffix(".html");
        templateResolver.setCharacterEncoding("UTF-8");
        templateResolver.setTemplateMode(TemplateMode.HTML);
        return templateResolver;
    }

    //生成模板引擎并为模板引擎注入模板解析器
    @Bean
    public SpringTemplateEngine templateEngine(ITemplateResolver templateResolver) {//自动装配的方式进行赋值
        SpringTemplateEngine templateEngine = new SpringTemplateEngine();
        templateEngine.setTemplateResolver(templateResolver);
        return templateEngine;
    }

    //生成视图解析器并未解析器注入模板引擎
    @Bean
    public ViewResolver viewResolver(SpringTemplateEngine templateEngine) {
        ThymeleafViewResolver viewResolver = new ThymeleafViewResolver();
        viewResolver.setCharacterEncoding("UTF-8");
        viewResolver.setTemplateEngine(templateEngine);
        return viewResolver;
    }

}

上面的只是视图解析模块

接下来就是另外的一些功能

首先我们需要认识一些注解@Configuration 用来将当前的类标识为配置类

,@CommponentScan 用于扫描组件(这是springmvc的配置文件中一定不能少的)

@EnableWebMvc 启动mvc的注解驱动

//用于代替springMVC 的配置文件
//1.扫描组件   2.视图解析器    3.视图控制view-controller 4.default-servlet-handler(静态资源处理)  5.mvc注解驱动   6.文件上传解析器    7.异常处理   8.拦截器
@Configuration//将当前类标识为配置类
@ComponentScan("com.kobedu.mvc.controller")//扫描组件
@EnableWebMvc//注解驱动
public class WebConfig implements WebMvcConfigurer {

    //配置生成模板解析器

    @Bean
    public ITemplateResolver templateResolver() {
        //ioc 容器在springmvc中的实现
        WebApplicationContext webApplicationContext = ContextLoader.getCurrentWebApplicationContext();
        // ServletContextTemplateResolver需要一个ServletContext作为构造参数,可通过WebApplicationContext 的方法获得
        ServletContextTemplateResolver templateResolver = new ServletContextTemplateResolver(
                webApplicationContext.getServletContext());
        templateResolver.setPrefix("/WEB-INF/templates/");
        templateResolver.setSuffix(".html");
        templateResolver.setCharacterEncoding("UTF-8");
        templateResolver.setTemplateMode(TemplateMode.HTML);
        return templateResolver;
    }

    //生成模板引擎并为模板引擎注入模板解析器
    @Bean
    public SpringTemplateEngine templateEngine(ITemplateResolver templateResolver) {//自动装配的方式进行赋值
        SpringTemplateEngine templateEngine = new SpringTemplateEngine();
        templateEngine.setTemplateResolver(templateResolver);
        return templateEngine;
    }

    //生成视图解析器并未解析器注入模板引擎
    @Bean
    public ViewResolver viewResolver(SpringTemplateEngine templateEngine) {
        ThymeleafViewResolver viewResolver = new ThymeleafViewResolver();
        viewResolver.setCharacterEncoding("UTF-8");
        viewResolver.setTemplateEngine(templateEngine);
        return viewResolver;
    }

    //默认静态资源
    @Override
    public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
        configurer.enable();//代表默认的servlet可用!
    }

    //拦截器
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new TestInterceptor()).addPathPatterns("/**");//添加拦截器,且设定拦截规则!
    }

    // mvc 试图控制组件的测试
    @Override
    public void addViewControllers(ViewControllerRegistry registry) {
        registry.addViewController("/hello").setViewName("hello");
    }

    //文件上传解析器
    @Bean
    public MultipartResolver multipartResolver(){
        CommonsMultipartResolver commonsMultipartResolver = new CommonsMultipartResolver();
        return commonsMultipartResolver;
    }

    //异常处理
    @Override
    public void configureHandlerExceptionResolvers(List<HandlerExceptionResolver> resolvers) {
        SimpleMappingExceptionResolver simpleMappingExceptionResolver = new SimpleMappingExceptionResolver();
        Properties prop = new Properties();//键值对
//        prop.put("")
        prop.setProperty("java.lang.ArithmeticException","error");
        simpleMappingExceptionResolver.setExceptionMappings(prop);//异常映射
        simpleMappingExceptionResolver.setExceptionAttribute("exception");//设置在请求域中共享异常信息的键
        resolvers.add(simpleMappingExceptionResolver);
    }
}