SpringMvc知识点梳理(二)

一.文件上传(重要)

1.文件上传分析

在这里插入图片描述

2.步骤

2.1 浏览器端要求(通用浏览器的要求)

  • 表单提交方式 post
  • 提供文件上传框(组件) input type=“file”
  • 表单的entype属性必须为 multipart/form-data(没有这个属性值的话, 文件的内容是提交不过去的)
    创建update.html
    在这里插入图片描述

2.2 服务器端要求

  1. 获取客户端上传的文件

    1. 准备一个目录存储客户端上传的文件
    2. 将客户端上传的文件写入到准备好的目录中

注意:

  • 若表单使用了 multipart/form-data ,使用原生request.getParameter()去获取参数的时候都为null

2.3 所需组件

我们做文件上传一般会借助第三方组件(jar, 框架 SpringMVC)实现文件上传.

2.3.1 常见的文件上传jar包和框架

​ serlvet3.0(原生的文件上传的API)

​ commons-fileupload : apache出品的一款专门处理文件上传的工具包 (我们肯定不会直接使用)

​ struts2(底层封装了:commons-fileupload)

​ SpringMVC(底层封装了:commons-fileupload)

<dependencies>
    <!--文件上传组件的依赖-->
    <dependency>
      <groupId>commons-fileupload</groupId>
      <artifactId>commons-fileupload</artifactId>
      <version>1.3.1</version>
    </dependency>
    <!--springmvc的依赖-->
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-webmvc</artifactId>
      <version>5.0.2.RELEASE</version>
    </dependency>

    <dependency>
      <groupId>javax.servlet</groupId>
      <artifactId>servlet-api</artifactId>
      <version>2.5</version>
      <scope>provided</scope>
    </dependency>

    <dependency>
      <groupId>javax.servlet.jsp</groupId>
      <artifactId>jsp-api</artifactId>
      <version>2.0</version>
      <scope>provided</scope>
    </dependency>
  </dependencies>

2.4 springmvc.xml中配置文件上传解析器

<!--5.配置文件上传解析器-->
    <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<!-- 设置文件上传的最大尺寸为5MB-->
        <property name="maxUploadSize" value="5242880"></property>
    </bean>

2.5 FileController

//1.在springmvc的配置文件中配置文件解析器,将字节输入流解析成MultipartFile对象
//2.在控制器方法中添加MultipartFile类型的参数
@RestController
@RequestMapping("/file")
public class FileController {
    @RequestMapping("/upload")
    public String upload(MultipartFile upload, String pdesc, HttpSession session) throws IOException {
        //在部署的项目路径下准备一个upload目录
        //upload这个形参要和前端的名字保持一致
        ServletContext servletContext = session.getServletContext();
        String realPath = servletContext.getRealPath("upload");
        File file=new File(realPath);
        if(!file.exists()){
            file.mkdirs();
        }
        //获取文件名
        String filename = upload.getOriginalFilename();
        //使用文件输出流将客户端上传的文件输出到指定目录
        FileOutputStream fileOutputStream = new FileOutputStream(new File(file, filename));
        //客户端上传文件的输入流
        InputStream inputStream = upload.getInputStream();
        IOUtils.copy(inputStream, fileOutputStream);
        inputStream.close();
        fileOutputStream.close();
        return "success";
    }

二. 跨服务器方式的文件上传(了解)

1.需求

  • 了解使用springmvc 跨服务器方式的文件上传

2.分析

2.1分服务器的目的

在实际开发中,我们会有很多处理不同功能的服务器(注意:此处说的不是服务器集群)。 例如:

​ 应用服务器:负责部署我们的应用
​ 数据库服务器:运行我们的数据库
​ 缓存和消息服务器:负责处理高并发访问的缓存和消息
​ 文件服务器:负责存储用户上传文件的服务器。

分服务器处理的目的是让服务器各司其职,从而提高我们项目的运行效率。
在这里插入图片描述

2.2跨服务器方式的文件上传图解
  • 准备两个服务器(默认情况下,tomcat是不允许其他服务器往它里面写入数据的), 修改tomcat的的conf目录下的web.xml, 添加readonly参数为false

3.实现

