SpringMVC详解及SSM框架整合项目【上】

本文涉及的产品
全局流量管理 GTM,标准版 1个月
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
云解析 DNS,旗舰版 1个月
简介: SpringMVC ssm : mybatis + Spring + SpringMVC MVC三层架构 JavaSE:认真学习,老师带,入门快 JavaWeb:认真学习,老师带,入门快 SSM框架:研究官方文档,锻炼自学能力,锻炼笔记能力,锻炼项目能力 SpringMVC + Vue + Spri

SpringMVC


ssm : mybatis + Spring + SpringMVC MVC三层架构


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


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


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

SpringMVC + Vue + SpringBoot + SpringCloud + Linux

SSM = JavaWeb做项目;

Spring : IOC 和 AOP


SpringMVC : SpringMVC的执行流程!【重点】


SpringMVC : SSM框架整合!


Spring

MVC : 模型Model(dao,service) 视图(view) 控制器Controller(Servlet)


1、回顾MVC


1.1、什么是MVC


  • MVC是模型(Model)、视图(View)、控制器(Controller)的简写,是一种软件设计规范。


  • 是将业务逻辑、数据、显示分离的方法来组织代码。


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


  • MVC不是一种设计模式,MVC是一种架构模式。当然不同的MVC存在差异。


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


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


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

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



1.2、Model1时代


  • 在web早期的开发中,通常采用的都是Model1。


  • Model1中,主要分为两层,视图层和模型层。



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


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


1.3、Model2时代


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



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


职责分析:


Controller:控制器

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


Model:模型

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


View:视图


  1. 显示页面

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


1.4、回顾Servlet


  1. 新建一个Maven工程当作父工程! pom依赖!


<!--依赖-->
<dependencies>
    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>4.12</version>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-webmvc</artifactId>
        <version>5.3.17</version>
    </dependency>
    <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>
</dependencies>


  1. 建立一个Module:springmvc-01-servlet,添加Web-app的支持!


  1. 导入servlet 和 jsp 的 jar 依赖,已继承父工程的依赖时可省略


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


  1. 编写一个Servlet类,用来处理用户的请求


//实现Servlet接口
public class HelloServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //1.获取前端参数
        String method = req.getParameter("method");
        if (method.equals("add")){
            req.getSession().setAttribute("msg","执行了add方法");
        }
        if (method.equals("delete")){
            req.getSession().setAttribute("msg","执行了delete方法");
        }
        //2.调用业务层
        //3.视图转发或者重定向
        req.getRequestDispatcher("/WEB-INF/jsp/test.jsp").forward(req,resp); //request 转发,不换URL
        //resp.sendRedirect(); //response 重定向,换URL
    }
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req, resp);
    }
}


  1. 编写Hello.jsp,在WEB-INF目录下新建一个jsp的文件夹,新建test.jsp


<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
${msg}
</body>
</html>


  1. 在web.xml中注册Servlet


<?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">
    <servlet>
        <servlet-name>hello</servlet-name>
        <servlet-class>com.kuang.servlet.HelloServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>hello</servlet-name>
        <url-pattern>/hello</url-pattern>
    </servlet-mapping>
<!--    <session-config>-->
<!--        <session-timeout>15</session-timeout>-->
<!--    </session-config>-->
<!--    <welcome-file-list>-->
<!--        <welcome-file>index.jsp</welcome-file>-->
<!--    </welcome-file-list>-->
</web-app>


  1. 配置Tomcat,并启动测试



流程图:



MVC框架要做哪些事情


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


说明:


常见的服务器端MVC框架有:Structs、SpringMVC、ASP.NET MVC、Zend Framework、JSF;常见前端MVC框架:vue、angularjs、react、backbone;由MVC演化出了另外一些模式如:MVP、MVVM等等...


2、什么是SpringMVC


2.1、概述:


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


官方文档:https://docs.spring.io/spring-framework/docs/current/reference/html/web.html#spring-web


我们为什么要学习SpringMVC呢?


  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、中心控制器


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


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



SpringMVC的原理如下图所示:


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



2.3、第一个MVC程序:HelloSpringMVC


  1. 新建一个Module,springmvc-02-hello,添加web的支持!
  2. 确定导入了SpringMVC的依赖!
  3. 配置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">
    <servlet>
        <servlet-name>springmvc</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<!--        &lt;!&ndash;关联一个springmvc的配置文件:【servlet-name】-servlet.xml&ndash;&gt;-->
