SprinMvc快速入门

Posted Create Sun

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了SprinMvc快速入门相关的知识,希望对你有一定的参考价值。

1.spring mvc

Spring MVC是Spring Framework的一部分,是基于Java实现MVC的轻量级Web框架。

查看官方文档:https://docs.spring.io/spring/docs/5.2.0.RELEASE/spring-framework-reference/web.html#spring-web

1.1.三层结构

B/S架构系统标准的三层架构包括表现层业务层持久层,每一层各司其职, 接下来我们就说说每层都负责哪些方面。

表现层

也就是我们常说的web层。它负责接收客户端请求,向客户端响应结果,通常客户端使用http协议请求web 层,web 需要接收 http 请求,完成 http 响应。

  1. 表现层又包括展示层和控制层:控制层负责接收请求,展示层负责结果的展示。

  2. 表现层依赖业务层,接收到客户端请求一般会调用业务层进行业务处理,并将处理结果响应给客户端。

  3. 表现层的设计一般都使用 MVC 模型。(MVC 是表现层的设计模型,和其他层没有关系)

业务层:

也就是我们常说的 service 。它负责业务逻辑处理,和我们开发项目的需求息息相关。

  1. web 层依赖业务层,但是业务层不依赖 web 层。

  2. 业务层在业务处理时可能会依赖持久层,如果要对数据持久化需要保证事务一致性。(也就是我们说的,事务应该放到业务层来控制)

持久层

也就是我们是常说的 dao 。负责数据持久化,包括数据层即数据库和数据访问层,数据库是对数据进行持久化的载体,数据访问层是业务层和持久层交互的接口,业务层需要通过数据访问层将数据持久化到数据库中。通俗的讲,持久层就是和数据库交互,对数据库表进行曾删改查的。

通过分层更好的实现了各个部分的职责,在每一层将再细化出不同的框架,分别解决各层关注的问题。三层架构与SSM的关系示意图如下,其中SpringMVC属于表现层框架,MyBatis属于持久层框架,而Spring不属于任何一层,是用来整合其它框架的。

1.2.mvc 模型

MVC全名是Model View Controller,是模型(model)-视图(view)-控制器(controller)的缩写,是一种用于设计创建 Web 应用程序表现层的模式。MVC 中每个部分各司其职:

Model(模型)

指的就是我们的数据模型,一般情况下用于封装数据。

View(视图)

指的就是我们的 jsp 或者 html等页面,一般用于展示数据的,其是依据模型数据创建的。

Controller(控制器)

是应用程序中处理用户交互的部分,用来处理程序逻辑的。例如参数校验等。

1.3.Spring MVC

1.3.1.特点:

  1. 清晰的角色划分

    前端控制器(DispatcherServlet)

    请求到处理器映射(HandlerMapping)

    处理器适配器(HandlerAdapter)

    视图解析器(ViewResolver)

    处理器或页面控制器(Controller)

    验证器( Validator)

    命令对象(Command 请求参数绑定到的对象就叫命令对象)

    表单对象(Form Object 提供给表单展示和提交到的对象就叫表单对象)。

  2. 分工明确,而且扩展点相当灵活,可以很容易扩展,虽然几乎不需要。

  3. 由于命令对象就是一个 POJO,无需继承框架特定 API,可以使用命令对象直接作为业务对象。

  4. 和 Spring 其他框架无缝集成,是其它 Web 框架所不具备的。

  5. 可适配,通过 HandlerAdapter 可以支持任意的类作为处理器。

  6. 可定制性,HandlerMapping、ViewResolver 等能够非常简单的定制。

  7. 功能强大的数据验证、格式化、绑定机制。

  8. 利用 Spring 提供的 Mock 对象能够非常简单的进行 Web 层单元测试。

  9. 本地化、主题的解析的支持,使我们更容易进行国际化和主题的切换。

  10. 强大的 JSP 标签库,使 JSP 编写更容易。

  11. 还有比如RESTful风格的支持、简单的文件上传、约定大于配置的契约式编程支持、基于注解的零配置支持,数据验证、格式化、本地化、主题等等。

  12. 用的人多。

1.3.2.执行流程

1.4.SpringMVC 和 Struts2

共同点

  1. 它们都是表现层框架,都是基于 MVC 模型编写的。

  2. 它们的底层都离不开原始 ServletAPI。

  3. 它们处理请求的机制都是一个核心控制器。

区别:

  1. Spring MVC 的入口是 Servlet, 而 Struts2 是 Filter

  2. Spring MVC 是基于方法设计的,而 Struts2 是基于类,Struts2 每次执行都会创建一个动作类。所以 Spring MVC 会稍微比 Struts2 快些。

  3. Spring MVC 使用更加简洁,同时还支持 JSR303, 处理 ajax 的请求更方便(JSR303 是一套 JavaBean 参数校验的标准,它定义了很多常用的校验注解,我们可以直接将这些注解加在我们 JavaBean 的属性上面,就可以在需要校验的时候进行校验了。)

  4. Struts2 的 OGNL 表达式使页面的开发效率相比 Spring MVC 更高些,但执行效率并没有比 JSTL 提升,尤其是 struts2 的表单标签,远没有 html 执行效率高

2.spring mvc入门demo

2.1.配置版

创建model,添加目录java,resources.

实现步骤其实非常的简单:

  1. 新建一个web项目
  2. 导入相关jar包
  3. 编写web.xml , 注册DispatcherServlet
  4. 编写springmvc配置文件
  5. 接下来就是去创建对应的控制类 , controller
  6. 最后完善前端视图和controller之间的对应
  7. 测试运行调试.

2.1.1.添加依赖

<dependencies>
    <!--spring-->
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-context</artifactId>
      <version>${spring.version}</version>
    </dependency>
    <!--spring-web-->
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-web</artifactId>
      <version>${spring.version}</version>
    </dependency>
    <!--spring-mvc-->
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-webmvc</artifactId>
      <version>${spring.version}</version>
    </dependency>
    <!--servletAPI-->
    <dependency>
      <groupId>javax.servlet</groupId>
      <artifactId>servlet-api</artifactId>
      <version>2.5</version>
      <scope>provided</scope>
    </dependency>
