SpringMVC框架

SpringMVC 概述

SpringMVC 是什么

  1. 是一种基于Java实现的MVC设计模型的请求驱动类型的轻量级WEB框架。
  2. Spring MVC属于SpringFrameWork的后续产品,已经融合在Spring Web Flow里面。Spring 框架提供
    了构建 Web 应用程序的全功能 MVC 模块。
  3. 使用 Spring 可插入的 MVC 架构,从而在使用Spring进行WEB开发时,可以选择使用Spring的
    SpringMVC框架或集成其他MVC开发框架,如Struts1(现在一般不用),Struts2等。

SpringMVC 在三层架构的位置

在这里插入图片描述

SpringMVC 的优势

1、清晰的角色划分:

  1. 前端控制器(DispatcherServlet)
  2. 请求到处理器映射(HandlerMapping)
  3. 处理器适配器(HandlerAdapter)
  4. 视图解析器(ViewResolver)
  5. 处理器或页面控制器(Controller)
  6. 验证器(Validator)
  7. 命令对象(Command 请求参数绑定到的对象就叫命令对象)
  8. 表单对象(Form Object提供给表单展示和提交到的对象就叫表单对象

2、分工明确,而且扩展点相当灵活,可以很容易扩展,虽然几乎不需要。
3、由于命令对象就是一个POJO,无需继承框架特定 API,可以使用命令对象直接作为业务对象。
4、和 Spring 其他框架无缝集成,是其它 Web 框架所不具备的。
5、可适配,通过 HandlerAdapter 可以支持任意的类作为处理器。
6、可定制性,HandlerMapping、ViewResolver 等能够非常简单的定制。
7、功能强大的数据验证、格式化、绑定机制。
8、利用 Spring 提供的 Mock 对象能够非常简单的进行 Web 层单元测试。
9、本地化、主题的解析的支持,使我们更容易进行国际化和主题的切换。
10、强大的 JSP 标签库,使 JSP 编写更容易。
………………还有比如RESTful风格的支持、简单的文件上传、约定大于配置的契约式编程支持、基于注解的零配 置支持等等

SpringMVC 和 Struts2 的优略分析

共同点: 它们都是表现层框架,都是基于 MVC 模型编写的。 它们的底层都离不开原始 ServletAPI。
它们处理请求的机制都是一个核心控制器。

区别:
Spring MVC 的入口是 Servlet, 而 Struts2 是 Filter
Spring MVC 是基于方法设计的,而Struts2 是基于类,Struts2 每次执行都会创建一个动作类。所 以 Spring MVC 会稍微比 Struts2 快些。
Spring MVC 使用更加简洁,同时还支持 JSR303, 处理 ajax 的请求更方便 (JSR303 是一套 JavaBean参数校验的标准,它定义了很多常用的校验注解,我们可以直接将这些注 解加在我们 JavaBean的属性上面,就可以在需要校验的时候进行校验了)
Struts2 的 OGNL 表达式使页面的开发效率相比 Spring MVC更高些,但执行效率并没有比 JSTL 提 升,尤其是 struts2 的表单标签,远没有 html 执行效率高。

SpringMVC入门

快速入门

  1. 创建WEB骨架的Maven工程

为了解决Maven项目创建过慢(每次都从中央仓库下载),可以添加一行
key: archetypeCatalog
value:internal
在这里插入图片描述

  1. 配置Tomcat,补全遗漏的文件(java,resources)
    在这里插入图片描述
  2. 配置依赖坐标
 <!-- 版本锁定 -->
<properties>
    <spring.version>5.0.2.RELEASE</spring.version>
</properties>
<dependencies>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context</artifactId>
        <version>${spring.version}</version>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-web</artifactId>
        <version>${spring.version}</version>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-webmvc</artifactId>
        <version>${spring.version}</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>
  1. 创建前端控制器(servlet)
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.4"
         xmlns="http://java.sun.com/xml/ns/j2ee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
  <servlet>
    <servlet-name>servlet1</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <init-param>
      <!--用于让该servlet一初始化,就读取SpringMvc配置文件-->
      <param-name>contextConfigLocation</param-name>
      <param-value>classpath:SpringMvc.xml</param-value>
    </init-param>
    <!--服务器一开启,该servlet就被创建-->
    <load-on-startup>1</load-on-startup>
  </servlet>
  <servlet-mapping>
    <servlet-name>servlet1</servlet-name>
    <url-pattern>/</url-pattern>
  </servlet-mapping>
</web-app>   
  1. 创建控制器类
/*
* 该类是一个控制器类
* */

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
public class HelloController {

    @RequestMapping("/hello")
    public String sayHello(){
        System.out.println("HelloController");
        return "success";
    }
}
  1. 创建SpringMVC的配置文件
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:mvc="http://www.springframework.org/schema/mvc"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="
       http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd
       http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd
       http://www.springframework.org/schema/context
       http://www.springframework.org/schema/context/spring-context.xsd">
    <!--配置spring容器创建时要扫描的包-->
    <context:component-scan base-package="controller"></context:component-scan>
    <!--开启springMVC的支持-->
    <mvc:annotation-driven></mvc:annotation-driven>
    <!--视图解析器-->
    <bean id="viewController" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <!--前端控制器会将数据发送到 WEB-INF下的xxx.jsp中-->
        <property name="prefix" value="WEB-INF/"></property>
        <property name="suffix" value=".jsp"></property>
    </bean>
</beans>

运行原理

在这里插入图片描述

  1. 当启动Tomcat服务器的时候,因为配置了load-on-startup标签,所以会创建DispatcherServlet对象,就会加载springmvc.xml配置文件

  2. 开启了注解扫描,那么HelloController对象就会被创建

  3. 从index.jsp发送请求,请求会先到达DispatcherServlet核心控制器,根据配置@RequestMapping注解,找到执行的具体方法

  4. 根据执行方法的返回值,再根据配置的视图解析器,去指定的目录下查找指定名称的JSP文件

  5. Tomcat服务器渲染页面,做出响应

  6. 入门案例中的组件分析

    1. 前端控制器(DispatcherServlet)
    2. 处理器映射器(HandlerMapping)
    3. 处理器(Handler)
    4. 处理器适配器(HandlAdapter)
    5. 视图解析器(View Resolver)
    6. 视图(View)

< mvc:annotation-driven >说明
在 SpringMVC 的各个组件中,处理器映射器、处理器适配器、视图解析器称为 SpringMVC 的三大组件。
使 用 mvc:annotation-driven 自动加载 RequestMappingHandlerMapping (处理映射器) 和RequestMappingHandlerAdapter ( 处 理 适 配 器 ) , 可 用 在 SpringMVC.xml 配 置 文 件 中, 使 用mvc:annotation-driven替代注解处理器和适配器的配置

RequestMapping注解

  1. RequestMapping注解的作用是建立请求URL和处理方法之间的对应关系
  2. RequestMapping注解可以作用在方法和类上
    1. 作用在类上:第一级的访问目录
    2. 作用在方法上:第二级的访问目录
    3. 细节:路径可以不编写 / 表示应用的根目录开始
    4. 细节:${ pageContext.request.contextPath }也可以省略不写,但是路径上不能写 /
  3. RequestMapping的属性
    1. path 指定请求路径的url
    2. value value属性和path属性是一样的
    3. mthod 指定该方法的请求方式
    4. params 用于指定限制请求参数的条件。它支持简单的表达式。要求请求参数的 key 和 value 必须和配置的一模一样。
      例如:
      params = {“accountName”},表示请求参数必须有 accountName
      params = {“moeny!100”},表示请求参数中 money 不能是 100。
    5. headers 发送的请求中必须包含的请求头
    6. 以上四个属性只要出现 2 个或以上时,他们的关系是与的关系

请求参数绑定

1、绑定机制

  1. 表单提交的数据都是k=v格式的 username=haha&password=123
  2. SpringMVC的参数绑定过程是把表单提交的请求参数,作为控制器中方法的参数进行绑定的
  3. 要求:提交表单的name和参数的名称是相同的
<a href="account/findAccount?accountId=10">查询账户</a>

@RequestMapping("/findAccount")
//自动绑定accountId参数
public String findAccount(Integer accountId) {
System.out.println("查询了账户。。。。"+accountId);
return "success"; }

2、支持的数据类型

  1. 基本类型参数:包括基本类型和 String 类型
  2. POJO 类型参数:包括实体类,以及关联的实体类
  3. 数组和集合类型参数:包括 List 结构和 Map 结构的集合(包括数组)

注意

  1. 当参数类型为POJO,提交表单的name和JavaBean中的属性名称需要一致; 如果一个JavaBean类中包含其他的引用类型,那么表单的name属性需要编写成:对象.属性 例如:user.name
<form action="/params" method="post">
    姓名:<input type="text" name="name">
    余额:<input type="text" name="money">
    用户姓名:<input type="text" name="user.name">
    用户年龄:<input type="text" name="user.age">
    <input type="submit" value="提交">
</form>
  1. 当参数类型为集合类型时
<form action="/params" method="post">
    姓名:<input type="text" name="name">
    余额:<input type="text" name="money">
    
    用户姓名:<input type="text" name="list[0].name">
    用户年龄:<input type="text" name="list[0].age">

    用户姓名:<input type="text" name="map['one'].name">
    用户年龄:<input type="text" name="map['one'].age">
    <input type="submit" value="提交">
</form>

请求参数解决中文乱码问题

在web.xml中配置Spring提供的过滤器类

<!--配置编码过滤器-->
<filter>
  <filter-name>encodingFilter</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>encodingFilter</filter-name>
  <url-pattern>/*</url-pattern>
</filter-mapping>

自定义类型转换器

使用步骤

  1. 自定义转换器类,实现Converter接口
public class DIYConverter implements Converter<String, Date> {
    @Override
    //自定义转换器,将String类型转为Date类型
    public Date convert(String source) {
        if (source == null) {
            throw new RuntimeException("参数为null");
        }else{
            try {
                DateFormat df=new SimpleDateFormat("yyyy-MM-dd");
                //若String类型格式符合规则,转换成Date对象
                Date date = df.parse(source);
                return date;
            } catch (ParseException e) {
                e.printStackTrace();
                throw new RuntimeException("转换异常");
            }
        }
    }
}
  1. 配置自定义转换器
<!--自定义转换器,将我们自定义的转换器类,添加到spring的转换器中-->
<bean id="converter" class="org.springframework.context.support.ConversionServiceFactoryBean">
    <property name="converters">
        <set>
            <bean class="converter.DIYConverter"></bean>
        </set>
    </property>
</bean>
  1. 开启自定义转换器
<!--开启springMVC的支持,并且使自定义转换器生效-->
<mvc:annotation-driven conversion-service="converter"></mvc:annotation-driven>

获取原生ServletAPI

直接在方法参数上添加Http请求,Http响应即可

public void getAPI(HttpServletRequest req, HttpServletResponse resp){
    HttpSession session = req.getSession();
    ServletContext servletContext = session.getServletContext();
    System.out.println(req);
    System.out.println(session);
    System.out.println(resp);
    System.out.println(servletContext);
}

常用注解

  1. RequestParam

    1. 作用:把请求中的指定名称的参数传递给控制器中的形参赋值
    2. 属性
      1. value:请求参数中的名称
      2. required:请求参数中是否必须提供此参数,默认值是true,为必须提供此参数,且名称必须一致
    3. 例如
      @RequestMapping(“reqParam”)
      public void requestParam(@RequestParam(“name”) String username){
      System.out.println(username);
      }
  2. RequestBody

    1. 作用:用于获取请求体的内容(注意:get方法不可以)

    2. 属性

      1. required:是否必须有请求体,默认值是true‘
    3. 例如
      @RequestMapping(“reqBody”)
      public void requestBody(@RequestBody String body){
      System.out.println(body);
      }

  3. PathVariable注解

    1. 作用:拥有绑定url中的占位符的。例如:url中有/delete/{id},{id}就是占位符
    2. 属性
      1. value:指定url中的占位符名称
    3. 例如
      @RequestMapping(“pathVariable/{sid}”)
      //将占位符的sid的值,赋值给形参id
      public void pathVariable(@PathVariable(“sid”) String id){
      System.out.println(id);
      }
    4. Restful风格的URL
      1. 请求路径一样,可以根据不同的请求方式去执行后台的不同方法
    5. restful风格的URL优点
      1. 结构清晰
      2. 符合标准
      3. 易于理解
      4. 扩展方便
  4. RequestHeader注解

    1. 作用:获取指定请求头的值
    2. 属性
      1. value:请求头的名称
    3. 例如
      @RequestMapping(“requestHeader”)
      public void requestHeader(@RequestHeader(“accept”) String header){
      System.out.println(header);
      }
  5. CookieValue注解

    1. 作用:用于获取指定cookie的名称的值
    2. 属性
      1. value:cookie的名称
    3. 例如
      @RequestMapping(“cookieValue”)
      public void cookieValue (@CookieValue(“JSESSIONID”) String cookie){
      System.out.println(cookie);
      }
  6. ModelAttribute注解

    1. 作用
      1. 出现在方法上:表示当前方法会在控制器方法执行前先执行。
      2. 出现在参数上:获取指定的数据给参数赋值。
    2. 应用场景
      当提交表单数据不是完整的实体数据时,保证没有提交的字段使用数据库原来的数据
  7. SessionAttributes注解

    1. 作用:用于多次执行控制器方法间的参数共享,只能作用于类上
    2. 属性
      1. value:指定存入属性的名称

ModelAttribute注解示例

/*
 * @ModelAttribute
 * 先于控制器方法前执行,作用于方法或者参数上
 *   1. 出现在方法上:表示当前方法会在控制器方法执行前先执行。
 *   2. 出现在参数上:获取指定的数据给参数赋值。
 * */
@RequestMapping("modelAttribute")
public void modelAttribute(@ModelAttribute("user1") User user) {
    System.out.println(user);
}

/*
 * 先于控制器方法执行,获取到传递的参数,手动封装user,返回user对象
 * 控制器方法执行时,获取到该user对象
 * */
@ModelAttribute
public User completeUser(String name, Integer age) {
    User user = new User();
    user.setId(1);
    user.setAge(age);
    user.setName(name);
    return user;
}

/*
 * 先于控制器方法执行,获取到传递的参数,手动封装user,存入Map集合,无返回值
 * 控制器方法执行时,使用@ModelAttribute注解,获取Map集合中的数据
 * */
@ModelAttribute
public void completeUser(String name, Integer age, Map<String, User> map) {
    User user = new User();
    user.setId(2);
    user.setAge(age);
    user.setName(name);
    map.put("user1",user);
}

SessionAttributes注解示例

/*
 * 设置请求对象中参数
 * @SessionAttributes注解设置到类上,可以将请求参数添加到session中
 * */
@RequestMapping("setSession")
public void setRequest(ModelMap model) {
    //相当于request.setAttribute()
    model.addAttribute("msg", "请求信息");
}

/*
 * 获取session中的参数
 * */
@RequestMapping("getSession")
public void getSession(ModelMap model) {
    String msg = (String) model.get("msg");
    System.out.println(msg);
}
/*
* 删除session中的参数
* */
@RequestMapping("delSession")
public void delSession(SessionStatus status){
    status.setComplete();
}

响应数据和结果视图

返回值分类

  1. 返回字符串
    Controller方法返回字符串可以指定逻辑视图的名称,根据视图解析器为物理视图的地址。
/*
* 返回值为String
* 视图解析器会自动帮助查找页面
* */
@RequestMapping("/testString")
public String testString(ModelMap modelMap){
   //模拟从数据库获取数据,并转发给jsp页面过程
   User user=new User();
   user.setId(1);
   user.setName("maki");
   user.setMoney(1000);

   modelMap.addAttribute("user",user);
   //根据视图解析器,查找页面
   return "success";
}
  1. 返回值是void
    1. 默认会跳转到@RequestMapping("/xxx") xxx的页面
    2. 可以使用请求转发或者重定向跳转到指定的页面
    3. 注意:请求转发和重定向,不再使用视图解析器
/*
* 返回值为void
* 默认情况会找,请求映射中的文件地址 例如:xxx/xxx/testVoid.jsp
* 可以手动编写请求转发,重定向
* */
@RequestMapping("/testVoid")
public void testVoid(HttpServletRequest req, HttpServletResponse resp) throws Exception{
   //模拟从数据库获取数据,并转发给jsp页面过程
   User user=new User();
   user.setId(2);
   user.setName("maki");
   user.setMoney(2313);

/*      //请求转发
   req.setAttribute("user",user);
   req.getRequestDispatcher("pages/success.jsp").forward(req,resp);*/

   //重定向
   resp.sendRedirect(req.getContextPath()+"pages/success.jsp");

   resp.setContentType("text/html;charset=UTF-8");
   resp.getWriter().println("hello");
   return;
}
}
  1. 返回值是ModelAndView对象
    ModelAndView对象是Spring提供的一个对象,可以用来调整具体的JSP视图