<!--        <init-param>-->
<!--            <param-name>contextConfigLocation</param-name>-->
<!--            <param-value>classpath:springmvc-servlet.xml</param-value>-->
<!--        </init-param>-->
<!--        &lt;!&ndash;启动级别-1&ndash;&gt;-->
<!--        <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>


  1. 编写SpringMVC的配置文件!名称:springmvc-servlet.xml:[servletname]-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"
         xsi:schemaLocation="http://www.springframework.org/schema/beans
         http://www.springframework.org/schema/beans/spring-beans.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/jsp/"/>
        <!--后缀-->
        <property name="suffix" value=".jsp"/>
    </bean>
    <!--Handler-->
    <bean id="/hello" class="com.kuang.controller.HelloController"/>
</beans>


  1. 编写我们要操作业务Controller,要么实现Controller接口,要么增加注解;需要返回一个ModelAndView,装数据,封视图;


//注意:这里我们先导入Controller接口
public class HelloController implements Controller {
    @Override
    public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception {
        //ModelAndView 模型和视图
        ModelAndView mv = new ModelAndView();
        //封装对象,放在ModelAndView中。Model
        mv.addObject("msg","HelloSpringMVC!");
        //封装要跳转的视图,放在ModelAndView中
        mv.setViewName("hello"); //: /WEB-INF/jsp/hello.jsp
        return mv;
    }
}


  1. 写要跳转的jsp页面,显示ModelAndView存放的数据,以及我们的正常页面;


<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
${msg}
</body>
</html>


  1. 将自己的类交给SpringIOC容器,注册bean


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


  1. 配置Tomcat启动测试!


可能遇到的问题:访问出现404,排查步骤:


  1. 查看控制台输出,看一下是不是缺少了什么jar包


  1. 如果jar包存在,显示无法输出,就在IDEA的项目发布中,添加lib依赖!



  1. 重启Tomcat即可解决!


2.4、SpringMVC执行原理



图为SpringMVC的一个较完整的流程图,实线表示SpringMVC框架提供的技术,不需要开发者实现,虚线表示需要开发者实现。


简要分析执行流程


  1. DispatcherServlet表示前置控制器,是整个SpringMVC的控制中心。用户发出请求,DispatcherServlet接收请求并拦截请求。
  • 我们假设请求的url为:http://localhost:8080/SpringMVC/hello
  • 如上url拆分成三部分:
  • http://localhost:8080服务器域名
  • SpringMVC部署在服务器上的web站点
  • hello表示控制器
  • 通过分析,如上url表示为:请求位于服务器localhost:8080上的SpringMVC站点的hello控制器。


  1. HandlerMapping为处理器映射。DispatcherServlet调用
    HandlerMapping,HandlerMapping根据请求url查找Handler。


  1. HandlerExecution表示具体的Handler,其主要作用是根据url查找控制器,如上url被查找控制器为:hello。


  1. HandlerExecution将解析后的信息传递给DispatcherServlet,如解析控制器映射等。


  1. HandlerAdapter表示处理器适配器,其按照特定的规则去执行Handler。


  1. Handler让具体的Controller执行。


  1. Controller将具体的执行信息返回给HandlerAdapter,如ModelAndView。


  1. HandlerAdapter将视图逻辑名或模型传递给DispatcherServlet。


  1. DispatcherServlet调用视图解析器(ViewResolver)来解析HandlerAdapter传递的逻辑视图名。


  1. 视图解析器将解析的逻辑视图名传给DispatcherServlet。


  1. DispatcherServlet根据视图解析器解析的视图结果,调用具体的试图。


  1. 最终视图呈现给用户。


2.5、使用注解再次实现第一个MVC程序


  1. 新建一个Module,springmvc-03-annotation,添加web支持!


  1. 由于Maven可能存在资源过滤的问题,我们将配置完善


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


  1. 在pom.xml文件中引入相关的依赖:主要有Spring框架核心库、Spring MVC、servlet、jstl等。我们在父依赖中已经引入了!


  1. 配置web.xml


<?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">
    <servlet>
        <servlet-name>springmvc</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <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>
    <servlet-mapping>
        <servlet-name>springmvc</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>