  • 添jersey依赖 (跨服务器上传图片的代码)
<dependencies>
    <!--引入文件上传的依赖-->
    <!--文件上传组件的依赖-->
    <dependency>
        <groupId>commons-fileupload</groupId>
        <artifactId>commons-fileupload</artifactId>
        <version>1.3.1</version>
    </dependency>
    <!--springmvc的依赖-->
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-webmvc</artifactId>
        <version>5.0.2.RELEASE</version>
    </dependency>

    <dependency>
        <groupId>javax.servlet</groupId>
        <artifactId>servlet-api</artifactId>
        <version>2.5</version>
        <scope>provided</scope>
    </dependency>

    <dependency>
        <groupId>javax.servlet.jsp</groupId>
        <artifactId>jsp-api</artifactId>
        <version>2.0</version>
        <scope>provided</scope>
    </dependency>

    <!--跨服务器上传的文件的依赖-->
    <dependency>
        <groupId>com.sun.jersey</groupId>
        <artifactId>jersey-core</artifactId>
        <version>1.18.1</version>
    </dependency>
    <dependency>
        <groupId>com.sun.jersey</groupId>
        <artifactId>jersey-client</artifactId>
        <version>1.18.1</version>
    </dependency>
</dependencies>
  • 前端页面
<h1>二,springmvc 跨服务器方式的文件上传</h1>
<form action="/file/upload" method="post" enctype="multipart/form-data">
    图片: <input type="file" name="upload"/><br/>
    图片描述:<input type="text" name="pdesc"/>
    <input type="submit" value="上传"/>
</form>
  • 控制器
package com.itheima.controller;

import com.sun.jersey.api.client.Client;
import com.sun.jersey.api.client.WebResource;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;

/**
 * 跨服务器文件上传:
 * 1. 使用springmvc的方式获取客户端上传的文件
 * 2. 使用跨服务器上传文件的API,将图片上传到文件服务器
 */
@RestController
@RequestMapping("/file")
public class FileController {

    /**
     * 改成跨服务器文件上传
     * @param upload
     * @param pdesc
     * @return
     * @throws IOException
     */
    @RequestMapping("/upload")
    public String upload(MultipartFile upload, String pdesc) throws IOException {
        System.out.println(pdesc);
        try {
            //获取文件名
            String originalFilename = upload.getOriginalFilename();
            //上传文件的路径
            String uploadPath = "http://localhost:8899/upload/"+originalFilename;

            //创建一个文件上传的客户端
            Client client = Client.create();
            //建立与服务器的连接
            WebResource resource = client.resource(uploadPath);
            //将文件上传给服务器
            resource.put(upload.getBytes());
            return "success";
        } catch (Exception e) {
            e.printStackTrace();
            return "fail";
        }
    }
}

三. SpringMVC中的异常处理(了解)

SpringMVC 中的异常处理

1.目标

  • 掌握SpringMVC的统一异常处理

2.分析

​ 系统中异常包括两类:编译时异常和运行时异常RuntimeException,前者通过捕获异常从而获取异常信息,后者主要通过规范代码开发、测试通过手段减少运行时异常的发生。

   系统的dao、service、controller出现都通过throws Exception向上抛出,最后由springmvc前端控制器交由异常处理器进行异常处理.

​ springmvc在处理请求过程中出现异常信息交由异常处理器进行处理,自定义异常处理器可以实现一个系统的异常处理逻辑。

3.代码实现

3.1自定义异常处理器
package com.wjs.handler;

import org.springframework.web.servlet.HandlerExceptionResolver;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * 全局异常处理器:
 *     作用: 处理整个项目中所有的controller抛出的异常
 *     步骤: 1. 编写一个类实现HandlerExceptionResolver接口
 *          2. 重写resolveException方法
 *          3. 在springmvc的配置文件中,配置异常解析器
 */
public class GlobalExceptionHandler implements HandlerExceptionResolver {