/*
* 返回值为ModelAndView对象
* 其实就是返回值为String的另一种写法格式
* */
@RequestMapping("/testModelAndView")
public ModelAndView testModelAndView(){
 ModelAndView mv=new ModelAndView();
   //模拟从数据库获取数据,并转发给jsp页面过程
   User user=new User();
   user.setId(4);
   user.setName("yui");
   user.setMoney(2333);

   //相当于modelMap.addAttribute("user",user);
   mv.addObject("user",user);
   //相当于 return "success";
   mv.setViewName("success");
   return mv;
}
  1. 使用关键字请求转发/重定向
/*
* 使用关键字进行请求转发和重定向
* */
@RequestMapping("testForwardOrRedirect")
public String testForwardOrRedirect(){
   //请求转发
   //return "forward:/pages/success.jsp";

   //请求重定向,spring框架自动在路径上添加了全项目名
   return "redirect:index.jsp";
}

ResponseBody响应异步请求

静态资源不拦截

  1. DispatcherServlet会拦截到所有的资源,导致一个问题就是静态资源
    (img、css、js)也会被拦截到,从而不能被使用。
  2. 解决问题就是需要配置静态资源不进行拦截,在springmvc.xml配置文件添加如下配置
    mvc:resources标签配置不过滤
    location元素表示webapp目录下的包下的所有文件
    mapping元素表示以/xxx开头的所有请求路径,如/xxx/a 或者/xxx/a/b