</web-app>


  1. 添加Spring MVC配置文件


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


<?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
         http://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.kuang.controller"/>
    <!--让Spring MVC不处理静态资源 .css .js .html .mp3 .mp4-->
    <mvc:default-servlet-handler/>
    <!--
    支持mvc注解驱动
        在spring中一般采用@RequestMapping注解来完成映射关系
        要想使@RequestMapping注解生效
        必须让上下文中注册DefaultAnnotationHandlerMapping
        和一个AnnotationMethodHandlerAdapter实例
        这两个实例分别在类级别和方法级别处理。
        而annotation-driven配置帮助我们自动完成上述两个实例的注入。
    -->
    <mvc:annotation-driven/>
    <!--视图解析器
  在视图解析器中,我们把所有的视图都存放在/WEB-INF/目录下,这样可以保证视图安全,因为这个目录下的文件,客户端不能直接访问-->
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" id="internalResourceViewResolver">
        <!--前缀-->
        <property name="prefix" value="/WEB-INF/jsp/"/>
        <!--后缀-->
        <property name="suffix" value=".jsp"/>
    </bean>
</beans>


  1. 创建Controller编写一个Java控制类:com.kuang.controller.HelloController,注意编码规范


@Controller
@RequestMapping("/hello")
public class HelloController {
    // localhost:8080/hello/h1 两级映射路径
    @RequestMapping("/h1")
    public String hello(Model model){
        //封装数据
        model.addAttribute("msg","Hello,SpringMVCAnnotation!");
        return "hello"; //会被视图解析器处理;
    }
}


  • @Controller是为了让Spring IOC容器初始化时自动扫描到;
  • @RequestMapping是为了映射请求路径,这里因为类与方法上都有映射所以访问时应该是/hello/h1;
  • 方法中声明Model类型的参数是为了把Action中的数据带到视图中;
  • 方法返回的结果是视图的名称hello,加上配置文件中的前后缀变成/WEB-INF/jsp/hello.jsp。


  1. 创建视图层
    在WEB-INF/jsp目录中创建hello.jsp,视图可以直接取出并展示从Controller带回的信息;
    可以通过EL表达式取出Model中存放的值,或者对象;


<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
${msg}
</body>
</html>


  1. 配置Tomcat运行


配置Tomcat,开启服务器,访问对应的请求路径!


小结:


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


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


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


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

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


3、RestFul风格与控制器


3.1、控制器Controller


控制器Controller:


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


实现Controller接口


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


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


测试:


  1. 新建一个Module,springmvc-04-controller。将刚才的03拷贝一份,我们进行操作!
  • 删掉HelloController
  • mvc的配置文件只留下视图解析器!


  1. 编写一个Controller类,HelloController


public class HelloController implements Controller {
    @Override
    public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception {
        ModelAndView mv = new ModelAndView();
        mv.addObject("msg","hello,controller");
        mv.setViewName("hello");
        return mv;
    }
}


  1. 编写完毕后,去Spring配置文件中注册请求的bean;name对应请求路径,class对应处理请求的类


<bean id="/hello" class="com.kuang.controller.HelloController"/>


  1. 编写前端hello.jsp,注意在WEB-INF/jsp目录下编写,对应我们的视图解析器


<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
${msg}
</body>
</html>


  1. 配置Tomcat运行测试!


说明:


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


使用注解@Controller


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


<!--自动扫描指定的包,下面所有注解类交给IOC容器管理-->
<context:component-scan base-package="com.kuang.controller"/>


  • 新建HelloController2类,使用注解实现;


//@Controller注解的类会自动添加到Spring上下文中
@Controller //代表这个类会被Spring托管,
// 被这个注解的类中的所有方法,如果返回值是String,并且有具体页面可以跳转,那么就会被视图解析器解析;
public class HelloController2 {
    @RequestMapping("/hello2") //RequestMapping注解必须放在方法的上面,否则无法找到,404错误
    public String test(Model model){
        model.addAttribute("msg","hello,controller2");
        return "hello";
    }
}


  • 运行Tomcat测试


此外,不同的请求可以指向一个视图,但是页面结果中的内容可以是不一样的,视图可以被复用,而控制器与视图之间是弱耦合关系。


