SpringMVC

1、回顾MVC

1.1 什么是mvc

  • MVC是模型(Model)、视图(View)、控制器(Controller)的简写,是一种软件设计规范。
  • 是将业务逻辑、数据、显示分离的方法来组织代码。
  • MVC主要作用是降低了视图与业务逻辑间的双向耦合。
  • MVC不是一种设计模式,MVC是一种架构模式。

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

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

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

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

**个人理解:**持久层和service层对应的MVC中的M也就是Model,用来处理数据和业务也就是行为。视图VIew来进行模型展示就是我么你的前端页面。Controller层在 model和view中间起作用用来接受用户请求并传递数据。

1.2 Model 1时代

  • 在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这样不仅提高的代码的复用率与项目的扩展性,且大大降低了项目的维护成本。Model 1模式的实现比较简单,适用于快速开发小规模项目,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.1.9.RELEASE</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>
    
  2. 建立一个Moudle:spring-01-servlet,添加WEB支持

  3. 导入servlet 喝jsp 的 jar 依赖

    <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>
    
  4. 编写一个Servlet类,用来处理用户请求

    //实现Servlet接口
    public class HelloServlet extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {//取得参数String method = req.getParameter("method");if (method.equals("add")){req.getSession().setAttribute("msg","执行了add方法");}if (method.equals("delete")){req.getSession().setAttribute("msg","执行了delete方法");}//业务逻辑//视图跳转req.getRequestDispatcher("/WEB-INF/jsp/hello.jsp").forward(req,resp);}@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {doGet(req,resp);}
    }
    
  5. 编写Hello.jsp,在WEB-INF目录下新建一个jsp的文件夹,新建hello.jsp

    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <html>
    <head><title>Kuangshen</title>
    </head>
    <body>
    ${msg}
    </body>
    </html>
    
  6. 在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><servlet-name>HelloServlet</servlet-name><servlet-class>com.zdx.servlet.HelloServlet</servlet-class></servlet><servlet-mapping><servlet-name>HelloServlet</servlet-name><url-pattern>/user</url-pattern></servlet-mapping><!--    配置session超时时间--><session-config><session-timeout>15</session-timeout></session-config><!--    配置欢迎页--><welcome-file-list><welcome-file>index.jsp</welcome-file></welcome-file-list>
    </web-app>
    
  7. 配置Tomcat,启动并测试

    • localhost:8080/user?method=add
    • localhost:8080/user?method=delete

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)(双向绑定)

2、什么是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

我们为什么要学习SpringMVC呢?

Spring MVC的特点:

  1. 轻量级,简单易学
  2. 高效 , 基于请求响应的MVC框架
  3. 与Spring兼容性好,无缝结合,我们可以将SpringMVC需要的bean注册到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 基类)
  • DispathcherServlet 实现了spring 的FrameworkServlet 最终实现了Servlet接口说到底本质还是一个Servlet。核心方法为doService()方法。

SpringMVC工作原理

  1. 用户发送请求,也就是在地址栏中输入的url请求
  2. 前端控制器获取请求,也就是在web.xml中配置的DispathcherServlet
  3. 前端控制器把请求给处理器映射器,处理器映射器获取请求的url找到handler返回给DispathcherServlet
  4. DispathcherServlet调用处理器适配器根据url解析解析到的handler,找到对应的Controller类。
  5. Controller 调用业务对象,并返回模型数据给处理器
  6. 处理器返回ModelAndView 给前端控制器
  7. 前端控制器调用调用视图解析器解析 ModelAndView,获取数据,解析视图的视图名字,拼接视图名字找到视图,并把数据渲染到视图中返回给DispathcherServlet
  8. DispatherServlet找到视图进行展示。

2.3 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控制器。

  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. 最终视图呈现给用户。

3、第一个MVC程序