    @Override
    public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {
        //ex表示这次的异常信息,使用它可以收集异常信息
        ex.printStackTrace();//这句代码仅仅是在控制台打印文件

        //返回ModelAndView对象就必然要走视图解析器
        ModelAndView modelAndView = new ModelAndView();
        modelAndView.setViewName("error");
        return modelAndView;
    }
}
3.2配置异常处理器
  • 在springmvc.xml配置
<bean id="sysExceptionResolver" class="com.itheima.handler.GlobalExceptionHandler"></bean>

四. SpringMVC 中的拦截器(掌握)

1.拦截器概述

​ Spring MVC 的处理器拦截器类似于 Servlet 开发中的过滤器 Filter,用于对处理器(自己编写的Controller)进行预处理和后处理。用户可以自己定义一些拦截器来实现特定的功能。谈到拦截器,还要向大家提一个词——拦截器链(Interceptor Chain)。拦截器链就是将拦截器按一定的顺序联结成一条链。在访问被拦截的方法或字段时,拦截器链中的拦截器就会按其之前定义的顺序被调用。说到这里,可能大家脑海中有了一个疑问,这不是我们之前学的过滤器吗?是的它和过滤器是有几分相似,但
是也有区别,接下来我们就来说说他们的区别:

类别使用范围拦截范围
拦截器SpringMVC项目只会拦截访问的控制器方法的请求
过滤器任何web项目任何资源(servlet,控制器,jsp,html等)

​ 我们要想自定义拦截器, 要求必须实现: HandlerInterceptor 接口。

2.自定义拦截器入门

  • 编写一个普通类实现 HandlerInterceptor 接口
package com.wjs.interceptor;

import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * 拦截器:
 *    作用: 在执行controller的方法之前做预处理,以及执行controller的方法之后做后处理
 *    步骤:
 *       1. 写一个类实现HandlerInterceptor接口
 *       2. 选择实现其中的方法:
 *          1. preHandle() 在处理器方法之前执行
 *          2. postHandle() 在处理器方法之后、视图渲染之前执行
 *          3. afterCompletion() 在视图渲染之后执行,官方建议可以在该方法中做一些资源清理操作
 *       3. 在springmvc配置文件中进行拦截器的配置(配置拦截器的拦截路径)
 */
public class PermissionInterceptor implements HandlerInterceptor{
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {

        System.out.println("PermissionInterceptor的preHandle方法执行了...");
        //返回值为true就是放行
        return true;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        System.out.println("PermissionInterceptor的postHandle方法执行了...");
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        System.out.println("PermissionInterceptor的afterCompletion方法执行了...");
    }
}
  • 在springmvc.xml配置拦截器
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:mvc="http://www.springframework.org/schema/mvc"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd
       http://www.springframework.org/schema/context
       http://www.springframework.org/schema/context/spring-context.xsd
       http://www.springframework.org/schema/mvc
       http://www.springframework.org/schema/mvc/spring-mvc.xsd">
    <context:component-scan base-package="com.wjs"/>

    <!--配置拦截器-->
    <mvc:interceptors>
        <!--
            里面可以配置多个拦截器,每一个interceptor就是一个拦截器
        -->
        <mvc:interceptor>
            <!--
                mapping表示这个拦截器的拦截范围
            -->
            <mvc:mapping path="/**" />
            <!--
                exclude-mapping
            -->
            <mvc:exclude-mapping path="/hello/sayHaha.do"/>
            <!--
                bean标签表示对我们要进行配置的拦截器做IOC
            -->
            <bean id="permissionInterceptor" class="com.wjs.interceptor.PermissionInterceptor">	</bean>
        </mvc:interceptor>
    </mvc:interceptors>
</beans>

3.拦截器的其它方法

  • afterCompletion 在目标方法完成视图层渲染后执行。3
  • postHandle 在目标方法执行完毕获得了返回值后执行(一定要经过handle,2)。
  • preHandle 被拦截的目标方法执行之前执行。1
  • 如果拦截器都是放行状态则1–>2–>3执行
  • 如果被被拦截返回,postHandle是肯定不能执行的,afterCompletion是会被执行的

4 多个拦截器执行顺序

​ 回想多个过滤器的执行顺序:

  1. 如果采用配置文件方式配置过滤器,那么就按照过滤器的配置先后顺序执行

     	2. 如果采用注解方式配置过滤器,那么就按照类名的排序执行
    

​ 我们可以配置多个拦截器, 所以就存在一个优先级问题了.多个拦截器的优先级是按照配置的顺序决定的。
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值