<!--告知前端控制器,静态资源不拦截-->
<mvc:resources location="/css/" mapping="/css/**"/>
<mvc:resources location="/images/" mapping="/images/**"/> 
<mvc:resources location="/js/" mapping="/js/**"/>

导入依赖坐标

json字符串和JavaBean对象互相转换的过程中,需要使用jackson的jar包

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

发送异步请求

发送一个json数据类型的异步请求

<script src="js/jquery-3.3.1.min.js"></script>
<script>
    //页面加载,绑定单击事件
    $(function (){
        $("#bt").click(function () {
            //发送异步请求
            $.ajax({
                url:"testAjax",                                         //请求url
                contentType:"application/json;charset=utf-8",           //请求头信息,表示mime类型和字符集
                data:'{"name":"maki","money":"2000","id":"3"}',         //请求体内容(发送给服务器端的数据)
                dataType:"json",                                        //请求体内容的数据格式
                type:"post",                                            //请求方式
                success:function (data) {                               //回调函数,响应成功后执行
                    //data表示服务器端响应的json数据
                    //有了jackson的坐标,spring会自动将javaBean转为json
                    alert(data.name);
                    alert(data.money);
                    alert(data.id);
                }
            });
        });
    });
</script>

接收并响应异步请求

/*
* 有了jackson坐标,spring会自动将请求体中的json数据转为javaBean
* 使用@ResponseBody注解
* spring会自动将javaBean转为json,传给回调函数
* */
@RequestMapping("testAjax")
public @ResponseBody User testAjax(@RequestBody User jsonData){
    System.out.println(jsonData);
    jsonData.setName("yui");
    jsonData.setId(2);
    jsonData.setMoney(2333);
    return jsonData;
}