注解方式是平时使用的最多的方式!


3.2、RequestMapping


@RequestMapping


  • @RequestMapping注解用于映射url到控制器类或一个特定的处理程序方法。可用于类或方法上。用于类上,表示类中的所有响应请求的方法都是以该地址作为父路径。
  • 为了测试结论更加准确,我们可以加上一个项目名测试 myweb
  • 只注解在方法上面


@Controller //代表这个类会被Spring托管,
// 被这个注解的类中的所有方法,如果返回值是String,并且有具体页面可以跳转,那么就会被视图解析器解析;
public class HelloController {
    @RequestMapping("/hello") //RequestMapping注解必须放在方法的上面,否则无法找到,404错误
    public String test(Model model){
        model.addAttribute("msg","hello,controller");
        return "hello";
    }
}



  • 同时注解类与方法


@Controller //代表这个类会被Spring托管,
// 被这个注解的类中的所有方法,如果返回值是String,并且有具体页面可以跳转,那么就会被视图解析器解析;
@RequestMapping("/hello")
public class HelloController {
    @RequestMapping("/hello") //RequestMapping注解必须放在方法的上面,否则无法找到,404错误
    public String test(Model model){
        model.addAttribute("msg","hello,controller");
        return "hello";
    }
}



  • 其实使用如下方式更方便


@Controller 
public class HelloController {
    @RequestMapping("/hello/hello") 
    public String test(Model model){
        model.addAttribute("msg","hello,controller");
        return "hello";
    }
}



3.3、RestFul风格


概念


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


功能


资源:互联网所有的事物都可以被抽象为资源


资源操作:使用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


学习测试


  1. 新建一个类 RestFulController


@Controller
public class RestFulController {
}


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


@Controller
public class RestFulController {
    @RequestMapping("/add/{a}/{b}")
    public String test1(@PathVariable int a,@PathVariable int b, Model model){
        int res = a + b;
        model.addAttribute("msg","结果1是:"+res);
        return "hello";
    }
}


  1. 我们来测试请求查看下



  1. 思考:使用路径变量的好处?
  • 使路径变得更加简洁;
  • 获得参数更加方便,框架会自动进行类型转换。
  • 通过路径变量的类型可以约束访问参数,如果类型不一样,则访问不到对应的请求方法,如这里访问的路径是/add/1/a,则路径与方法不匹配400错误,而不会是参数转换失败。


使用method属性指定请求类型


用于约束请求的类型,可以收窄请求范围。指定请求的类型如GET,POST,HEAD,OPTIONS,PUT,PATCH,DELETE,TRACE等


我们来测试一下:


  • 增加一个方法


@Controller
public class RestFulController {
    @RequestMapping(value = "/add/{a}/{b}",method = RequestMethod.GET)
    //@GetMapping("/add/{a}/{b}")
    public String test1(@PathVariable int a,@PathVariable int b, Model model){
        int res = a + b;
        model.addAttribute("msg","结果1是:"+res);
        return "hello";
    }
}


  • 浏览器地址栏进行访问默认是GET请求,如果手动设置为其他请求类型则会报405错误


小结:


Spring MVC的@RequestMapping注解能够处理HTTP请求的方法,比如GET,PUT,POST,DELETE以及PATCH。

所有的地址栏请求默认都会是 HTTP GET 类型的。


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


@GetMapping
@PostMapping
@PutMapping
@DeleteMapping
@PatchMapping


@GetMapping 是一个组合注解,平时使用的会比较多!

它所扮演的是 @RequestMapping(method =RequestMethod.GET) 的一个快捷方式。


4、数据处理及跳转


4.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类


@Controller
public class ModelTest1 {
    @RequestMapping("/m1/t1")
    public String test(HttpServletRequest request,HttpServletResponse response){
        //返回一个模型视图对象
        ModelAndView mv = new ModelAndView();
        mv.addObject("msg","ModelTest1");
        mv.setViewName("hello");
        return mv;
    }
}


ServletAPI


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


  1. 通过HttpServletResponse进行输出
  2. 通过HttpServletResponse实现重定向
  3. 通过HttpServletRequest实现转发


