SpringMVC

MVC

什么是MVC?

MVC是一种软件设计规范:模型(Model)、视图(View)、控制器(Controller)的简写。
是用将业务逻辑、数据、显示分离的方法来组织代码。
MVC不是一种设计模式,而是一种架构模式。当然不同的MVC存在差异。

MVC主要作用是降低视图与业务逻辑间的双向耦合。

**Model(模型):**数据模型,提供要展示的数据,因此包含数据和行为,可以认为是领域模型或 JavaBean组件(包含数据和行为),不过现在一般都分离开来:Value Object(数据 Dao)和服务层(行为 Service)。也就是模型提供了模型数据查询和模型数据的状态更新等功能,包括数据和业务。

View(视图):负责进行模型的展示,一般就是我们见到的用户界面,客户想看到的东西。

Controller(控制器):接收用户请求,委托给模型进行处理(状态改变),处理完毕后把返回的模型数据返回给视图,由视图负责展示。也就是说控制器做了个调度员的工作。

最典型的MVC就是JSP + servlet + javabean的模式。

时代发展

1、Model1时代

  • 在web早期的开发中,通常采用的都是Model1。
  • Model1中,主要分两层,视图层和模型层。
image-20210201181329926

优点:架构简单,比较适合小型项目开发。

缺点:JSP职责不单一,职责过重,不便于维护。

2、Model2时代

Model2把一个项目分成三部分。包括视图、控制、模型

image-20210201181732664
  1. 用户发请求
  2. Servlet接收请求数据,并调用对应的业务逻辑方法
  3. 业务处理完毕,返回更新后的数据给servlet
  4. servlet转向到JSP,由JSP来渲染页面
  5. 响应给前端更新后的页面

职责分析:

Controller(控制器):

  1. 取得表单数据
  2. 调用业务逻辑
  3. 转向指定的页面

Model(模型):

  1. 业务逻辑
  2. 保存数据的状态

View(视图):

  1. 显示页面

总结:Model2这样不仅提高了代码的复用率与项目的扩展性,且大大降低了项目的维护成本。Model1模式的实现比较简单,适用于快速开发小规模项目,Model1中JSP页面兼View和Controller两种角色,将控制逻辑和表现逻辑混杂在一起,从而导致代码的重用性比较低,增加了应用的扩展性和维护的难度。Model2消除了Model1的缺点。

SpringMVC

一:概述

1、什么是SpringMVC?

  • SpringMVC是Spring Framework的一部分,是基于Java实现MVC的轻量级Web框架。
    • 是在Spring3.0后发布的。
    • springmvc内部是使用mvc架构模式。
  • SpringMVC 是一个容器, 管理对象的,使用IoC核心技术。 springmvc管理界面层中的控制器对象。
  • SpringMVC底层也是Servlet。 以Servlet为核心, 接收请求,处理请求。 显示处理结果给用户。

官方文档

特点:

  1. 约定优于配置

Spring的web框架围绕DispatcherServlet(调度Servlet)设计。
DispatcherServlet的作用是将请求分发到不同的处理器。从Spring 2.5开始,使用Java5或者以上版本的用户可以采用基于注解形式进行开发,十分简洁。

2、SpringMVC优点

  1. 基于 MVC 架构

    1. 功能分工明确。解耦合,
  2. 轻量级,简单易学

    1. SpringMVC 也是轻量级的, jar 很小。不依赖的特定的接口和类。
  3. 作为 Spring 框架一部分,能够使用 Spring 的 IOC 和 Aop。方便整合 Strtus,MyBatis,Hiberate,JPA 等其他框架。

  4. 功能强大:RESTful、数据验证、格式化、本地化、主题等

3、中心控制器

  • Spring的web框架围绕DispatcherServlet设计。DispatcherServlet的作用是将请求分发到不同的处理器。从Spring 2.5开始,使用Java5或者以上版本的用户可以采用基于注解的controller声明方式。

  • SpringMVC框架像许多其他MVC框架一样,以请求为驱动,围绕一个中心Servlet分派请求及提供其他功能,DispatcherServlet实际上是一个Servlet(它继承自HttpServlet基类)。

