文章目录
一、响应数据和结果视图
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配置文件添加如下配置:
- mvc:resources标签配置不过滤
- location元素表示webapp目录下的包下的所有文件
- 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包:
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、拦截器链演示:
如果此时是有两个拦截器:
再配置一个拦截器:
最后再测试即可。