@Controller
public class ModelTest1 {
    @RequestMapping("/hello/t1")
    public void test1(HttpServletRequest req, HttpServletResponse rsp) throws IOException {
        rsp.getWriter().println("Hello,Spring BY servlet API");
  }
    @RequestMapping("/hello/t2")
    public void test2(HttpServletRequest req, HttpServletResponse rsp) throws IOException {
        rsp.sendRedirect("/index.jsp");
  }
    @RequestMapping("/hello/t3")
    public void test3(HttpServletRequest req, HttpServletResponse rsp) throws Exception {
        //转发
        req.setAttribute("msg","/hello/t3");
        req.getRequestDispatcher("/WEB-INF/jsp/hello.jsp").forward(req,rsp);
    }
}


SpringMVC

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

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


@Controller
public class ModelTest1 {
    @RequestMapping("/m1/t1")
    public String test1(){
        //转发
        return "/index.jsp";
    }
    @RequestMapping("/m1/t2")
    public String test2(){
        //转发二
        return "forward:/index.jsp";
    }
    @RequestMapping("/m1/t3")
    public String test3(){
        //重定向
        return "redirect:/index.jsp";
    }
}


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


显式使用forward及redirect拼接完整路径实现转发(URL地址不变)和重定向(URL地址改变)时,都不需要视图解析器,开启视图解析器时,视图解析器会被忽略。

重定向,不需要视图解析器,本质就是重新请求一个新地方,所以注意路径问题。可以重定向到另一个请求实现。


@Controller
public class ModelTest1 {
    @RequestMapping("/m1/t1")
    public String test1(){
        //通过视图解析器转发
        return "test";
    }
    @RequestMapping("/m1/t1")
    public String test(Model model){
        //不通过视图解析器转发
        model.addAttribute("msg","ModelTest1");
        return "forward:/WEB-INF/jsp/hello.jsp";
    }
    @RequestMapping("/m1/t2")
    public String test2(){
        //不通过视图解析器重定向
        return "redirect:/index.jsp";
        //return "redirect:hello.do"; //hello.do为另一个请求/
    }
}


4.2、数据处理


处理提交数据


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

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

处理方法:


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


后台输出:kuangshen


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

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

处理方法:


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


后台输出:kuangshen


  1. 提交的是一个对象

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


  • 实体类


@Data
@NoArgsConstructor
@AllArgsConstructor
public class User {
    private int id;
    private String name;
    private int age;
}



  • 处理方法:


@RequestMapping("/t2")
public String user(User user){
   System.out.println(user);
   return "hello";
}


  • 后台输出:User { id=1, name='kuangshen', age=15 }
    说明:如果使用对象的话,前端传递的参数名和对象名必须一致,否则就是null。参数顺序可任意变换。


数据显示到前端


第一种:通过ModelAndView

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


public class HelloController implements Controller {
    @Override
    public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception {
        ModelAndView mv = new ModelAndView();
        mv.addObject("msg","hello,controller");
        mv.setViewName("hello");
        return mv;
    }
}


第二种:通过ModelMap

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";
}


第三种:通过Model

Model


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


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


乱码问题


测试步骤:


  1. 我们可以在首页编写一个提交的表单


<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
<form action="/hello/t1" method="post">
    <input type="text" name="name"><br>
    <input type="submit">
</form>
</body>
</html>


  1. 后台编写对应的处理类


@Controller
public class EncodingController {
    @RequestMapping("/hello/t1")
    public String test(String name,Model model){
        model.addAttribute("msg",name);//获取表单提交的值
        return "hello";//跳转到hello页面显示输入的值
    }
}


  1. 输入中文测试,发现乱码



不得不说,乱码问题是在我们开发中十分常见的问题,也是让我们程序员比较头大的问题!


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


修改了xml文件需要重启服务器!


<filter>
    <filter-name>encoding</filter-name>
    <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
    <init-param>
        <param-name>encoding</param-name>
        <param-value>utf-8</param-value>
    </init-param>