3.1 xml配置版

  1. 新建一个Moudle , 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"><!--    注册DispathcherServlet--><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>
    <!--        启动级别1--><load-on-startup>1</load-on-startup></servlet><!--/ 匹配所有的请求;(不包括.jsp)--><!--/* 匹配所有的请求;(包括.jsp)--><servlet-mapping><servlet-name>springmvc</servlet-name><url-pattern>/</url-pattern></servlet-mapping>
    </web-app>
    
  4. 编写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/beanshttp://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.zdx.controller.HelloController"/>
    </beans>
    
  5. 编写我们要操作业务Controller ,要么实现Controller接口,要么增加注解;需要返回一个ModelAndView,装数据,封视图;

    package com.zdx.controller;import org.springframework.web.servlet.ModelAndView;
    import org.springframework.web.servlet.mvc.Controller;import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;//实现Controller 接口
    public class HelloController implements Controller {public ModelAndView handleRequest(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws Exception {//模型和视图ModelAndView mv = new ModelAndView();//封装数据mv.addObject("msg","HelloSpringMVC!!");//封装要跳转的视图到ModelAndView中mv.setViewName("hello");   // WEB-INF/jsp/hello.jspreturn mv;}
    }
    

​ ModelAndView 对象 的addObject方法,进行封装数据。

​ setViewName方法,写入要转发的视图的名称。

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

    <%--  Created by IntelliJ IDEA.  User: ZYH  Date: 2021/7/28  Time: 21:55  To change this template use File | Settings | File Templates.--%><%@ page contentType="text/html;charset=UTF-8" language="java" %><html><head>    <title>张大仙</title></head><body>${msg}</body></html>
    
  2. 配置Tomcat 启动测试!

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

  1. 查看控制台输出,看一下是不是缺少了什么jar包。
  2. 如果jar包存在,显示无法输出,就在IDEA的项目发布中,添加lib依赖!
  3. 重启Tomcat 即可解决!

3.2 注解版

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

  2. 由于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>
    
  3. 在pom.xml文件引入相关的依赖:主要有Spring框架核心库、Spring MVC、servlet , JSTL等。我们在父依赖中已经引入了!

  4. 配置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></web-app>
    
  5. */和/的区别:

    < url-pattern > / </ url-pattern > 不会匹配到.jsp, 只针对我们编写的请求;即:.jsp 不会进入spring的 DispatcherServlet类 。

    当url为http://localhost:8080/hello.jsp时DispathcherServlet不会把他当成一个请求。

    < url-pattern > /* </ url-pattern > 会匹配 *.jsp,会出现返回 jsp视图 时再次进入spring的DispatcherServlet 类,最后拼接视图的时候会出现hello.jsp.jsp的情况,导致找不到对应的controller所以报404错。

  6. 添加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/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.zdx.controller"/>
    <!--让SpringMVC不处理静态资源--><mvc:default-servlet-handler/>
    <!--支持mvc注解驱动在spring中一般采用@RequestMapping 注解来完成映射关系要想使@RequerstMapping注解生效必须向上下文中注册@DefaultAnnotationHandlerMapping和一个AnnotationMethodHandler Adapter实例这两个实例分别在类级别和方法级别处理。而annotation-driven配置帮助我们自动完成上述两个实例的注入。自动注入处理器映射器和处理器适配器对象
    --><mvc:annotation-driven/>
    <!--    视图解析器--><bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" id="internalResourceViewResolver">
    <!--        前缀--><property name="prefix" value="/WEB-INF/jsp/"/>
    <!--        后缀--><property name="suffix" value=".jsp"/></bean>
    </beans>
    

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

    • 让IOC的注解生效
    • 静态资源过滤 :HTML . JS . CSS . 图片 , 视频 …
      • MVC的注解驱动
      • 配置视图解析器
  7. 创建Controller

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

    package com.zdx.controller;import org.springframework.stereotype.Controller;
    import org.springframework.ui.Model;
    import org.springframework.web.bind.annotation.RequestMapping;@Controller
    @RequestMapping("/HelloController")
    public class HelloController {//真实访问地址 : 项目名/HelloController/hello@RequestMapping("/hello")public String sayHello(Model model){//向模型中添加属性msg与值,可以在JSP页面中取出并渲染model.addAttribute("msg","hello springmvc()");//web-inf/jsp/hello.jspreturn "hello";}
    }
    
    1. @Controller是为了让Spring IOC容器初始化时自动扫描到;
    2. @RequestMapping是为了映射请求路径,这里因为类与方法上都有映射所以访问时应该是/HelloController/hello;
    3. 方法中声明Model类型的参数是为了把Action中的数据带到视图中;
    4. 方法返回的结果是视图的名称hello,加上配置文件中的前后缀变成WEB-INF/jsp/hello.jsp
  8. 创建视图层

    在WEB-INF/ jsp目录中创建hello.jsp , 视图可以直接取出并展示从Controller带回的信息;

    可以通过EL表示取出Model中存放的值,或者对象;

    <%--Created by IntelliJ IDEA.User: OneAPMDate: 2021/7/29Time: 10:10To change this template use File | Settings | File Templates.
    --%>
    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <html>
    <head><title>zdx</title>
    </head>
    <body>
    ${msg}
    </body>
    </html>
    
  9. 配置Tomcat运行

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

OK,运行成功!

小结

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

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

使用springMVC必须配置的三大件

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

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

4、RestFul和控制器

4.1 控制器Controller

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

4.2 实现Controller接口

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

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

测试

  1. 新建一个Moudle,springmvc-04-controller!

  2. 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>DispathcherServlet</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>DispathcherServlet</servlet-name><url-pattern>/</url-pattern></servlet-mapping></web-app>
    
  3. springmvc-servlet.xml

    只留一个视图解析器,请求也可以访问成功,因为处理器的配置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:mvc="http://www.springframework.org/schema/mvc"xmlns:context="http://www.springframework.org/schema/context"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/mvchttps://www.springframework.org/schema/mvc/spring-mvc.xsdhttp://www.springframework.org/schema/contexthttps://www.springframework.org/schema/context/spring-context.xsd"><!--    视图解析器--><bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" id="internalResourceViewResolver"><!--        前缀--><property name="prefix" value="/WEB-INF/jsp/"/><!--        后缀--><property name="suffix" value=".jsp"/></bean><bean id="/test" class="com.zdx.controller.ControllerTest1"/></beans>
    
  4. 编写一个Controller类

    package com.zdx.controller;import org.springframework.web.servlet.ModelAndView;
    import org.springframework.web.servlet.mvc.Controller;import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;public class ControllerTest1 implements Controller {public ModelAndView handleRequest(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws Exception {//创建视图模型对象ModelAndView mv = new ModelAndView();//封装数据mv.addObject("msg","ControllerTest1");//返回视图mv.setViewName("test");return mv;}
    }
  5. 配置tomcat并访问test请求

说明:

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

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

使用注解@Controller

  • @Controller注解类型用于声明Spring类的实例是一个控制器(在讲IOC时还提到了另外3个注解);

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

    <!--    自动扫描包-->    <context:component-scan base-package="com.zdx.controller"/>
    
  • 增加一个ControllerTest2类,使用注解实现;

    package com.zdx.controller;import org.springframework.stereotype.Controller;import org.springframework.ui.Model;import org.springframework.web.bind.annotation.RequestMapping;@Controller@RequestMapping("test")public class ControllerTest2 {    @RequestMapping("t1")    public String index(Model model){        model.addAttribute("msg","ControllerTest2");        return "test";    }}
    

    ControllerTest2中 返回的视图也是test.jsp,这里实现了视图的复用。

  • 运行Tomcat

可以发现,我们的两个请求都可以指向一个视图(test),但是页面结果的结果是不一样的,从这里可以看出视图是被复用的,而控制器与视图之间是弱偶合关系。

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

RequestMapping

@RequestMapping

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

    用于类上,表示类中的所有响应请求的方法都是以该地址作为父路径。

    @RequestMapping("test")public class ControllerTest2 {    @RequestMapping("t1")    public String index(Model model){        model.addAttribute("msg","ControllerTest2");        return "test";    }}
    

    访问地址:http:localhost:8080/test/t1

4.3 ResFul风格

概念

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

学习测试

创建一个ResFulController类

package com.zdx.controller;import org.springframework.stereotype.Controller;import org.springframework.ui.Model;import org.springframework.web.bind.annotation.*;@Controller@RequestMapping("test")public class ResfulController {//    @RequestMapping(value = "add/{a}/{b}",method = RequestMethod.GET)    @GetMapping("add/{a}/{b}")    public String t1(@PathVariable int a, @PathVariable int b, Model model){        int sum = a+b;        model.addAttribute("msg","结果:"+sum);        return "test";    }//    @RequestMapping(value = "add/{a}/{b}",method = RequestMethod.POST)    @PostMapping("add/{a}/{b}")    public String t2(@PathVariable int a ,@PathVariable String b ,Model model){        String sum = a+b;        model.addAttribute("msg","sum="+sum);        return "test";    }}

@PathVariable 注解 让参数路径化,访问路径变成"add/{a}/{b}", add/1/2 会自动匹配参数。

@RequestMapping(value=“add/{a}/{b}” ,method=RequestMethod.Post),通过method参数设置请求的方式

还可以用注解设置请求方式

@GetMapping@PostMapping@PutMapping@DeleteMapping@PatchMapping

测试结果

小结:

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

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

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

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

4.4 扩展:小黄鸭调试法

场景一:我们都有过向别人(甚至可能向完全不会编程的人)提问及解释编程问题的经历,但是很多时候就在我们解释的过程中自己却想到了问题的解决方案,然后对方却一脸茫然。

场景二:你的同行跑来问你一个问题,但是当他自己把问题说完,或说到一半的时候就想出答案走了,留下一脸茫然的你。

其实上面两种场景现象就是所谓的小黄鸭调试法(Rubber Duck Debuging),又称橡皮鸭调试法,它是我们软件工程中最常使用调试方法之一。

5、结果跳转方式

5.1 ModelAndView

实现Controller 接口,创建ModelAndView 对象,根据addObject方法封装数据,在根据setViewName方法指定跳转视图名称,视图解析器根据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>    <bean id="/test" class="com.zdx.controller.ControllerTest1"/>

对应的Controller类

public class ControllerTest1 implements Controller {    public ModelAndView handleRequest(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws Exception {        //创建视图模型对象        ModelAndView mv = new ModelAndView();        //封装数据        mv.addObject("msg","ControllerTest1");        //返回视图        mv.setViewName("test");        return mv;    }}

**缺点:**一个Controller类只能实现一个handlerRequest方法,一个处理器就要对应一个controller类。

5.2 ServletAPI的方式跳转

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

  1. 通过HttpServletResponse进行输出
  2. 通过HttpServletResponse实现重定向
  3. 通过HttpServlet Response实现转发
package com.zdx.controller;import org.springframework.stereotype.Controller;import org.springframework.web.bind.annotation.RequestMapping;import javax.servlet.ServletException;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import java.io.IOException;@Controller@RequestMapping("/servletapi")public class ServletApiController {    @RequestMapping("/t1")    public void test1(HttpServletRequest request, HttpServletResponse response){        try {            response.getWriter().println("Hello Spring MVC");        } catch (IOException e) {            e.printStackTrace();        }    }    @RequestMapping("/t2")    public void test2(HttpServletRequest request,HttpServletResponse response){        //重定向        try {            response.sendRedirect("/index.jsp");        } catch (IOException e) {            e.printStackTrace();        }    }    @RequestMapping("/t3")    public void test3(HttpServletRequest request, HttpServletResponse response){        try {        //转发,可以携带数据,因为最后forward携带了两个参数            request.setAttribute("msg","hello springmvc test3");            request.getRequestDispatcher("/WEB-INF/jsp/test.jsp").forward(request,response);        } catch (ServletException e) {            e.printStackTrace();        } catch (IOException e) {            e.printStackTrace();        }    }}

5.3 SpringMVC

通过SpringMVC来实现转发重定向,无视图解析器。

  • 默认为forward转发
  • 重定向为redirect 重定向需要参数
package com.zdx.controller;import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;@Controller
@RequestMapping("/SpringMVCApi")
public class SpringMvcApiController {@RequestMapping("/t1")public String test1(){//默认为转发return "/index.jsp";}@RequestMapping("/t2")public String  test2(Model model){//加forward参数的转发model.addAttribute("msg","hello zdx");return "forward:/WEB-INF/jsp/test.jsp";}@RequestMapping("/t3")public String test3(){//重定向return "redirect:/index.jsp";}}

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

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

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

package com.zdx.controller;import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;@Controller
@RequestMapping("springmvcapi2")
public class SpringMVCApiController2 {@RequestMapping("/t1")public String test1(){//重定向return "redirect:/index.jsp";}@RequestMapping("/t2")public String  test2(Model model){model.addAttribute("msg","hello zdx");return "test";}}

6、数据处理

6.1 处理提交数据

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

 //当参数与前端参数命名一致时,可以直接接受前端参数。 //提交请求:http://localhost:8080/usercontroller/t1?name=zdx    @RequestMapping("/t1")    public String test1(String name , Model model){        System.out.println(name);        model.addAttribute("msg",name);        return "test";    }

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

 //当前端参数名称与后端参数名称不一样的时候在后端参数加入@RequestParam()参数即可接受前端参数。@RequestMapping("/t2")public String test2(@RequestParam("username")String name, Model model){System.out.println(name);model.addAttribute("msg",name);return "test";}

3.当前端提交的参数为对象

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

  1. 实体类

    public class User {private int id;private String name;private int age;
    }
    
  2. 请求提交数据:http://localhost:8080/usercontroller/t3?id=1&name=zdx&age=23

  3. 处理方法

    //  当前端传入对象时,会匹配后端对象的字段名,如果字段名与前端参数名不一致则无法获取前端参数值
    //  http://localhost:8080/usercontroller/t3?id=1&name=zdx&age=23@RequestMapping("/t3")public String test3(User user,Model model){System.out.println(user.toString());model.addAttribute("msg",user);return "test";}
    

说明:如果使用对象的话,前端传递的参数名和对象字段名必须一致,否则就是null。

6.2 数据显示到前端

**第一种:**通过ModelAndView

实现Controller接口的时候用这种方法

public class ControllerTest1 implements Controller {public ModelAndView handleRequest(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws Exception {//创建视图模型对象ModelAndView mv = new ModelAndView();//封装数据mv.addObject("msg","ControllerTest1");//返回视图mv.setViewName("test");return mv;}
}

第二种:通过ModelMap

ModelMap

 @RequestMapping("/t3")public String test3(User user, ModelMap modelMap){System.out.println(user.toString());modelMap.addAttribute("name",user);return "test";}

第三种:通过model

  @RequestMapping("/t2")public String test2(@RequestParam("username")String name, Model model){System.out.println(name);model.addAttribute("msg",name);return "test";}

6.4 对比

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

7、乱码问题

测试步骤:

  1. 编写提交表单

    <%--Created by IntelliJ IDEA.User: ZYHDate: 2021/7/29Time: 21:17To change this template use File | Settings | File Templates.
    --%>
    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <html><head><title>$Title$</title></head><body><form action="/encode/t1" method="get"><input type="text" name="name"><input type="submit" value="提交"></form></body>
    </html>
  2. controller

    package com.zdx.controller;import org.springframework.stereotype.Controller;
    import org.springframework.ui.Model;
    import org.springframework.web.bind.annotation.GetMapping;
    import org.springframework.web.bind.annotation.PostMapping;
    import org.springframework.web.bind.annotation.RequestMapping;@Controller
    @RequestMapping("encode")
    public class EncodeController {@RequestMapping("t1")public String test(String name, Model model){System.out.println(name);model.addAttribute("name",name);return "test";}
    }
  3. 解决乱码问题

    第一种:自定义filter过滤器

    package com.zdx.filter;import javax.servlet.*;import java.io.IOException;public class EncodeFilter implements Filter {    public void init(FilterConfig filterConfig) throws ServletException {    }    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {        servletRequest.setCharacterEncoding("UTF-8");        servletResponse.setCharacterEncoding("utf-8");        filterChain.doFilter(servletRequest,servletResponse);    }    public void destroy() {    }}
    
     <filter><filter-name>encoding</filter-name><filter-class>com.zdx.filter.EncodeFilter</filter-class></filter><filter-mapping><filter-name>encoding</filter-name><url-pattern>/*</url-pattern></filter-mapping>
    
  4. 第二种万能自定义过滤器

    package com.zdx.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 {@Overridepublic void destroy() {}@Overridepublic void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {//处理response的字符编码HttpServletResponse myResponse=(HttpServletResponse) response;myResponse.setContentType("text/html;charset=UTF-8");System.out.println("+++++++++++++++++++++++++++");// 转型为与协议相关对象HttpServletRequest httpServletRequest = (HttpServletRequest) request;// 对request包装增强HttpServletRequest myrequest = new MyRequest(httpServletRequest);chain.doFilter(myrequest, response);}@Overridepublic 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;}// 对需要增强方法 进行覆盖@Overridepublic 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();}//取一个值@Overridepublic String getParameter(String name) {Map<String, String[]> parameterMap = getParameterMap();String[] values = parameterMap.get(name);if (values == null) {return null;}return values[0]; // 取回参数的第一个值}//取所有值@Overridepublic String[] getParameterValues(String name) {Map<String, String[]> parameterMap = getParameterMap();String[] values = parameterMap.get(name);return values;}
    }
    
     <filter>        <filter-name>encoding</filter-name>        <filter-class>com.zdx.filter.GenericEncodingFilter</filter-class>    </filter>    <filter-mapping>        <filter-name>encoding</filter-name>        <url-pattern>/*</url-pattern>    </filter-mapping>
    
  5. 第三种SpringMVC过滤器

    <!--    配置乱码过滤器 过滤器在请求进入后端的时候进行拦截过滤-->    <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>
    

    注意:这里写/*,写/的话过滤不了jsp页面,不能解决乱码

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

    处理方法 :

修改tomcat的server.xml配置文件 :设置编码!

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

经过我实测使用SpringMVC 的过滤器需要修改此配置文件get请求才不会出现乱码的情况。

但是自定义的过滤器不用修改此文件。修改了get请求反而出现乱码。

8、JSON 交互

8.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 字符串,本质是一个字符串

8.2 JSON 和 Javascript 对象转换

JavaScript对象转换成json对象,使用JSON.stringify();方法把JavaScript对象转换为json对象。

 //编写一个JavaScript对象    var user = {        name:"张大仙",        age:3,        sex:"男"    };    console.log(user);    //将js对象转换成json对象;    var json =JSON.stringify(user);    console.log(json);

JSON对象转换为Javascript对象,使用JSON.parse()方法把JSON转换成JavaScript();

 //编写一个JavaScript对象    var user = {        name:"张大仙",        age:3,        sex:"男"    };    console.log(user);    //将js对象转换成json对象;    var json =JSON.stringify(user);    console.log(json);    //将json对象转换成JavaScript对象    var obj  = JSON.parse(json);    console.log(obj);

8.3 controller返回json数据

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

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

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

    <!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-core --><dependency>   <groupId>com.fasterxml.jackson.core</groupId>   <artifactId>jackson-databind</artifactId>   <version>2.9.8</version></dependency>
    
  • 配置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"><!--    前端控制器dispathcherservlet-->    <servlet>        <servlet-name>dispathcherservlet</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>    </servlet>    <servlet-mapping>        <servlet-name>dispathcherservlet</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 这里只列出了解决json前端显示乱码的问题

      <!--        解决json乱码问题-->        <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>
      
    • user 实体类

      public class User {    private int id;    private String name;    private int age;}
      
    • controller类

      @Controller
      //@RestController   不经过视图解析器,全部返回字符串
      @RequestMapping("/jsontest")
      public class UserController {@RequestMapping("/t1")@ResponseBody    //ResponseBody 会直接返回字符串不走视图解析器public String test1() throws JsonProcessingException {//Jackson 使用 ObjectMapper对象转换成json对象ObjectMapper mapper = new ObjectMapper();//创建一个对象User user = new User(1, "张大仙", 18);//Jackson 用writeValueAsString()方法把对象转换成json字符串给格式String str = mapper.writeValueAsString(user);return str;}@RequestMapping("/t2")@ResponseBodypublic String test2() throws JsonProcessingException {//Jackson 使用 ObjectMapper对象转换成json对象
      //        ObjectMapper mapper = new ObjectMapper();//创建一个list集合来存放多个user对象并转换成json对象List<User> userList = new ArrayList();User user1 = new User(1, "张大仙1", 18);User user2 = new User(1, "张大仙2", 18);User user3 = new User(1, "张大仙3", 18);User user4 = new User(1, "张大仙4", 18);userList.add(user1);userList.add(user2);userList.add(user3);userList.add(user4);
      //      String str = mapper.writeValueAsString(userList);return JsonUtil.getJson(userList);}@RequestMapping("/t3")@ResponseBodypublic String test3() throws JsonProcessingException {//时间date格式直接转换成json对象会返回成时间戳Timestamp类型,也就是1970.1.1到现在的毫秒数。
      //        Date date = new Date();
      //        ObjectMapper objectMapper = new ObjectMapper();
      //        String str = objectMapper.writeValueAsString(date);
      //        return str;//转换成 参数的时间格式
      //        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
      //        Date date = new Date();
      //        ObjectMapper mapper = new ObjectMapper();
      //        String str = mapper.writeValueAsString(sdf.format(date));
      //        return str;//        通过格式化ObjectMapper的方式来格式化时间
      //        ObjectMapper mapper = new ObjectMapper();
      //        设置属性使用不适用时间戳的格式
      //        mapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
      //        自定义是时间格式对象
      //        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
      //        为objectmapper指定时间格式
      //        mapper.setDateFormat(simpleDateFormat);Date date = new Date();
      //        String str = mapper.writeValueAsString(date);
      //        return str;String dateformat="yyyy-MM-dd HH:mm:ss";return JsonUtil.objectToJson(date,dateformat);//        // 通过格式化ObjectMapper的方式来格式化时间
      //        ObjectMapper mapper = new ObjectMapper();
      //    //    设置属性使用不适用时间戳的格式
      //        mapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
      //    //    自定义是时间格式对象
      //        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
      //    //    为objectmapper指定时间格式
      //        mapper.setDateFormat(simpleDateFormat);
      //        Date date = new Date();
      //        String str = mapper.writeValueAsString(date);
      //        return str;}
      }
      

我们可以写一个JSON工具类

package com.zdx.util;import com.fasterxml.jackson.core.JsonProcessingException;import com.fasterxml.jackson.databind.ObjectMapper;import com.fasterxml.jackson.databind.SerializationFeature;import java.text.SimpleDateFormat;public class JsonUtil {    public static String getJson(Object object) throws JsonProcessingException {        return objectToJson(object, "yyyy-MM-dd HH:mm:ss");    }    public static String objectToJson(Object object,String dateformat) throws JsonProcessingException {        ObjectMapper objectMapper = new ObjectMapper();        //    设置属性使用不适用时间戳的格式        objectMapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);        //    自定义是时间格式对象        SimpleDateFormat sdf = new SimpleDateFormat(dateformat);        //为objectmapper指定时间格式        objectMapper.setDateFormat(sdf);        return objectMapper.writeValueAsString(object);    }}

8.4 fastjson

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

fastjson 的 pom依赖!

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

fastjson 三个主要的类:

  1. JSONObject 代表 json 对象

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

    1. 内部是有List接口中的方法来完成操作的。
  3. JSON代表 JSONObject和JSONArray的转化

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

测试controller

package com.zdx.controller;import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.zdx.pojo.User;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;import java.util.ArrayList;
import java.util.List;@RestController
@RequestMapping("/fastjson")
public class FastJsonController {@RequestMapping("/t1")public String test1(){User user1 = new User(1, "秦疆1号", 12);User user2 = new User(2, "秦疆2号", 12);User user3 = new User(3, "秦疆3号", 12);User user4 = new User(4, "秦疆4号", 12);User user5 = new User(5, "秦疆5号", 12);List<User> users = new ArrayList<User>();users.add(user1);users.add(user2);users.add(user3);users.add(user4);users.add(user5);System.out.println("java对象转json字符串");String s = JSON.toJSONString(users);System.out.println("JSON.toJSONString(list)==>"+s);String s1 = JSON.toJSONString(user1);System.out.println("use1"+s1);System.out.println("json字符串转java对象");User user = JSON.parseObject(s1, User.class);System.out.println(user.toString());System.out.println("java对象转Json对象"); //json对象为JavaScript对象JSONObject jsonObject= (JSONObject)JSON.toJSON(user1);System.out.println("jsonobject"+jsonObject);System.out.println("json转java对象");User user6 = JSON.toJavaObject(jsonObject,User.class);System.out.println("user6"+user6);return "ssss";}
}
java对象转json字符串JSON.toJSONString(list)==>[{"age":12,"id":1,"name":"秦疆1号"},{"age":12,"id":2,"name":"秦疆2号"},{"age":12,"id":3,"name":"秦疆3号"},{"age":12,"id":4,"name":"秦疆4号"},{"age":12,"id":5,"name":"秦疆5号"}]use1{"age":12,"id":1,"name":"秦疆1号"}json字符串转java对象User{id=1, name='秦疆1号', age=12}java对象转Json对象jsonobject{"name":"秦疆1号","id":1,"age":12}json转java对象user6User{id=1, name='秦疆1号', age=12}

9、SSM框架整合

  • 需要熟练掌握MySQL数据库,Spring,JavaWeb及MyBatis知识,简单的前端知识;

    基本结构

  • com.kuang.pojo

  • com.kuang.dao

  • com.kuang.service

  • com.kuang.controller

9.1 dao层整合

  • mybatis-config.xml

    <?xml version="1.0" encoding="UTF-8" ?><!DOCTYPE configuration       PUBLIC "-//mybatis.org//DTD Config 3.0//EN"       "http://mybatis.org/dtd/mybatis-3-config.dtd"><configuration></configuration>
    
  • applicationContext.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"></beans>
    

搭建数据库

注意要一条一条执行

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

新建Maven项目添加jar包

<!--    依赖 junit,数据库驱动、连接池、servlet、jsp、mybatis、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> 5.1.47</version>        </dependency>        <!-- 数据库连接池 -->        <!-- https://mvnrepository.com/artifact/com.mchange/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.2</version>        </dependency>        <dependency>            <groupId>org.mybatis</groupId>            <artifactId>mybatis-spring</artifactId>            <version>2.0.2</version>        </dependency>        <!--Spring-->        <dependency>            <groupId>org.springframework</groupId>            <artifactId>spring-webmvc</artifactId>            <version>5.1.9.RELEASE</version>        </dependency>        <dependency>            <groupId>org.springframework</groupId>            <artifactId>spring-jdbc</artifactId>            <version>5.1.9.RELEASE</version>        </dependency>        <dependency>            <groupId>org.aspectj</groupId>            <artifactId>aspectjweaver</artifactId>            <version>1.8.13</version>        </dependency>        <dependency>            <groupId>org.projectlombok</groupId>            <artifactId>lombok</artifactId>            <version>1.16.10</version>        </dependency>    </dependencies>

配置资源导出

<!--资源导出问题-->    <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>
<!--资源导出问题-->    <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>

创建实体类

package com.zdx.pojo;import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;@Data
@AllArgsConstructor
@NoArgsConstructor
public class Books {private int bookID;private String bookName;private int bookCounts;private String detail;
}

创建dao层接口类和mapper

package com.zdx.dao;import com.zdx.pojo.Books;
import org.apache.ibatis.annotations.Param;import java.util.List;public interface BookMapper {//增加一本书int addBook(Books books);//删除一本书int deleteBook(@Param("bookId") int id);//更新一本书int updateBook(Books books);//查询一本书Books queryBookById(@Param("bookId") int id);//查询全部的书List<Books> queryAllBook();List<Books> queryBookByName(@Param("bookName") String bookName);
}
<?xml version="1.0" encoding="UTF-8" ?><!DOCTYPE mapper        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.zdx.dao.BookMapper">
<insert id="addBook" parameterType="Books">      insert into books(bookName,bookCounts,detail)        values (#{bookName},#{bookCounts},#{detail});
</insert> <delete id="deleteBook" parameterType="int">        delete from books where bookID=#{bookId};
</delete> <update id="updateBook" parameterType="Books">       update books set bookName=#{bookName},bookCounts=#{bookCounts},detail=#{detail}where bookID=#{bookID};
</update>   <select id="queryBookById" resultType="Books">        select * from books where bookID=#{bookId};
</select>    <select id="queryAllBook" resultType="Books">        select * from books;
</select>  <select id="queryBookByName" resultType="Books">       select * from books where bookName=#{bookName};
</select></mapper>

创建mybatis配置文件 mybatis-config.xml

1、配置日志
2、取别名
3、注册mapper
<?xml version="1.0" encoding="UTF-8" ?><!DOCTYPE configuration        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"        "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<!--    配置日志-->
<settings>        <setting name="logImpl" value="STDOUT_LOGGING"/>
</settings>
<!--    配置数据源,交给spring去做-->
<!--    取别名-->
<typeAliases>        <package name="com.zdx.pojo"/>
</typeAliases>
<!--    注册mapper-->
<mappers>        <mapper class="com.zdx.dao.BookMapper"/>
</mappers>
</configuration>

创建数据库配置文件 database.properties

jdbc.driver=com.mysql.jdbc.Driver
#如果使用的是mysql8.0版本需要配置一个时区的设置
jdbc.url=jdbc:mysql://localhost:3306/ssmbuilduseSSL=false&useUnicode=true&characterEncoding=utf8
jdbc.username=root
jdbc.password=root

spring整合mybatis创建spring-dao.xml

1.引用数据库文件2.创建数据库连接池3.创建sqlSessionFactory<?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"       xsi:schemaLocation="http://www.springframework.org/schema/beans       http://www.springframework.org/schema/beans/spring-beans.xsd       http://www.springframework.org/schema/context       https://www.springframework.org/schema/context/spring-context.xsd"><!--    关联数据库配置文件-->    <context:property-placeholder location="classpath:database.properties"/><!--    连接池   dbcp:半自动化操作   c3p0:自动化操作(自动化加载配置文件,并且可以自动设置到对象中去)   driud:hikai-->    <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">        <property name="driverClass" value="${jdbc.driver}"/>        <property name="jdbcUrl" value="${jdbc.url}"/>        <property name="user" value="${jdbc.username}"/>        <property name="password"  value="${jdbc.password}"/>        <!-- c3p0连接池的私有属性 --><!--        最大连接数和最小连接数-->        <property name="maxPoolSize" value="30"/>        <property name="minPoolSize" value="10"/>        <!-- 关闭连接后不自动commit -->        <property name="autoCommitOnClose" value="false"/>        <!-- 获取连接超时时间 -->        <property name="checkoutTimeout" value="10000"/>        <!-- 当获取连接失败重试次数 -->        <property name="acquireRetryAttempts" value="2"/>    </bean><!--    sqlSessionFactory-->    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"><!--        配置数据源-->        <property name="dataSource" ref="dataSource"/><!--        绑定配置文件-->        <property name="configLocation" value="classpath:mybatis-config.xml"/>    </bean><!--    配置dao层接口扫描包,动态的实现了Dao接口注入到spring容器中-->    <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer"><!--        注入sqlSessionFactory-->        <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/><!--        要扫描的dao包-->        <property name="basePackage" value="com.zdx.dao"/>    </bean></beans>

9.2 service 层整合

创建service层接口和实体类

package com.zdx.service;import com.zdx.pojo.Books;import java.util.List;public interface BookService {    //增加一本书    int addBook(Books books);    //删除一本书    int deleteBook(int id);    //更新一本书    int updateBook(Books books);    //查询一本书    Books queryBookById(int id);    //查询全部的书    List<Books> queryAllBook();    List<Books> queryBookByName(String bookName);}
package com.zdx.service;import com.zdx.dao.BookMapper;
import com.zdx.pojo.Books;
import org.springframework.stereotype.Service;import java.util.List;@Service
public class BookServiceImpl implements BookService{//组合dao层private BookMapper bookMapper;public void setBookMapper(BookMapper bookMapper) {this.bookMapper = bookMapper;}public int addBook(Books books) {return bookMapper.addBook(books);}public int deleteBook(int id) {return bookMapper.deleteBook(id);}public int updateBook(Books books) {return bookMapper.updateBook(books);}public Books queryBookById(int id) {return bookMapper.queryBookById(id);}public List<Books> queryAllBook() {return bookMapper.queryAllBook();}public List<Books> queryBookByName(String bookName) {return bookMapper.queryBookByName(bookName);}
}
package com.zdx.service;import com.zdx.dao.BookMapper;
import com.zdx.pojo.Books;
import org.springframework.stereotype.Service;import java.util.List;@Service
public class BookServiceImpl implements BookService{//组合dao层private BookMapper bookMapper;public void setBookMapper(BookMapper bookMapper) {this.bookMapper = bookMapper;}public int addBook(Books books) {return bookMapper.addBook(books);}public int deleteBook(int id) {return bookMapper.deleteBook(id);}public int updateBook(Books books) {return bookMapper.updateBook(books);}public Books queryBookById(int id) {return bookMapper.queryBookById(id);}public List<Books> queryAllBook() {return bookMapper.queryAllBook();}public List<Books> queryBookByName(String bookName) {return bookMapper.queryBookByName(bookName);}
}

创建配置文件spring-service.xml

1.扫描包
2.注入bean
3.配置声明式事务
4.aop(非必须)
<?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:aop="http://www.springframework.org/schema/aop"xmlns:tx="http://www.springframework.org/schema/tx"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/aophttp://www.springframework.org/schema/aop/spring-aop.xsdhttp://www.springframework.org/schema/txhttp://www.springframework.org/schema/tx/spring-tx.xsd"><!--    扫描service 包--><context:component-scan base-package="com.zdx.service"/><!--将所有的业务类注入到spring中,也可以用注解实现--><bean id="bookServiceImpl" class="com.zdx.service.BookServiceImpl"><property name="bookMapper" ref="bookMapper"/></bean><!--声明式事务--><bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"><!--注入数据源        --><property name="dataSource" ref="dataSource"/></bean>
<!--    4.aop事务支持-->
<!--    事务通知--><tx:advice id="txAdvice" transaction-manager="transactionManager"><tx:attributes><tx:method name="*" propagation="REQUIRED"/></tx:attributes></tx:advice>
<!--    配置事务切入--><aop:config><aop:pointcut id="txPointCut" expression="execution(* com.zdx.dao.*.*(..))"/><aop:advisor advice-ref="txAdvice" pointcut-ref="txPointCut"/></aop:config></beans>

配置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>dispathcherServlet</servlet-name><servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class><init-param><param-name>contextConfigLocation</param-name><param-value>classpath:applicationContext.xml</param-value></init-param><load-on-startup>1</load-on-startup></servlet><servlet-mapping><servlet-name>dispathcherServlet</servlet-name><url-pattern>/</url-pattern></servlet-mapping>
<!--    乱码过滤--><filter><filter-name>encodingFilter</filter-name><filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class><init-param><param-name>encoding</param-name><param-value>utf-8</param-value></init-param></filter><filter-mapping><filter-name>encodingFilter</filter-name><url-pattern>/*</url-pattern></filter-mapping><!--    设置session有效时间--><session-config><session-timeout>15</session-timeout></session-config>
</web-app>

9.3 controller 层整合

创建controller层的实现类

package com.zdx.controller;import com.zdx.pojo.Books;
import com.zdx.service.BookService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;import java.util.ArrayList;
import java.util.List;@Controller
@RequestMapping("/book")
public class BookController {@Autowired@Qualifier("bookServiceImpl")private BookService bookService;//查询全部书籍,并返回一个页面@RequestMapping("allBook")public String list(Model model){List<Books> list = bookService.queryAllBook();model.addAttribute("booklist",list);return "allBook";}//跳转到增加书籍页面@RequestMapping("/toAddPaper")public String toAddPaper(){return "addbook";}//添加书籍的请求@RequestMapping("/addBook")public String addBook(Books books){System.out.println("addBook=>"+books);bookService.addBook(books);//添加完要重定向到首页return "redirect:/book/allBook";}//跳转到修改页面@RequestMapping("/toUpdate")public String toUpdatePaper(int id,Model model){Books books = bookService.queryBookById(id);model.addAttribute("query",books);return "updateBook";}//修改书籍@RequestMapping("/updateBook")public String updateBook(Books books){System.out.println(books);bookService.updateBook(books);return "redirect:/book/allBook";}//删除书籍@RequestMapping("/delete/{bookId}")public String delete(@PathVariable("bookId") int id){bookService.deleteBook(id);return "redirect:/book/allBook";}//查询书籍@RequestMapping("/queryBookByName")public String queryBook(String queryBookName,Model model){List<Books> list = bookService.queryBookByName(queryBookName);System.out.println(list.toArray().toString());if (list.isEmpty()){list = bookService.queryAllBook();model.addAttribute("error","未查到");}model.addAttribute("booklist",list);return "allBook";}
}

创建mvc配置文件spring-mvc.xml

1.注解驱动
2.扫描包
3.静态资源过滤
4.视图解析器
<?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">
<!--    注解驱动--><mvc:annotation-driven/>
<!--    静态资源过滤--><mvc:default-servlet-handler/>
<!--    扫描包--><context:component-scan base-package="com.zdx.controller"/>
<!--    视图解析器--><bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"><property name="prefix" value="/WEB-INF/jsp/"/><property name="suffix" value=".jsp"/></bean><!--&lt;!&ndash;    handel&ndash;&gt;-->
<!--    <bean id="bookController" class="com.zdx.controller.BookController">-->
<!--        <property name="bookService" ref="bookServiceImpl"/>-->
<!--    </bean>-->
<!--    -->
</beans>

9.4 创建总配置文件application.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/beanshttp://www.springframework.org/schema/beans/spring-beans.xsd">导入所有配置文件,并在web.xml关联词文件<import resource="classpath:spring-dao.xml"/><import resource="classpath:spring-service.xml"/><import resource="classpath:spring-mvc.xml"/>
</beans>

10、Ajax初识

10.1 简介

  • AJAX = Asynchronous JavaScript and XML(异步的JavaScript 和 XML)。

  • AJAX 是一种在无需重新加载整个网页的情况下,能够更新部分网页的技术。不用加载整个网页。

  • 在 2005 年,Google 通过其 Google Suggest 使 AJAX 变得流行起来。Google Suggest能够自动帮你完成搜索单词。

  • Google Suggest 使用 AJAX 创造出动态性极强的 web 界面:当您在谷歌的搜索框输入关键字时,JavaScript 会把这些字符发送到服务器,然后服务器会返回一个搜索建议的列表。

  • 就和国内百度的搜索框一样!

  • 传统的网页,想要更新内容或者提交一个表单,都需要重新加载整个网页。

  • 使用ajax技术的网页,通过在后台服务器进行少量的数据交换,就可以实现异步局部更新。

  • 使用Ajax,用户可以创建接近本地桌面应用的直接、高可用、更丰富、更动态的Web用户界面。

10.2 体验伪造ajax

我们可以使用前端的一个标签来伪造一个ajax的样子。iframe标签

1、新建一个module :sspringmvc-06-ajax , 导入web支持!

2、编写一个 ajax-frame.html 使用 iframe 测试,感受下效果

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>iframe页面无刷新</title><script>function go() {var url = document.getElementById("url").value;document.getElementById("ifrmae1").src=url;}</script>
</head>
<body>
<div><p>请输入网址</p><input type="text" id="url" value="https://www.baidu.com/"><input type="button" value="提交" onclick="go()">
</div><iframe id="ifrmae1" style="width: 100%;height:500px"></iframe>
</body>
</html>

体验页面无刷新 就可以访问网页,当点击按钮提交的时候 iframe 框直接进入一个网站,不用刷新整个页面,只有局部刷新。

10.3 Ajax体验

使用Ajax可以做

  • 注册时,输入用户名自动检测用户是否已经存在。
  • 登陆时,提示用户名密码错误
  • 删除数据行时,将行ID发送到后台,后台在数据库中删除,数据库删除成功后,在页面DOM中将数据行也删除。
  • …等等

jQuery.ajax

纯JS的原生实现Ajax自己又兴趣去钻研,这里直接使用jQuery提供的,方便学习和使用,避免 重复造轮子,有兴趣的可以去学习一下js原生XMLHttpRequest !

Ajax的核心是XMLHttpRequest对象(XHR)。XHR为向服务器发送请求和解析服务器响应提供了接口。能够以异步方式从服务器获取新数据。

jQuery 提供多个与 AJAX 有关的方法。

通过 jQuery AJAX 方法,您能够使用 HTTP Get 和 HTTP Post 从远程服务器上请求文本、HTML、XML 或 JSON – 同时您能够把这些外部数据直接载入网页的被选元素中。

jQuery 不是生产者,而是大自然搬运工。

jQuery Ajax本质就是 XMLHttpRequest,对他进行了封装,方便调用!

jQuery.ajax(...)部分参数:url:请求地址type:请求方式,GETPOST1.9.0之后用method)headers:请求头data:要发送的数据contentType:即将发送信息至服务器的内容编码类型(默认: "application/x-www-form-urlencoded; charset=UTF-8")async:是否异步timeout:设置请求超时时间(毫秒)beforeSend:发送请求前执行的函数(全局)complete:完成之后执行的回调函数(全局)success:成功之后执行的回调函数(全局)error:失败之后执行的回调函数(全局)accepts:通过请求头发送给服务器,告诉服务器当前客户端可接受的数据类型dataType:将服务器端返回的数据转换成指定类型"xml": 将服务器端返回的内容转换成xml格式"text": 将服务器端返回的内容转换成普通文本格式"html": 将服务器端返回的内容转换成普通文本格式,在插入DOM中时,如果包含JavaScript标签,则会尝试去执行。"script": 尝试将返回值当作JavaScript去执行,然后再将服务器端返回的内容转换成普通文本格式"json": 将服务器端返回的内容转换成相应的JavaScript对象"jsonp": JSONP 格式使用 JSONP 形式调用函数时,如 "myurl?callback=?" jQuery 将自动替换 ? 为正确的函数名,以执行回调函数

**我们来个简单的测试 **

  1. 配置web.xml 和 springmvc 的配置文件

applicationContext.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/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"><!--    扫描包--><context:component-scan base-package="com.zdx.controller"/>
<!--自动注入处理器类--><mvc:annotation-driven><!--        解决json乱码问题--><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><!--过滤静态资源--><mvc:default-servlet-handler/>
<!--视图解析器--><bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" id="internalResourceViewResolver"><property name="prefix" value="/WIN-INF/jsp/"/><property name="suffix" value=".jsp"/></bean></beans>

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>dispathcherServlet</servlet-name><servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class><init-param><param-name>contextConfigLocation</param-name><param-value>classpath:applicationContext.xml</param-value></init-param></servlet><servlet-mapping><servlet-name>dispathcherServlet</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>
  1. 编写一个AjaxController

    需要新建一个user实体类

    package com.zdx.pojo;import lombok.AllArgsConstructor;
    import lombok.Data;
    import lombok.NoArgsConstructor;public class User {private String name;private int age;private String sex;//还有setget tostring
    }

    AjaxController.java

    package com.zdx.controller;import com.zdx.pojo.User;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RestController;import javax.servlet.http.HttpServletResponse;
    import java.io.IOException;
    import java.util.ArrayList;
    import java.util.List;@RestController
    public class AjaxController {@RequestMapping("/t1")public String test(){return "hello";}@RequestMapping("/a1")public void ajax1(String name, HttpServletResponse response) throws IOException {if ("admin".equals(name)){response.getWriter().print("true");}else {response.getWriter().println("false");}}@RequestMapping("/a2")public List<User> a2(){List<User> userList = new ArrayList<User>();userList.add(new User("zdx1",1,"nan"));userList.add(new User("zdx2",2,"nv"));userList.add(new User("zdx3",3,"nan"));return userList;}
    }
    1. 创建test2.jsp

      导入jQuery.js

      <script src="https://code.jquery.com/jquery-3.1.1.min.js"></script>
      <script src="${pageContext.request.contextPath}/statics/js/jquery-3.1.1.min.js"></script>
      

      第二种导入方式需要提前下载好jQuery 并导入到项目中

      test2.jsp

      为按钮创建点击事件,在时间中添加ajax请求,获取controller的响应数据并在前端展示。

      通过html方法在页面中添加html来展示数据。

      <%--Created by IntelliJ IDEA.User: ZYHDate: 2021/8/8Time: 22:30To change this template use File | Settings | File Templates.
      --%>
      <%@ page contentType="text/html;charset=UTF-8" language="java" %>
      <html>
      <head><title>Title</title><script src="${pageContext.request.contextPath}/statics/js/jquery-3.4.1.min.js"></script><script>$(function () {$("#btn").click(function () {/** 简写* $.post(url,param[可省略],success)* */$.post("${pageContext.request.contextPath}/a2",function (data) {console.log(data)var html="";for (var i=0 ; i < data.length; i++){html += "<tr>" +"<td>" + data[i].name + "</td>" +"<td>" + data[i].age + "</td>" +"<td>" + data[i].sex + "</td>" +"</tr>"}$("#content").html(html);});})});</script>
      </head>
      <body>
      <input type="button" value="加载数据" id="btn">
      <table><tr><td>姓名</td><td>年龄</td><td>性别</td></tr><tbody id="content"></tbody>
      </table></body>
      </html>
      1. 启动tomcat进行测试