文件上传

文件上传的必要前提

  1. form 表单的 enctype 取值必须是:multipart/form-data
    (默认值是:application/x-www-form-urlencoded)
    enctype:是表单请求正文的类型
  2. method 属性取值必须是 Post
  3. 提供一个文件选择域< input type=”file” />

文件上传的原理分析

当 form 表单的 enctype 取值不是默认值后,request.getParameter()将失效。 enctype=”application/x-www-form-urlencoded”时,form 表单的正文内容是:
key=value&key=value&key=value
当 form 表单的 enctype 取值为 Mutilpart/form-data 时,请求正文内容就变成:
每一部分都是 MIME 类型描述的正文
----------------------------------------------7de1a433602ac 分界符
Content-Disposition: form-data; name=“userName” 协议头
-----------------------------7de1a433602ac
Content-Disposition: form-data; name=“file”; 协议的正文
filename=“C:\Users\zhy\Desktop\fileupload_demofile\b.txt”
Content-Type: text/plain 协议的类型(MIME 类型)
bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
-----------------------------7de1a433602ac–

借助第三方组件实现文件上传

使用 Commons-fileupload 组件实现文件上传,需要导入该组件相应的支撑 jar 包:Commons-fileupload 和commons-io。
commons-io 不属于文件上传组件的开发 jar 文件,但Commons-fileupload 组件从 1.1 版本开始,它工作时需要 commons-io 包的支持。
依赖坐标