</filter>
<filter-mapping>
    <filter-name>encoding</filter-name>
    <!--一定要使用/*才能过滤所有网页-->
    <url-pattern>/*</url-pattern>
</filter-mapping>


但是我们发现,有些极端情况下,这个过滤器对get的支持不好。


处理方法:

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

路径:D:\environment\apache-tomcat-9.0.58-windows-x64\apache-tomcat-9.0.58\conf server.xml文件


<Connector port="8080" protocol="HTTP/1.1"
               connectionTimeout="20000"
               redirectPort="8443" 
         URLEncoding="UTF-8"/>


  1. 自定义过滤器


package com.kuang.filter;
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.Map;
/**
* 解决get和post请求 全部乱码的过滤器
*/
public class GenericEncodingFilter implements Filter {
    @Override
    public void destroy() {
    }
    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        //处理response的字符编码
        HttpServletResponse myResponse=(HttpServletResponse) response;
        myResponse.setContentType("text/html;charset=UTF-8");
        // 转型为与协议相关对象
        HttpServletRequest httpServletRequest = (HttpServletRequest) request;
        // 对request包装增强
        HttpServletRequest myrequest = new MyRequest(httpServletRequest);
        chain.doFilter(myrequest, response);
    }
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
    }
}
//自定义request对象,HttpServletRequest的包装类
class MyRequest extends HttpServletRequestWrapper {
    private HttpServletRequest request;
    //是否编码的标记
    private boolean hasEncode;
    //定义一个可以传入HttpServletRequest对象的构造函数,以便对其进行装饰
    public MyRequest(HttpServletRequest request) {
        super(request);// super必须写
        this.request = request;
    }
    // 对需要增强方法 进行覆盖
    @Override
    public Map getParameterMap() {
        // 先获得请求方式
        String method = request.getMethod();
        if (method.equalsIgnoreCase("post")) {
            // post请求
            try {
                // 处理post乱码
                request.setCharacterEncoding("utf-8");
                return request.getParameterMap();
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
            }
        } else if (method.equalsIgnoreCase("get")) {
            // get请求
            Map<String, String[]> parameterMap = request.getParameterMap();
            if (!hasEncode) { // 确保get手动编码逻辑只运行一次
                for (String parameterName : parameterMap.keySet()) {
                    String[] values = parameterMap.get(parameterName);
                    if (values != null) {
                        for (int i = 0; i < values.length; i++) {
                            try {
                                // 处理get乱码
                                values[i] = new String(values[i]
                                                       .getBytes("ISO-8859-1"), "utf-8");
                            } catch (UnsupportedEncodingException e) {
                                e.printStackTrace();
                            }
                        }
                    }
                }
                hasEncode = true;
            }
            return parameterMap;
        }
        return super.getParameterMap();
    }
    //取一个值
    @Override
    public String getParameter(String name) {
        Map<String, String[]> parameterMap = getParameterMap();
        String[] values = parameterMap.get(name);
        if (values == null) {
            return null;
        }
        return values[0]; // 取回参数的第一个值
    }
    //取所有值
    @Override
    public String[] getParameterValues(String name) {
        Map<String, String[]> parameterMap = getParameterMap();
        String[] values = parameterMap.get(name);
        return values;
    }
}


这个也是在网上找的一些大神写的,一般情况下,Spring MVC默认的乱码处理就已经能够很好的解决了!


然后在web.xml中配置这个过滤器即可!


乱码问题,需要平时多注意,在尽可能能设置编码的地方,都设置为统一编码 UTF-8!


5、JSON


5.1、什么是JSON?


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

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

  • 对象表示为键值对,数据由逗号分隔
  • 花括号保存对象
  • 方括号保存数组


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


{"name": "QinJiang"}
{"age": "3"}
{"sex": "男"}


很多人搞不清楚 JSON 和 JavaScript 对象的关系,甚至连谁是谁都不清楚。其实,可以这么理解:


JSON 是 JavaScript 对象的字符串表示法,它使用文本表示一个 JS 对象的信息,本质是一个字符串。


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


JSON 和 JavaScript 对象互转


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

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


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


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


代码测试

1、新建一个module ,springmvc-05-json , 添加web的支持

2、在web目录下新建一个 jsontest.html , 编写测试内容


<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <!--script不能自闭合-->
    <script type="text/javascript">
        //编写一个JavaScript对象 ES6
        var user = {
            name:"秦疆",
            age:3,
            sex:"男"
        };
        //将js对象转换为JSON对象;
        var json = JSON.stringify(user);
        console.log(json);
        console.log("==================================");
        //将JSON对象转换为JavaScript对象
        var obj = JSON.parse(json);
        console.log(obj);
    </script>
</head>
<body>
</body>
</html>