10.4 注册提示效果

  1. controller
 @RequestMapping("/a3")public String a3(String name,String pwd){String msg = "";if (name != null){if ("admin".equals(name)){msg="ok";}else {msg="用户名有误";}}if (pwd != null){if ("123456".equals(pwd)){msg="ok";}else {msg="密码有误";}}return msg;}
  1. 创建test3.jsp 并导入jQuery.js
<%--Created by IntelliJ IDEA.User: ZYHDate: 2021/8/9Time: 22:08To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head><title>Title</title><script src="${pageContext.request.contextPath}/statics/js/jquery-3.4.1.js"></script><script>function a1(){$.post({url:"${pageContext.request.contextPath}/a3",data:{"name":$("#username").val()},success:function(data){if (data.toString()=== 'ok'){$("#userInfo").css("color","green");}else {$("#userInfo").css("color","red");}$("#userInfo").html(data);}})}function a2() {$.post({url:"${pageContext.request.contextPath}/a3",data:{"pwd":$("#pwd").val()},success:function(data){if (data.toString()=== 'ok'){$("#pwdInfo").css("color","green");}else {$("#pwdInfo").css("color","red");}$("#pwdInfo").html(data);}})}</script>
</head>
<body><div>用户名:  <input id="username" name="name1" type="text" οnblur="a1()"><span id="userInfo"></span></div><div>密  码:   <input id="pwd" name="pwd" type="text" οnblur="a2()"><span id="pwdInfo"></span></div>
</body>
</html>

