SpringMVC

MVC三层架构

JavaSE:认真学习,老师带,入门快

JavaWeb:认真学习,老师带,入门快

框架:研究官方文档,锻炼自学能力,锻炼笔记能力,锻炼项目能力

Spring: IOC 和 AOP

SpringMVC:SpringMVC的执行流程

1. 什么是MVC?

模型(Model):dao,service

视图(View):jsp

控制器(Controller):Servlet

  • 拓展的一个思想:

实体类:pojo 例如User类有20个字段(用户名、密码、生日。。。)

当前端所需要的实体类字段没有那么多时,可能还会在pojo的基础上拆分出vo等

vo:意思为视图层中的实体类

pojo中的实体类可以写上所有字段,vo中的实体类就写需要在前端显示的字段

2. Maven创建web项目

1. 创建一个web项目,采用不勾选的方式:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-TecNF9Zw-1602517447290)(G:\学习笔记\SpringMVC学习笔记\image\1.PNG)]

2. 右键项目,选择Add Frameworks Support,添加框架支持

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-37xI41pI-1602517447293)(G:\学习笔记\SpringMVC学习笔记\image\2.PNG)]

3. 右键项目,选择Add Frameworks Support,添加框架支持

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-0VmZVtnn-1602517447295)(G:\学习笔记\SpringMVC学习笔记\image\3.PNG)]

这样原来的默认项目就成为了web项目:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-XeWnNv0A-1602517447298)(G:\学习笔记\SpringMVC学习笔记\image\4.PNG)]

这种不勾选的方式存在一个弊端:

就是我们的导入的依赖jar包,无法导出到war包中,需要我们手动创建lib文件夹并导入:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-aIadeWrq-1602517447301)(G:\学习笔记\SpringMVC学习笔记\image\5.PNG)]

要想不用手动导入依赖Jar包,还是要选择Maven骨架中的webapp进行创建web项目

3. MVC框架要做的事情

  1. 将url映射到java类或者java类的方法
  2. 封装用户提交的数据
  3. 处理请求–调用相关的业务处理–封装相应数据
  4. 将响应的数据进行渲染 jsp/html等视图层
  • 扩展

    MVVM:M , V , VM → ViewModel:双向绑定 (在Vue中有体现)

4. 为什么学习SpringMVC

  • SpringMVC的特点

    1. 轻量级,简单易学

    2. 高效,基于请求响应的MVC框架

    3. 与Spring兼容性好,无缝结合

      Spring:大杂烩,我们可以将SpringMVC中所有要用到的bean,注册到Spring中

    4. 约定优于配置

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

    6. 简洁灵活

  • 最重要的一点还是用的人多,使用的公司多

5. SpringMVC开发步骤

  1. 在pom.xml中导入相关依赖

  2. 在web.xml中配置DispatcherServlet(前端控制器)

  3. 编写springmvc的配置文件:

    扫描注解、视图解析器、不处理静态资源、适配器和映射器的注册

  4. 编写Controller类,@Controller注解 或者 @RestController注解

    接收前端数据 + 封装数据 + 跳转视图 或者 接收前端数据 + 返回Json字符串

  5. 编写视图层,数据渲染

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-3nIoyWlE-1602517447303)(G:\学习笔记\SpringMVC学习笔记\image\6.png)]

6. SpringMVC的执行原理

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-LgCxzI3l-1602517447305)(G:\学习笔记\SpringMVC学习笔记\image\7.png)]

  1. 用户发送请求至前端控制器DispatcherServlet。

  2. DispatcherServlet收到请求调用HandlerMapping处理器映射器。

  3. 处理器映射器找到具体的处理器(可以根据xml配置、注解进行查找),生成处理器对象及处理器拦截器(如果有则生成)一并返回给DispatcherServlet。

  4. DispatcherServlet调用HandlerAdapter处理器适配器。

  5. HandlerAdapter经过适配调用具体的处理器(Controller,也叫后端控制器)。

  6. Controller执行完成返回ModelAndView。

  7. HandlerAdapter将controller执行结果ModelAndView返回给DispatcherServlet。

  8. DispatcherServlet将ModelAndView传给ViewReslover视图解析器。

  9. ViewReslover解析后返回具体View。

  10. DispatcherServlet根据View进行渲染视图(即将模型数据填充至视图中)。

  11. DispatcherServlet响应用户。

7. SpringMVC组件解析

1. 前端控制器

Spring的web框架围绕DispatcherServlet设计。

DispatcherServlet的作用是拦截请求,并将请求分发到不同的处理器。

从Spring 2.5开始,使用Java 5或者以上版本的用户可以采用基于注解的controller声明方式。

DispatcherServlet是一个实际的Servlet,它继承了HttpServlet。

DispatcherServlet 的存在降低了组件之间的耦合性

我们需要在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"><!-- 注册DispatcherServlet:这个是SpringMVC的核心(请求分发器,或者叫前端控制器) --><servlet><servlet-name>springmvc</servlet-name><servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class><!--DispatcherServlet要绑定Spring的配置文件注意:在ssm框架整合后,这里绑定的Spring配置文件必须为三层配置文件的集合:在applicationContext.xml中对三层配置文件进行import,然后在下方param-value中绑定applicationContext.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><!--在SpringMVC中,/ 和 /* 的区别:/: 只匹配所有的请求,不会去匹配jsp页面。例如:/a.jsp/*: 匹配所有的请求,包括jsp页面,这样会导致我们转发到jsp页面后,又被DispatcherServlet拦截给处理器所以往往不需要匹配jsp页面,一般只写一个/即可。--><servlet-mapping><servlet-name>springmvc</servlet-name><url-pattern>/</url-pattern></servlet-mapping></web-app>

2. 处理器映射器

HandlerMapping

负责根据用户的请求找到Handler(即处理器)

SpringMVC提供了不同的映射器实现不同的映射方式。

例如:配置文件方式、实现接口方式、注解方式等

3. 处理器适配器

HandlerAdapter

通过HandlerAdapter对处理器进行执行,这是适配器模式的的应用,通过扩展适配器可以对更多类型的处理器进行执行

  • 处理器映射器 和 处理器适配器 需要在springmvc配置文件中注册:

    方式一:【不推荐】

    <!-- 处理器映射 -->
    <bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"/>
    <!-- 处理器适配器 -->
    <bean class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter"/>
    

    方式二:【推荐】

    <!--支持mvc注解驱动在spring中一般采用@RequestMapping注解来完成映射关系要想使@RequestMapping注解生效必须向上下文中注册DefaultAnnotationHandlerMapping和一个AnnotationMethodHandlerAdapter实例这两个实例分别在类级别和方法级别处理。而annotation-driven配置帮助我们自动完成上述两个实例的注入。而且底层封装了Jackson:由适配器自动地将处理方法返回的Java对象转换为Json字符串
    -->
    <mvc:annotation-driven />
    

    使用<mvc:annotation-driven /> 自动加载处理器映射器和处理器映射器,替代处理器映射器和处理器适配器的注册。
    同时默认底层就会集成jackson进行对象或集合的json格式字符串的转换