<dependency>
  <groupId>commons-fileupload</groupId>
  <artifactId>commons-fileupload</artifactId>
  <version>1.3.1</version>
</dependency>
<dependency>
  <groupId>commons-io</groupId>
  <artifactId>commons-io</artifactId>
  <version>2.4</version>
</dependency>

原始的上传方法

@RequestMapping("befUpload")
public String befUpload(HttpServletRequest req) throws Exception {
   //先获取到要上传的文件目录
   String realPath = req.getSession().getServletContext().getRealPath("/uploads");
   System.out.println(realPath);
   //创建File对象,一会向该路径下上传文件
   File file = new File(realPath);
   if (!file.exists()) {
       //若文件不存在,创建文件
       file.mkdirs();
   }
   //创建磁盘文件项工厂
   DiskFileItemFactory factory = new DiskFileItemFactory();
   ServletFileUpload upload = new ServletFileUpload(factory);
   //解析request对象
   List<FileItem> items = upload.parseRequest(req);
   for (FileItem item : items) {
       //判断文件项是普通字段,还是上传字段
       if (item.isFormField()) {

       } else {
           //获取到上传文件的名称
           String filename = item.getName();
           //上传文件
           item.write(new File(file, filename));
           //删除临时文件
           item.delete();
       }
   }
   return "success";
}