创建两个input标签分别代表用户名和密码,并为这两个标签创建焦点失去事件,当鼠标离开输入框时触发焦点失去时间,在各自的焦点失去时间中,通过ajax请求把 input 标签里输入的值传到controller ,controller传回相应数据并展示。

  1. 启动tomcat测试

11.拦截器

11.1 概述

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

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

过滤器

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

拦截器

  • 拦截器是SpringMVC框架自己的,只有使用了SpringMVC框架的工程才能使用
  • 拦截器只会拦截访问的控制器方法, 如果访问的是jsp/html/css/image/js是不会进行拦截的

11.2 自定义拦截器

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

  1. 新建一个Moudle 并添加web支持
  2. 配置web.xml 和 springmvc-servlet.xml文件
  3. 编写一个拦截器
package com.zdx.config;import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;public class MyInterceptor implements HandlerInterceptor {//return ture  执行下一个拦截器,放行//return false 不放行public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {System.out.println("==============处理前===========");return true;}//拦截日志public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {System.out.println("==============处理后===========");}public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {System.out.println("==============清理===========");}
}
  1. 在springmvc的配置文件中配置拦截器
<!--    拦截器配置--><mvc:interceptors><mvc:interceptor>
<!--            包括这个请求在内的所有请求--><mvc:mapping path="/**"/><bean class="com.zdx.config.MyInterceptor"/></mvc:interceptor></mvc:interceptors>
  1. 编写一个controller 接受请求
