SpringMVC详解二(响应篇)

一、响应数据和结果视图

1.1、搭建环境

1、新建一个Mven的web项目:
在这里插入图片描述
在这里插入图片描述

2、引入jar:

<properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <maven.compiler.source>1.9</maven.compiler.source>
    <maven.compiler.target>1.9</maven.compiler.target>
    <!--jar版本控制-->
    <spring.version>5.0.2.RELEASE</spring.version>
</properties>
  
<dependencies>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-context</artifactId>
      <version>${spring.version}</version>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-web</artifactId>
      <version>${spring.version}</version>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-webmvc</artifactId>
      <version>${spring.version}</version>
    </dependency>
    <dependency>
      <groupId>javax.servlet</groupId>
      <artifactId>servlet-api</artifactId>
      <version>2.5</version>
      <scope>provided</scope>
    </dependency>
    <dependency>
      <groupId>javax.servlet.jsp</groupId>
      <artifactId>jsp-api</artifactId>
      <version>2.0</version>
      <scope>provided</scope>
    </dependency>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.11</version>
      <scope>test</scope>
    </dependency>
  </dependencies>

3、新建文件:
在这里插入图片描述
在这里插入图片描述

4、配置springmvc.xml配置文件:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:mvc="http://www.springframework.org/schema/mvc"
       xmlns:context="http://www.springframework.org/schema/context"
       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
        http://www.springframework.org/schema/mvc
        http://www.springframework.org/schema/mvc/spring-mvc.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context.xsd">

        <!--开启注解扫描-->
        <context:component-scan base-package="com.it"/>

        <!--配置视图解析器对象-->
        <bean id="internalResourceViewResolver"
              class="org.springframework.web.servlet.view.InternalResourceViewResolver">

            <property name="prefix" value="/WEB-INF/jsp/" />
            <property name="suffix" value=".jsp" />
        </bean>

         <!--开启SpringMVC框架注解支持
            该注解默认开启了
            (1)HandlerMapping:处理器映射器
            (2)Handler:处理器
            (3)HandlAdapter:处理器适配器
         -->
    <mvc:annotation-driven />
</beans>

5、配置web.xml,注册SpringMVC所必要组件:

