一、概述

1.1、什么是MVC

  • MVC是模型(dao、service) 视图(jsp) 控制层(Servlet),是一种软件设计规范。
  • 是将业务逻辑、数据、显示分离的⽅法来组织代码。
  • MVC主要作⽤是降低了视图与业务逻辑间的双向偶合
  • MVC不是⼀种设计模式,MVC是⼀种架构模式。当然不同的MVC存在差异。

Model(模型):数据模型,提供要展示的数据,因此包含数据和⾏为,可以认为是领域模型或 JavaBean组件(包含数据和⾏为),不过现在⼀般都分离开来:Value Object(数据Dao) 和 服务层 (⾏为Service)。也就是模型提供了模型数据查询和模型数据的状态更新等功能,包括数据和业务。
View(视图):负责进⾏模型的展示,⼀般就是我们⻅到的⽤户界⾯,客户想看到的东⻄。
Controller(控制器):接收⽤户请求,委托给模型进⾏处理(状态改变),处理完毕后把返回的模型数据返回给视图,由视图负责展示。也就是说控制器做了个调度员的⼯作。
最典型的MVC就是JSP + servlet + javabean的模式。
SpringMVC - 图2

1.2、Model1时代

jsp的本质就是一个Servlet。

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

SpringMVC - 图3
Model1优点:架构简单,⽐较适合⼩型项⽬开发;
Model1缺点:JSP职责不单⼀,职责过重,不便于维护;

1.3、Model2时代

Model2把⼀个项⽬分成三部分,包括视图控制模型
SpringMVC - 图4

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

职责分析:
Controller:控制器

  1. 取得表单数据
  2. 调⽤业务逻辑
  3. 转向指定的⻚⾯

Model:模型

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

View:视图

  1. 显示⻚⾯

Model2这样不仅提⾼的代码的复⽤率与项⽬的扩展性,且⼤⼤降低了项⽬的维护成本。Model 1模式的 实现⽐较简单,适⽤于快速开发⼩规模项⽬,Model1中JSP⻚⾯身兼View和Controller两种⻆⾊,将控 制逻辑和表现逻辑混杂在⼀起,从⽽导致代码的重⽤性⾮常低,增加了应⽤的扩展性和维护的难度。
Model2消除了Model1的缺点。

1.4、回顾Servlet

步骤一:创建Maven工程,添加pom依赖
  1. <!-- 导入依赖 -->
  2. <dependencies>
  3. <dependency>
  4. <groupId>junit</groupId>
  5. <artifactId>junit</artifactId>
  6. <version>4.12</version>
  7. </dependency>
  8. <dependency>
  9. <groupId>org.springframework</groupId>
  10. <artifactId>spring-webmvc</artifactId>
  11. <version>5.1.9.RELEASE</version>
  12. </dependency>
  13. <dependency>
  14. <groupId>javax.servlet</groupId>
  15. <artifactId>servlet-api</artifactId>
  16. <version>2.5</version>
  17. </dependency>
  18. <dependency>
  19. <groupId>javax.servlet.jsp</groupId>
  20. <artifactId>jsp-api</artifactId>
  21. <version>2.2</version>
  22. </dependency>
  23. <dependency>
  24. <groupId>javax.servlet</groupId>
  25. <artifactId>jstl</artifactId>
  26. <version>1.2</version>
  27. </dependency>
  28. </dependencies>

步骤二:删除src文件,创建一个新Moudle,添加Web Application支持

SpringMVC - 图5SpringMVC - 图6

步骤三:导⼊servlet 和 jsp 的 jar 依赖

可能会继承父项目的依赖,但是为了安全起见,可以先添加,后期再优化时候再删掉。

  1. <dependencies>
  2. <dependency>
  3. <groupId>javax.servlet</groupId>
  4. <artifactId>servlet-api</artifactId>
  5. <version>2.5</version>
  6. </dependency>
  7. <dependency>
  8. <groupId>javax.servlet.jsp</groupId>
  9. <artifactId>jsp-api</artifactId>
  10. <version>2.2</version>
  11. </dependency>
  12. </dependencies>

步骤四:编写⼀个Servlet类,⽤来处理⽤户的请求
  1. package com.learn.servlet;
  2. import javax.servlet.ServletException;
  3. import javax.servlet.http.HttpServlet;
  4. import javax.servlet.http.HttpServletRequest;
  5. import javax.servlet.http.HttpServletResponse;
  6. import java.io.IOException;
  7. public class HelloServlet extends HttpServlet {
  8. @Override
  9. protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
  10. //1.获取前端参数
  11. String method = req.getParameter("method");
  12. if (method.equals("add")) {
  13. req.getSession().setAttribute("msg", "执⾏了add⽅法");
  14. }
  15. if (method.equals("delete")) {
  16. req.getSession().setAttribute("msg", "执⾏了delete⽅法");
  17. }
  18. //2.调用业务层
  19. //3.视图转发或者重定向
  20. req.getRequestDispatcher("/WEB-INF/jsp/test.jsp").forward(req,resp);//转发
  21. // resp.sendRedirect();//重定向
  22. }
  23. @Override
  24. protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
  25. doGet(req, resp);
  26. }
  27. }

步骤五:编写Hello.jsp,在WEB-INF⽬录下新建⼀个jsp的⽂件夹,新建hello.jsp

Web目录:公共的页面 WEB-INF⽬录:用户不可见

  1. <%@ page contentType="text/html;charset=UTF-8" language="java" %>
  2. <html>
  3. <head>
  4. <title>Title</title>
  5. </head>
  6. <body>
  7. ${msg}
  8. </body>
  9. </html>

步骤六:在web.xml中注册Servlet
  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
  3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4. xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
  5. version="4.0">
  6. <!-- 配置Servlet -->
  7. <servlet>
  8. <servlet-name>hello</servlet-name>
  9. <servlet-class>com.learn.servlet.HelloServlet</servlet-class>
  10. </servlet>
  11. <servlet-mapping>
  12. <servlet-name>hello</servlet-name>
  13. <url-pattern>/hello</url-pattern>
  14. </servlet-mapping>
  15. <!-- 超时时间 -->
  16. <session-config>
  17. <session-timeout>15</session-timeout>
  18. </session-config>
  19. <!-- 默认欢迎页面 -->
  20. <welcome-file-list>
  21. <welcome-file>index.jsp</welcome-file>
  22. </welcome-file-list>
  23. </web-app>