@RestController
public class TestController {@GetMapping("/t1")public String test(){System.out.println("test执行了");return "ok";}
}
  1. 启动tomcat测试 ,当访问t1请求时候 控制台会打印出拦截器的输出语句

    ====处理前=

    test执行了

    ====处理后=

    ====清理=

11.3 验证用户是否登录(认证用户)

实现思路

  1. 有一个登录页面、一个首页 需要写一个controller

  2. 用户必须登录后才能进入首页,如果没有登录则跳到登录页。

    思路:拦截器中对 进入首页的url进行拦截,判断session是否存在用户信息,如果不存在则重定向到登录页,如果存在则放行进入首页。

    因为我们配置的是拦截所有请求,所以我们要对跳转到登陆页面的请求放行,

    当我们第一次登录的 需要对登录操作放行。

  3. 创建controller

    @Controller
    @RequestMapping("/user")
    public class LoginController {@RequestMapping("/login")public String login(HttpSession session, String username, String password, Model model){//把用户的信息存在session中session.setAttribute("userLoginInfo",username);model.addAttribute("username",username);return "main";}@RequestMapping("/goLogin")public String goLogin(){return "login";}@RequestMapping("/goMain")public String main(){return "main";}@RequestMapping("/goOut")public String goOut( HttpSession session){session.removeAttribute("userLoginInfo");return "main";}
    }
    
  4. springmvc 配置

    <!--    拦截器配置--><mvc:interceptors><mvc:interceptor>
    <!--            包括这个请求在内的所有请求--><mvc:mapping path="/**"/><bean class="com.zdx.config.MyInterceptor"/></mvc:interceptor><mvc:interceptor><!--            包括这个请求在内的所有请求--><mvc:mapping path="/user/**"/><bean class="com.zdx.config.LoginInterceptor"/></mvc:interceptor></mvc:interceptors>
    </beans>
    
  5. 拦截器

    public class LoginInterceptor implements HandlerInterceptor {public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {//放行的判断,判断什么情况下登录//第一次登录也是没有session的if (request.getRequestURI().contains("login")){return true;}//登陆页面放行if (request.getRequestURI().contains("goLogin")){return true;}HttpSession session = request.getSession();if (session.getAttribute("userLoginInfo") != null){return true;}//判断什么情况下没有登录request.getRequestDispatcher("/WEB-INF/jsp/login.jsp").forward(request,response);return false;}public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {}public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {}
    }
  6. 编写前端页面

    login.jsp

    <%--Created by IntelliJ IDEA.User: ZYHDate: 2021/8/9Time: 23:11To change this template use File | Settings | File Templates.
    --%>
    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <html>
    <head><title>Title</title>
    </head>
    <body>
    <%---在web-inf 下的所有页面或者资源,都这只能通过controller去访问,或servlet进行访问--%>
    <h1>登录页面</h1><form action="${pageContext.request.contextPath}/user/login" method="post">用户名 :<input type="text" name="username">密  码 :<input type="text" name="password"><input type="submit" value="提交">
    </form>
    </body>
    </html>

    main.jsp

    <%--Created by IntelliJ IDEA.User: ZYHDate: 2021/8/9Time: 23:10To change this template use File | Settings | File Templates.
    --%>
    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <html>
    <head><title>Title</title>
    </head>
    <body>
    <h1>首页</h1><span>${username}</span><p><a href="${pageContext.request.contextPath}/user/goOut">注销</a></p></body>
    </html>

8.完整的springmvc.xml 和 web.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/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"><!--    扫描包--><context:component-scan base-package="com.zdx.controller"/>
<!--自动注入处理器类--><mvc:annotation-driven><!--        解决json乱码问题--><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><!--过滤静态资源--><mvc:default-servlet-handler/>
<!--视图解析器--><bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" id="internalResourceViewResolver"><property name="prefix" value="/WEB-INF/jsp/"/><property name="suffix" value=".jsp"/></bean><!--    拦截器配置--><mvc:interceptors><mvc:interceptor>
<!--            包括这个请求在内的所有请求--><mvc:mapping path="/**"/><bean class="com.zdx.config.MyInterceptor"/></mvc:interceptor><mvc:interceptor><!--            包括这个请求在内的所有请求--><mvc:mapping path="/user/**"/><bean class="com.zdx.config.LoginInterceptor"/></mvc:interceptor></mvc:interceptors></beans>
<?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>dispathcherServlet</servlet-name><servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class><init-param><param-name>contextConfigLocation</param-name><param-value>classpath:applicationContext.xml</param-value></init-param></servlet><servlet-mapping><servlet-name>dispathcherServlet</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>

12、 文件上的上传和下载

准备工作

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

前端表单要求:为了能上传文件,必须将表单的method设置为POST,并将enctype设置为multipart/form-data。只有在这样的情况下,浏览器才会把用户选择的文件以二进制数据发送给服务器;

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

  • application/x-www=form-urlencoded:默认方式,只处理表单域中的 value 属性值,采用这种编码方式的表单会将表单域中的值处理成 URL 编码方式。
  • multipart/form-data:这种编码方式会以二进制流的方式来处理表单数据,这种编码方式会把文件域指定文件的内容也封装到请求参数中,不会对字符编码。
  • text/plain:除了把空格转换为 “+” 号外,其他字符都不做编码处理,这种方式适用直接通过表单发送邮件。
<form action="" enctype="multipart/form-data" method="post"><input type="file" name="file"/><input type="submit">
</form>

一旦设置了enctype为multipart/form-data,浏览器即会采用二进制流的方式来处理表单数据,而对于文件上传的处理则涉及在服务器端解析原始的HTTP响应。在2003年,Apache Software Foundation发布了开源的Commons FileUpload组件,其很快成为Servlet/JSP程序员上传文件的最佳选择。

  • Servlet3.0规范已经提供方法来处理文件上传,但这种上传需要在Servlet中完成。
  • 而Spring MVC则提供了更简单的封装。
  • Spring MVC为文件上传提供了直接的支持,这种支持是用即插即用的MultipartResolver实现的。
  • Spring MVC使用Apache Commons FileUpload技术实现了一个MultipartResolver实现类:
  • CommonsMultipartResolver。因此,SpringMVC的文件上传还需要依赖Apache Commons FileUpload的组件。

文件上传

1、导入文件上传的jar包,commons-fileupload , Maven会自动帮我们导入他的依赖包 commons-io包;

<!--文件上传-->
<dependency><groupId>commons-fileupload</groupId><artifactId>commons-fileupload</artifactId><version>1.3.3</version>
</dependency>
<!--servlet-api导入高版本的-->
<dependency><groupId>javax.servlet</groupId><artifactId>javax.servlet-api</artifactId><version>4.0.1</version>
</dependency>

2、配置bean:multipartResolver

注意!!!这个bena的id必须为:multipartResolver , 否则上传文件会报400的错误!在这里栽过坑,教训!

<!--文件上传配置-->
<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>

CommonsMultipartFile 的 常用方法:

  • String getOriginalFilename():获取上传文件的原名
  • InputStream getInputStream():获取文件流
  • void transferTo(File dest):将上传文件保存到一个目录文件中

我们去实际测试一下

3、编写前端页面

<form action="/upload" enctype="multipart/form-data" method="post"><input type="file" name="file"/><input type="submit" value="upload">
</form>

4、Controller

package com.kuang.controller;import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.multipart.commons.CommonsMultipartFile;import javax.servlet.http.HttpServletRequest;
import java.io.*;@Controller
public class FileController {//@RequestParam("file") 将name=file控件得到的文件封装成CommonsMultipartFile 对象//批量上传CommonsMultipartFile则为数组即可@RequestMapping("/upload")public String fileUpload(@RequestParam("file") CommonsMultipartFile file , HttpServletRequest request) throws IOException {//获取文件名 : file.getOriginalFilename();String uploadFileName = file.getOriginalFilename();//如果文件名为空,直接回到首页!if ("".equals(uploadFileName)){return "redirect:/index.jsp";}System.out.println("上传文件名 : "+uploadFileName);//上传路径保存设置String path = request.getServletContext().getRealPath("/upload");//如果路径不存在,创建一个File realPath = new File(path);if (!realPath.exists()){realPath.mkdir();}System.out.println("上传文件保存地址:"+realPath);InputStream is = file.getInputStream(); //文件输入流OutputStream os = new FileOutputStream(new File(realPath,uploadFileName)); //文件输出流//读取写出int len=0;byte[] buffer = new byte[1024];while ((len=is.read(buffer))!=-1){os.write(buffer,0,len);os.flush();}os.close();is.close();return "redirect:/index.jsp";}
}

5、测试上传文件,OK!

采用file.Transto 来保存上传的文件

1、编写Controller

/*
* 采用file.Transto 来保存上传的文件
*/
@RequestMapping("/upload2")
public String  fileUpload2(@RequestParam("file") CommonsMultipartFile file, HttpServletRequest request) throws IOException {//上传路径保存设置String path = request.getServletContext().getRealPath("/upload");File realPath = new File(path);if (!realPath.exists()){realPath.mkdir();}//上传文件地址System.out.println("上传文件保存地址:"+realPath);//通过CommonsMultipartFile的方法直接写文件(注意这个时候)file.transferTo(new File(realPath +"/"+ file.getOriginalFilename()));return "redirect:/index.jsp";
}

2、前端表单提交地址修改

3、访问提交测试,OK!

文件下载

文件下载步骤:

1、设置 response 响应头

2、读取文件 – InputStream

3、写出文件 – OutputStream

4、执行操作

5、关闭流 (先开后关)

代码实现:

@RequestMapping(value="/download")
public String downloads(HttpServletResponse response ,HttpServletRequest request) throws Exception{//要下载的图片地址String  path = request.getServletContext().getRealPath("/upload");String  fileName = "基础语法.jpg";//1、设置response 响应头response.reset(); //设置页面不缓存,清空bufferresponse.setCharacterEncoding("UTF-8"); //字符编码response.setContentType("multipart/form-data"); //二进制传输数据//设置响应头response.setHeader("Content-Disposition","attachment;fileName="+URLEncoder.encode(fileName, "UTF-8"));File file = new File(path,fileName);//2、 读取文件--输入流InputStream input=new FileInputStream(file);//3、 写出文件--输出流OutputStream out = response.getOutputStream();byte[] buff =new byte[1024];int index=0;//4、执行 写出操作while((index= input.read(buff))!= -1){out.write(buff, 0, index);out.flush();}out.close();input.close();return null;
}

前端

<a href="/download">点击下载</a>

测试,文件下载OK,大家可以和我们之前学习的JavaWeb原生的方式对比一下,就可以知道这个便捷多了!

SpringMVC (注解、拦截器、json、Ajax)相关推荐

  1. AJAX,SpringMVC,拦截器(Ajax发送请求 经过SpringMVC拦截器重定向其他页面失败)

    Ajax发送请求 经过SpringMVC拦截器重定向其他页面失败 借鉴出处 Ajax是通过异步请求后台,获取数据,局部刷新页面,因此,即使后台进行页面跳转的编码,前台请求完毕以后,只会执行ajax的回 ...

  2. springmvc高级(拦截器,全局异常处理,文件上传)

    SpringMVC 1.文件上传 文件上传: 指的就是将用户本地计算机中文件上传到服务器上的过程称之为文件上传 1).文件上传编程步骤 # 1.项目中引入相关依赖 <dependency> ...

  3. SpringMVC自定义拦截器与异常处理(自定义异常)

    SpringMVC自定义拦截器与异常处理 拦截器概念 拦截器代码演示 创建maven工程 pom.xml <?xml version="1.0" encoding=" ...

  4. SpringMVC之拦截器使用

    拦截器的介绍 SpringMVC的处理器拦截器类似于Servlet开发中的过滤器Filter,用于对处理器进行预处理和后处理,可以通过自定义拦截器来实现特定的功能. 过滤器与拦截器的区别:拦截器是AO ...

  5. java 判断请求为 ajax请求_Java过滤器处理Ajax请求,Java拦截器处理Ajax请求,java 判断请求是不是ajax请求...

    Java过滤器处理Ajax请求,Java拦截器处理Ajax请求,拦截器Ajax请求 java 判断请求是不是ajax请求,Java判断是否为ajax请求 >>>>>> ...

  6. Java过滤器处理Ajax请求,Java拦截器处理Ajax请求,java 判断请求是不是ajax请求

    Java过滤器处理Ajax请求,Java拦截器处理Ajax请求,java 判断请求是不是ajax请求 Java过滤器处理Ajax请求,Java拦截器处理Ajax请求,拦截器Ajax请求 java 判断 ...

  7. springMVC使用拦截器针对控制器方法做预处理、后处理、资源清理

    简单了解一下过滤器和拦截器: 过滤器是servlet规范中的一部分,任何java web工程都可以使用:在url-pattern中配置/*之后,可以对所有要访问的资源拦截.拦截器是springMVC框 ...

  8. springboot 自定义注解拦截器

    springboot 自定义注解拦截器 最近在工作中,发现自定义注解拦截使用起来特别方便,现在来写出来给大家看看 环境springboot 首先写一个自定义注解 package com.study.c ...

  9. Springboot + redis + 注解 + 拦截器来实现接口幂等性校验

    点击上方"方志朋",选择"设为星标" 回复"666"获取新整理的面试文章 作者:wangzaiplus www.jianshu.com/p/ ...

  10. springboot + redis + 注解 + 拦截器 实现接口幂等性校验

    点击上方"方志朋",选择"设为星标" 做积极的人,而不是积极废人 来源:https://www.jianshu.com/p/6189275403ed 一.概念 ...

最新文章

  1. (OCR论文)Mask TextSpotter V3机翻
  2. 12、动态视图组件ListView、GridView
  3. OpenCV的图像处理——iOS与OpenCV之间图像转换
  4. TCP/IP总结(4)TCP 之最大消息长度
  5. 神曲背后的故事:算法工程师带你理性解构“蚂蚁呀嘿”
  6. 蓝桥杯2015初赛-饮料换购-枚举
  7. $.ajax所犯的错误。success后面不执行
  8. The following classes could not be instantiated:
  9. 09-mysql-分组函数-最大最小总和平均值
  10. 阿里Q2财报:阿里云势头猛进领跑全球
  11. python与贝叶斯_python-与PyMC3的贝叶斯相关
  12. 傅里叶变换和拉普拉斯变换
  13. Win8串口驱动完美支持
  14. matlab 创建同型矩阵_以经典同型样式创建新地图
  15. java super是什么意思_Java中super是什么意思?
  16. 【牛客刷题-SQL进阶挑战】NO5.窗口函数
  17. 淘宝U站运营推广方法
  18. 用vue去实现百度下拉菜单
  19. 提取住房公积金有什么影响
  20. 透视映客半年报:亏损背后的长期价值

热门文章

  1. vue-管道符“ | “(竖杠)的作用
  2. 混合app 安卓用户将手机系统字体大小调整后会影响app的字体大小及样式
  3. 微信小程序 调取云函数 信息推送失败response out of time limit or subscription is canceled hint的具体解决方法
  4. Python可视化分析《雪中悍刀行》,看看它为什么这么火?
  5. 初学者如何使用PS剪切蒙版?
  6. 完全基于C++ 实现的人机对战五子棋小游戏
  7. 跨考计算机性价比学校,高性价比院校推荐第五波,又想骗我考你们学校!
  8. 细数 NFT 十大类别:PFP、艺术、游戏......
  9. L1范数与L2范数的区别与联系
  10. 分享3个音频合并无缝衔接软件,音频合并超简单