<web-app>
  <display-name>Archetype Created Web Application</display-name>

  <!--配置解决中文乱码的过滤器-->
  <filter>
    <filter-name>characterEncodingFilter</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>characterEncodingFilter</filter-name>
    <url-pattern>/*</url-pattern>
  </filter-mapping>

<!--配置前端控制器-->
  <servlet>
    <servlet-name>dispatcherServlet</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <init-param>
      <param-name>contextConfigLocation</param-name>
      <param-value>classpath:springmvc.xml</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
  </servlet>
  <servlet-mapping>
    <servlet-name>dispatcherServlet</servlet-name>
    <url-pattern>/</url-pattern>
  </servlet-mapping>
</web-app>

1.2、响应之返回值是String类型

响应发出的请求,并取值响应。
流程:
1、发出请求
2、根据请求查询数据库
3、从数据库中取出想要的结果集,并存入request域中
4、成功跳转页面之后从域中取出结果显示

1、新建一个jsp来发出请求:
在这里插入图片描述

2、新建一个bean类和控制器来将结果集存入域中:
在这里插入图片描述
在这里插入图片描述

3、成功跳转页面,并取出结果集:
在这里插入图片描述

1.3、响应之返回值是void类型

1、新增请求:
在这里插入图片描述
2、控制器:
在这里插入图片描述

3、启动服务测试:点击请求之后发现如图
在这里插入图片描述


  当控制器方法返回值为void的时候,springmvc默认会去找以当前控制器@RequestMapping中的请求路径去WEB-INFO下找以类名命名的jsp文件。如果要求该控制器必须是void方法,且想要不报错,那么可以使用servlet的转发:
在这里插入图片描述
当然,也可以使用重定向:
在这里插入图片描述
还可以直接去做页面响应:
在这里插入图片描述
总结
页面发生跳转的三种方式:转发,重定向,直接响应。

1.4、响应之返回值是ModelAndView类型

  ModelAndView是SpringMVC为我们提供的一个对象,该对象也可以用作控制器方法的返回值。 其实返回值是String类型的控制器,底层也是用了SpringMVC的ModelAndView
1、新建一个请求:
在这里插入图片描述
2、控制器:
在这里插入图片描述
3、启动服务进行测试。


1.5 响应之使用forward和redirect关键字进行页面跳转

1、请求:
在这里插入图片描述
2、控制器:
在这里插入图片描述

注意
1、转发只发一次请求,所以在转发的时候不需要写项目名称,只需要些转发路径即可
2、重定向需要发两次请求,且不能重定向到WEB-INFO目录下的文件。在重定向的时候需要写完成项目名,但是使用springmvc提供的关键字redirect可以只写重定向的目标文件。

3、运行服务测试。


1.6、响应json数据之过滤静态资源

需求
  客户端发送json数据,服务端来接,服务端处理完数据再将数据封装成json数据返回给客户端,实现json数据页面跳转。

知识
DispatcherServlet会拦截到所有的资源,导致一个问题就是静态资源(img、css、js)也会被拦截到,从而
不能被使用。解决问题就是需要配置静态资源不进行拦截,在springmvc.xml配置文件添加如下配置:

  1. mvc:resources标签配置不过滤
  2. location元素表示webapp目录下的包下的所有文件
  3. mapping元素表示以/static开头的所有请求路径,如/static/a 或者/static/a/b

1、在项目中引入jquery文件,方便使用ajax来发送json数据:
在这里插入图片描述


2、使用jquery编写来发一个请求:
在这里插入图片描述
在这里插入图片描述

3、启动服务,打印hello。测试按钮绑定事件是否生效。

问题
  当启动服务之后,点击按钮,发现并不会打印hello,也就是绑定事件不生效,为什么会这样呢?
答案
  因为在web.xml中配置了前段控制器,而该前段控制器是配置所以请求,已经静态资源文件都会被拦截:
在这里插入图片描述
如果想要告诉让拦截器,不对js、css、图片等静态文件不进行拦截,可以在springmvc.xml配种文件中进行如下配置:
在这里插入图片描述
配置完成以后,此时重新部署即可解决问题。

如果加了过滤路径之后还是找不到,请用谷歌F12检查是否加载到了jquery.js文件:
在这里插入图片描述
遇到这种问题,需要检查js的引用路径是否写对,在正确的情况下重新部署项目,启动服务。具体原因可以参考:
https://www.cnblogs.com/ianhuafeng/p/12441403.html


1.7、响应json数据之发送ajax的请求

1、使用ajax向后台发请求:
在这里插入图片描述

2、服务端来接收请求:
在这里插入图片描述
3:、启动服务测试:
在这里插入图片描述


1.8、响应json数据之响应json格式数据

  由Spring框架提供支持,只需要发送的json数据中存在的key和服务端Bean类的成员属性名一致,那么就会将请求数据自动封装成对象,发送的服务端。json的key与实体的成员名关系是如何实现映射的呢?答案:具体的json转Java对象或者java对象转Json,还需要使用一些工具jar包:
在这里插入图片描述

Json详细学习可以参考:
https://blog.csdn.net/wangmx1993328/article/details/88598625?depth_1-utm_source=distribute.pc_relevant.none-task&utm_source=distribute.pc_relevant.none-task

1、完成控制器代码:
在这里插入图片描述

2、完善前端代码:
在这里插入图片描述
3、启动服务测试。

总结
本章主要学习了同步请求中的转发和重定向来实现页面跳转。还学习了异步请求使用ajax来实现json与实体对象之间的互相转换。


二、SpringMVC实现文件上传

2.1、传统文件上传

2.1.1、文件上传必要前提

1、form表单的enctype取值必须是:multipart/form-data。 (默认值是:application/x-www-form-urlencoded,其数据形式的key-value等都放在一起。设置成multipart/form-data后是将元素内容分开,需要取内容,使用标签名即可。)
enctype:是表单请求正文的类型 。
具体详解查看文章:
https://blog.csdn.net/qq_33706382/article/details/78168325

2、method属性取值必须是Post
因为get请求是把请求参数放到url地址后面,而url请求参数地址是有长度限制的。

3、提供一个文件选择域<input type=”file” />

2.1.2 文件上传的原理分析

在这里插入图片描述
原理:如果需要实现文件上传,需要拿到整个请求体,然后对整个请求体进行解析,取出上传文件的内容,最后才能将内容转成字节流写出到一个文件中去。
  由于解析我们对该请求体格式不是很熟,且解析起来比较麻烦,所以我们利用现成的工具类进行解析,如下:
在这里插入图片描述

2.1.3 传统上传文件演示:

1、新建一个表单
在这里插入图片描述
2、引入工具jar包,用以对上传的文件进行解析:

<dependency>
      <groupId>commons-fileupload</groupId>
      <artifactId>commons-fileupload</artifactId>
      <version>1.3.1</version>
    </dependency>
    <dependency>
      <groupId>commons-io</groupId>
      <artifactId>commons-io</artifactId>
      <version>2.4</version>
    </dependency>

3、写一个控制器:
在这里插入图片描述

4、测试即可。


2.2、SpringMVC文件上传

2.2.1、SpringMVC文件上传原理

  在DispatcherServlet封装了一个CommonsMultipartResolver(文件解析器组件),该组件中定义了一个MultipartResolver属性,如果用户配置了该Bean,启动容器的时候,会自动注入参数,如果用户没有配置,则默认为null。当DispaterServlet收到请求时,它的checkMultipart()方法会调用MultipartResolver的isMultipart()方法判断请求中是否包含了文件且multipartResolver属性存在实例。如果满足条件,则调用MultipartResolver的resolveMultipart()方法对请求数据进行解析,然后将文件数据解析成MultipartFile并封装在MultipartHttpServletRequest对象中返回给DispatcherServlet。
流程图如下:
在这里插入图片描述

详解可参考帖子:
https://blog.csdn.net/qq_41656471/article/details/89258073

2.2.2、SpringMVC文件上传代码

1、新建一个表单:
在这里插入图片描述
2、配置文件解析器:
在这里插入图片描述

3、编写控制器代码:
在这里插入图片描述
4、启动服务测试运行。


2.3、SpringMVC跨服务器文件上传

2.3.1、分服务器的目的

在实际开发中,我们会有很多处理不同功能的服务器。例如:
应用服务器:负责部署我们的应用
数据库服务器:运行我们的数据库
缓存和消息服务器:负责处理大并发访问的缓存和消息
文件服务器:负责存储用户上传文件的服务器。 (注意:此处说的不是服务器集群)
分服务器处理的目的是让服务器各司其职,从而提高我们项目的运行效率。
在这里插入图片描述

2.3.2、代码演示

1、在原IDEA窗口不关的情况下,新增一个Tomcat服务,用以代替文件服务器:
在这里插入图片描述
2、再创建一个Maven的webapp项目,部署到文件上传服务器。

应用服务器只负责处理请求,文件服务器负责上传和下载文件

在这里插入图片描述
在这里插入图片描述
此时部署项目,启动服务,图片服务器就搭建完成了。

3、在应用服务器新建一个表单:
在这里插入图片描述


4、实现跨服务器上传,需要用到工具jar包:

<dependency>
   <groupId>com.sun.jersey</groupId>
   <artifactId>jersey-core</artifactId>
   <version>1.18.1</version>
</dependency>
<dependency>
   <groupId>com.sun.jersey</groupId>
   <artifactId>jersey-client</artifactId>
   <version>1.18.1</version>
</dependency>

5、写控制器:
在这里插入图片描述
6、启动项目运行测试。如果项目报错409,请去检查图片服务器上是否存在uploads目录


三、SpringMVC异常处理和拦截器

3.1、异常处理

3.1.1、异常处理思路

  系统中异常包括两类:预期异常和运行时异常。前者通过捕获异常从而获取异常信息,后者主要通过规范代码开发、测试通过手段减少运行时异常的发生。
  系统的dao、service、controller出现都通过throws Exception向上抛出,最后由springmvc前端控制器交由异常处理器进行异常处理,如下图:
在这里插入图片描述

3.1.2、环境搭建

就用上一个例子的环境。

3.1.3、代码编写

1、增加一个请求:
在这里插入图片描述
2、写一个控制器,模拟一个异常,将异常直接配给客户端:
在这里插入图片描述
3、此时可以测试运行。

4、新建一个自定义异常类,用以人性的提示信息:
在这里插入图片描述
5、修改控制器:
在这里插入图片描述
6、编写一个自定义异常处理器:
在这里插入图片描述
7、将异常处理器注册到容器:
在这里插入图片描述
8、新建一个错误跳转页面error.jsp
在这里插入图片描述
最后启动服务测试即可。

3.2、SpringMVC拦截器

3.2.1、SpringMVC拦截器作用

拦截器的作用
  Spring MVC 的处理器拦截器类似于Servlet开发中的过滤器Filter,用于对处理器进行预处理和后处理。 用户可以自己定义一些拦截器来实现特定的功能。
  谈到拦截器,还要向大家提一个词——拦截器链(Interceptor Chain)。拦截器链就是将拦截器按一定的顺序联结成一条链。在访问被拦截的方法或字段时,拦截器链中的拦截器就会按其之前定义的顺序被调用。 说到这里,可能大家脑海中有了一个疑问,这不是我们之前学的过滤器吗?
  是的它和过滤器是有几分相似,但是也有区别,接下来我们就来说说他们的区别:
(1) 过滤器是servlet规范中的一部分,任何java web工程都可以使用。 拦截器是SpringMVC框架自己的,只有使用了SpringMVC框架的工程才能用。
(2)过滤器在url-pattern中配置了/*之后,可以对所有要访问的资源拦截(包括静态资源)。 拦截器它是只会拦截访问的控制器方法,如果访问的是jsp,html,css,image或者js是不会进行拦截的。 它也是AOP思想的具体应用。 我们要想自定义拦截器, 要求必须实现:HandlerInterceptor接口。

原理:
在这里插入图片描述

总结
拦截器能拦截的过滤器一定可以过滤
过滤器能过滤的拦截器不一定能拦截。

3.2.2、SpringMVC拦截器代码演示

1、环境搭建:用上一个Demo的环境
2、写一个请求:
在这里插入图片描述

3、编写一个控制器:
在这里插入图片描述
4、新增一个自定义拦截器:
在这里插入图片描述

package com.it.interceptor;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
 * 自定义拦截器
 */