步骤七:配置Tomcat,并启动测试

点击 + , 选择Tomcat Server local
SpringMVC - 图7SpringMVC - 图8
点击Fix
SpringMVC - 图9SpringMVC - 图10
结果:
SpringMVC - 图11

1.5、MVC框架要做哪些事情

  1. 将url映射到java类或java类的⽅法 .
  2. 封装⽤户提交的数据 .
  3. 处理请求—调⽤相关的业务处理—封装响应数据 .
  4. 将响应的数据进⾏渲染 . jsp / html 等表示层数据 .

说明:
常⻅的服务器端MVC框架有:Struts、Spring MVC、ASP.NET MVC、Zend Framework、JSF; 常⻅前端MVC框架:vue、angularjs、react、backbone;由MVC演化出了另外⼀些模式如:MVP、 MVVM 等等….
MVVM:M V VM(ViewModel:双向绑定)


二、初识SpringMVC

2.1 概述

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

查看官⽅⽂档:https://docs.spring.io/spring/docs/5.2.0.RELEASE/spring-framework-reference/web.html#spring-web 或者老版本:https://docs.spring.io/spring-framework/docs/4.3.24.RELEASE/spring-framework-reference/html/mvc.html

我们为什么要学习SpringMVC?
Spring MVC的特点:

  1. 轻量级,简单易学
  2. ⾼效 , 基于请求响应的MVC框架
  3. 与Spring兼容性好,⽆缝结合
  4. 约定优于配置
  5. 功能强⼤:RESTful、数据验证、格式化、本地化、主题等
  6. 简洁灵活

Spring的web框架围绕DispatcherServlet [ 调度Servlet ] 设计。
DispatcherServlet的作⽤是将请求分发到不同的处理器。从Spring 2.5开始,使⽤Java 5或者以上版本 的⽤户可以采⽤基于注解形式进⾏开发,⼗分简洁;
正因为SpringMVC好 , 简单 , 便捷 , 易学 , 天⽣和Spring⽆缝集成(使⽤SpringIoC和Aop) , 使⽤约定优 于配置 . 能够进⾏简单的junit测试 . ⽀持Restful⻛格 .异常处理 , 本地化 , 国际化 , 数据验证 , 类型转换 , 拦截器 等等……所以我们要学习。
最重要的⼀点还是⽤的⼈多 , 使⽤的公司多