</dependencies>

2.1.2.配置web.xml , 注册DispatcherServlet

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
         version="4.0">

  <!--1.注册DispatcherServlet-->
  <servlet>
    <servlet-name>springmvc</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <!--关联一个springmvc的配置文件:【servlet-name】-servlet.xml-->
    <init-param>
      <param-name>contextConfigLocation</param-name>
      <param-value>classpath:springmvc-servlet.xml</param-value>
    </init-param>
    <!--启动级别-1-->
    <load-on-startup>1</load-on-startup>

  </servlet>
  <!--/ 匹配所有的请求;(不包括.jsp)-->
  <!--/* 匹配所有的请求;(包括.jsp)-->
  <servlet-mapping>
    <servlet-name>springmvc</servlet-name>
    <url-pattern>/</url-pattern>
  </servlet-mapping>

</web-app>

2.1.3.添加资源文件springmvc-servlet.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
       https://www.springframework.org/schema/context/spring-context.xsd
       http://www.springframework.org/schema/mvc
       https://www.springframework.org/schema/mvc/spring-mvc.xsd">

    <!--添加 处理映射器-->
    <bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"/>
    <!--添加 处理器适配器-->
    <bean class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter"/>
    <!--视图解析器:DispatcherServlet给他的ModelAndView-->
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" id="InternalResourceViewResolver">
        <!--前缀-->
        <property name="prefix" value="/WEB-INF/page/"/>
        <!--后缀-->
        <property name="suffix" value=".jsp"/>
    </bean>
    <!--将自己的类交给SpringIOC容器,注册bean-->
    <!--Handler-->
    <bean id="/hello" class="com.wyl.HelloController"/>
</beans>

使用springMVC必须配置的三大件:

处理器映射器、处理器适配器、视图解析器

通常,我们只需要手动配置视图解析器,而处理器映射器处理器适配器只需要开启注解驱动即可,而省去了大段的xml配置

2.1.4.添加软件包 com.wyl.controller,添加controller

package com.wyl.controller;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.Controller;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
 * @创建人 王延领
 * @创建时间 2021/10/15
 * 描述
 **/
public class HelloController implements Controller{
    public ModelAndView handleRequest(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws Exception {
        //ModelAndView模型和视图
        ModelAndView mv = new ModelAndView();
        //封装对象,放在ModeAndView
        mv.addObject("msg","王延领学习java");
        //封装要跳转的视图,放在ModelAndView中
        mv.setViewName("hello");
        return mv;
    }
}

2.1.5. 添加映射

 <!--将自己的类交给SpringIOC容器,注册bean-->
    <!--Handler-->
    <bean id="/hello" class="com.wyl.HelloController"/>

2.1.6.添加页面

2.1.7.tomcat运行

2.2.注解版

2.2.1.添加依赖

<dependencies>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.11</version>
      <scope>test</scope>
    </dependency>
    <!--spring-->
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-context</artifactId>
      <version>${spring.version}</version>
    </dependency>
    <!--spring-web-->
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-web</artifactId>
      <version>${spring.version}</version>
    </dependency>
    <!--spring-mvc-->
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-webmvc</artifactId>
      <version>${spring.version}</version>
    </dependency>
    <!--servletAPI-->
    <dependency>
      <groupId>javax.servlet</groupId>
      <artifactId>servlet-api</artifactId>
      <version>2.5</version>
      <scope>provided</scope>
    </dependency>
      <dependency>
          <groupId>org.projectlombok</groupId>
          <artifactId>lombok</artifactId>
          <version>RELEASE</version>
          <scope>compile</scope>
      </dependency>
  </dependencies>

2.2.1.配置web.xml

<?xml version="1.0" encoding="UTF-8"?>
 <!--不要web-app,不然model 返回失效-->
 <web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
         version="4.0">
 
    <!--注册servlet-->
    <servlet>
        <servlet-name>SpringMVC</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <!--通过初始化参数指定SpringMVC配置文件的位置,进行关联-->
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath:springmvc-servlet.xml</param-value>
        </init-param>
        <!-- 启动顺序,数字越小,启动越早 -->
        <load-on-startup>1</load-on-startup>
    </servlet>
 
    <!--所有请求都会被springmvc拦截 -->
    <servlet-mapping>
        <servlet-name>SpringMVC</servlet-name>
        <!--
/ 和/* 的区别:
< url-pattern > / </ url-pattern > 
	不会匹配到.jsp, 只针对我们编写的请求;即:.jsp 不会进入spring的 DispatcherServlet类 。
< url-pattern > /* </ url-pattern > 
	会匹配 *.jsp,会出现返回 jsp视图 时再次进入spring的DispatcherServlet 类,导致找不到对应的controller所以报404错-->
        <url-pattern>/</url-pattern>
    </servlet-mapping>
 </web-app>

2.2.3.添加资源文件springmvc-servlet.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
       https://www.springframework.org/schema/context/spring-context.xsd
       http://www.springframework.org/schema/mvc
       https://www.springframework.org/schema/mvc/spring-mvc.xsd">

   <!-- 自动扫描包,让指定包下的注解生效,由IOC容器统一管理 -->
   <context:component-scan base-package="com.wyl.controller"/>
   <!-- 让Spring MVC不处理静态资源 -->
   <mvc:default-servlet-handler />
   <!--
   支持mvc注解驱动
       在spring中一般采用@RequestMapping注解来完成映射关系
       要想使@RequestMapping注解生效
       必须向上下文中注册DefaultAnnotationHandlerMapping
       和一个AnnotationMethodHandlerAdapter实例
       这两个实例分别在类级别和方法级别处理。
       而annotation-driven配置帮助我们自动完成上述两个实例的注入。
    -->
   <mvc:annotation-driven />

   <!-- 视图解析器 -->
   <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"
         id="internalResourceViewResolver">
       <!-- 前缀 -->
       <property name="prefix" value="/WEB-INF/jsp/" />
       <!-- 后缀 -->
       <property name="suffix" value=".jsp" />
   </bean>

</beans>

2.2.4.添加软件包 com.wyl.controller,添加controller

package com.wyl.controller;

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

/**
 * @创建人 王延领
 * @创建时间 2021/10/18
 * 描述
 **/
@Controller
@RequestMapping("/hello")
public class HelloController {
    @RequestMapping("/sayHello")
    public String hello(Model model) {
        //会被视图解析器处理
        return "hello";
    }
}

2.1.5.添加页面

<%--
  Created by IntelliJ IDEA.
  User: 17144
  Date: 2021/10/15
  Time: 23:55
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
成功!!!
</body>
</html>

3.控制器

3.1.@Controller