4. 处理器

Handler

它就是我们开发中要编写的具体业务控制器。

由 DispatcherServlet 把用户请求转发到 Handler。

由Handler 对具体的用户请求进行处理。

  • 以注解方式映射的处理器(控制器),需要在springmvc配置文件中注册

    <!-- Handler -->
    <bean id="/hello" class="com.anuo.controller.HelloController"/>
    

5. 视图解析器

View Resolver

负责将处理结果(ModelAndView)生成View视图对象返回给前端控制器

View Resolver根据逻辑视图名解析成物理视图名,即具体的页面地址,再生成View视图对象。

View视图对象包含 具体的页面地址 和 model模型数据

  • 默认的视图解析器:

SpringMVC有默认组件配置,默认组件都是DispatcherServlet.properties配置文件中配置的,该配置文件地址org/springframework/web/servlet/DispatcherServlet.properties,该文件中配置了默认的视图解析器,如下:

org.springframework.web.servlet.ViewResolver=org.springframework.web.servlet.view.InternalResourceViewResolver

翻看该解析器源码,可以看到该解析器的默认设置,如下:

REDIRECT_URL_PREFIX = "redirect:"  --重定向前缀
FORWARD_URL_PREFIX = "forward:"    --转发前缀
prefix = "";     --视图名称前缀
suffix = "";     --视图名称后缀

我们可以通过属性注入的方式修改视图的的前后缀:

<!--配置内部资源视图解析器-->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"><property name="prefix" value="/WEB-INF/jsp/"></property><property name="suffix" value=".jsp"></property>
</bean>

当使用了 重定向前缀 或者 转发前缀,将不进行视图名称的拼接

6. 视图:View

SpringMVC 框架提供了很多的 View 视图类型的支持,包括:jstlView、freemarkerView、pdfView等。最常用的视图就是 jsp。

一般情况下需要通过页面标签或页面模版技术将模型数据通过页面展示给用户,需要由程序员根据业务需求开发具体的页面

8. SpringMVC基本配置整合

<?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/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/contexthttps://www.springframework.org/schema/context/spring-context.xsdhttp://www.springframework.org/schema/mvchttps://www.springframework.org/schema/mvc/spring-mvc.xsd"><!-- 自动扫描包,让指定包下的注解生效,由IOC容器统一管理 --><context:component-scan base-package="com.anuo.controller"/><!-- 让Spring MVC不处理静态资源 例如:.css .js .html .mp3 .mp4等--><mvc:default-servlet-handler/><!--支持mvc注解驱动在spring中一般采用@RequestMapping注解来完成映射关系要想使@RequestMapping注解生效必须向上下文中注册DefaultAnnotationHandlerMapping和一个AnnotationMethodHandlerAdapter实例这两个实例分别在类级别和方法级别处理。而annotation-driven配置帮助我们自动完成上述两个实例的注入。而且底层封装了Jackson:由适配器自动地将处理方法返回的Java对象转换为Json字符串--><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>

9. SpringMVC入门

9.1 配置版