3、在IDEA中使用浏览器打开,查看控制台输出!



5.2、Controller返回JSON数据


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

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

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


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


配置SpringMVC需要的配置

web.xml


<?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.注册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>
   </servlet-mapping>
   <filter>
       <filter-name>encoding</filter-name>
       <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
       <init-param>
           <param-name>encoding</param-name>
           <param-value>utf-8</param-value>
       </init-param>
   </filter>
   <filter-mapping>
       <filter-name>encoding</filter-name>
       <url-pattern>/</url-pattern>
   </filter-mapping>
</web-app>


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
         http://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.kuang.controller"/>
    <!--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>
    <!--视图解析器-->
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" id="internalResourceViewResolver">
        <property name="prefix" value="/WEB-INF/jsp/"/>
        <property name="suffix" value=".jsp"/>
    </bean>
</beans>


我们随便编写一个User的实体类,然后我们去编写我们的测试Controller;


//需要导入lombok
@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {
   private String name;
   private int age;
   private String sex;
}


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

编写一个Controller;


//@Controller
@RestController //下面的类只会返回字符串,不走视图解析器
public class UserController {
    @RequestMapping(value = "/j1")
    //@ResponseBody //它就不会走视图解析器,会直接返回一个字符串,可以配合 @Controller 使用
    public String json1() throws JsonProcessingException {
        //jackson, ObjectMapper
        ObjectMapper mapper = new ObjectMapper();
        //创建一个对象
        User user = new User("秦疆一号",3,"男");
        return mapper.writeValueAsString(user);
    }
}


配置Tomcat , 启动测试一下!

http://localhost:8080/j1


乱码问题的解决:


  1. 通过@RequestMaping的produces属性来实现,修改下代码

//produces:指定响应体返回类型和编码
@RequestMapping(value = "/j1",produces = "application/json;charset=utf-8")


  1. 通过Springmvc-servlet.xml配置文件解决,加入StringHttpMessageConverter转换配置


<!--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字符串统一解决


在类上直接使用 @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("秦疆1号", 3, "男");
        //将我们的对象解析成为json格式
        String str = mapper.writeValueAsString(user);
        //由于@ResponseBody注解,这里会将str转成json格式返回;十分方便
        return str;
    }
}


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


测试集合输出


增加一个新的方法


@RequestMapping(value = "/j2")
public String json2() throws JsonProcessingException {
    //创建一个jackson的对象映射器,用来解析数据
    ObjectMapper mapper = new ObjectMapper();
    List<User> userList = new ArrayList<User>();
    User user1 = new User("秦疆1号",3,"男");
    User user2 = new User("秦疆2号",3,"男");
    User user3 = new User("秦疆3号",3,"男");
    User user4 = new User("秦疆4号",3,"男");
    userList.add(user1);
    userList.add(user2);
    userList.add(user3);
    userList.add(user4);
    //return mapper.writeValueAsString(userList);
    return JsonUtils.getJson(userList);
}


运行结果:十分完美,没有任何问题!



输出时间对象


增加一个新的方法


@RequestMapping("/j3")
public String json3() throws JsonProcessingException {
    ObjectMapper mapper = new ObjectMapper();
    //创建时间一个对象,java.util.Date
    Date date = new Date();
    //将我们的对象解析成为json格式
    String str = mapper.writeValueAsString(date);
    return str;
}


运行结果:



  • 默认日期格式会变成一个数字,是1970年1月1日到当前日期的毫秒数!


  • Jackson 默认是会把时间转成timestamps形式


解决方案:取消timestamps形式 , 自定义时间格式


@RequestMapping(value = "/j3")
public String json3() throws JsonProcessingException {
    ObjectMapper mapper = new ObjectMapper();
    //Date date = new Date();
    //自定义日期的格式
    //SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    //ObjectMapper,时间解析后的默认格式为:Timestamp,时间戳
    //不使用时间戳的方式
    mapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS,false);
    //自定义日期的格式
    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    mapper.setDateFormat(sdf);
    Date date = new Date();
    //ObjectMapper,时间解析后的默认格式为: Timestamp,时间戳
    return mapper.writeValueAsString(sdf.format(date));
}


运行结果 : 成功的输出了时间!



抽取为工具类