  • @Controller注解类型用于声明Spring类的实例是一个控制器;

  • Spring可以使用扫描机制来找到应用程序中所有基于注解的控制器类,为了保证Spring能找到你的控制器,需要在配置文件中声明组件扫描。

    <!-- 自动扫描指定的包,下面所有注解类交给IOC容器管理 -->
    <context:component-scan base-package="com.wyl.controller"/>
    
    //@Controller注解的类会自动添加到Spring上下文中
    @Controller
    public class ControllerTest2{
    
       //映射访问路径
       @RequestMapping("/t2")
       public String index(Model model){
           //Spring MVC会自动实例化一个Model对象用于向视图中传值
           model.addAttribute("msg", "ControllerTest2");
           //返回视图位置
           return "test";
      }
    }
    

3.2.@RequestMapping

3.2.1.RequestMapping注解:

* 作用:

* 用于建立请求URL和处理请求方法之间的对应关系

* 它可以作用在方法、类上

* 作用来类上:作用在类上时,类上的路径作为一级目录

* 在访问方法时需要加类上的路径

* 作用在方法上:指定这个方法要拦截处理哪个URL请求

* 属性:

* value:与path属性的作用是相同的,当只有value一个属性时,属性可以省略,直接写属性值

* path:与value属性作用一致,用于指定请求的URL

* method:用于指定请求的方式,比如POST、GET等使用RequestMethod枚举

* params:用于指定限制请求参数的条件,它支持简单的表达式

* 要求请求参数的key和value必须和配置的一模一样

* headers:用于指定限制请求消息头的条件

@Controller
@RequestMapping("/User")
public class RequestMappingDemoController {
    @RequestMapping("SetView")
    public String SetView(){
        System.out.println("Hello SpringMvc");
        //返回逻辑视图名
        return "success";
    }
    //类上加了@RequestMapping注解后,此方法拦截的URL变成了:user/testRequestMapping
    @RequestMapping("/testRequestMapping")
    public String testRequestMapping(){
        System.out.println("测试RequestMapping注解。。");
        //返回逻辑视图名
        return "success";
    }

    //指定此方法只能由POST请求访问
    @RequestMapping(path = {"/testRequestMappingMethod"},method = {RequestMethod.POST})
    public String testRequestMappingMethod(){
        System.out.println("测试RequestMapping注解的method属性。。");
        //返回逻辑视图名
        return "success";
    }
    //指定此方法必须带有name属性,且属性值必须为admin
    //http://localhost:8080/User/testRequestMappingParams?name=admin
    @RequestMapping(path = {"/testRequestMappingParams"},params = {"name=admin"})
    public String testRequestMappingParams(){
        System.out.println("测试RequestMapping注解的params属性。。");
        //返回逻辑视图名
        return "success";
    }
    //指定请求头中必须包含accept属性
    @RequestMapping(path = {"/testRequestMappingHeaders"},headers = {"accept"})
    public String testRequestMappingHeaders(){
        System.out.println("测试RequestMapping注解的headers属性。。");
        //返回逻辑视图名
        return "success";
    }
  }

3.2.2.RestFul风格

    //映射访问路径
   @RequestMapping("/commit/{p1}/{p2}")
   public String index(@PathVariable int p1, @PathVariable int p2, Model model){
       
       int result = p1+p2;
       //Spring MVC会自动实例化一个Model对象用于向视图中传值
       model.addAttribute("msg", "结果:"+result);
       //返回视图位置
       return "test";
       
  }   
  • REST(英文:Representational State Transfer,简称REST)描述了一个架构样式的网络系统,比如 web 应用程序。它首次出现在 2000 年 Roy Fielding 的博士论文中,他是 HTTP 规范的主要编写者之一。在目前主流的三种Web服务交互方案中,REST相比于SOAP(Simple Object Access protocol,简单对象访问协议)以及XML-RPC更加简单明了,无论是对URL的处理还是对Payload的编码,REST都倾向于用更加简单轻量的方法设计和实现。值得注意的是REST并没有一个明确的标准,而更像是一种设计的风格。

  • 它本身并没有什么实用性,其核心价值在于如何设计出符合REST风格的网络接口。

  • restful的优点 :

    • 它结构清晰、符合标准、易于理解、扩展方便,所以正得到越来越多网站的采用。
  • restful的特性:

    • 资源(Resources):

      • 网络上的一个实体,或者说是网络上的一个具体信息。 它可以是一段文本、一张图片、一首歌曲、一种服务,总之就是一个具体的存在。可以用一个URI(统一资源定位符)指向它,每种资源对应一个特定的 URI 。要 获取这个资源,访问它的URI就可以,因此 URI 即为每一个资源的独一无二的识别符。
    • 表现层(Representation):

      • 把资源具体呈现出来的形式,叫做它的表现层 (Representation)。 比如,文本可以用 txt 格式表现,也可以用 HTML 格式、XML 格式、JSON 格式表现,甚至可以采用二进制格式。
    • 状态转化(State Transfer):