SpringMVC上传原理

在这里插入图片描述

SpringMVC上传方法

  1. 上传页面
<%-- SpringMvc上传文件操作,由前端控制器将请求体内容,发给文件解析器,获取到表单中的上传项,自动绑定到方法的形参上(形参名必须等于表单项的name值)--%>
<h3>SpringMVC文件上传方式</h3>
<form action="/mvcUpload" method="post" enctype="multipart/form-data" >
    <input type="file" value="选择文件" name="upload">
    <input type="submit" value="提交">
</form>
  1. 配置一个文件解析器(需要jar包支持)
<!--
   文件解析器,用来解析表单中的上传文件项
   id值为固定写法
   可以设置一些参数,例如:限制文件上传大小
-->
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
   <property name="maxUploadSize" value="10485760"></property>
</bean>
  1. 控制器中的方法
/*
* SpringMVC方式实现文件上传
* 形参必须与input文件上传标签的name属性值一样,才能自动绑定
* */
@RequestMapping("mvcUpload")
public String mvcUpload(HttpServletRequest req,MultipartFile upload) throws IOException {
   //获取要上传的文件目录
   String realPath = req.getSession().getServletContext().getRealPath("uploads");
   System.out.println(realPath);
   //创建File对象,一会向该文件目录下上传文件
   File file=new File(realPath);
   if(!file.exists()){
       file.mkdirs();
   }
   //获取上传文件项的文件名
   String uploadName = upload.getOriginalFilename();
   System.out.println(uploadName);
   //上传文件
   upload.transferTo(new File(file,uploadName));
   return "success";
}

SpringMVC跨平台服务器上传

  1. 搭建一个新的服务器
  2. 导入开发需要的jar包
<!--用于使用spring MVC方式实现跨平台服务器上传-->
<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>
  1. 上传页面
<%-- SpringMVC跨服务器上传--%>
<h3>SpringMVC跨服务器上传</h3>
<form action="/acrossServiceUpload" method="post" enctype="multipart/form-data" >
    <input type="file" value="选择文件" name="upload">
    <input type="submit" value="提交">
</form>
  1. 同样需要文件解析器
<!--
   文件解析器,用来解析表单中的上传文件项
   id值为固定写法
   可以设置一些参数,例如:限制文件上传大小
-->
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
   <property name="maxUploadSize" value="10485760"></property>
</bean>
  1. 后台代码
/*
* SpringMVC方式实现跨服务器上传
* 形参必须与input文件上传标签的name属性值一样,才能自动绑定
* */
@RequestMapping("acrossServiceUpload")
public String acrossServiceUpload(MultipartFile upload) throws IOException {
   //获取要上传的服务器中的路径
   String path="http:localhost:9090/uploads/";
   //获取上传文件项的文件名
   String uploadName = upload.getOriginalFilename();
   System.out.println(uploadName);
   //向另一个服务器上传文件

   //1. 创建客户端对象
   Client client = Client.create();
   //2. 连接另一个服务器
   WebResource resource = client.resource(path+uploadName);
   //3. 上传文件
   resource.put(upload.getBytes());
   return "success";
}