2.2 中心控制器

  1. Springweb框架围绕**DispatcherServlet**设计。DispatcherServlet的作⽤是将**请求分发**到不同的处理器。从Spring 2.5开始,使⽤Java 5或者以上版本的⽤户可以采⽤基于注解的controller声明⽅式。<br /> Spring MVC框架像许多其他MVC框架⼀样, 以请求为驱动 , **围绕⼀个中⼼Servlet分派请求及提供其他功能,DispatcherServlet是⼀个实际的Servlet (它继承⾃HttpServlet基类)**。<br />![](https://gitee.com/ah_faga/MacPicgo/raw/master/20210414224642.jpg#)

2.3 SpringMVC执行原理

SpringMVC的原理如下图所示:
SpringMVC - 图12
当发起请求时被前置的控制器拦截到请求,根据请求参数⽣成代理请求,找到请求对应的实际控制器,控制器处理请求,创建数据模型,访问数据库,将模型响应给中⼼控制器,控制器使⽤模型与视图渲染视图结果,将结果返回给中⼼控制器,再将结果返回给请求者。
下图为SpringMVC的⼀个较完整的流程图,实线表示SpringMVC框架提供的技术,不需要开发者实现,虚线表示需要开发者实现。
SpringMVC - 图13
简要分析执⾏流程

  1. DispatcherServlet表示前置控制器,是整个SpringMVC的控制中⼼。⽤户发出请求, DispatcherServlet接收请求并拦截请求。
    我们假设请求的url为 : http://localhost:8080/SpringMVC/hello
    如上url拆分成三部分:
    http://localhost:8080服务器域名
    SpringMVC部署在服务器上的web站点
    hello表示控制器
    通过分析,如上url表示为:请求位于服务器localhost:8080上的SpringMVC站点的hello控制器。
  2. HandlerMapping为处理器映射。DispatcherServlet调⽤HandlerMapping,HandlerMapping根据请求url查找Handler。
  3. HandlerExecution表示具体的Handler,其主要作⽤是根据url查找控制器,如上url被查找控制器为: hello。
  4. HandlerExecution将解析后的信息传递给DispatcherServlet,如解析控制器映射等。
  5. HandlerAdapter表示处理器适配器,其按照特定的规则去执⾏Handler。
  6. Handler让具体的Controller执⾏。
  7. Controller将具体的执⾏信息返回给HandlerAdapter,如ModelAndView。
  8. HandlerAdapter将视图逻辑名或模型传递给DispatcherServlet。
  9. DispatcherServlet调⽤视图解析器(ViewResolver)来解析HandlerAdapter传递的逻辑视图名。
  10. 视图解析器将解析的逻辑视图名传给DispatcherServlet。
  11. DispatcherServlet根据视图解析器解析的视图结果,调⽤具体的视图。
  12. 最终视图呈现给⽤户。

在这⾥先听⼀遍原理,不理解没有关系,我们⻢上来写⼀个对应的代码实现⼤家就明⽩了,如果不明⽩,那就写10遍,没有笨⼈,只有懒⼈!

三、SpringMVC入门案例

3.1 配置版(了解即可,用注解版实现)

目录结构如下:
SpringMVC - 图14
1、新建一个Moudle , springmvc-02-hello , 添加web的支持!
2、确定导入了SpringMVC 的依赖!
3、配置web.xml , 注册DispatcherServlet

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
  3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4. xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
  5. version="4.0">
  6. <!--配置dispatcherServlet:这是SpringMVC的核心:请求分发器|前端控制类-->
  7. <servlet>
  8. <servlet-name>springmvc</servlet-name>
  9. <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
  10. <!--DispatcherServlet要绑定Spring的配置文件-->
  11. <init-param>
  12. <param-name>contextConfigLocation</param-name>
  13. <param-value>classpath:springmvc-servlet.xml</param-value>
  14. </init-param>
  15. <!--启动级别:1-->
  16. <load-on-startup>1</load-on-startup>
  17. </servlet>
  18. <servlet-mapping>
  19. <servlet-name>springmvc</servlet-name>
  20. <!--/和 /*的区别:
  21. / : 只匹配所有的请求,不会去匹配jsp
  22. /* : 匹配所有的请求,包括匹配jsp
  23. -->
  24. <url-pattern>/</url-pattern>
  25. </servlet-mapping>
  26. </web-app>

4、编写SpringMVC 的 配置⽂件!名称:springmvc-servlet.xml : [servletname]-servlet.xml 说明,这⾥的名称要求是按照官⽅来的
5、添加 处理映射器
6、添加 处理器适配器
7、添加 视图解析器

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <beans xmlns="http://www.springframework.org/schema/beans"
  3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4. xsi:schemaLocation="http://www.springframework.org/schema/beans
  5. http://www.springframework.org/schema/beans/spring-beans.xsd">
  6. <!--添加 处理映射器-->
  7. <bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"/>
  8. <!--添加 处理器适配器-->
  9. <bean class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter"/>
  10. <!--视图解析器:DispatcherServlet给他的ModelAndView-->
  11. <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
  12. <!--前缀-->
  13. <property name="prefix" value="/WEB-INF/jsp/"/>
  14. <!--后缀-->
  15. <property name="suffix" value=".jsp"/>
  16. </bean>
  17. <!--Handler-->
  18. <bean id="/hello" class="com.learn.controller.HelloController"/>
  19. </beans>

8、编写我们要操作业务Controller ,要么实现Controller接⼝,要么增加注解;需要返回⼀个 ModelAndView,装数据,封视图;

  1. package com.learn.controller;
  2. import org.springframework.web.servlet.ModelAndView;
  3. import org.springframework.web.servlet.mvc.Controller;
  4. import javax.servlet.http.HttpServletRequest;
  5. import javax.servlet.http.HttpServletResponse;
  6. public class HelloController implements Controller {
  7. public ModelAndView handleRequest(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws Exception {
  8. ModelAndView modelAndView = new ModelAndView();
  9. //业务代码
  10. String result = "HelloSpringMVC";
  11. modelAndView.addObject("msg",result);
  12. //视图跳转
  13. modelAndView.setViewName("hello");
  14. return modelAndView;
  15. }
  16. }

9、将⾃⼰的类交给SpringIOC容器,注册bean

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

10、写要跳转的jsp⻚⾯,显示ModelandView存放的数据,以及我们的正常⻚⾯;

  1. <%@ page contentType="text/html;charset=UTF-8" language="java" %>
  2. <html>
  3. <head>
  4. <title>Title</title>
  5. </head>
  6. <body>
  7. ${msg}
  8. </body>
  9. </html>

11、配置Tomcat 启动测试!
SpringMVC - 图15

可能遇到的问题:访问出现404,排查步骤:
  1. 查看控制台输出,看⼀下是不是缺少了什么jar包。
  2. 如果jar包存在,显示⽆法输出,就在IDEA的项⽬发布中,添加lib依赖!
  3. 重启Tomcat 即可解决!

SpringMVC - 图16
⼩结:看这个估计⼤部分同学都能理解其中的原理了,但是我们实际开发才不会这么写,不然就疯了, 还学这个玩意⼲嘛!我们来看个注解版实现,这才是SpringMVC的精髓。

3.2 注解版

步骤一:新建⼀个Moudle,springmvc-03-hello-annotation 。添加web⽀持!

步骤二:在pom.xml⽂件引⼊相关的依赖:主要有Spring框架核⼼库、Spring MVC、servlet , JSTL 等。我们在⽗依赖中已经引⼊了!

步骤三:由于Maven可能存在资源过滤的问题,我们将配置完善

Maven项目都可以加以下代码

  1. <build>
  2. <resources>
  3. <resource>
  4. <directory>src/main/java</directory>
  5. <includes>
  6. <include>**/*.properties</include>
  7. <include>**/*.xml</include>
  8. </includes>
  9. <filtering>false</filtering>
  10. </resource>
  11. <resource>
  12. <directory>src/main/resources</directory>
  13. <includes>
  14. <include>**/*.properties</include>
  15. <include>**/*.xml</include>
  16. </includes>
  17. <filtering>false</filtering>
  18. </resource>
  19. </resources>
  20. </build>

步骤四:配置web.xml
  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
  3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4. xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
  5. version="4.0">
  6. <!--1.注册servlet-->
  7. <servlet>
  8. <servlet-name>springmvc</servlet-name>
  9. <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
  10. <!--通过初始化参数指定SpringMVC配置⽂件的位置,进⾏关联-->
  11. <init-param>
  12. <param-name>contextConfigLocation</param-name>
  13. <param-value>classpath:springmvc.xml</param-value>
  14. </init-param>
  15. <!-- 启动顺序,数字越⼩,启动越早 -->
  16. <load-on-startup>1</load-on-startup>
  17. </servlet>
  18. <!--所有请求都会被springmvc拦截 -->
  19. <servlet-mapping>
  20. <servlet-name>springmvc</servlet-name>
  21. <url-pattern>/</url-pattern>
  22. </servlet-mapping>
  23. </web-app>

注意点:
/ 和 /* 的区别:
< url-pattern > / </ url-pattern > 不会匹配到.jsp, 只针对我们编写的请求;即:.jsp 不会进⼊spring的 DispatcherServlet类 。
< url-pattern > / </ url-pattern > 会匹配 .jsp,会出现返回 jsp视图 时再次进⼊spring的DispatcherServlet 类,导致找不到对应的 controller所以报404错。

  • 注意web.xml版本问题,要最新版!
  • 注册DispatcherServlet
  • 关联SpringMVC的配置⽂件
  • 启动级别为1
  • **映射路径为 / 【不要⽤/,会404】

    步骤五:添加Spring MVC配置⽂件

    在resource⽬录下添加springmvc-servlet.xml配置⽂件,配置的形式与 Spring容器配置基本类似,为了⽀持基于注解的IOC,设置了⾃动扫描包的功能,具体配置信息如下:

    1. <?xml version="1.0" encoding="UTF-8"?>
    2. <beans xmlns="http://www.springframework.org/schema/beans"
    3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    4. xmlns:context="http://www.springframework.org/schema/context"
    5. xmlns:mvc="http://www.springframework.org/schema/mvc"
    6. xsi:schemaLocation="http://www.springframework.org/schema/beans
    7. http://www.springframework.org/schema/beans/spring-beans.xsd
    8. http://www.springframework.org/schema/context
    9. https://www.springframework.org/schema/context/spring-context.xsd
    10. http://www.springframework.org/schema/mvc
    11. https://www.springframework.org/schema/mvc/spring-mvc.xsd">
    12. <!-- 自动扫描包,让指定包下的注解生效,由IOC容器统一管理 -->
    13. <context:component-scan base-package="com.learn.controller"/>
    14. <!-- 让Spring MVC不处理静态资源 -->
    15. <mvc:default-servlet-handler/>
    16. <!--
    17. 支持mvc注解驱动
    18. 在spring中一般采用@RequestMapping注解来完成映射关系
    19. 要想使@RequestMapping注解生效
    20. 必须向上下文中注册DefaultAnnotationHandlerMapping
    21. 和一个AnnotationMethodHandlerAdapter实例
    22. 这两个实例分别在类级别和方法级别处理。
    23. 而annotation-driven配置帮助我们自动完成上述两个实例的注入。
    24. -->
    25. <mvc:annotation-driven/>
    26. <!-- 视图解析器 -->
    27. <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"
    28. id="internalResourceViewResolver">
    29. <!-- 前缀 -->
    30. <property name="prefix" value="/WEB-INF/jsp/"/>
    31. <!-- 后缀 -->
    32. <property name="suffix" value=".jsp"/>
    33. </bean>
    34. </beans>

    在视图解析器中我们把所有的视图都存放在/WEB-INF/目录下,这样可以保证视图安全,因为这个目录下的文件,客户端不能直接访问。

  • 让IOC的注解生效

  • 静态资源过滤 :HTML . JS . CSS . 图片 , 视频 …..
  • MVC的注解驱动
  • 配置视图解析器

    步骤六:创建Controller

    编写一个Java控制类:com.learn.controller.HelloController , 注意编码规范

    1. import org.springframework.stereotype.Controller;
    2. import org.springframework.ui.Model;
    3. import org.springframework.web.bind.annotation.RequestMapping;
    4. @Controller
    5. @RequestMapping("/HelloController")
    6. public class HelloController {
    7. //真实访问地址 : 项目名/HelloController/hello
    8. @RequestMapping("/hello")
    9. public String sayHello(Model model) {
    10. //1.封装数据
    11. //向模型中添加属性msg与值,可以在JSP页面中取出并渲染
    12. model.addAttribute("msg", "hello,SpringMVC");
    13. //2.返回视图
    14. //web-inf/jsp/hello.jsp
    15. return "hello";
    16. }
    17. }
  • @Controller是为了让Spring IOC容器初始化时⾃动扫描到;

  • @RequestMapping是为了映射请求路径,这⾥因为类与⽅法上都有映射所以访问时应该是/HelloController/hello;
  • ⽅法中声明Model类型的参数是为了把Action中的数据带到视图中;
  • ⽅法返回的结果是视图的名称hello,加上配置⽂件中的前后缀变成WEB-INF/jsp/hello.jsp。
    步骤七:创建视图层
    在WEB-INF/ jsp⽬录中创建hello.jsp , 视图可以直接取出并展示从 Controller带回的信息;
    可以通过EL表示取出Model中存放的值,或者对象;
    1. <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    2. <html>
    3. <head>
    4. <title>Title</title>
    5. </head>
    6. <body>
    7. ${msg}
    8. </body>
    9. </html>
    步骤八:配置Tomcat运⾏
    SpringMVC - 图17
    总结

    使⽤springMVC必须配置的三⼤件: 处理器映射器、处理器适配器、视图解析器 通常,我们只需要⼿动配置视图解析器,⽽处理器映射器和处理器适配器只需要开启注解驱动即可, ⽽省去了⼤段的xml配置

_@_Controller
  • @Controller注解类型用于声明Spring类的实例是一个控制器(在讲IOC时还提到了另外3个注解);
  • Spring可以使用扫描机制来找到应用程序中所有基于注解的控制器类,为了保证Spring能找到你的控制器,需要在配置文件中声明组件扫描。

    1. <!-- 自动扫描指定的包,下面所有注解类交给IOC容器管理 -->
    2. <context:component-scan base-package="com.kuang.controller"/>
  • 增加一个ControllerTest2类,使用注解实现;

    1. //@Controller注解的类会自动添加到Spring上下文中
    2. @Controller
    3. public class ControllerTest2{
    4. //映射访问路径
    5. @RequestMapping("/t2")
    6. public String index(Model model){
    7. //Spring MVC会自动实例化一个Model对象用于向视图中传值
    8. model.addAttribute("msg", "ControllerTest2");
    9. //返回视图位置
    10. return "test";
    11. }
    12. }
  • 运行tomcat测试
    SpringMVC - 图18

可以发现,我们的两个请求都可以指向一个视图,但是页面结果的结果是不一样的,从这里可以看出视图是被复用的,而控制器与视图之间是弱偶合关系。
注解方式是平时使用的最多的方式!

_@_RequestMapping

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

  1. 只注解在方法上面

    1. @Controller
    2. public class TestController {
    3. @RequestMapping("/h1")
    4. public String test(){
    5. return "test";
    6. }
    7. }
  2. 访问路径:http://localhost:8080/项目名/h1

  3. 同时注解类与方法

    1. @Controller
    2. @RequestMapping("/admin")
    3. public class TestController {
    4. @RequestMapping("/h1")
    5. public String test(){
    6. return "test";
    7. }
    8. }
  4. 访问路径:http://localhost:8080/项目名/admin /h1
    需要先指定类的路径再指定方法的路径;

    1. <!--/和 /*的区别:
    2. / : 只匹配所有的请求,不会去匹配jsp
    3. /* : 匹配所有的请求,包括匹配jsp
    4. -->

四、RestFul 风格

4.1 概念

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

4.2 功能

资源:互联网所有的事物都可以被抽象为资源
资源操作:使用POST、DELETE、PUT、GET,使用不同方法对资源进行操作。
分别对应 添加、 删除、 修改、查询。
传统方式操作资源 :通过不同的参数来实现不同的效果!方法单一,post 和 get
http://127.0.0.1/item/queryItem.action?id=1 查询,GET
http://127.0.0.1/item/saveItem.action 新增,POST
http://127.0.0.1/item/updateItem.action 更新,POST
http://127.0.0.1/item/deleteItem.action?id=1 删除,GET或POST
使用RESTful操作资源 :可以通过不同的请求方式来实现不同的效果!如下:请求地址一样,但是功能可以不同!
http://127.0.0.1/item/1 查询,GET
http://127.0.0.1/item 新增,POST
http://127.0.0.1/item 更新,PUT
http://127.0.0.1/item/1 删除,DELETE

4.3 代码

  1. package com.learn.controller;
  2. import org.springframework.stereotype.Controller;
  3. import org.springframework.ui.Model;
  4. import org.springframework.web.bind.annotation.*;
  5. @Controller
  6. public class RestfulController {
  7. //原来的风格:http://localhost:8080/SpringMVC_03_annotation_war_exploded/add?a=1&b=1
  8. @RequestMapping("/add")
  9. public String test(int a, int b, Model model) {
  10. int res = a + b;
  11. model.addAttribute("msg", "结果为" + res);
  12. return "hello";
  13. }
  14. //restful风格:http://localhost:8080/SpringMVC_03_annotation_war_exploded/add2/1/2
  15. //@RequestMapping(value = "/add2/{a}/{b}",method = RequestMethod.DELETE )
  16. @GetMapping("add3/{a}/{b}")
  17. public String test2(@PathVariable int a, @PathVariable int b, Model model) {
  18. int res = a + b;
  19. model.addAttribute("msg", "结果1为" + res);
  20. return "hello";
  21. }
  22. @PostMapping("add3/{a}/{b}")
  23. public String test3(@PathVariable int a, @PathVariable int b, Model model) {
  24. int res = a + b;
  25. model.addAttribute("msg", "结果2为" + res);
  26. return "hello";
  27. }
  28. }

4.4 总结

1、_@_PathVariable 让方法参数的值对应绑定到一个URI模板变量上。 2、所有的地址栏请求默认都会是 HTTP GET 类型的。 3、Spring MVC 的 _@_RequestMapping 注解能够处理 HTTP 请求的方法, 比如 GET, PUT, POST, DELETE 以及 PATCH。 4、方法级别的注解变体有如下几个:组合注解

_@_GetMapping 是一个组合注解,平时使用的会比较多!它所扮演的是 _@_RequestMapping(method =RequestMethod.GET) 的一个快捷方式。


五、数据处理及转发

5.1 结果跳转方式

5.1.1 ModelAndView(不建议)

设置ModelAndView对象 , 根据view的名称 , 和视图解析器跳到指定的页面 .
页面 : {视图解析器前缀} + viewName +{视图解析器后缀}

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

对应的controller类

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

5.1.2 ServletAPI(不建议)

通过设置ServletAPI , 不需要视图解析器 .
1、通过HttpServletResponse进行输出
2、通过HttpServletResponse实现重定向
3、通过HttpServletResponse实现转发

  1. @Controller
  2. public class ResultGo {
  3. @RequestMapping("/result/t1")
  4. public void test1(HttpServletRequest req, HttpServletResponse rsp) throws IOException {
  5. rsp.getWriter().println("Hello,Spring BY servlet API");
  6. }
  7. @RequestMapping("/result/t2")
  8. public void test2(HttpServletRequest req, HttpServletResponse rsp) throws IOException {
  9. rsp.sendRedirect("/index.jsp");
  10. }
  11. @RequestMapping("/result/t3")
  12. public void test3(HttpServletRequest req, HttpServletResponse rsp) throws Exception {
  13. //转发
  14. req.setAttribute("msg","/result/t3");
  15. req.getRequestDispatcher("/WEB-INF/jsp/test.jsp").forward(req,rsp);
  16. }
  17. }

5.1.3 SpringMVC(建议!!!)

方式一:通过SpringMVC来实现转发和重定向 - 无需视图解析器;
测试前,需要将视图解析器注释掉

  1. @Controller
  2. public class ResultSpringMVC {
  3. @RequestMapping("/rsm/t1")
  4. public String test1(){
  5. //转发
  6. return "/index.jsp";
  7. }
  8. @RequestMapping("/rsm/t2")
  9. public String test2(){
  10. //转发二
  11. return "forward:/index.jsp";
  12. }
  13. @RequestMapping("/rsm/t3")
  14. public String test3(){
  15. //重定向
  16. return "redirect:/index.jsp";
  17. }
  18. }

方式二:通过SpringMVC来实现转发和重定向 - 有视图解析器;
重定向 , 不需要视图解析器 , 本质就是重新请求一个新地方嘛 , 所以注意路径问题.
可以重定向到另外一个请求实现 。

  1. @RequestMapping("/t1")
  2. public String test(Model model){
  3. model.addAttribute("msg","ForwardController");
  4. return "hello";
  5. }
  6. @RequestMapping("/t2")
  7. public String test2(Model model){
  8. model.addAttribute("msg","ForwardController");
  9. return "redirect:/index.jsp";
  10. }

转发:return “hello”; 重定向:return “redirect:/index.jsp”;

5.2 数据处理

5.2.1 处理提交数据

(1) 提交的域名称和处理方法的参数名一致

提交数据 :http://localhost:8080/d/t1?name=qizhao
处理方法 :String name

  1. @Controller()
  2. @RequestMapping("/d")
  3. public class DealData {
  4. @RequestMapping("/t1")
  5. public String test1(String name, Model model){
  6. //1.接受前端参数
  7. System.out.println("接收到前端的参数为"+name);
  8. //2.返回前端的参数
  9. model.addAttribute("msg",name);
  10. //3.跳转视图
  11. return "hello";
  12. }
  13. }

后台输出:kuangshen

(2) 提交的域名称和处理方法的参数名不一致

提交数据 : http://localhost:8080/d/t1?name=qizhao
处理方法 :@RequestParam(“username”) : username提交的域的名称 .

  1. //@RequestParam("username") : username提交的域的名称 .
  2. @RequestMapping("/hello")
  3. public String hello(@RequestParam("username") String name){
  4. System.out.println(name);
  5. return "hello";
  6. }

后台输出:qizhao
无论名字一不一样,都把@RequestParam(“username”)写上,表明这个参数是从前端接收的,可以和其他参数区别开

(3) 提交的是一个对象

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

  1. public class User {
  2. private int id;
  3. private String name;
  4. private int age;
  5. //构造
  6. //get/set
  7. //tostring()
  8. }
  1. <dependency>
  2. <groupId>org.projectlombok</groupId>
  3. <artifactId>lombok</artifactId>
  4. <version>1.16.10</version>
  5. </dependency>

lomko可以简便实体类的写法

  1. @Data
  2. @AllArgsConstructor
  3. @NoArgsConstructor
  4. public class Student {
  5. private int id;
  6. private String name;
  7. private int age;
  8. }

SpringMVC - 图19

提交数据 : http://localhost:8080/d/t3?id=1&name=qz&age=10
处理方法 :User user

  1. @RequestMapping("/t3")
  2. public String test3(User user, Model model){
  3. //1.接受前端参数
  4. System.out.println("接收到前端的参数为"+user);
  5. //2.返回前端的参数
  6. model.addAttribute("msg",user);
  7. //3.跳转视图
  8. return "hello";
  9. }

后台输出 :User{id=1, name=’qz’, age=10}
说明:如果使用对象的话,前端传递的参数名和对象名必须一致,否则就是null。

5.2.2 数据显示到前端

方式一:通过ModelAndView

我们前面一直都是如此 . 就不过多解释

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

方式二:通过ModelMap
  1. @RequestMapping("/hello")
  2. public String hello(@RequestParam("username") String name, ModelMap model){
  3. //封装要显示到视图中的数据
  4. //相当于req.setAttribute("name",name);
  5. model.addAttribute("name",name);
  6. System.out.println(name);
  7. return "hello";
  8. }

方式三:通过Model
  1. @RequestMapping("/ct2/hello")
  2. public String hello(@RequestParam("username") String name, Model model){
  3. //封装要显示到视图中的数据
  4. //相当于req.setAttribute("name",name);
  5. model.addAttribute("msg",name);
  6. System.out.println(name);
  7. return "test";
  8. }

对比:

就对于新手而言简单来说使用区别就是:

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

当然更多的以后开发考虑的更多的是性能和优化,就不能单单仅限于此的了解。

5.3 乱码问题

1、写一个表单页面,

  1. <%@ page contentType="text/html;charset=UTF-8" language="java" %>
  2. <html>
  3. <head>
  4. <title>Title</title>
  5. </head>
  6. <body>
  7. <form action="/e/t1" method="post">
  8. <input type="text" name="name">
  9. <input type="submit">
  10. </form>
  11. </body>
  12. </html>

2、EncodingController,将表单提交的信息输出到test.jsp页面

  1. @Controller
  2. public class EncodingController {
  3. @RequestMapping("/e/t1")
  4. public String test1(String name, Model model) {
  5. System.out.println(name);
  6. model.addAttribute("msg", name);
  7. return "test";
  8. }
  9. }

3、测试发现,页面和控制台中文都乱码。(控制台都乱码,说明是出现在java层面)
SpringMVC - 图20

解决办法一(自己写过滤器)(了解即可)

1、编写EncodingFilter类实现Filter接口,重写doFilter方法
  1. import javax.servlet.*;
  2. import java.io.IOException;
  3. public class EncodingFilter implements Filter {
  4. public void init(FilterConfig filterConfig) throws ServletException {
  5. }
  6. public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
  7. servletRequest.setCharacterEncoding("utf-8");
  8. servletResponse.setCharacterEncoding("utf-8");
  9. //继续往下走
  10. filterChain.doFilter(servletRequest,servletResponse);
  11. }
  12. public void destroy() {
  13. }
  14. }

2、在web.xml文件中配置过滤器
  1. <!--过滤器-->
  2. <filter>
  3. <filter-name>encoding</filter-name>
  4. <filter-class>com.learn.filter.EncodingFilter</filter-class>
  5. </filter>
  6. <filter-mapping>
  7. <filter-name>encoding</filter-name>
  8. <url-pattern>/*</url-pattern>
  9. </filter-mapping>

解决办法二(使用SpringMVC过滤器)
  1. <!--过滤器-->
  2. <filter>
  3. <filter-name>encoding</filter-name>
  4. <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
  5. <init-param>
  6. <param-name>encoding</param-name>
  7. <param-value>utf-8</param-value>
  8. </init-param>
  9. </filter>
  10. <filter-mapping>
  11. <filter-name>encoding</filter-name>
  12. <url-pattern>/*</url-pattern>
  13. </filter-mapping>

六、JSON

什么是JSON?

  • JSON( JavaScript Object Notation, JS 对象标记 ) 是一种轻量级的数据交换格式,目前使用特别广泛。
  • 采用完全独立于编程语言的文本格式来存储和表示数据。
  • 简洁和清晰的层次结构使得 JSON 成为理想的数据交换语言。
  • 易于人阅读和编写,同时也易于机器解析和生成,并有效地提升网络传输效率。

    JavaScript 语言中,一切都是对象。因此,任何JavaScript 支持的类型都可以通过 JSON 来表示,例如字符串、数字、对象、数组等。看看他的要求和语法格式:

  • 对象表示为键值对,数据由逗号分隔

  • 花括号保存对象
  • 方括号保存数组

JSON 键值对是用来保存 JavaScript 对象的一种方式,和 JavaScript 对象的写法也大同小异,键/值对组合中的键名写在前面并用双引号 “” 包裹,使用冒号 : 分隔,然后紧接着值:

  1. {"name": "QinJiang"}
  2. {"age": "3"}
  3. {"sex": "男"}

很多人搞不清楚 JSON 和 JavaScript 对象的关系,甚至连谁是谁都不清楚。其实,可以这么理解:
JSON 是 JavaScript 对象的字符串表示法,它使用文本表示一个 JS 对象的信息,本质是一个字符串。

  1. var obj = {a: 'Hello', b: 'World'}; //这是一个对象,注意键名也是可以使用引号包裹的
  2. var json = '{"a": "Hello", "b": "World"}'; //这是一个 JSON 字符串,本质是一个字符串

JSON 和 JavaScript 对象互转
要实现从JSON字符串转换为JavaScript 对象,使用 JSON.parse() 方法:

  1. var obj = JSON.parse('{"a": "Hello", "b": "World"}');
  2. //结果是 {a: 'Hello', b: 'World'}

要实现从JavaScript 对象转换为JSON字符串,使用 JSON.stringify() 方法:

  1. var json = JSON.stringify({a: 'Hello', b: 'World'});
  2. //结果是 '{"a": "Hello", "b": "World"}'

SpringMVC - 图21

JSON的使用

1、新建项目,导入依赖

  1. <!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-core -->
  2. <dependency>
  3. <groupId>com.fasterxml.jackson.core</groupId>
  4. <artifactId>jackson-databind</artifactId>
  5. <version>2.9.8</version>
  6. </dependency>

2、配置web.xml和配置文件springmvc-sevlet.xml

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
  3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4. xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
  5. version="4.0">
  6. <!--1.注册servlet-->
  7. <servlet>
  8. <servlet-name>SpringMVC</servlet-name>
  9. <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
  10. <!--通过初始化参数指定SpringMVC配置文件的位置,进行关联-->
  11. <init-param>
  12. <param-name>contextConfigLocation</param-name>
  13. <param-value>classpath:springmvc-servlet.xml</param-value>
  14. </init-param>
  15. <!-- 启动顺序,数字越小,启动越早 -->
  16. <load-on-startup>1</load-on-startup>
  17. </servlet>
  18. <!--所有请求都会被springmvc拦截 -->
  19. <servlet-mapping>
  20. <servlet-name>SpringMVC</servlet-name>
  21. <url-pattern>/</url-pattern>
  22. </servlet-mapping>
  23. <!--过滤器-->
  24. <filter>
  25. <filter-name>encoding</filter-name>
  26. <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
  27. <init-param>
  28. <param-name>encoding</param-name>
  29. <param-value>utf-8</param-value>
  30. </init-param>
  31. </filter>
  32. <filter-mapping>
  33. <filter-name>encoding</filter-name>
  34. <url-pattern>/</url-pattern>
  35. </filter-mapping>
  36. </web-app>
  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <beans xmlns="http://www.springframework.org/schema/beans"
  3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4. xmlns:context="http://www.springframework.org/schema/context"
  5. xmlns:mvc="http://www.springframework.org/schema/mvc"
  6. xsi:schemaLocation="http://www.springframework.org/schema/beans
  7. http://www.springframework.org/schema/beans/spring-beans.xsd
  8. http://www.springframework.org/schema/context
  9. https://www.springframework.org/schema/context/spring-context.xsd
  10. http://www.springframework.org/schema/mvc
  11. https://www.springframework.org/schema/mvc/spring-mvc.xsd">
  12. <!-- 自动扫描指定的包,下面所有注解类交给IOC容器管理 -->
  13. <context:component-scan base-package="com.learn.controller"/>
  14. <!-- 视图解析器 -->
  15. <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"
  16. id="internalResourceViewResolver">
  17. <!-- 前缀 -->
  18. <property name="prefix" value="/WEB-INF/jsp/" />
  19. <!-- 后缀 -->
  20. <property name="suffix" value=".jsp" />
  21. </bean>
  22. </beans>

3、新建User类和UserController类

  1. @Data
  2. @AllArgsConstructor
  3. @NoArgsConstructor
  4. public class User {
  5. private String name;
  6. private int age;
  7. private String sex;
  8. }
  1. @Controller
  2. public class UserController {
  3. @RequestMapping("/j1")
  4. @ResponseBody
  5. //它就不会走视图解析器,会直接返回一个字符串
  6. public String json1() {
  7. User user = new User("齐钊1号", 2, "男");
  8. return user.toString();
  9. }
  10. }

4、测试,发现成功但是乱码,而且是对象类型!
SpringMVC - 图22

5、使用ObjectMapper类的writeValueAsString()方法将对象进行解析
  1. @Controller
  2. public class UserController {
  3. @RequestMapping("/j1")
  4. @ResponseBody
  5. //它就不会走视图解析器,会直接返回一个字符串
  6. public String json1() throws JsonProcessingException {
  7. //创建一个jackson的对象映射器,用来解析数据
  8. ObjectMapper mapper = new ObjectMapper();
  9. User user = new User("齐钊1号", 2, "男");
  10. //将我们的对象解析成为json格式
  11. String s = mapper.writeValueAsString(user);
  12. return s;
  13. }
  14. }

6、测试,对象转换成了json格式。
SpringMVC - 图23
7、通过@RequestMaping的produces属性解决乱码

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

SpringMVC - 图24

8、代码优化

a.乱码统一解决

上一种方法比较麻烦,如果项目中有许多请求则每一个都要添加,可以通过Spring配置统一指定,这样就不用每次都去处理了!
我们可以在springmvc的配置文件上添加一段消息StringHttpMessageConverter转换配置!

  1. <mvc:annotation-driven>
  2. <mvc:message-converters register-defaults="true">
  3. <bean class="org.springframework.http.converter.StringHttpMessageConverter">
  4. <constructor-arg value="UTF-8"/>
  5. </bean>
  6. <bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
  7. <property name="objectMapper">
  8. <bean class="org.springframework.http.converter.json.Jackson2ObjectMapperFactoryBean">
  9. <property name="failOnEmptyBeans" value="false"/>
  10. </bean>
  11. </property>
  12. </bean>
  13. </mvc:message-converters>
  14. </mvc:annotation-driven>

b.返回json字符串统一解决

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

  1. @RestController
  2. public class UserController {
  3. //produces:指定响应体返回类型和编码
  4. @RequestMapping(value = "/json1")
  5. public String json1() throws JsonProcessingException {
  6. //创建一个jackson的对象映射器,用来解析数据
  7. ObjectMapper mapper = new ObjectMapper();
  8. //创建一个对象
  9. User user = new User("秦疆1号", 3, "男");
  10. //将我们的对象解析成为json格式
  11. String str = mapper.writeValueAsString(user);
  12. //由于@ResponseBody注解,这里会将str转成json格式返回;十分方便
  13. return str;
  14. }
  15. }

启动tomcat测试,结果都正常输出!

不同类型的json输出

1、集合类型
  1. @RequestMapping("/j2")
  2. public String json2() throws JsonProcessingException {
  3. //创建一个jackson的对象映射器,用来解析数据
  4. ObjectMapper mapper = new ObjectMapper();
  5. List<User> users = new ArrayList<User>();
  6. User user1 = new User("齐钊1号", 1, "男");
  7. User user2 = new User("齐钊2号", 2, "男");
  8. User user3 = new User("齐钊3号", 3, "男");
  9. users.add(user1);
  10. users.add(user2);
  11. users.add(user3);
  12. String s = mapper.writeValueAsString(users);
  13. return s;
  14. //可以写成return new ObjectMapper().writeValueAsString(users);
  15. }

SpringMVC - 图25

2、时间类型
  1. @RequestMapping("/j3")
  2. public String json3() throws JsonProcessingException {
  3. //创建一个jackson的对象映射器,用来解析数据
  4. ObjectMapper mapper = new ObjectMapper();
  5. Date date = new Date();
  6. String s = mapper.writeValueAsString(date);
  7. return s;
  8. }

输出是时间戳
SpringMVC - 图26

格式化时间,方法一:关闭mapper配置
  1. @RequestMapping("/j4")
  2. public String json4() throws JsonProcessingException {
  3. ObjectMapper mapper = new ObjectMapper();
  4. mapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS,false);
  5. Date date = new Date();
  6. String s = mapper.writeValueAsString(date);
  7. return s;
  8. }

SpringMVC - 图27

格式化时间,方法二:使用SimpleDateFormat
  1. @RequestMapping("/j3")
  2. public String json3() throws JsonProcessingException {
  3. ObjectMapper mapper = new ObjectMapper();
  4. //使用SimpleDateFormat格式化时间
  5. SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
  6. Date date = new Date();
  7. String s = mapper.writeValueAsString(sdf.format(date));
  8. return s;
  9. }

SpringMVC - 图28

创建工具类SpringMVC - 图29
  1. package com.learn.utils;
  2. import com.fasterxml.jackson.core.JsonProcessingException;
  3. import com.fasterxml.jackson.databind.ObjectMapper;
  4. import com.fasterxml.jackson.databind.SerializationFeature;
  5. import java.text.SimpleDateFormat;
  6. /**
  7. * 工具类
  8. */
  9. public class JsonUtils {
  10. //方法的重载,不需要传递日期格式
  11. public static String getJson(Object object){
  12. return getJson(object,"yyyy-MM-dd HH:mm:ss");
  13. }
  14. //需要传递日期格式
  15. public static String getJson(Object object,String dateFormat){
  16. ObjectMapper mapper = new ObjectMapper();
  17. //不使用时间戳的方式
  18. mapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS,false);
  19. //自定义日期的格式
  20. SimpleDateFormat sdf = new SimpleDateFormat(dateFormat);
  21. mapper.setDateFormat(sdf);
  22. try {
  23. return mapper.writeValueAsString(object);
  24. } catch (JsonProcessingException e) {
  25. e.printStackTrace();
  26. }
  27. return null;
  28. }
  29. }