      • 每 发出一个请求,就代表了客户端和服务器的一次交互过程。 HTTP协议,是一个无状态协议,即所有的状态都保存在服务器端。因此,如果客户端想要操作服务器,必须通过某种手段,让服务器端发生“状态转化”(State Transfer)。而这种转化是建立在表现层之上的,所以就是 “表现层状态转化”。具体说,就是 HTTP 协议里面,四个表示操作方式的动词:GET、POST、PUT、DELETE。它们分别对应四种基本操作:GET 用来获取资源,POST 用来新建资源,PUT 用来更新资源,DELETE 用来删除资源。

3.2.3.组合注解

@GetMapping
@PostMapping
@PutMapping
@DeleteMapping
@PatchMapping

@GetMapping 是一个组合注解@RequestMapping(method =RequestMethod.GET) 的一个快捷方式

//原来的:http://localhost:8080/add?a=1&b=2
    //RestFul风格:http://localhost:8080/add/a/b
    // @RequestMapping(value = "/add/{a}/{b}",method = RequestMethod.GET)
    @GetMapping("/add/{a}/{b}")
    public String test1(@PathVariable int a, @PathVariable int b, Model model) {//@PathVariable路径变量
        int res = a + b;
        model.addAttribute("msg", "结果为:" + res);
        return "test";
    }

    // @RequestMapping(value = "/add/{a}/{b}",method = RequestMethod.Post)
    @PostMapping("/add/{a}/{b}")
    public String test2(@PathVariable int a, @PathVariable int b, Model model) {//@PathVariable路径变量
        int res = a + b;
        model.addAttribute("msg", "结果为:" + res);
        return "test";
    }

3.3.结果跳转

3.3.1.ModelAndView

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

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

<!-- 视图解析器 -->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"
     id="internalResourceViewResolver">
   <!-- 前缀 -->
   <property name="prefix" value="/WEB-INF/jsp/" />
   <!-- 后缀 -->
   <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","ModelAndView 返回!!!");
       mv.setViewName("test");
       return mv;
  }
}

3.3.2.ServletAPI

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

1、通过HttpServletResponse进行输出

2、通过HttpServletResponse实现重定向

3、通过HttpServletResponse实现转发

@Controller
public class ResultGo {

   @RequestMapping("/result/t1")
   public void test1(HttpServletRequest req, HttpServletResponse rsp) throws IOException {
       rsp.getWriter().println("Hello,Spring BY servlet API");
  }

   @RequestMapping("/result/t2")
   public void test2(HttpServletRequest req, HttpServletResponse rsp) throws IOException {
       rsp.sendRedirect("/index.jsp");
  }
   @RequestMapping("/result/t3")
   public void test3(HttpServletRequest req, HttpServletResponse rsp) throws Exception {
       //转发
       req.setAttribute("msg","/result/t3");
       req.getRequestDispatcher("/WEB-INF/jsp/test.jsp").forward(req,rsp);
  }

}

3.3.3.SpringMVC

通过SpringMVC来实现转发和重定向 - 无需视图解析器;

测试前,需要将视图解析器注释掉

@Controller
public class ResultSpringMVC {
   @RequestMapping("/rsm/t1")
   public String test1(){
       //转发
       return "/index.jsp";
  }

   @RequestMapping("/rsm/t2")
   public String test2(){
       //转发二
       return "forward:/index.jsp";
  }

   @RequestMapping("/rsm/t3")
   public String test3(){
       //重定向
       return "redirect:/index.jsp";
  }
}

通过SpringMVC来实现转发和重定向 - 有视图解析器;

重定向 , 不需要视图解析器 , 本质就是重新请求一个新地方嘛 , 所以注意路径问题.

可以重定向到另外一个请求实现 .

@Controller
public class ResultSpringMVC2 {
   @RequestMapping("/rsm2/t1")
   public String test1(){
       //转发
       return "test";
  }

   @RequestMapping("/rsm2/t2")
   public String test2(){
       //重定向
       return "redirect:/index.jsp";
  }
     @RequestMapping("/rsm2/t2")
   public String test2(){
       //重定向
       return "redirect:hello.do";
  }
}

3.4.处理提交数据

3.4.1.提交的域名称和处理方法的参数名一致

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

处理方法 :

@RequestMapping("/hello")
public String hello(String name){
   System.out.println(name);
   return "test";
}

3.4.2.提交的域名称和处理方法的参数名不一致

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

处理方法 :

/**
* 请求参数绑定
* 请求的参数中如果有username属性的话,
* SpringMVC会自动将参数传入与方法参数列表对应的入参中
* @return
*/
@RequestMapping("/hello")
public String hello(@RequestParam("username") String name){
   System.out.println(name);
   return "test";
}

3.4.3.提交的是一个对象

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

1、实体类

public class User {
   private int id;
   private String name;
   private int age;
   //构造
   //get/set
   //tostring()
}

2、提交数据 : http://localhost:8080/mvc04/user?name=wyl&id=1&age=18

3、处理方法

/**
*1、接收到的前端用户传递参数,判断参数的名字,假设名字直接在方法上,可以直接使用
*2、假设传递的是一个对象user,就会匹配user对象的字段名;如果字段一致则OK,否则匹配不到
*/
@RequestMapping("/user")
public String user(User user){
   System.out.println(user);
   return "hello";
}

3.3.4.获取原生ServletAPI对象

提交数据 : http://localhost:8080/hello?username=wyl&password=123456

处理方法

/**
* 获取原生ServletAPI对象
* 需要哪个对象,在方法入参处定义就好了
* @param request
* @param response
* @return
*/
    @RequestMapping("/hello")
    public String hello(HttpServletRequest request, HttpServletResponse response){
        System.out.println("获取原生ServletAPI对象。。。");
        System.out.println("request:"+request);
        System.out.println("从request对象中获取的用户名:"+request.getParameter("username"));
        System.out.println("从request对象中获取的密码:"+request.getParameter("password"));
        System.out.println("response:"+response);
        System.out.println("session:"+request.getSession());
        System.out.println("application:"+request.getSession().getServletContext());
        //返回逻辑视图名
        return "success";
    }

3.5.返回结果

3.5.1.ModelAndView

public class ControllerTest1 implements Controller {

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

3.5.2.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 "hello";
}

3.5.3.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 可以在储存数据的同时,可以进行设置返回的逻辑视图,进行控制展示层的跳转。

4.异常处理

4.1.异常处理的思路

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

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