如果要经常使用的话,这样是比较麻烦的,我们可以将这些代码封装到一个工具类中;我们去编写下


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();
        //不使用时间差的方式
        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;
    }
}


我们使用工具类,代码就更加简洁了!


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


大功告成!完美!


5.3、FastJson


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

fastjson 的 pom依赖!


<!-- https://mvnrepository.com/artifact/com.alibaba/fastjson -->
<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>fastjson</artifactId>
    <version>1.2.80</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 类


public class FastJsonDemo {
    public static void main(String[] args) {
        //创建一个对象
        User user1 = new User("秦疆1号", 3, "男");
        User user2 = new User("秦疆2号", 3, "男");
        User user3 = new User("秦疆3号", 3, "男");
        User user4 = new User("秦疆4号", 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);
    }
}


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

相关文章
|
4月前
|
Java 数据库连接 Maven
手把手教你如何搭建SSM框架、图书商城系统案例
这篇文章是关于如何搭建SSM框架以及实现一个图书商城系统的详细教程,包括了项目的配置文件整合、依赖管理、项目结构和运行效果展示,并提供了GitHub源码链接。
手把手教你如何搭建SSM框架、图书商城系统案例
|
2月前
|
设计模式 前端开发 Java
Spring MVC——项目创建和建立请求连接
MVC是一种软件架构设计模式,将应用分为模型、视图和控制器三部分。Spring MVC是基于MVC模式的Web框架,通过`@RequestMapping`等注解实现URL路由映射,支持GET和POST请求,并可传递参数。创建Spring MVC项目与Spring Boot类似,使用`@RestController`注解标记控制器类。
38 1
Spring MVC——项目创建和建立请求连接
|
3月前
|
Java 应用服务中间件 数据库连接
ssm项目整合,简单的用户管理系统
文章介绍了一个使用SSM框架(Spring、SpringMVC、MyBatis)构建的简单用户管理系统的整合过程,包括项目搭建、数据库配置、各层代码实现以及视图展示。
ssm项目整合,简单的用户管理系统
|
2月前
|
SQL Java 数据库连接
快速搭建SSM项目【最全教程】~令狐小哥版
快速搭建SSM项目【最全教程】~令狐小哥版
33 1
|
2月前
|
前端开发 Java 应用服务中间件
【Spring】Spring MVC的项目准备和连接建立
【Spring】Spring MVC的项目准备和连接建立
59 2
|
2月前
|
前端开发 Java 关系型数据库
【保姆级SSM教程】高并发朋友圈点赞项目设计
【保姆级SSM教程】高并发朋友圈点赞项目设计
35 0
|
4月前
|
Java 数据库连接 Spring
后端框架入门超详细 三部曲 Spring 、SpringMVC、Mybatis、SSM框架整合案例 【爆肝整理五万字】
文章是关于Spring、SpringMVC、Mybatis三个后端框架的超详细入门教程,包括基础知识讲解、代码案例及SSM框架整合的实战应用,旨在帮助读者全面理解并掌握这些框架的使用。
后端框架入门超详细 三部曲 Spring 、SpringMVC、Mybatis、SSM框架整合案例 【爆肝整理五万字】
|
3月前
|
XML Java 数据库连接
如何搭建SSM框架、图书商城系统
这是一份详尽的《Spring + SpringMVC + Mybatis 整合指南》,作者耗时良久整理出约五万字的内容,现已经全部笔记公开。此文档详细地介绍了如何搭建与整合SSM框架,具体步骤包括创建Maven项目、添加web骨架、配置pom文件以及整合Spring、SpringMVC和Mybatis等。无论是对初学者还是有一定基础的开发者来说,都是很好的学习资源。此外,作者还提供了项目源码的GitHub链接,方便读者实践。虽然当前主流推荐学习SpringBoot,但了解SSM框架仍然是不可或缺的基础。
38 0
|
4月前
|
Java 应用服务中间件 Maven
Mac使用Idea配置传统SSM项目(非maven项目)
Mac使用Idea配置传统SSM项目(非maven项目)
57 1
|
4月前
|
Java 数据库
使用ssm框架搭建的图书管理系统
本文介绍了使用SSM框架搭建的图书管理系统,包括图书信息管理、借阅记录管理、公告管理、出入库管理以及用户管理等功能。
使用ssm框架搭建的图书管理系统