image-20210201194251639

SpringMVC的原理如下图所示:

​ 当发起请求时被前置的控制器拦截到请求,根据请求参数生成代理请求,找到请求对应的实际控制器,控制器处理请求,创建数据模型,访问数据库,将模型响应给中心控制器,控制器使用模型与视图渲染视图结果,将结果返回给中心控制器,再将结果返回给请求者。

image-20210201194935055

4、SpringMVC执行流程

image-20210201200104654

实线表示SpringMVC框架提供的技术,不需要开发者实现,虚线表示需要开发者实现。

简要分析执行流程:

  1. DispatcherServlet表示前置控制器,是整个SpringMVC的控制中心。用户发出请求,DispathcerServlet接收请求并拦截请求。
    • 我们假设请求的url为:http://localhost:8080/SpringMVC/hello
    • 如上url拆分成三部分:
      • http://localhost:8080 服务器域名
      • SpringMVC 部署在服务器上的web站点
      • hello 表示控制器
    • 通过分析,如上url表示为:请求位于服务器localhost:8080上的SpringMVC站点的hello控制器。
  2. HandlerMapping为处理器映射。DispatcherServlet调用HandlerMapping,HandlerMapping根据请求url查找Handler。
  3. HandlerExecution表示具体的Handler,其主要作用是根据url查找控制器,如上url被查找控制器为:hello。
  4. HandlerExecution将解析后的信息传递给DispatcherServlet,如解析控制器映射等。
  5. HandlerAdapter表示处理器适配器,其按照特定的规则去执行Handler。
  6. Handler让具体的Controller执行。

5、SpringMVC配置流程

SpringMVC用到的依赖:

<dependency>
    <groupId>javax.servlet</groupId>
    <artifactId>javax.servlet-api</artifactId>
    <version>3.1.0</version>
    <scope>provided</scope>
</dependency>
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-webmvc</artifactId>
    <version>5.2.5.RELEASE</version>
</dependency>