配置版一个类只能写一个处理方法(类似于servlet的service方法)

  1. 写一个类实现Controller接口,重写handleRequest(..)方法

    public class HelloController implements Controller {@Overridepublic ModelAndView handleRequest(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws Exception {//ModelAndView 模型和视图ModelAndView mv = new ModelAndView();//封装对象,放在ModelAndView中。Modelmv.addObject("msg","HelloSpringMVC!");//封装要跳转的视图,放在ModelAndView中mv.setViewName("hello"); //: /WEB-INF/jsp/hello.jspreturn mv;}
    }
    
  2. 在springmvc配置文件中进行bean注册(前提是准备工作要配置好)

    <!-- Handler -->
    <bean id="/hello" class="com.anuo.controller.HelloController"/>
    

    其中id就是该处理器的路由。

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

配置版的代码便于理解SpringMVC的原理,但是实际开发中并不会这么写!

9.2 注解版【重点】

注解版的实现,才是SpringMVC的精髓所在!

  • 实现的步骤:
  1. 创建一个web项目

  2. 导入相关jar包依赖

  3. 编写web.xml配置,注册DispatcherServlet

  4. 编写springmvc配置文件

  5. 创建一个Controller类

    @Controller用于表明这个类是一个控制器类,被spring容器接管

    @Requestmapping用于指定处理器的路由

    返回ModelAndView的写法:

    写法一:返回String ,参数使用Model封装数据

    @Controller
    public class HelloController {@RequestMapping("/h1")public String hello(Model model) {// 1.封装数据model.addAttribute("msg", "hello,SpringMVCAnnotation!");// 2.视图跳转,现在return即可return "hello"; // 会被视图解析器处理}
    }
    

    写法二:返回ModelAndView对象

    @Controller
    public class HelloController {@RequestMapping("/h1")public ModelAndView hello() {ModelAndView mv = new ModelAndView();// 1.封装数据mv.addObject("msg", "hello,SpringMVCAnnotation!");// 2.设置跳转视图的逻辑名mv.setViewName("hello");// 3.返回ModelAndView对象,会被视图解析器处理return mv;}
    }
    

    两种写法的本质都是一样的,经常用的是第一种写法

  6. 在SpringMVC配置文件中扫描注解(前提是准备工作要配置好)

    <!-- 自动扫描包,让指定包下的Controller注解生效,由IOC容器统一管理 -->
    <context:component-scan base-package="com.anuo.controller"/>
    
  7. 视图页面hello.jsp

    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <html>
    <head><title>注解版springmvc</title>
    </head>
    <body>${msg}
    </body>
    </html>
    
  8. 运行项目,浏览器访问测试

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-tkko5ggc-1602517447307)(G:\学习笔记\SpringMVC学习笔记\image\8.PNG)]

10. 控制器Controller

  • 控制器负责提供访问应用程序的行为,通常通过接口定义或者注解定义两种方法实现
  • 控制器负责解析用户的请求并将其转换为一个模型

10.1 实现Controller接口

需要在配置文件中注册bean

  • 总结

    1. 实现接口Controller定义控制器是较老的办法

    2. 缺点:

      一个控制器中只有一个办法,如果要多个办法则需要定义多个Controller。

      定义的方式比较麻烦!

10.2 使用注解@Controller

  • 回顾Spring中的注解

    @Component  // 组件
    @Service    // service层
    @Controller // controller层
    @Repository // dao层
    
  • 在类的上方使用注解@Controller:

    代表这个类是一个控制器,会被Spring容器接管

  • 需要在springmvc配置文件中进行 命名空间引入 和 组件扫描

    1. mvc命名空间引入

      命名空间:xmlns:context="http://www.springframework.org/schema/context"xmlns:mvc="http://www.springframework.org/schema/mvc"
      约束地址:http://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context.xsdhttp://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd
      
    2. 组件扫描

      SpringMVC基于Spring容器,所以在进行SpringMVC操作时,需要将Controller存储到Spring容器中。

      如果使用@Controller注解标注的话,就需要组件扫描:

      <!-- 自动扫描包,让指定包下的Controller注解生效,由IOC容器统一管理 -->
      <context:component-scan base-package="com.anuo.controller"/>
      

10.3 SpringMVC注解解析

@RequestMapping

  • 作用

    @RequestMapping注解用于映射url到控制器类或一个特定的处理程序方法

  • 使用位置

    可用于类或者方法上:

    用于类上,请求URL 的第一级访问目录。此处不写的话,就相当于应用的根目录

    用于方法上,则表示请求 URL 的第二级访问目录

    类与方法上的使用@ReqquestMapping标注的一级目录一起组成访问的虚拟路径

    一般都需要在类上写@ReqquestMapping的:

    作为对该Controller类和其他Controller类的一个区分,

    并且日后更好地完成权限的控制。

  • 属性

    1. value:用于指定请求的URL。它和path属性的作用是一样的

    2. method:用于指定请求的方式

      方法级别的注解变体有如下几个:组合注解

      @GetMapping

      @PostMapping

      @PutMapping

      @DeleteMapping

      @PatchMapping

      例如:@GetMapping 等于 @RequestMapping(method=RequestMethod.GET)

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

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

      例如: params = {“accountName”},表示请求参数必须有accountName

      ​ params = {“moeny!100”},表示请求参数中money不能是100

@Controller

  • 作用

    表示这个类是一个控制器组件,被spring容器接管

  • 使用位置

    类上

@ResponseBody

  • 作用

    告知SpringMVC框架,不进行视图跳转,直接进行数据响应。

  • 使用位置

    用在类或者方法上

    用在类上:表示该控制器类中的所有处理方法都不进行视图跳转

    用在方法上:表示该处理方法不进行视图跳转,直接响应数据

@RestController

  • 作用

    @RestController = @Controller + @ResponseBody

  • 使用位置

    类上

@RequestParam

  • 作用

    与请求参数名进行匹配

  • 使用位置

    controller处理方法的参数上

  • 使用场景

    1. 当方法的参数是普通类型时(String、Integer…等等),

      方法参数名与想要匹配的请求参数名不一致时必须使用

    2. 当方法的参数是Map<String, String>类型的时候,在参数前直接加上@RequestParam,否则无法接收请求参数。

@PathVariable

  • 作用

    用来匹配请求url的占位符

  • 使用位置

    controller处理方法的参数上

  • 使用场景

    常用于restful风格,当方法需要接收的值在url地址中时,例如"/user/1/2",

    而并不是在请求参数中的。

@RequestBody

  • 作用

    json类型请求体中(body)的信息装配到方法的pojo类型的参数中

    如果是get请求方式,请求参数在url中的,可以不加这个注解,自动会装配到方法的pojo类型的参数中。

  • 使用位置

    controller处理方法的参数上

  • 使用条件

    1. 请求参数在方法体中(常见的:post请求和put请求)

    2. 信息传输的格式为json时(Content-Type为application/json

  • 使用场景

    常用于pojo类型的参数以及List集合类型(泛型为pojo类型)的参数

11. SpringMVC的数据响应

11.1 ModelAndView

封装了 数据模型(Model) 和 视图逻辑名(未经过拼接的视图名) 的对象

其中Model作为域对象,它类似于我们的request对象,生命周期就是仅一次的请求相应

  • 方法:

    ModelAndView mv = new ModelAndView();
    mv.addObject("key", Object value)
    mv.setViewName("视图逻辑名")
    
  • 单独使用Model对象时,它的方法:

    Model model = new Model();
    model.addAttribute("key", Object value)
    

11.2 数据响应的方式

  1. 页面跳转

    不携带数据,直接返回字符串

    携带数据,通过ModelAndView对象返回

  2. 回显数据

    直接返回字符串

    返回对象或者集合

11.3 页面跳转1-不携带数据

  1. 不带前缀:经过视图解析器,并进行拼接

    页面物理地址 : {prefix} + viewName +{suffix}

  2. 带前缀:经过视图解析器,但不进行拼接

    "redirect:" 或者 "forward:"

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-XpyjCM4J-1602517447308)(G:\学习笔记\SpringMVC学习笔记\image\9.jpg)]

// 经过视图解析器拼接
@RequestMapping("/m1")
public String test01(Model model) {model.addAttribute("msg", "转发方式跳转过来了");return "test";
}
// 重定向到新的页面
@RequestMapping("/m2")
public String test02() {return "redirect:/restfulTest.jsp";
}// 转发到新的页面 或者 新的处理方法
@RequestMapping("/m3")
public String test03(Model model) {model.addAttribute("msg", "转发方式跳转过来了");return "forward:/m1";
}

注意事项:

  1. 使用"redirect:" 或者 "forward:"后面跟的路径开头一定不能加空格

    不要写贯了yaml格式,在:后面就喜欢加空格

  2. 重定向到新的页面,该页面不能在WEB-INF下,且无法使用Model携带数据

  3. 请求转发的新的处理方法,还是比较常用的。

    比如,当我们更新好数据,往往转发到查询显示的处理方法,达到刷新的效果

11.4 页面跳转2-携带数据

有三种形式,最常用的是形式二

  • 返回ModelAndView形式一:

    在Controller中方法返回ModelAndView对象,并且设置视图名称

    @RequestMapping("/quick2")
    public ModelAndView save2(){/*Model:模型 作用封装数据View:视图 作用展示数据*/ModelAndView modelAndView = new ModelAndView();// 设置模型数据modelAndView.addObject("username","itcast");// 设置视图名称modelAndView.setViewName("success");return modelAndView;
    }
    

    也可以在Controller中方法形参上直接声明ModelAndView,无需在方法中自己创建,在方法中直接使用该对象设置视图,同样可以跳转页面

    @RequestMapping("/quick3")
    public ModelAndView save3(ModelAndView modelAndView){modelAndView.addObject("username","itheima");modelAndView.setViewName("success");return modelAndView;
    }
    
  • 返回ModelAndView形式二:

    使用Model对象封装数据,视图逻辑名直接作为返回值

    // 单独
    @RequestMapping("/quick4")
    public String save4(Model model){model.addAttribute("username","博学谷");return "success";
    }
    
  • 返回ModelAndView形式三:

    在Controller方法的形参上可以直接使用原生的HttpServeltRequest对象,进行数据封装

    @RequestMapping("/quick5")
    public String save5(HttpServletRequest request){request.setAttribute("username","酷丁鱼");return "success";
    }
    

11.5 数据回显1-文本字符串

  1. 将需要回显的字符串直接返回,但此时需要通过@ResponseBody注解告知SpringMVC框架,方法返回的字符串不是跳转是直接在http响应体中返回:

    @RequestMapping("/quick6")
    @ResponseBody //告知SpringMVC框架 不进行视图跳转 直接进行数据响应
    public String save7(){return "hello itheima";
    }
    
  2. 通过SpringMVC框架注入的response对象,使用response回显数据,此时不需要视图跳转,业务方法返回值为void:【不常用】

    @RequestMapping("/quick7")
    public void save6(HttpServletResponse response){response.getWriter().print("hello itcast");
    }
    

11.6 数据回显2-Json字符串

直接以String作为方法返回值

@RequestMapping(value="/quick8")
@ResponseBody
public String save8(){return "{\"username\":\"zhangsan\",\"age\":18}";
}

手动拼接Json格式的字符串太麻烦,我们往往需要使用JSON转换工具,将Java对象转换成Json字符串:Jackson | Fastjson

@RequestMapping(value="/quick9")
@ResponseBody
public String save9() throws IOException {User user = new User();user.setUsername("lisi");user.setAge(30);//使用json的转换工具将对象转换成json格式字符串在返回ObjectMapper objectMapper = new ObjectMapper();String json = objectMapper.writeValueAsString(user);return json;
}

为什么我要强调以String作为返回值呢?

因为以对象或集合作为返回值的话,SpringMVC会自动帮我们将Java对象转换为Json字符串进行数据回显。其实也是内部封装了Jackson去完成的【需要配置】

但是可以想想,返回String也有它的好处,我们可以返回任意的Java对象的Json字符串格式,只需要自己手动加上转换的过程

11.7 数据回显3-对象或集合

我曾经有这样一个困惑,当我们直接以Java对象作为返回值时,最后SpringMVC会帮助我们将Java对象以Json字符串的格式进行回显,那么我们还需要Jackson等Json转换工具吗?

其实呀,是我们在配置的时候,将SpringMVC底层集成了Jackson来帮我们完成这件事

怎么配置的?,SpringMVC自动帮助我们将对象或集合进行json字符串的转换并回显,是==在处理器适配器中完成的==,所以我们要为处理器适配器配置消息转换参数,指定使用jackson进行对象或集合的转换,因此需要在spring-mvc.xml中进行如下配置:

<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter"><property name="messageConverters"><list><bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter"/></list></property>
</bean>

这样配置比较麻烦,配置的代码比较多。
因此,我们可以使用mvc的注解驱动代替上述配置:

<mvc:annotation-driven/>

在 SpringMVC 的各个组件中,处理器映射器、处理器适配器、视图解析器称为 SpringMVC 的三大组件。
使用<mvc:annotation-driven /> 自动加载处理器映射器和处理器映射器,替代处理器映射器和处理器适配器的注册。
同时默认底层就会集成jackson进行对象或集合的json格式字符串的转换

@RequestMapping(value="/quick10")
@ResponseBody
//期望SpringMVC自动将User转换成json格式的字符串
public User save10(){User user = new User();user.setUsername("lisi2");user.setAge(32);return user;
}

12. SpringMVC的请求接收

12.1 请求参数类型

客户端请求参数的格式是:name=value&name=value……

服务器端要获得请求的参数,有时还需要进行数据的封装。

SpringMVC可以接收如下类型的参数:

  1. 基本类型参数

  2. POJO类型参数

  3. 数组类型参数

  4. 集合类型参数

12.2 获得基本类型参数

Controller中的业务方法的参数名称要与请求参数的name一致。

  • 如果不一致,我们需要在处理方法参数中使用**@RequestParam(“请求参数名”)**注解

参数值会自动映射匹配,并且能自动做类型转换

自动的类型转换是指从String向其他类型的转换

例如:

请求URL:http://localhost:8080/user?username=zhangsan&age=12

处理方法:

@RequestMapping("/user")
@ResponseBody
public void save11(@RequestParam("username") String name,int age){System.out.println(username);System.out.println(age);
}

12.3 获得POJO类型参数

Controller中的业务方法的POJO参数的属性名与请求参数的name一致,参数值会自动映射匹配。

属性名与请求参数的name不一致,是不会进行封装的,也无法使用@RequestParam(),那怎么解决这个问题呢?

在实体类相应的属性中使用jackson中的**@JsonAlias** 或者 @JsonProperty注解

有以下两种情况:

  1. 当请求参数在url中时(get请求),不加注解也会自动映射匹配

    public class User {private String username;private int age;// ...以下省略getter和setter
    }
    

    请求URL:http://localhost:8080/user?username=zhangsan&age=12

    @RequestMapping("/user")
    @ResponseBody
    public void save11(User user){System.out.println(user);
    }
    
  2. 当请求参数在请求体body中时,需要加@RequestBody注解,才能自动匹配

    并且Content-Type需要设置为application/json

    public class User {private String username;private int age;// ...以下省略getter和setter
    }
    

    请求URL:http://localhost:8080/user

    请求体:{“username”: “zhangsan”, “age”: “12” }

    @RequestMapping("/user")
    @ResponseBody
    public void save11(@RequestBody User user){System.out.println(user);
    }
    

12.4 获得数组类型参数

Controller中的业务方法数组名称与请求参数的name一致,参数值会自动映射匹配。

当我们的请求参数name都是一致的,但是value不同时,使用数组进行接收。

例如:

请求URL:http://localhost:8080/user?strs=111&strs=222

@RequestMapping("/user")
@ResponseBody
public void save11(String[] strs){System.out.println(Arrays.asList(strs));
}

12.5 获取Map类型的参数

当我们进行条件查询的时候,条件有很多并且不确定传过来的是哪个条件

比如可能是name=”zhangsan“,也可能是age=”12“,所以我们统一用**Map<String, String>**类型去接收。

但是我们需要对参数使用**@RequestParam**注解,否则接收不到。

例如:

请求url: http://localhost:8080/user?name=zhangsan&age=12

controller:

@RequestMapping(value="/quick13")
@ResponseBody
public void save14(@Requestparam Map<String, String> map) throws IOException {System.out.println(nap);
}

12.5 获得List类型的参数I

当前端传过来的集合并不是Ajax的Json字符串格式时:

获得集合参数时,要将集合参数包装到一个VO中才可以。

例如:

前端表单:

<form action="${pageContext.request.contextPath}/user/quick14" method="post"><%--表明是第一个User对象的username age--%><input type="text" name="userList[0].username"><br/><input type="text" name="userList[0].age"><br/><%--表明是第二个User对象的username age--%>  <input type="text" name="userList[1].username"><br/><input type="text" name="userList[1].age"><br/><input type="submit" value="提交">
</form>

VO对象:

public class VO {private List<User> userList;// 以下省略getter、setter和toString方法
}

Controller:

@RequestMapping(value="/quick14")
@ResponseBody
public void save14(VO vo) throws IOException {System.out.println(vo);
}

12.6 获得List类型的参数II

在我们的开发中,经常使用到ajax实现的异步请求。

那么,当使用ajax提交时,可以指定contentType为json形式,

那么在方法参数位置使用**@RequestBody**可以直接接收集合数据而无需使用VO进行包装

例如:

前端:

<script>var userList = new Array();userList.push({username:"zhangsan",age:18});userList.push({username:"lisi",age:28});$.ajax({type:"POST",url:"${pageContext.request.contextPath}/user/quick15",data:JSON.stringify(userList),contentType:"application/json;charset=utf-8"});
</script>

ajax的属性:

contentType:发送给服务器的数据类型

​ 当发送的数据格式为json时,设置编码类型为:“application/json; charset=utf-8”

dataType:预期服务器返回的数据类型

​ 例如:dataType: “json”

Controller:

@RequestMapping(value="/quick15")
@ResponseBody
public void save15(@RequestBody List<User> userList) throws IOException {System.out.println(userList);
}

12.7 静态资源访问的开启

当有静态资源需要被加载时,比如JS、CSS、Image、html、mp3、mp4等,你会发现加载不了。

  • 原因:

    SpringMVC的前端控制器DispatcherServlet的url-pattern配置的是/,代表对所有的资源都进行过滤操作,除了JSP页面以外

  • 解决方案:

    我们可以通过以下两种方式指定放行静态资源:

    <!--放行静态资源方式1-->
    <mvc:resources mapping="/js/**" location="/js/"/>
    <mvc:resources mapping="/img/**" location="/img/"/>
    <!--放行静态资源方式2 推荐-->
    <mvc:default-servlet-handler/>
    

12.8 解决请求乱码问题

当post请求时,中文数据会出现乱码,我们可以设置一个过滤器来进行编码的过滤:

在web.xml中配置:

<!-- 2.注册过滤器 -->
<filter><filter-name>encodingFilter</filter-name><filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class><!-- 设置字符集参数,参数名必须用encoding --><init-param><param-name>encoding</param-name><param-value>UTF-8</param-value></init-param>
</filter>
<!-- 拦截映射配置,一定要用/*,过滤所有请求,包括.jsp文件 -->
<filter-mapping><filter-name>encodingFilter</filter-name><url-pattern>/*</url-pattern>
</filter-mapping>

Tomcat8 以后tomcat的默认编码已经不是ISO-8859-1,而是改成了UTF-8,我们不需要再对get请求进行转码了。

12.9 参数绑定注解

@RequestParam

当请求的参数名称与Controller的处理方法参数名称不一致时,就需要通过@RequestParam注解显示的绑定。

  • 属性:

    value 与请求参数匹配

    required 此在指定的请求参数是否必须包括,默认是true,提交时如果没有此参数则报错

    defaultValue 指定默认值。当没有指定请求参数时,则使用指定的默认值赋值

例如:

<form action="${pageContext.request.contextPath}/quick16" method="post"><input type="text" name="name"><br><input type="submit" value="提交"><br>
</form>
@RequestMapping(value="/quick16")
@ResponseBody
public void save16(@RequestParam(value="name",required = false,defaultValue = "itcast") String username){System.out.println(username);
}

12.10 RestFul风格参数

Restful是一种软件架构风格、设计风格,而不是标准,只是提供了一组设计原则和约束条件。主要用于客户端和服务器交互类的软件

基于这个风格设计的软件可以更简洁,更有层次,更易于实现缓存机制等。

通过不同的请求方式,使同一个url,实现不同的功能

Restful风格的请求是使用“url+请求方式”表示一次请求目的的,HTTP 协议里面四个表示操作方式的动词如下:(常用的四种)

  • GET:用于获取资源
  • POST:用于新建资源
  • PUT:用于更新资源
  • DELETE:用于删除资源

注意:对于数据库的操作,不要使用@RequestMapping,因为这样表示所有类型的请求都能访问到该处理方法。这样不安全,所以Restful风格的注解要求:

查询操作使用:@GetMapping

添加操作使用:@PostMapping

更新操作使用:@PutMapping

删除操作使用:@DeleteMapping

例如:

  • /user/1 以GET方式请求 : 得到 id = 1 的 user
  • /user/1 以DELETE方式请求: 删除 id = 1 的 user
  • /user/1 以PUT方式请求: 更新 id = 1 的 user
  • /user 以POST方式请求: 新增 user

上述url地址/user/1中的1就是要获得的请求参数值,在SpringMVC中可以使用占位符进行参数绑定,并且我们可以为Controller处理方法设置请求方式,前端不同的请求方式会去找对应于该请求方式的处理方法。(@GetMapping、@PostMapping等等…)

地址/user/1可以写成/user/{id},占位符{id}对应的就是1的值。在业务方法中我们可以使用==@PathVariable==注解进行占位符的匹配获取工作:

例如:

get请求url:http://localhost:8080/itheima_springmvc1/quick17/zhangsan

@GetMapping(value="/quick17/{name}")
@ResponseBody
public void save17(@PathVariable("name") String username){System.out.println(username);
}

注意:所有的地址栏请求默认都是GET方式请求的

@PathVariable属性:

value 与请求参数匹配

required 此在指定的请求参数是否必须包括,默认是true,提交时如果没有此参数则报错

技巧:如何以一个controller处理方法,映射不同的url地址?

现在有如下页面需要跳转:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-DnZo3A8w-1602517447310)(G:\学习笔记\SpringMVC学习笔记\image\12.PNG)]

我们怎么样只写一个controller处理方法,能够跳转到/level1/1 /level1/2 /level1/3?

答案是:使用@PathVariable注解,进行请求参数匹配

@RequestMapping("/level1/{id}")
public String toLevel1(@PathVariable("id") String id) {return "views/level1/" + id;
}

12.11 自定义类型转换器

SpringMVC 默认已经提供了一些常用的类型转换器,例如客户端提交的字符串转换成int型进行参数设置。
但是不是所有的数据类型都提供了转换器,没有提供的就需要自定义转换器.

  • 例如:日期类型的数据:

    在springmvc中默认只能对"yyyy/MM/dd"格式字符串进行转换成Data类型

    但我们最常用的还是"yyyy-MM-dd" 格式字符串,就需要自定义转换器。

    否则,会报出400错误。

  • 自定义类型转换器的开发步骤

    1. 定义转换器类实现Converter接口

      // 实现Converter<String, 要转换成的类型>接口
      public class DateConverter implements Converter<String, Date> {// 重写convert方法public Date convert(String dateStr) {//将日期字符串转换成日期对象 返回SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");Date date = null;try {date = format.parse(dateStr);} catch (ParseException e) {e.printStackTrace();}return date;}
      }
      
    2. 在配置文件中声明转换器,转换器工厂中可以声明多个转换器

      <!-- 声明转换器 -->
      <bean id="conversionService" class="org.springframework.context.support.ConversionServiceFactoryBean"><property name="converters"><list><bean class="com.anuo.converter.DateConverter"/></list></property>
      </bean>
      
    3. <annotation-driven>中引用转换器

      <!-- mvc的注解驱动 -->
      <mvc: annotation-driven conversion-service="conversionService"/>
      
  • 转换器定义好之后,进行测试

    请求URL:http://localhost:8080/itheima_springmvc1/quick18

    Controller方法:

    @RequestMapping("/quick18")
    @ResponseBody
    public void save18(Date date) {System.out.println(date);
    }
    

    发现已经不会出现400错误了。

  • 总结:

    其实在工作中不常用到自定义类型转换器,SpringMVC内置的类型转换器往往够用。

    你想想Date类型的数据我们往往是实体类的属性,

    那么我们可以在实体类中Date类型的属性中使用:

    1. 入参格式化,将前端的"yyyy-MM-dd HH:mm:ss"格式字符串转换为Date类型封装到属性中:

      @DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss")
      private Date date;
      
    2. 出参格式化,将Date类型转换为"yyyy-MM-dd HH:mm:ss"格式字符串返回前端

      @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8"
      )
      private Date date;
      

      为什么需要timezone=“GMT+8”?

      因为,@JsonFormat是Jackson所带的注解。

      Jackson在序列化时间时是按照国际标准时间GMT进行格式化的,而在国内默认时区使用的是CST时区,两者相差8小时。

      如果不设置timezone="GMT+8"的话,在Jackson进行格式化的时候,会将CST时区的时间早8个小时。

      @JsonFormat 注解不是 Spring 自带的注解,所以使用该注解前需要添加 jackson 相关的依赖包。

      当然,如果是 SpringBoot 项目就不需要自己手动添加依赖了,因为在 spring-boot-start-web 下已经包含了 jackson 相关依赖

12.12 获取Servlet相关API

SpringMVC支持使用原始ServletAPI对象作为控制器方法的参数进行注入,常用的对象如下:

HttpServletRequest

HttpServletResponse

HttpSession

@RequestMapping(value="/quick19")
@ResponseBody
public void save19(HttpServletRequest request, HttpServletResponse response, HttpSession session){System.out.println(request);System.out.println(response);System.out.println(session);
}

12.13 获取请求头信息

使用==@RequestHeader可以获得请求头信息==

相当于web阶段学习的request.getHeader(name)

  • @RequestHeader注解的属性如下:

    value:请求头的名称

    required:是否必须携带此请求头,默认为true

@RequestMapping(value="/quick20")
@ResponseBody
public void save20(@RequestHeader(value = "User-Agent",required = false) String user_agent){System.out.println(user_agent);
}

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

使用@CookieValue可以获得指定Cookie的值

  • @CookieValue注解的属性如下:

    value:指定cookie的名称

    required:是否必须携带此cookie

@RequestMapping(value="/quick21")
@ResponseBody
public void save21(@CookieValue(value = "JSESSIONID") String jsessionId){System.out.println(jsessionId);
}

12.14 文件上传

1. 文件上传客户端三要素

  • 表单项type=“file”

  • 表单的提交方式是post

  • 表单的enctype属性是多部分表单形式:enctype=“multipart/form-data”

<form action="${pageContext.request.contextPath}/user/quick22" method="post"
enctype="multipart/form-data">名称<input type="text" name="username"><br/>文件1<input type="file" name="uploadFile"><br/><input type="submit" value="提交">
</form>

2. 文件上传的原理

  • 当form表单修改为多部分表单时,request.getParameter()将失效

  • enctype="application/x-www-form-urlencoded"时,form表单的正文内容格式是:

    key=value&key=value&key=value 【这是默认的,不需要设置enctype属性值】

  • 当form表单的enctype取值为multipart/form-data时,请求正文内容就变成多部分形式:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-EJ7xsTZK-1602517447312)(G:\学习笔记\SpringMVC学习笔记\image\10.PNG)]

3. 单文件上传步骤

  1. 导入fileupload和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.3</version>
    </dependency>
    
  2. 在spring-mvc.xml配置文件上传解析器

    <!--配置文件上传解析器,注意id必须为multipartResolver,否则报错-->
    <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver"><!-- 上传文件的编码类型 --><property name="defaultEncoding" value="UTF-8"/><!-- 上传单个文件的大小 --><property name="maxUploadSize" value="5242800"/><!-- 上传文件总大小 --><property name="maxUploadSizePerFile" value="5242800"/>
    </bean>
    
  3. 编写文件上传代码

    前端表单:

    <form action="${pageContext.request.contextPath}/user/quick22" method="post"
    enctype="multipart/form-data">名称<input type="text" name="username"><br/>文件1<input type="file" name="uploadFile"><br/><input type="submit" value="提交">
    </form>
    

    controller:文件数据在处理方法中需要用MutipartFile类型参数去接收

    @RequestMapping(value="/quick22")
    @ResponseBody
    public void save22(String username, MultipartFile uploadFile) throws IOException {System.out.println(username);// 获得上传文件原本的名称String originalFilename = uploadFile.getOriginalFilename();// 保存文件uploadFile.transferTo(new File("C:\\upload\\" + originalFilename));
    }
    

4. 多文件上传

和单文件上传的步骤基本一致:

  1. 只需要将页面修改为多个文件上传项

    上传项的name相同,后端就用数组参数接收

    上传项的name不同,后端就用多个MultipartFile类型参数接收

  2. 我们演示上传项的name相同时,将方法参数MultipartFile类型修改为MultipartFile[]即可

前端表单:

<form action="${pageContext.request.contextPath}/user/quick23" method="post"
enctype="multipart/form-data">名称<input type="text" name="username"><br/>文件1<input type="file" name="uploadFile"><br/>文件2<input type="file" name="uploadFile"><br/><input type="submit" value="提交">
</form>

controller:

@RequestMapping(value="/quick23")
@ResponseBody
public void save23(String username, MultipartFile[] uploadFile) throws IOException {System.out.println(username);for (MultipartFile multipartFile : uploadFile) {String originalFilename = multipartFile.getOriginalFilename();multipartFile.transferTo(new File("C:\\upload\\"+originalFilename));}
}

12.15 知识点总结

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-YX8I0bQ5-1602517447313)(G:\学习笔记\SpringMVC学习笔记\image\11.PNG)]

11. 接收请求参数和数据回显

11.1 接收请求参数

  • 提交的域名称和处理方法的参数名一致的情况

  • 提交的域名称和处理方法的参数名不一致的情况

    @RequestParam(“username”)

规范:无论两名称是否一致都使用@RequestParam("请求参数名称"),这样能够清晰的告诉阅读者这是前端传过来的参数

规范:无论两名称是否一致都使用@RequestParam(“请求参数名称”),这样能够清晰的告诉阅读者这是前端传过来的参数

13. JSON

前后端分离时代:不再使用jsp

后端部署后端,提供接口:@GetMapping("/hello")

​ | JSON

前端独立部署,负责渲染后端的数据

13.1 Controller返回JSON数据

Jackson

  • Jackson是目前比较好的json解析工具,我们之前学习的是阿里巴巴的Fastjson

这里我们使用Jackson,使用步骤:前提先搭建好springmvc的环境

  1. pom.xml中需要导入Jar包依赖:
<!-- Jackson -->
<dependency><groupId>com.fasterxml.jackson.core</groupId><artifactId>jackson-databind</artifactId><version>2.11.1</version>
</dependency>
  1. 在spring配置文件中JSON乱码问题配置:springmvc-servlet.xml

    <!-- JSON乱码问题配置    -->
    <mvc:annotation-driven><mvc:message-converters register-defaults="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>
    

    当然,上面这种解决JSON乱码问题的方式比较简便,属于全局配置。

    还有一种了解即可:在@RequestMapping注解的produces属性中设置:

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

    类似于早期servlet中的:

    response.setContentType("application/json;charset=utf-8");

  2. 实体类:User

    import lombok.AllArgsConstructor;
    import lombok.Data;
    import lombok.NoArgsConstructor;@Data
    @AllArgsConstructor
    @NoArgsConstructor
    public class User {private int id;private String name;private int age;
    }
    
  3. 控制器:UserController

    @Controller
    public class UserController {@RequestMapping(value = "/j1", produces = "application/json;charset=utf-8")@ResponseBody // 它就不会走视图解析器,会直接返回一个json字符串public String json1() throws JsonProcessingException {// jackson, objectMapperObjectMapper mapper = new ObjectMapper();// 创建一个对象User user = new User(1, "陈健", 23);String str = mapper.writeValueAsString(user);return str;}
    }
    

不经过视图解析器跳转的两种方法:

  1. 在控制器类上用@Controller注解的情况下:

    ​ 在对应处理方法上添加注解@ResponseBody

  2. 在控制器类上用@RestController注解:

    ​ 类中的所有处理方法的返回值都不经过视图解析器,直接返回字符串显示

Fastjson

  1. 导入Jar包依赖:

    <!-- FastJson -->
    <dependency><groupId>com.alibaba</groupId><artifactId>fastjson</artifactId><version>1.2.72</version>
    </dependency>
    
  2. 序列化:Java对象转换为JSON字符串

    JSON.toJSONString(Java对象或数组或集合) // 返回String
    
  3. 反序列化:JSON字符串转换为Java对象

    JSON.parseObject(json, Employee.class); // 返回指定的类对象
    
    JSON.parseArray(json, Employee.class); // 返回指定类对象的集合
    

14 SSM框架整合

创建数据库ssmbuild和表books

CREATE DATABASE ssmbuild;
USE ssmbuild;
CREATE TABLE `books`(
`bookID` INT NOT NULL AUTO_INCREMENT COMMENT '书id',
`bookName` VARCHAR(100) NOT NULL COMMENT '书名',
`bookCounts` INT NOT NULL COMMENT '数量',
`detail` VARCHAR(200) NOT NULL COMMENT '描述',
KEY `bookID`(`bookID`)
)ENGINE=INNODB DEFAULT CHARSET=utf8;INSERT INTO `books`(`bookID`,`bookName`,`bookCounts`,`detail`)VALUES
(1,'Java',1,'从入门到放弃'),
(2,'MySQL',10,'从删库到跑路'),
(3,'Linux',5,'从进门到进牢');

14.1 基本环境搭建

  1. 第一步:导入jar包依赖、解决静态资源导出问题

    <!-- 依赖:junit、数据库驱动、连接池、servlet、jsp、mybatis-spring、spring -->
    <dependencies><!-- Junit --><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.12</version></dependency><!-- 数据库驱动 --><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>8.0.21</version></dependency><!-- 数据库连接池:c3p0 --><dependency><groupId>com.mchange</groupId><artifactId>c3p0</artifactId><version>0.9.5.5</version></dependency><!-- Servlet - Jsp --><dependency><groupId>javax.servlet</groupId><artifactId>servlet-api</artifactId><version>2.5</version></dependency><dependency><groupId>javax.servlet.jsp</groupId><artifactId>jsp-api</artifactId><version>2.2</version></dependency><dependency><groupId>javax.servlet</groupId><artifactId>jstl</artifactId><version>1.2</version></dependency><!-- Mybatis --><dependency><groupId>org.mybatis</groupId><artifactId>mybatis</artifactId><version>3.5.5</version></dependency><!-- Mybatis-spring --><dependency><groupId>org.mybatis</groupId><artifactId>mybatis-spring</artifactId><version>2.0.5</version></dependency><!-- spring --><dependency><groupId>org.springframework</groupId><artifactId>spring-webmvc</artifactId><version>5.2.7.RELEASE</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-jdbc</artifactId><version>5.2.7.RELEASE</version></dependency>
    </dependencies><!-- 静态资源导出问题 -->
    <build><!-- 防止Maven资源过滤的问题 --><resources><resource><directory>src/main/java</directory><includes> <include>**/*.properties</include><include>**/*.xml</include></includes><filtering>false</filtering></resource><resource><directory>src/main/resources</directory><includes> <include>**/*.properties</include><include>**/*.xml</include></includes><filtering>false</filtering></resource></resources>
    </build>
    
  2. 建立基本结构和配置框架

    database.properties

    jdbc.driver=com.mysql.jdbc.Driver
    # 如果使用的是MySQL8.0+,需要增加一个时区的配置: &serverTimezone=Asia/Shanghai
    jdbc.url=jdbc:mysql://localhost:3306/ssmbuild?useUnicode=true&characterEncoding=utf8
    jdbc.username=root
    jdbc.password=chenjian123
    

    如果使用的是MySQL8.0+,需要在url增加一个时区的配置: &serverTimezone=Asia/Shanghai

隐藏域

非表单数据Restful风格

15. Ajax

页面异步刷新

ES6更安全的语法:let代替var

例如:for(var i;i<10;i++) {…}中的i在for语句结束后的代码中依旧可以使用

for(let i;i<10;i++) {…}中的i和Java中一样,for语句结束后将不能使用

16. 拦截器

16.1 概述

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

16.2 过滤器与拦截器的区别

拦截器是AOP思想的具体应用

不同点

过滤器

  • servlet规范中的一部分,任何java web工程都可以使用

  • 在url-pattern中配置了/*之后,可以==对所有要访问的资源进行拦截==

拦截器

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

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

相同点

拦截器和过滤器都可以有多个,执行顺序取决于在web.xml中的配置顺序

17. 文件上传

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

前端表单要求:为了能上传文件,必须将表单的method设置为POST,并将enctype设置为

multipart/form-data。只有在这样的情况下,浏览器才会把用户选择的文件以二进制数据发送给服务器;

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

application/x-www=form-urlencoded:默认方式,只处理表单域中的 value 属性值,采用这种编码方式的表单会将表单域中的值处理成 URL 编码方式。

multipart/form-data:这种编码方式会以二进制流的方式来处理表单数据,这种编码方式会把文件域指定文件的内容也封装到请求参数中,不会对字符编码。

text/plain:除了把空格转换为 “+” 号外,其他字符都不做编码处理,这种方式适用直接通过表单发送邮件。

  1. 导入jar包依赖

    <!-- 文件上传 -->
    <dependency><groupId>commons-fileupload</groupId><artifactId>commons-fileupload</artifactId><version>1.4</version>
    </dependency>
    <!-- 导入高版本的servlet-api -->
    <dependency><groupId>javax.servlet</groupId><artifactId>javax.servlet-api</artifactId><version>4.0.1</version>
    </dependency>
    
  2. spring配置文件中配置

    <!-- 文件上传配置,id必须为multipartResolver,否则会404错误 -->
    <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>
    

SpringMVC笔记相关推荐

  1. 【SpringMVC 笔记】控制器 Controller 与 RestFul 风格

    SpringMVC 笔记 控制器 Controller 实现 Controller 接口 创建控制器 @Controller 注解创建控制器 @RequestMapping 使用 method 属性指 ...

  2. 开涛SpringMVC笔记

    SpringMVC笔记 再次学习开涛SpingMVC,总结此笔记,鸣谢开涛: 1.SpringMVC简介 2.Spring MVC-HelloWorld 3.DispatcherServlet理解 4 ...

  3. 狂神SpringMvc笔记

    目录 SpringMvc笔记 一.什么是mvc 1.Model2时代 2.回顾Servlet 4.Spring MVC的特点: 5.中心控制器 6.SpringMVC执行原理 7. 第一个MVC程序 ...

  4. SSM框架专题-从零入门SpringMVC笔记

    从零入门的SpringMVC笔记 一.Spring概述 1. SSM框架优化的方向 2.SpringMVC框架的优点 3. 时序图解析 4.SpringMVC的执行流程 二.SpringMVC注解式开 ...

  5. 跟杨春娟学SpringMVC笔记:Form表单之JSR303验证

    跟杨春娟学SpringMVC笔记:Form表单之JSR303验证 完成:第一遍 1.如何使用JSR303验证要先导入validation-api和hibernate-validator的依赖jar包? ...

  6. 跟杨春娟学SpringMVC笔记:Form表单之Spring验证框架

    跟杨春娟学SpringMVC笔记:Form表单之Spring验证框架 完成:第一遍 1.Spring框架验证和JSR303验证的不同之处在哪里? 不同一:Spirng框架验证需要实现Validator ...

  7. 狂神说SpringMVC笔记(全网最全)

    SpringMVC 狂神说SpringMVC笔记(全网最全) 1.回顾MVC 1.1.什么是MVC MVC是模型(Model).视图(View).控制器(Controller)的简写,是一种软件设计规 ...

  8. 【SpringMVC笔记】拦截器 + 文件上传下载

    拦截器 + 文件上传下载 拦截器(interceptor) 自定义拦截器 验证用户是否登录 (认证用户) 没有拦截器 配置拦截器 文件的上传 文件输出流进行文件上传 file.Transto 进行文件 ...

  9. 【SpringMVC 笔记】Json 交互处理

    Json 什么是 Json? JSON 和 JavaScript 对象互转 Jackson 统一乱码解决 返回 Json 字符串统一解决 Json 返回集合 Json 输出时间对象 抽取工具类 fas ...

  10. 【SpringMVC 笔记】结果跳转、数据处理、乱码问题

    结果跳转和数据处理 结果跳转方式 ModelAndView Servlet API SpringMVC - 无视图解析器 SpringMVC - 有视图解析器 处理提交数据 1.提交的域名称和处理方法 ...

最新文章

  1. 关于ValueError: Unknown projection ‘3d‘报错的解决方法
  2. China Daily | 技术不是拦路虎:在线音乐教学可完美还原线下场景
  3. python字符串库函数_Python标准库概览(1):string
  4. 重学java基础第九课:软件和软件关系
  5. Linux系统管理(11)——linux下jdk的安装及环境变量配置
  6. mysql 作业调度及问题解决
  7. 关于jet db的连接字串,以及加密后的字串
  8. python爬虫数据存储文本_Python爬虫开发系列之五》数据存储为TXT、JSON格式
  9. CTP: 初始化成功和TradeAPI、MDAPI登陆成功
  10. 用计算机制作简谱,雅乐简谱免费版
  11. cmos逻辑门传输延迟时间_什么是TTL电平、CMOS电平?区别是什么?
  12. python交互式日历制作_python tkinter制作日历界面的简单步骤
  13. Python实现“求职APP网络爬虫”
  14. 面试被虐题— 谨以此致,mark一个悲惨的下午
  15. K8S 在微服务架构下做服务注册中心的一种思路
  16. 老厉害了!2600亿,紫光集团南京再投半导体生产线
  17. 软件测试需求评审目的,需求评审的重要性
  18. 边缘态半无穷格林函数谱函数计算
  19. 定时器软件RH Timer for Mac了解一下
  20. 协处理器CP15介绍—MCR/MRC指令

热门文章

  1. nginx uwsgi django部署
  2. Rk3326 Android8.0HAL服务添加
  3. 用 CSS 画一个带阴影的三角形
  4. 2017年1月15日 星期日 --出埃及记 Exodus 22:5
  5. 【mysql】mysql查询优化之索引类型、最左前缀
  6. SpaceX SN8飞船爆炸,马斯克:已拿到全部所需数据,火星,我们来了!
  7. 录屏软件哪个好?电脑录屏软件排行榜推荐
  8. postgresql分割字符串_PostgreSQL 字符串拆分与合并案例
  9. 2018西安工业大学第二届萌新线上赛MISC WP
  10. vue修改浏览器的标题和图标