4.2.编写异常类和错误页面

/**
 * 自定义异常
 */
public class CustomException extends Exception {
  private String message;

  public CustomException(String message) {
    this.message = message;
  }

  public String getMessage() {
    return message;
  }
}
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>

<head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <title>执行失败</title>
</head>

<body>
    执行失败!
    ${message }
</body>
</html>

4.3.自定义异常处理器

/**
 * 自定义异常处理器
 */
public class CustomExceptionResolver implements HandlerExceptionResolver {

  @Override
  public ModelAndView resolveException(
    HttpServletRequest request,
    HttpServletResponse response,
    Object handler,
    Exception ex
  ) {
    ex.printStackTrace();
    CustomException customException = null;

    //如果抛出的是系统自定义异常则直接转换
    if (ex instanceof CustomException) {
      customException = (CustomException) ex;
    } else {
      //如果抛出的不是系统自定义异常则重新构造一个系统错误异常。
      customException = new CustomException("系统错误,请与系统管理 员联系!");
    }
    ModelAndView modelAndView = new ModelAndView();
    modelAndView.addObject("message", customException.getMessage());
    modelAndView.setViewName("error");
    return modelAndView;
  }
}

4.4.

<!-- 配置自定义异常处理器 -->
 <bean id="handlerExceptionResolver" 
        class="com.wyl.exception.CustomExceptionResolver" />

5.json处理

ajax我经常用到,传的数据是json数据,json数据又有对象,数组。所有总结下springmvc获取前端传来的json数据方式

5.1.Controller接受JSON数据

作用:

@ResponseBody注解用于将Controller的方法返回的对象,通过springmvc提供的HttpMessageConverter接口转换为指定格式的数据如:json,xml等,通过Response响应给客户端。

本例子应用:

@ResponseBody注解实现将Controller方法返回java对象转换为json响应给客户端。

5.1.1.以RequestParam接收

前端传来的是json数据不多时:[id:id],可以直接用@RequestParam来获取值

@Autowired
private AccomodationService accomodationService;

@RequestMapping(value = "/update")
@ResponseBody
public String updateAttr(@RequestParam ("id") int id) {
    int res=accomodationService.deleteData(id);
    return "success";
}

5.1.2.以实体类方式接收

前端传来的是一个json对象时:{【id,name】},可以用实体类直接进行自动绑定

@Autowired
private AccomodationService accomodationService;

    @RequestMapping(value = "/add")
    @ResponseBody
    public String addObj(@RequestBody Accomodation accomodation) {
        this.accomodationService.insert(accomodation);
        return "success";
    }

5.1.3.以Map接收

前端传来的是一个json对象时{【id,name】},可以用Map来获取

@Autowired
private AccomodationService accomodationService;