配置:

  1. 配置DispatcherServlet。(在web.xml中配置)如:

    ...
    <servlet>
    	<servlet-name>springmvc</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <!-- DispatcherServlet要绑定spring-mvc的配置文件(也就是Spring的配置文件) -->
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath:路径名(如:spring-mvc.xml)</param-value>
             <!--
                在tomcat启动后,创建Servlet对象
                load-on-startup:表示tomcat启动后创建对象的顺序,它的值是大于0的整数,数值越小,tomcat创建对象的时间越早。
    
            -->
            <load-on-startup>1</load-on-startup>
        </init-param>
    </servlet>
    <servlet-mapping>
    	<servlet-name>springmvc</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>
    <!-- 
    	注意:
     	在SpringMVC中,/ /*的区别:
    	/:只匹配所有的请求,不会去匹配jsp页面
    	/*:匹配所有的请求,包括jsp页面
    -->
    ...
    
  2. 配置spring-mvc.xml文件

    ...
    <!-- 开发中可省(开启注解驱动后会自动配置) -->
    <!-- 处理器映射器 -->
    <bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"/>
    <!-- 处理器适配器 -->
    <bean class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter"/>
    
    <!-- 开发中不可省(因为有数据需动态修改)-->
    <!-- 视图解析器:有第三方库:模板引擎 Thymeleaf Freemarker ... 
    我们把所有的视图都存放在/WEB-INF/目录下,这样可以保证视图安全,因为这个目录下的文件,客户端不能直接访问。
    -->
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" id="InternalResourceViewResolver">
    	<!-- 前缀 -->
        <property name="prefix" value="/WEB-INF/jsp/"/>
        <!-- 后缀 -->
        <property name="suffix" value=".jsp"/>
    </bean>
    
    <!-- 请求映射,配合处理器映射器使用 -->
    <!-- BeanNameUrlHandlerMapping:Bean -->
    <bean id="/hello" class="HelloController"/>
    ...
    
  3. 写Controller控制器处理请求

    //可以用注解简化开发,这里是不用注解的例子。
    public class HelloController implements Controller {
        //会根据ModelAndView处理业务逻辑并实现视图跳转
        public ModelAndView handleRequest(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws Exception {
            ModelAndView mv = new ModelAndView();
            
            //业务代码
            
            //视图跳转
            
            return mv;
        }
    }
    

二:基于注解开发

1、基本配置(流程)

  1. 引入相关的依赖:主要有Spring框架核心库、Spring MVC、servlet、JSTL等。

  2. 配置web.xml。

    1. 注意web.xml版本问题,要用最新版
    2. 配置DispathcerServlet
  3. 添加Spring MVC配置文件:

    1. 让IOC的注解生效

    2. 静态资源过滤:HTML、JS、CSS、图片、视频 ……

    3. MVC的注解驱动

    4. 配置视图解析器

      <!-- 自动扫描包,让指定包下的注解生效,由IOC容器统一管理 -->
      <context:component-scan base-package="需扫描的包的路径"/>
      <!-- 让Spring MVC不处理静态资源 -->
      <mvc:default-servlet-handler />
      <!--
      支持MVC注解驱动:
      	在spring中一般采用@RequestMapping注解来完成映射关系
      	要想使用@RequestMapping注解生效
      	必须向上下文注册DefaultAnnotationHandlerMapping
      	和一个AnnotationMethodHandlerAdapter实例
      	这两个实例分别在类级别和方法级别处理。
      	而annotation-driven配置帮助我们自动完成上述两个实例的注入。
      -->
      <mvc:annotaion-driven />
      
      <!--
      第二种处理静态资源的方式:
          mvc:resources 加入后框架会创建 ResourceHttpRequestHandler这个处理器对象。
                   让这个对象处理静态资源的访问,不依赖tomcat服务器。
                   mapping:访问静态资源的url地址,使用通配符 **
                   location:静态资源在你的项目中的目录位置。
      <mvc:resources mapping="/images/**" location="/images/"/>
      -->
      
      
  4. 处理请求:编写Controller或Servlet

    1. Servlet方式:@WebServlet。举例:

      @WebServlet(name = "helloServlet", value = "/hello-servlet")
      public class HelloServlet extends HttpServlet {
          private String message;
      
          public void init() {
              message = "Hello World!";
          }
      
          public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException {
              response.setContentType("text/html");
      
              // Hello
              PrintWriter out = response.getWriter();
              out.println("<html><body>");
              out.println("<h1>" + message + "</h1>");
              out.println("</body></html>");
          }
      
          public void destroy() {
          }
      }
      

2、Controller编写

2.1 常见注解
@RequestMapping
@Target({ElementType.TYPE, ElementType.METHOD})//说明此注解可以在类上也可以在方法上,两种情况作用域不一样。
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Mapping
public @interface RequestMapping {
    String name() default "";

    @AliasFor("path")
    String[] value() default {};

    @AliasFor("value")
    String[] path() default {};

    RequestMethod[] method() default {};

    String[] params() default {};

    String[] headers() default {};

    String[] consumes() default {};

    String[] produces() default {};
}
  • @RequestMapping 注解用于映射url到控制器类或一个特定的处理程序方法。可用于类或方法上。用于类上,表示类中的所有响应请求的方法都是以该地址作为父路径。

    @RequestMapping(...)
    /*
    参数(可选):
    	1、value:String型,作为请求路径名。
    	2、method:约束请求的类型。默认是GET类型。有给定的属性可选 RequestMethod.GET等。
    	
            public enum RequestMethod {
                GET,
                HEAD,
                POST,
                PUT,
                PATCH,
                DELETE,
                OPTIONS,
                TRACE;
    
                private RequestMethod() {
                }
            }
        3、produces:可以设置文本类型。
    */
    
  • 示例:

    /**
    value值为字符串类型,表路径,开头可以加/,也可不加,都是拼接在当前工程根路径下。
    */
    @Controller
    @RequestMapping("system")
    public class SystemController {
    
        @RequestMapping(value = "/index", method = RequestMethod.GET)
        public String index() {
            return "system/index";
        }
    }
    
  • 所有的地址栏请求默认都会是HTTP GET类型的。

  • 方法级别的注解变体有如下几个:组合注解
    @GetMapping
    @PostMapping
    @PutMapping
    @DeleteMapping
    @PatchMapping
    如 @GetMapping 扮演的是 @RequestMapping(method = RequestMethod.GET)的一个快捷方式。