SpringMVC中的异常处理

异常处理原理分析

在这里插入图片描述

实现步骤

  1. 编写自定义异常类
public class MyException extends Exception{
    //异常提示信息
    private String message;
    @Override
    public String getMessage() {
        return message;
    }
    public void setMessage(String message) {
        this.message = message;
    }
    public MyException(String message) {
        this.message = message;
    }
}
  1. 编写自定义的异常处理器(实现HandlerExceptionResolver接口)
public class MyExceptionResolver implements HandlerExceptionResolver {
    /*
    * 当前端控制器接收到异常信息时,会跳转到异常处理器来解决(需要先注册该处理器)
    * 跳转到具体的错误页面的方法
    * */
    public ModelAndView resolveException(HttpServletRequest req, HttpServletResponse resp, Object o, Exception e) {
        ModelAndView mv=new ModelAndView();
        MyException myexc=null;
        //若接收到的异常信息属于我们自定义的异常类,强转
        if(e instanceof MyException){
            myexc=(MyException)e;
        }else{
            //若接收到的异常信息不属于自定义的异常类,设置一个新的异常信息
            myexc=new MyException("服务器维护中...");
        }
        //存入异常信息
        mv.addObject("errorMsg",myexc.getMessage());
        //跳转错误页面
        mv.setViewName("error");
        return mv;
    }
}
  1. 配置异常处理器
<!--注册异常处理器-->
<bean id="exceptionResolver" class="exception.MyExceptionResolver"></bean>

SpringMVC中的拦截器

  1. 拦截器的概述
    SpringMVC框架中的拦截器用于对Controller中的方法进行预处理和后处理的技术。
  2. 可以定义拦截器链,就是将拦截器按着一定的顺序结成一条链,在访问被拦截的方法时,拦截器链中的拦截器会按着定义的顺序执行。
  3. 拦截器和过滤器的功能比较类似,有区别
    1. 过滤器是Servlet规范的一部分,任何框架都可以使用过滤器技术。
    2. 拦截器是SpringMVC框架独有的。
    3. 过滤器配置了/*,可以拦截任何资源。
    4. 拦截器只会对控制器中的方法进行拦截。
  4. 拦截器也是AOP思想的一种实现方式
  5. 想要自定义拦截器,需要实现HandlerInterceptor接口。

自定义拦截器步骤

  1. 创建类,实现HandlerInterceptor接口,重写需要的方法
public class MyInterceptor implements HandlerInterceptor {

    /*
    * 控制器中方法执行前,先执行
    * 返回值:true-放行   false-不放行
    * */
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.println("拦截器在方法执行前...........执行了");
        return true;
    }

    /*
     * 控制器中方法执行后,跳转页面前,先执行
     * */
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        System.out.println("拦截器在方法执行后,跳转页面前...........执行了");
    }

    /*
     * 控制器中方法执行后,跳转页面后,再执行
     * */
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        System.out.println("拦截器在方法执行后,跳转页面后...........执行了");
    }
}
  1. 在springmvc.xml中配置拦截器类
<!--配置拦截器们-->
<mvc:interceptors>
   <!--配置拦截器,若有多个拦截器,需要写多个该标签-->
   <mvc:interceptor>
       <!--那些方法进行拦截-->
       <mvc:mapping path="/*"/>
       <!--哪些方法不拦截-->
       <mvc:exclude-mapping path="/find*"/>
       <!--注册拦截器对象-->
       <bean class="interceptor.MyInterceptor"></bean>
   </mvc:interceptor>
</mvc:interceptors>

HandlerInterceptor接口中的方法

  1. preHandle方法是controller方法执行前拦截的方法
    1. 可以使用request或者response跳转到指定的页面
    2. return true放行,执行下一个拦截器,如果没有拦截器,执行controller中的方法。
    3. return false不放行,不会执行controller中的方法。
  2. postHandle是controller方法执行后执行的方法,在JSP视图执行前。
    1. 可以使用request或者response跳转到指定的页面
    2. 如果指定了跳转的页面,那么controller方法跳转的页面将不会显示。
  3. postHandle方法是在JSP执行后执行
    1. request或者response不能再跳转页面了
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值