public class MyInterceptor1 implements HandlerInterceptor{

    /**
     * 预处理,controller方法执行前
     * return true 放行,执行下一个拦截器,如果没有,执行controller中的方法
     * return false不放行
     */
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.println("MyInterceptor1执行了...前1111");
        // request.getRequestDispatcher("/WEB-INF/pages/error.jsp").forward(request,response);
        return true;
    }

    /**
     * 后处理方法,controller方法执行后,success.jsp执行之前
     */
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        System.out.println("MyInterceptor1执行了...后1111");
        // request.getRequestDispatcher("/WEB-INF/pages/error.jsp").forward(request,response);
    }

    /**
     * success.jsp页面执行后,该方法会执行
     * @throws Exception
     */
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        System.out.println("MyInterceptor1执行了...最后1111");
    }

}

5、配置一个拦截器:
在这里插入图片描述
6、为了测试时候效果明显,跳转页面增加一句代码:
在这里插入图片描述
7、此时测试即可。

8、拦截器链演示:
如果此时是有两个拦截器:
在这里插入图片描述
在这里插入图片描述
再配置一个拦截器:
在这里插入图片描述
最后再测试即可。

发布了22 篇原创文章 · 获赞 16 · 访问量 2891

猜你喜欢

转载自blog.csdn.net/qq_25083447/article/details/105156794