@ResponseBody
  • @ResponseBody 注解能让方法或类,不走视图解析器,直接返回数据至前端。

  • @RestController:标在类上,让类里所有的请求都不走视图解析器,直接返回至前端页面。

  • 标注以上注解的方法的返回值会以json格式返回到页面,所以要注意引入json依赖。

2.2 结果跳转方式
2.2.1 ModelAndView

设置ModelAndView对象,根据view的名称,和视图解析器跳到指定的页面。

页面:{视图解析器前缀} + viewName + {视图解析器后缀}

<!-- 视图解析器 -->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
	<!--前缀:视图文件的路径-->
    <property name="prefix" value="/WEB-INF/view/"/>
    <!--后缀:视图文件的扩展名-->
    <property name="suffix" value=".jsp" />
</bean>

对应的Controller类

public class ControllerTest1 implements Controller {
    public ModelAndView handleRequest(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws Exception {
        //返回一个模型视图对象
        ModelAndView mv = new ModelAndView();
        mv.addObject("msg", "ControllerTest1")
        mv.setViewName("test")
        return mv;
    }
}
2.2.2 ServletAPI

通过设置ServletAPI,不需要视图解析器。

  1. 通过HttpServletResponse进行输出
  2. 通过HttpServletResponse实现重定向
  3. 通过HttpServletResponse实现转发
@Controller
public class ResultGo {
    
    @RequestMapping("/result/t1")
    public void test1(HttpServletRequest req, HttpServletResponse rsp) throws Excepiton {
        rsp.getWriter().println("Hello, Spring BY servlet API");
    }
    
    @RequestMapping("/result/t2")
    public void test2(HttpServletRequest req, HttpServletResponse rsp) throws Excepiton {
        rsp.sendRedirect("/index.jsp");
    }
    
    @RequestMapping("/result/t3")
    public void test3(HttpServletRequest req, HttpServletResponse rsp) throws Excepiton {
        //转发
        req.setAttribute("msg", "/result/t3");
        req.getRequestDispatcher("/WEB-INF/jsp/test.jsp").forward(req, rsp);
    }
}
2.2.3 SpringMVC

通过SpringMVC来实现转发和重定向。(无需视图解析器)

  • 返回值类型为String。返回转发或重定向的路径
@Controller
public class ResultSpringMVC {
    @RequestMapping("/rsm/t1")
    public String test1() {
        //转发
        return "/index.jsp";//有视图解析器时更简便,直接 return "index"
    }
    
    @RequestMapping("/rsm/t2")
    public String test1() {
        //转发二
        return "forward:/index.jsp";
    }
    
    @RequestMapping("/rsm/t3")
    public String test1() {
        //重定向(注意路径问题)
        return "redirect:/index.jsp";
    }
}
2.3 数据处理
2.3.1 处理提交的数据
  1. 提交的域名称和处理方法的参数名一致

    例:

    • 提交数据:http://localhost:8080/hello?name=kuangshen

    • 处理方法:

    @RequestMapping("/hello")
    public String hello(String name) {
        System.out.println(name);
        return "hello";
    }
    
    • 后台输出:kuangshen
  2. 提交的域名称和处理方法的参数名不一样

    • 提交数据:http://localhost:8080/hello?username=kuangshen

    • 处理方法:

      //@RequestParam("username") username是提交的域的名称,还可以加参数 required 是一个boolean,默认是true表示请求中必须包含此参数
      @RequestMapping("/hello")
      public String hello(@RequestParam("username") String name) {
          System.out.println(name);
          return "hello";
      }
      