工具类的测试

  1. @RequestMapping("/j5")
  2. public String json5() throws JsonProcessingException {
  3. Date date = new Date();
  4. return JsonUtils.getJson(date);
  5. //return JsonUtils.getJson(date,"yyyy-MM-dd HH:mm:ss");
  6. }

SpringMVC - 图30

  1. @RequestMapping("/j6")
  2. public String json6() throws JsonProcessingException {
  3. List<User> users = new ArrayList<User>();
  4. User user1 = new User("齐钊1号", 1, "男");
  5. User user2 = new User("齐钊2号", 2, "男");
  6. User user3 = new User("齐钊3号", 3, "男");
  7. users.add(user1);
  8. users.add(user2);
  9. users.add(user3);
  10. return JsonUtils.getJson(users);
  11. }

SpringMVC - 图31

fastjson(阿里的Json工具类)

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

  1. <dependency>
  2. <groupId>com.alibaba</groupId>
  3. <artifactId>fastjson</artifactId>
  4. <version>1.2.76</version>
  5. </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 类

  1. package com.kuang.controller;
  2. import com.alibaba.fastjson.JSON;
  3. import com.alibaba.fastjson.JSONObject;
  4. import com.kuang.pojo.User;
  5. import java.util.ArrayList;
  6. import java.util.List;
  7. public class FastJsonDemo {
  8. public static void main(String[] args) {
  9. //创建一个对象
  10. User user1 = new User("秦疆1号", 3, "男");
  11. User user2 = new User("秦疆2号", 3, "男");
  12. User user3 = new User("秦疆3号", 3, "男");
  13. User user4 = new User("秦疆4号", 3, "男");
  14. List<User> list = new ArrayList<User>();
  15. list.add(user1);
  16. list.add(user2);
  17. list.add(user3);
  18. list.add(user4);
  19. System.out.println("*******Java对象 转 JSON字符串*******");
  20. String str1 = JSON.toJSONString(list);
  21. System.out.println("JSON.toJSONString(list)==>"+str1);
  22. String str2 = JSON.toJSONString(user1);
  23. System.out.println("JSON.toJSONString(user1)==>"+str2);
  24. System.out.println("\n****** JSON字符串 转 Java对象*******");
  25. User jp_user1=JSON.parseObject(str2,User.class);
  26. System.out.println("JSON.parseObject(str2,User.class)==>"+jp_user1);
  27. System.out.println("\n****** Java对象 转 JSON对象 ******");
  28. JSONObject jsonObject1 = (JSONObject) JSON.toJSON(user2);
  29. System.out.println("(JSONObject) JSON.toJSON(user2)==>"+jsonObject1.getString("name"));
  30. System.out.println("\n****** JSON对象 转 Java对象 ******");
  31. User to_java_user = JSON.toJavaObject(jsonObject1, User.class);
  32. System.out.println("JSON.toJavaObject(jsonObject1, User.class)==>"+to_java_user);
  33. }
  34. }

这种工具类,我们只需要掌握使用就好了,在使用的时候在根据具体的业务去找对应的实现。和以前的commons-io那种工具包一样,拿来用就好了!