@RequestMapping(value = "/update")
@ResponseBody
public String updateAttr(@RequestBody Map<String, String> map) {
    if(map.containsKey("id"){
        Integer id = Integer.parseInt(map.get("id"));
    }
    if(map.containsKey("name"){
        String objname = map.get("name").toString();
    }
    // 操作 ...
    return "success";
}

5.1.4.以List接收

当前端传来这样一个json数组[{id,name},{id,name},{id,name},...]时,用List接收

@Autowired
private AccomodationService accomodationService;

@RequestMapping(value = "/update")
@ResponseBody
//参数前面必须又@RequestBody
public String updateAttr(@RequestBody List<Accomodation> list) {
    for(Accomodation accomodation:list){
        System.out.println(accomodation.toString());
    }
    return "success";
}

ajax请求

var testList=[];
var user={};
user.id=1;
user.name=\'jack\';
testList.push(user);
var user2={};
user2.id=2;
user2.name=\'tom\';
testList.push(user2);
$.ajax({
    // headers必须添加,否则会报415错误
    headers: {
        \'Accept\': \'application/json\',
        \'Content-Type\': \'application/json\'
    },
  type: \'POST\',
  dataType: "json", //表示返回值类型,不必须
  data: JSON.stringify(testList),
  url: \'/test/postList\',
  success: function(){
      alert(\'success\');
  }
  
});

需要注意点:1、参数是数组类型

      2、传入data时,转换 JSON.stringify(testList)

      3、必须有headers:

{ \'Accept\': \'application/json\',
  \'Content-Type\': \'application/json\'
}

5.2.Controller返回JSON数据

5.2.1.Jackson

Jackson应该是目前比较好的json解析工具了

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

我们这里使用Jackson,使用它需要导入它的jar包;

<!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-core -->
<dependency>
   <groupId>com.fasterxml.jackson.core</groupId>
   <artifactId>jackson-databind</artifactId>
   <version>2.9.8</version>
</dependency>

Controller

这里我们需要两个新东西,一个是@ResponseBody,一个是ObjectMapper对象,我们看下具体的用法

public class UserController {

   @RequestMapping("/json1")
   @ResponseBody
   public String json1() throws JsonProcessingException {
       //创建一个jackson的对象映射器,用来解析数据
       ObjectMapper mapper = new ObjectMapper();
       //创建一个对象
       User user = new User("wyl", 3, "男");
       //将我们的对象解析成为json格式
       String str = mapper.writeValueAsString(user);
       //由于@ResponseBody注解,这里会将str转成json格式返回;十分方便
       return str;
  }
}

在类上直接使用 @RestController ,这样子,里面所有的方法都只会返回 json 字符串了,不用再每一个都添加@ResponseBody !我们在前后端分离开发中,一般都使用 @RestController ,十分便捷!

@RestController
public class UserController {

   //produces:指定响应体返回类型和编码
   @RequestMapping(value = "/json1")
   public String json1() throws JsonProcessingException {
       //创建一个jackson的对象映射器,用来解析数据
       ObjectMapper mapper = new ObjectMapper();
       //创建一个对象
       User user = new User("wyl", 3, "男");
       //将我们的对象解析成为json格式
       String str = mapper.writeValueAsString(user);
       //由于@ResponseBody注解,这里会将str转成json格式返回;十分方便
       return str;
  }

}

抽取为工具类

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;

import java.text.SimpleDateFormat;

public class JsonUtils {
   
   public static String getJson(Object object) {
       return getJson(object,"yyyy-MM-dd HH:mm:ss");
  }

   public static String getJson(Object object,String dateFormat) {
       ObjectMapper mapper = new ObjectMapper();
       //ps:Jackson 默认是会把时间转成timestamps形式(取消timestamps形式 , 自定义时间格式)
       mapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
       //自定义日期格式对象
       SimpleDateFormat sdf = new SimpleDateFormat(dateFormat);
       //指定日期格式
       mapper.setDateFormat(sdf);
       try {
           return mapper.writeValueAsString(object);
      } catch (JsonProcessingException e) {
           e.printStackTrace();
      }
       return null;
  }
}

demo

@RequestMapping("/jsonUnit")
public String json5() throws JsonProcessingException {
   Date date = new Date();
   String json = JsonUtils.getJson(date);
   return json;
}

5.2.2.FastJson

fastjson.jar是阿里开发的一款专门用于Java开发的包,可以方便的实现json对象与JavaBean对象的转换,实现JavaBean对象与json字符串的转换,实现json对象与json字符串的转换。实现json的转换方法很多,最后的实现结果都是一样的。

fastjson 的 pom依赖!

<dependency>
   <groupId>com.alibaba</groupId>
   <artifactId>fastjson</artifactId>
   <version>1.2.60</version>
</dependency>

fastjson 三个主要的类:

JSONObject 代表 json 对象

  • JSONObject实现了Map接口, 猜想 JSONObject底层操作是由Map实现的。
  • JSONObject对应json对象,通过各种形式的get()方法可以获取json对象中的数据,也可利用诸如size(),isEmpty()等方法获取"键:值"对的个数和判断是否为空。其本质是通过实现Map接口并调用接口中的方法完成的。

JSONArray 代表 json 对象数组

  • 内部是有List接口中的方法来完成操作的。

JSON代表 JSONObject和JSONArray的转化

  • JSON类源码分析与使用
  • 仔细观察这些方法,主要是实现json对象,json对象数组,javabean对象,json字符串之间的相互转化。

代码测试,我们新建一个FastJsonDemo 类

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.kuang.pojo.User;

import java.util.ArrayList;
import java.util.List;

public class FastJsonDemo {
   public static void main(String[] args) {
       //创建一个对象
       User user1 = new User("wyl1号", 3, "男");
       User user2 = new User("wyl2号", 3, "男");
       User user3 = new User("wyl3号", 3, "男");
       User user4 = new User("wyl4号", 3, "男");
       List<User> list = new ArrayList<User>();
       list.add(user1);
       list.add(user2);
       list.add(user3);
       list.add(user4);

       System.out.println("*******Java对象 转 JSON字符串*******");
       String str1 = JSON.toJSONString(list);
       System.out.println("JSON.toJSONString(list)==>"+str1);
       String str2 = JSON.toJSONString(user1);
       System.out.println("JSON.toJSONString(user1)==>"+str2);

       System.out.println("\\n****** JSON字符串 转 Java对象*******");
       User jp_user1=JSON.parseObject(str2,User.class);
       System.out.println("JSON.parseObject(str2,User.class)==>"+jp_user1);

       System.out.println("\\n****** Java对象 转 JSON对象 ******");
       JSONObject jsonObject1 = (JSONObject) JSON.toJSON(user2);
       System.out.println("(JSONObject) JSON.toJSON(user2)==>"+jsonObject1.getString("name"));

       System.out.println("\\n****** JSON对象 转 Java对象 ******");
       User to_java_user = JSON.toJavaObject(jsonObject1, User.class);
       System.out.println("JSON.toJavaObject(jsonObject1, User.class)==>"+to_java_user);
  }
}

6.拦截器

6.1.过滤器与拦截器的区别

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

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

过滤器

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

拦截器

  • 拦截器是SpringMVC框架自己的,只有使用了SpringMVC框架的工程才能使用

  • 拦截器只会拦截访问的控制器方法, 如果访问的是jsp/html/css/image/js是不会进行拦截的

6.2.自定义拦截器

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

6.2.1. 编写一个普通类实现HandlerInterceptor 接口

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

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

public class MyInterceptor implements HandlerInterceptor {

   //在请求处理的方法之前执行
   //如果返回true执行下一个拦截器
   //如果返回false就不执行下一个拦截器
   public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o) throws Exception {
       System.out.println("------------处理前------------");
       return true;
  }

   //在请求处理方法执行之后执行
   public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception {
       System.out.println("------------处理后------------");
  }

   //在dispatcherServlet处理后执行,做清理工作.
   public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception {
       System.out.println("------------清理------------");
  }
}

6.1.2. 配置拦截器

 <!--关于拦截器的配置-->
<mvc:interceptors>
   <mvc:interceptor>
       <!--/** 包括路径及其子路径-->
       <!--/admin/* 拦截的是/admin/add等等这种 , /admin/add/user不会被拦截-->
       <!--/admin/** 拦截的是/admin/下的所有-->
       <mvc:mapping path="/**"/>
       <!--bean配置的就是拦截器-->
       <bean class="com.wyl.interceptor.MyInterceptor"/>
   </mvc:interceptor>
</mvc:interceptors>

6.2.3.控制器

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

//测试拦截器的控制器
@Controller
public class InterceptorController {

   @RequestMapping("/interceptor")
   @ResponseBody
   public String testFunction() {
       System.out.println("控制器中的方法执行了");
       return "hello";
  }
}

6.2.3.前端 index.jsp

<a href="${pageContext.request.contextPath}/interceptor">拦截器测试</a>

6.3.拦截器的细节

6.3.1. 拦截器的放行

放行的含义是指,如果有下一个拦截器就执行下一个,如果该拦截器处于拦截器链的最后一个,则执行控制器中的方法。

6.3.2.拦截器中方法的说明

public interface HandlerInterceptor {
  /**
   * preHandle方法是controller方法执行前拦截的方法,按拦截器定义顺序调用
   *    return true放行,执行下一个拦截器,如果没有拦截器,执行controller中的方法进行业务处理。
   *    return false不放行,不会执行controller中的方法或调用其他的组件。
   */
  default boolean preHandle(
    HttpServletRequest request,
    HttpServletResponse response,
    Object handler
  )
    throws Exception {
    return true;
  }

  /**
   * postHandle是controller方法执行后执行的方法,在JSP视图执行前,按拦截器定义逆序调用。
   *     可以使用request或者response跳转到指定的页面
   *     如果指定了跳转的页面,那么controller方法跳转的页面将不会显示。
   */
  default void postHandle(
    HttpServletRequest request,
    HttpServletResponse response,
    Object handler,
    @Nullable ModelAndView modelAndView
  )
    throws Exception {}

  /**
   * afterCompletion方法是在JSP执行后执行,按拦截器定义逆序调用
   *      注意:因为结果页面已经返回完了,不能在该方法使用request或者response再跳转页面,但可以在该方法中进行一些资源清理的操作。
   */
  default void afterCompletion(
    HttpServletRequest request,
    HttpServletResponse response,
    Object handler,
    @Nullable Exception ex
  )
    throws Exception {}
}

6.3.3. 拦截器的作用路径

作用路径可以通过在配置文件中配置。

<!-- 配置拦截器的作用范围 -->
<mvc:interceptors>
    <mvc:interceptor>
        <mvc:mapping path="/**" /><!-- 用于指定对拦截的url -->
        <mvc:exclude-mapping path="" /><!-- 用于指定排除的url-->
        <bean id="handlerInterceptorDemo1" 
                class="com.wyl.interceptor.HandlerInterceptorDemo1">
         </bean>
    </mvc:interceptor>
</mvc:interceptors>

6.3.4. 多个拦截器的执行顺序

多个拦截器是按照配置的顺序决定的。

6.3.4.1. 拦截器1 的代码

public class HandlerInterceptorDemo1 implements HandlerInterceptor {

  @Override
  public boolean preHandle(
    HttpServletRequest request,
    HttpServletResponse response,
    Object handler
  )
    throws Exception {
    System.out.println("拦截器 1: preHandle 拦截器拦截了");
    return true;
  }

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

  @Override
  public void afterCompletion(
    HttpServletRequest request,
    HttpServletResponse response,
    Object handler,
    Exception ex
  )
    throws Exception {
    System.out.println("拦截器 1: afterCompletion 方法执行了");
  }
}

6.3.4.2. 拦截器2 的代码:

public class HandlerInterceptorDemo2 implements HandlerInterceptor {

  @Override
  public boolean preHandle(
    HttpServletRequest request,
    HttpServletResponse response,
    Object handler
  )
    throws Exception {
    System.out.println("拦截器2: preHandle 拦截器拦截了");
    return true;
  }

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

  @Override
  public void afterCompletion(
    HttpServletRequest request,
    HttpServletResponse response,
    Object handler,
    Exception ex
  )
    throws Exception {
    System.out.println("拦截器2: afterCompletion 方法执行了");
  }
}

6.3.4.3.配置拦截器的作用范围

  <mvc:interceptor>
    <mvc:mapping *path*="/**" />*<!--* *用于指定对拦截的**url -->*
    <bean *id*="handlerInterceptorDemo1" *class*="com.wyl.interceptor.HandlerInterceptorDemo1"></bean>
  </mvc:interceptor>
  <mvc:interceptor>
    <mvc:mapping *path*="/**" />   
      <bean *id*="handlerInterceptorDemo2" *class*="com.wyl.interceptor.HandlerInterceptorDemo2"></bean>
  </mvc:interceptor>

6.3.4.4.中断流程测试

拦截器2 返回false

7.上传文件

7.1.导入文件上传的jar包

<!--文件上传
commons-io 不属于文件上传组件的开发jar 文件,但Commons-fileupload 组件从1.1 版本开始,它 
工作时需要commons-io 包的支持。
-->
<dependency>
   <groupId>commons-fileupload</groupId>
   <artifactId>commons-fileupload</artifactId>
   <version>1.3.3</version>
</dependency>
<!--servlet-api导入高版本的-->
<dependency>
   <groupId>javax.servlet</groupId>
   <artifactId>javax.servlet-api</artifactId>
   <version>4.0.1</version>
</dependency>

7.2. 编写文件上传的jsp 页面

<h3>文件上传</h3>
<form action="user/fileupload" method="post" enctype="multipart/form-data">
    选择文件:<input type="file" name="upload" /><br />
    <input type="submit" value="上传文件" />
</form>
  1. 至少有一个文件选择域

  2. 以POST方式提交

  3. 表单的enctype必须为 multipart/form-data

7.3.控制器(非SpringMVC版)

package com.wyl.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.multipart.commons.CommonsMultipartFile;

import javax.servlet.http.HttpServletRequest;
import java.io.*;

@Controller
public class FileController {
   //@RequestParam("file") 将name=file控件得到的文件封装成CommonsMultipartFile 对象
   //批量上传CommonsMultipartFile则为数组即可
   @RequestMapping("/upload")
   public String fileUpload(@RequestParam("file") CommonsMultipartFile file , HttpServletRequest request) throws IOException {

       //获取文件名 : file.getOriginalFilename();
       String uploadFileName = file.getOriginalFilename();

       //如果文件名为空,直接回到首页!
       if ("".equals(uploadFileName)){
           return "redirect:/index.jsp";
      }
       System.out.println("上传文件名 : "+uploadFileName);

       //上传路径保存设置
       String path = request.getServletContext().getRealPath("/upload");
       //如果路径不存在,创建一个
       File realPath = new File(path);
       if (!realPath.exists()){
           realPath.mkdir();
      }
       System.out.println("上传文件保存地址:"+realPath);

       InputStream is = file.getInputStream(); //文件输入流
       OutputStream os = new FileOutputStream(new File(realPath,uploadFileName)); //文件输出流

       //读取写出
       int len=0;
       byte[] buffer = new byte[1024];
       while ((len=is.read(buffer))!=-1){
           os.write(buffer,0,len);
           os.flush();
      }
       os.close();
       is.close();
       return "redirect:/index.jsp";
  }
}

7.4.SpringMVC配置信息

SpringMVC框架提供了MultipartFile对象,该对象表示上传的文件,要求变量名称必须和表单file标签的name属性名称相同。

<!-- 配置文件解析器对象,要求id名称必须是multipartResolver -->
<bean id="multipartResolver" 
       class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
    <!-- 设置上传文件的最大尺寸为5MB -->
    <property name="maxUploadSize">
        <value>5242880</value>
    </property>
    <!-- property name="maxUploadSize" value="10485760"/ -->
</bean>

7.5.控制器代码(SpringMVC版)

/**
* SpringMVC方式的文件上传
*/
@RequestMapping(value="/fileupload2")
public String fileupload2(HttpServletRequest request,MultipartFile upload) throws Exception {
System.out.println("SpringMVC方式的文件上传...");
    // 先获取到要上传的文件目录
    String path = request.getSession().getServletContext().getRealPath("/uploads");
    // 创建File对象,一会向该路径下上传文件
    File file = new File(path);
    // 判断路径是否存在,如果不存在,创建该路径
    if(!file.exists()) {
        file.mkdirs();
    }

    // 获取到上传文件的名称
    String filename = upload.getOriginalFilename();
    String uuid = UUID.randomUUID().toString().replaceAll("-", "").toUpperCase();
    // 把文件的名称唯一化
    filename = uuid+"_"+filename;
    // 上传文件
    upload.transferTo(new File(file,filename));
    return "success";
}

7.6.跨服务器

准备两个tomcat 服务器,其中一个作为文件服务器,一个作为应用服务器。

7.6.1.在文件服务器tomcat的web.xml中修改tomcat配置,允许读写操作。

7.6.2.导入包

<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>

7.6.3.控制器

**
* SpringMVC跨服务器方式的文件上传
*/
@RequestMapping(value="/fileupload3")
public String fileupload3(MultipartFile upload) throws Exception {
    System.out.println("SpringMVC跨服务器方式的文件上传...");
    // 定义图片服务器的请求路径
    String path = "http://localhost:9090/day02_springmvc5_02image/uploads/";
    // 获取到上传文件的名称
    String filename = upload.getOriginalFilename();
    String uuid = UUID.randomUUID().toString().replaceAll("-", "").toUpperCase();
    // 把文件的名称唯一化
    filename = uuid+"_"+filename;
    
    // 向图片服务器上传文件
    // 创建客户端对象(sun公司提供的jersey 包)
    Client client = Client.c

Flume快速入门

参考技术A

Flume是开源日志系统。是一个分布式、可靠性和高可用的海量日志聚合系统,支持在系统中定制各类数据发送方,用于收集数据;同时,FLume提供对数据进行简单处理,并写到各种数据接收方(可定制)的能力。

Flume是流式日志采集工具,FLume提供对数据进行简单处理并且写到各种数据接收方(可定制)的能力,Flume提供从本地文件(spooling directory source)、实时日志(taildir、exec)、REST消息、Thift、Avro、Syslog、Kafka等数据源上收集数据的能力。

Flume是收集、聚合事件流数据的分布式框架。

Flume分布式系统中最核心的角色是 agent ,Flume采集系统就是由一个个agent所连接起来形成
每一个agent相当于一个数据传递员 ,内部有三个组件:

Source 到Channel 到Sink之间传递数据的形式是Event事件; Event事件是一个数据流单元 。

Flume基础架构:Flume可以单节点直接采集数据,主要应用于集群内数据。

Flume多agent架构:Flume可以将多个节点连接起来,将最初的数据源经过收集,存储到最终的存储系统中。主要应用于集群外的数据导入到集群内。

各组件具体介绍如下:

Source负责接收events或通过特殊机制产生events,并将events批量放到一个或多个Channels。有驱动和轮询2中类型的Source。

Source必须至少和一个channel关联。

Source的类型如下:

Channel位于Source和Sink之间,Channel的作用类似队列,用于临时缓存进来的events,当Sink成功地将events发送到下一跳的channel或最终目的,events从Channel移除。

不同的Channel提供的持久化水平也是不一样的:

Channels支持事物,提供较弱的顺序保证,可以连接任何数量的Source和Sink。

Sink负责将events传输到下一跳或最终目的,成功完成后将events从channel移除。

必须作用于一个确切的channel。

Sink类型:

Flume支持将集群外的日志文件采集并归档到HDFS、HBase、Kafka上,供上层应用对数据分析、清洗数据使用。

Flume支持将多个Flume级联起来,同时级联节点内部支持数据复制。

这个场景主要应用于:收集FusionInsight集群外上的节点上的日志,并通过多个Flume节点,最终汇聚到集群当中。

Flume级联节点之间的数据传输支持压缩和加密,提升数据传输效率和安全性。

在同一个Flume内部进行传输时,不需要加密,为进程内部的数据交换。

Source接收的数据量,Channel缓存的数据量,Sink写入的数据量,这些都可以通过Manager图形化界面呈现出来。

Flume在传输数据过程中,采用事物管理方式,保证数据传输过程中数据不会丢失,增强了数据传输的可靠性,同时缓存在channel中的数据如果采用了file channel,进程或者节点重启数据不会丢失。

Flume在传输数据过程中,如果下一跳的Flume节点故障或者数据接收异常时,可以自动切换到另外一路上继续传输。

Flume在传输数据过程中,可以见到的对数据简单过滤、清洗,可以去掉不关心的数据,同时如果需要对复杂的数据过滤,需要用户根据自己的数据特殊性,开发过滤插件,Flume支持第三方过滤插件调用

以上是关于SprinMvc快速入门的主要内容,如果未能解决你的问题,请参考以下文章

c#代码片段快速构建代码

freemaker 快速入门

推荐net开发cad入门阅读代码片段

前端开发工具vscode如何快速生成代码片段

前端开发工具vscode如何快速生成代码片段

如何使用sublime代码片段快速输入PHP头部版本声明