    • 后台输出:kuangshen

  3. 提交的是一个对象

    • 要求提交的表单域和对象的属性名一致,参数使用对象即可。

    • 实体类:

      public class User {
          private int id;
          private String name;
          private int age;
         
          ...
      }
      
    • 提交数据:http://localhost:8080/user?name=kuangshen&id=1&age=15

    • 处理方法:

      @RequestMapping("/user")
      public String user(User user) {
          System.out.println(user);
          return "hello";
      }
      
    • 后台输出:User{id=1, name=‘kuangshen’, age=15}

    • 说明

      • 如果使用对象的话,前端传递的参数名和对象名必须一致,否则就是null。框架会创建形参的Java对象,给属性赋值。请求中的参数是name,框架会调用setName()
2.3.2 数据显示到前端

第一种:通过ModelAndView

public class ControllerTest1 implements Controller {
    public ModelAndView handleRequest(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws Exception {
        //返回一个模型视图对象
        ModelAndView mv = new ModelAndView();
        mv.addObject("msg", "ControllerTest1")
        mv.setViewName("test")
        return mv;
    }
}

第二种:通过ModelMap

@RequestMapping("/hello")
public String hello(@RequestParam("username") String name, ModelMap model) {
    //封装要显示到视图中的数据
    //相当于req.setAttribute("name", name);
    model.addAttribute("name", name);
    System.out.println(name);
    return "test";
}

第三种:通过Model

@RequestMapping("/ct2/hello")
public String hello(@RequestParam("username") String name, Model model) {
    //封装要显示到视图中的数据
    //相当于req.setAttribute("name", name);
    model.addAttribute("msg", name);
    System.out.println(name);
    return "test";
}

对比

  • Model 只有寥寥几个方法,只适合用于储存数据,简化了新手对于Model对象的操作和理解。
  • ModelMap 继承了LinkedMap,除了实现了自身的一些方法,同样的继承了LinkedMap的方法和特性。
  • ModelAndView 可用在储存数据的同时,可以进行设置返回的逻辑视图,进行控制展示层的跳转。
2.3.3 乱码解决

以前乱码问题通过过滤器解决,而SpringMVC给我们提供了一个过滤器,可以在web.xml中配置。

<filter>
	<filter-name>encoding</filter-name>
    <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
    <init-param>
    	<param-name>encoding</param-name>
        <param-value>utf-8</param-value>
    </init-param>
</filter>
<filter-mapping>
	<filter-name>encoding</filter-name>
    <url-pattern>/</url-pattern><!-- 注意/和/*的区别 -->
</filter-mapping>

有些极端情况下,filter对get方法不支持。

其他解决方法:

  1. 修改tomcat配置文件:设置编码。

    <Connector URIEncoding="utf-8" port="8080" protocol="HTTP/1.1"
               connectionTimeout="2000"
               redirectPort="8443" />
    
  2. 自定义过滤器

2.3.4 Controller返回JSON数据
  • Jackson 应该是目前比较好的json解析工具了

  • 当然工具不止这一个,比如还有阿里巴巴的 fastjson等等。

  • 使用 Jackson,需要导入jar包

    <dependency>
    	<groupId>com.fasterxml.jackson.core</groupId>
        <artifactId>jackson-databind</artifactId>
        <version>2.9.8</version>
    </dependency>
    

乱码问题

1、@RequestMapping配置

@RequestMapping(..., produces="application/json;charset=utf-8")

2、SpringMVC配置处理json乱码问题:

<mvc:annotation-driven>
	<mvc:message-converters register-default="true">
    	<bean class="org.springframework.http.converter.StringHttpMessageConverter">
        	<constructor-arg value="UTF-8"/>
        </bean>
        <bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
        	<property name="objectMapper">
            	<bean class="org.springframework.http.converter.json.Jackson2ObjectMapperFactoryBean">
                	<property name="failOnEmptyBeans" value="false"/>
                </bean>
            </property>
        </bean>
    </mvc:message-converters>
</mvc:annotation-driven>

3、异常处理

SpringMVC 框架处理异常的常用方式:使用==@ExceptionHandler== 注解处理异常。

@ExceptionHandler 注解

  • 使用注解@ExceptionHandler 可以将一个方法指定为异常处理方法。
    • 该注解只有一个可选属性 value,为一个 Class数组,用于指定该注解的方法所要处理的异常类,即所要匹配的异常。
  • 对于异常处理注解的用法,也可以直接将异常处理方法注解于 Controller 之中。

不过,一般不这样使用。而是将异常处理方法专门定义在一个类中,作为 全局的异常处理类。 需要使用注解@ControllerAdvice,字面理解就是“控制器增强”,是给 控制器对象增强功能的。使用@ControllerAdvice 修饰的类中可以使用 @ExceptionHandler。 当使用@RequestMapping 注解修饰的方法抛出异常时,会执行 @ControllerAdvice 修饰的类中的异常处理方法。 @ControllerAdvice 是使用@Component 注解修饰的,可以 扫描到@ControllerAdvice 所在的类路径(包名), 创建对象

三:Controller

Controller(控制器)

  • 控制器负责提供访问应用程序的行为,通常通过接口定义或注解定义两种方法实现。
  • 控制器负责解析用户的请求并将其转换为一个模型。
  • 在Spring MVC中一个控制器类可以包含多个方法。
  • 在Spring MVC中,对于Controller的配置方式有很多种。

方式一:实现Controller接口

Controller是一个接口,在 org.springframework.web.servlet.mvc包下,接口中只有一个方法。

//实现该接口的类获得控制器功能
public interface Controller {
    //处理请求且返回一个模型与视图对象
    ModelAndView handleRequest(HttpServletRequest var1, HttpServletResponse var2) throws Exception;
}

(代码实现跟上面配置里的一样,这里不写了)

说明:

  • 实现接口Controller定义控制器是比较老的办法。
  • 缺点是:一个控制器吧中只有一个方法,如果要多个方法则需要定义多个Controller;定义的方式比较麻烦。

方式二:使用注解

@Controller 用于声明Spring类的实例是一个控制器。配合Spring的扫描机制使用。
被这个注解的类,中的所有方法的返回值,会被视图解析器解析。

@Controller
public TestController {
    
    @RequestMapping("/t1")
    String test1(Model model) {
        
       ……
       return 'test'
    }
    
    @RequestMapping("/t2)
    String test1(Model model) {
        
       ……
       return 'test'
    }
}
                    
/**
发现:
这种情况下,发送上述两个请求发现
两个请求都可以指向同一个视图,但是页面结果的内容是一样的,从这里可以看出视图是被复用的,而控制器与视图之间是弱耦合关系。
*/

四:拦截器

1、概述

SpringMVC的处理器拦截器类似于Servlet开发中的过滤器Filter,用于对处理器进行预处理和后处理。开发者可以自己定义一些拦截器来实现特定的功能。

**过滤器和拦截器的区别:**拦截器是AOP思想的具体应用。

过滤器:

  • servlet规范中的一部分,任何java web工程都可以使用
  • 在 url-pattern中配置了/*之后,可以对所有要访问的资源进行拦截

拦截器:

  • 拦截器是SpringMVC框架自己的,只有使用了SpringMVC框架的工程才能使用
  • 拦截器只会拦截访问的控制器方法,如果访问的是 jsp/html/css/image/js 是不会进行拦截的

2、自定义拦截器

想要自定义拦截器,必须实现 HandlerInterceptor 接口。

public class MyInterceptor implements HandlerInterceptor {

    //在请求处理的方法之前执行
    //如果返回true执行下一个拦截器
    //如果返回false就不执行下一个拦截器
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        return false;
    }

    //在请求处理方法执行之后执行
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {

    }

    //在dispatcherServlet处理后执行,做清理工作
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {

    }
}

springMVC配置:

<!--拦截器配置-->
<mvc:interceptors>
	<mvc:interceptor>
    	<!--包括这个请求下面的所有的请求 / -->
        <mvc:mapping path="/**"/>
        <!-- 用于指定排除的 url-->
        <mvc:exclude-mapping path=""/>
        <bean class="自定义拦截器的全类名"/>
    </mvc:interceptor>
</mvc:interceptors>

五:文件上传

1、准备工作

文件上传是项目开发中最常见的功能之一,springMVC可以很好地支持文件上传,但是SpringMVC上下文中默认没有装配MultipartResolver,因此默认情况下其不能处理文件上传工作。如果想使用Spring的文件上传功能,则需要在上下文中配置MultipartResolver。

前端表单要求:为了能上传文件,必须将表单的method设置为POST,并将enctype设置为multipart/form-data。只有在这样的情况下,浏览器才会把用户选择的文件以二进制数据发送给服务器:

对表单中的 enctype属性做个详细的说明:

  • application/x-www=form-urlencoded:默认方式,只处理表单域中的value属性值,采用这种编码方式的表单会将表单域中的值处理成URL编码方式。
  • multipart/form-data:这种编码方式会以二进制流的方式来处理表单数据,这种编码方式会把文件域指定文件的内容也封装到请求参数中,不会对字符编码。
  • text/plain:除了把空格转换为“+”号外,其他字符都不做编码处理,这种方式适用直接通过表单发送邮件。
<form action="" enctype="multipart/form-data" method="post">
	<input type="file" name="file"/>
    <Input type="submit"/>
</form>

​ 一旦设置了enctype为multipart/form-data,浏览器即会采用二进制流的方式来处理表单数据,而对于文件上传的处理则涉及在服务器端解析原始的HTTP响应。在2003年,Apache Software Foundation发布了开源的Commons FileUpload组件,其很快成为Servlet/JSP程序员上传文件的最佳选择。

  • Servlet3.0规范已经提供方法来处理文件上传,但这种上传需要在Servlet中完成。
  • 而SpringMVC则提供了更简单的封装。
  • SpringMVC为文件上传提供了直接的支持,这种支持是即插即用的MultipartResolver实现的。
  • SpringMVC适用Apache Commons FileUpload技术实现了一个MultipartResolver实现类:CommonsMultipartResolver。因此,SpringMVC的文件上传还需要依赖Apache Commons FileUpload的组件(要引入依赖包)。

2、文件上传

1、导入文件上传的jar包,commos-fileupload,Maven会自动帮我们导入它的依赖包:commons-io包。

<!-- 文件上传 -->
<dependecy>
	<groupId>commons-fileupload</groupId>
    <artifactId>commons-fileupload</artifactId>
    <version>1.3.3</version>
</dependecy>

2、配置bean:multipartResolver
注意:这个bean的id必须为:multipartResolver,否则上传文件会报400的错误!

<!--文件上传配置-->
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
	<!--请求的编码格式,必须和jsp的pageEncoding属性一致,以使正确读取表单的内容,默认为ISO-8859-1 -->
    <property name="defaultEncoding" value="utf-8"/>
    <!--上传文件大小上限,单位为字节(10485760=10M) -->
    <property name="maxUploadSize" value="10485760"/>
    <property name="maxInMemorySize" value="40960"/>
</bean>

CommonsMultipartFile 类的常用方法:

  • String getOriginalFilename():获取上传文件的原名
  • InputStream getInputStream():获取文件流
  • void transferTo(File dest):将上传文件保存到一个目录文件中

扩展

Restful风格

概念
Restful就是一个资源定位及资源操作的风格。不是标准也不是协议,只是一种风格。基于这个风格设计的软件可以更简洁,更有层次,更易于实现缓存等机制。

功能
资源操作

在SpringMVC中应用

在SpringMVC中可以使用 @PathVariable 注解,让方法参数的值对应绑定到一个URL模板变量上。

//映射访问路径
@RequestMapping("/commit/{p1}/(p2)")
public String index(@PathVariable int p1, @PathVariable int p2, Model model) {
    ……
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值