摘要:依赖于对请求的支持。使用解析兼容的没有构造器参数,也没有要设置的参数,这样,在应用上下文中,将其声明为就会非常简单。默认是没有限制的整个请求的容量。
Spring MVC 高级的技术
本章内容:
Spring MVC配置的替代方案
处理文件上传
在控制器中处理异常
使用flash属性
稍等还没结束
说明如果你有幸能看到。后面的章节暂时不更新了,改变学习方式了。重要理解思想,这本书写的太好了。记得要看作者的代码,书上只是阐述了知识点。还有以后会把重点放在GitHub上,阅读别人的代码,自己理解的同时在模仿出来,分享给大家。你们的点赞就是对我的支持,谢谢大家了。
1、本文参考了《Spring 实战》重点内容,参考了作者GitHub上的代码,推荐使用chrome上的GitHub插件Insight.io,FireFox也有。
2、本文只为记录作为以后参考,要想真正领悟Spring的强大,请看原书。跟着作者套路来,先别瞎捣腾!!!
3、在一次佩服老外,国外翻译过来的书,在GiuHub上大都有实例。看书的时候,跟着敲一遍,效果很好。
4、代码和笔记在这里GitHub,对你有帮助的话,欢迎点赞。
5、每个人的学习方式不一样,找到合适自己的就行。2018,加油。
6、Java 8 In Action 的作者Mario Fusco、Spring In Action 、Spring Boot In Action的作者Craig Walls
7、知其然,也要知其所以然。有些是在Atom上手敲的,有拼写错误,还请见谅。
8、从Spring Web Flow 开始,我要加快速度了,逻辑可能不完整,一切以原书为准,自己只是记录。加深印象。
谈一些个人感受
1、赶快学习Spring吧,Spring MVC 、Spring Boot 、微服务。
2、重点中的重点,学习JDK 8 Lambda,Stream,Spring 5 最低要求JDK1.8.
3、还有Netty、放弃SH吧,不然你会落伍的。
4、多看一些国外翻译过来的书,例如 Xxx In Action 系列。权威指南系列。用Kindle~
5、写代码之前先写测试,这就是老外不同之处。学到了很多技巧。
6、再一次佩服老外对细节的处理。值得我们每一个人学习
在很多方面,Spirng MVC(整个Spirng也是如此),也有还没结束这样的感觉。
在第五章,我们学习了Sprng MVC的基础知识,以及如何编写控制器来处理各种请求,基于这些知识。我们在第六章学习了如何创建JSP和Thymeleaf视图,这些视图会将模型数据展示给用户。你可能认为我们已经掌握了Spring MVC的全部知识,但是,稍等!还没结束。
在本章中,我们将会看到如何编写控制器处理文件上传,如何处理控制器所抛出的异常,以及如何在模型中传递数据,使其能够在重定向(redirect)之后依然存活。
但,首先我要兑现一个承诺。在第5章中,我们快速展现了如何通过AbstractAnnotationConfigDispatcherServletInitializer搭建Spring MVC,当时,我们承诺会为读者展现其他的配置方案。所以,在介绍文件上传和异常处理之前,我们花时间探讨一下如何使用其他方式来搭建DispatcherServlet和ContextLoaderListener
7.1 Spring MVC 配置的替代方案尽管对很多Spring应用来说,这是一种安全的假设,但是并不一定能满足我们的要求。除了DispatcherServlet以外,我们还可能需要额外的DispatcherServlet和Filter,我们可能还需要对DispatcherServlet本身做一些额外的配置:或者,如果我们需要将应用部署到Servlet3.0之前的容器中,那么还需要将DispatcherServlet配置到传统的web.xml中。
7.1.1 自定义DispatcherServlet配置public class SpitterWebInitializer extends AbstractAnnotationConfigDispatcherServletInitializer { @Override protected Class>[] getRootConfigClasses() { return new Class>[] { RootConfig.class }; } @Override protected Class>[] getServletConfigClasses() { return new Class>[] { WebConfig.class }; } @Override protected String[] getServletMappings() { return new String[] { "/" }; } }
AbstractAnnotationConfigDispatcherServletInitializer所完成的事其实比看上去要多,在SpitterWebInitializer中我们所编写的三个方法仅仅是必须要重载的三个抽象方法,但实际上还有更多的方法可以进行重载,从而实现额外的配置。
此类的方法之一就是customizeRegistration().在AbstractAnnotationConfigDispatcherServletInitializer将DispatcherServlet注册到Servlet容器中就会调用customizeRegistration(),并将Servlet注册后得到的Registration.Dynamic传递进来,通过重载customizeRegistration()方法,我们就可以对DispatcherServlet进行额外的配置。
在本章稍后,我们将会看到如何在Spirng MVC中处理multiparty请求和文件上传。如果计划使用Servlet3.0对multiparty配置的支持,那么我们需要使用DispatcherServlet的registration来启用multilpart请求。我们可以重载customizeRegistration()方法来设置MultipartConfigElement,
@Override protected void customizeRegistration(Dynamic registration) { registration.setMultipartConfig( new MultipartConfigElement("C:Temp")); //设置上传文件目录 }
借助customizeRegistration()方法中的ServletRegistration.Dynamic我们能够完成更多的任务,
包括通过调用setLoadOnstartup()设置load-on-startup 优先级,
通过setInitParameter()设置初始化参数,
通过调用setMultipartConfig()配置Servlet3.0对multipart的支持,
7.1.2 添加其他的Servlet和Filter按照AbstractAnnotationConfigDispatcherServletInitializer的定义,它会创建DispatcherServlet和ContextLoaderListener.但是如果你想要注册其他的Servlet、Filter、Listener的话,那该怎么办?
基于Java的初始化器(initializer)的一个好处在于我们可以定义任意数量的初始化类。如果我们想要往Web容器中注册其他组件的话,只需要创建一个 新的初始化类就可以了,最简单的方式就是实现Spring的WebApplicationInitializer并注册一个Servlet。
public class MyServletInitializer implements WebApplicationInitializer { @Override public void onStartup(ServletContext servletContext) throws ServletException { Dynamic myServlet = servletContext.addServlet("myServlet",myServlet.class); myServlet.addMapping("/custom/**"); } }
以上程序相当基础的Servlet注册初始化器类,它注册了一个Servlet并将其映射到了一个路径上,我们也可以通过这种方式来手动注册DispatcherServlet.(但是没必要,因为AbstractAnnotationConfigDispatcherServletInitializer没用太多代码就将这项任务完成得很漂亮)
类似的,我们还可以创建新的WebApplicationInitializer来实现注册Listener和 Filter,
@Override public void onStartup(ServletContext servletContext) throws ServletException { javax.servlet.FilterRegistration.Dynamic filter = servletContext.addFilter("myFilter",myFilter.class); filter.addMappingForUrlPatterns(null,false,"/custom/*"); }
如果你将应用部署到Servlet3.0的容器中,那么WebApplicationInitializer提供了一种通用的方法,实现在Java中注册Servlet和Filter、Listener,如果你只是注册Filter,并且该Filter只会映射到DispatcherServlet上的话,那么AbstractAnnotationConfigDispatcherServletInitializer还有一种快捷的方式。
为了注册Filter并将其映射到DispatcherServlet,所需要做的仅仅是重载AbstractAnnotationConfigDispatcherServletInitializer的getServletFilter()方法。
@Override protected Filter[] getServletFilters() { return new Filter[] {new Myfilter()}; }
这个方法返回一个javax.servlet.filter数组。在这里没有必要声明它的映射路径,getServletFilter()方法返回所有Filter都会被映射到DispatcherServlet上。
如果要将应用部署到Servlet3.0上,那么Spring容器提供了多种注册方式,而不必创建web.xml文件,但是,如果你不想采取上述方案的话,也是可以的,假设你将应用部署到不支持Servlet3.0的容器中(或者你只希望使用web.xml),那么我们完全可以按照传统的方式,通过web.xml配置Spirng MVC,
7.1.3 在web.xml中声明DispatcherServlet在典型的Spirng MVC应用中,我们会需要DispatcherServlet和ContextLoaderListener.AbstractAnnotationConfigDispatcherServletInitializer会自动注册它们,但如果需要在web.xml中注册的话,那就需要我们自己动手来完成了。
appServlet index.html contextConfigLocation classpath:spring/applicationContext-*.xml org.springframework.web.context.ContextLoaderListener CharacterEncodingFilter org.springframework.web.filter.CharacterEncodingFilter encoding utf-8 CharacterEncodingFilter /* appServlet org.springframework.web.servlet.DispatcherServlet contextConfigLocation classpath:spring/springmvc.xml 1 appServlet /
ContextLoaderListener和DispatcherServlet各自都会加载一个Spirng应用上下文。上下文ContextLoaderLocation指定了一个XMl文件的地址,这个文件定义了根据应用上下文,它会被ContextLoaderListener加载。根上下文会从"/WEB-INF/spring/applicationContext-*.xml"中加载bean的定义
DispatcherServlet会根据Servlet的名字找到一个文件,并基于该文件加载应用上下文。
如果你希望指定DispatcherServlet配置文件的话,那么可以在Servlet指定一个ContextLoaderLocation初始化参数。
appServlet org.springframework.web.servlet.DispatcherServlet contextConfigLocation classpath:spring/springmvc.xml 1 appServlet /
现在我们已经看到了如何以多种不同的方式来搭建Spring MVC,那么接下来我们看一下如何使用Spring MVC来处理文件上传。
7.2 处理multipart形式的数据在Web应用中,允许用户上传内容是很常见的需求,在Facebook和Flickr这样的网站中,允许用户会上传图片和视频,并与家人朋友分享。还有一些服务器中允许用户上传照片,然后按照传统的方式将其打印在纸上,或者咖啡杯上。
Spittr应用有两个地方需要文件上传。当新用户注册的时候,我们希望能够上传一张照片,从而与他的个人信息相关联。当用户提交新的Spittle时,除了文本信息外,他们可能还会上传一张照片。
一般表单提交所形成的请求结果是非常简单的,就是以"&"符号分割的多个name-value对,尽管这种方式简单,并且对于典型的基于文本的表单提交也足够满足需求,但是对于二进制数据,就显得力不从心了。与之不同的是multipart格式的数据会将一个表单拆分为多个部分(part),每个部分对应一个输入域。在一般的表单输入域中,它所对应的部分中会放置文本数据,但是如果是上传文件的话,它所对应的部分可以是二进制。
Content-Type 他表它的类型。尽管multipart请求看起来很复杂,但是在SpringMVC中处理它却很容易,在编写控制器方法处理文件上传之前,我们必须配置一个multipart解析器,通过它来告诉DispatcherServlet该如何读取multipart请求。
7.2.1 配置multipart解析器DispatcherServlet并没有实现爱你任何解析multipart请求数据的功能。它将该任务委托给了Spring中的MultipartResolver策略接口的实现,通过这个实现类来解析multipart请求中的内容。从Spirng 3.1开始,Spirng内置了两个MultipartResolver的实现供我们选择。
CommonsMultipartResolver:使用Jakarta Commons FileUpload解析multipart请求。
StandardServletMultipartResolver:依赖于Servlet3.0对multipart请求的支持。
一般来讲StandardServletMultipartResolver可能会是优选方案,他使用Servlet所提供的功能支持。并不需要依赖任何其他的项目。如果,我们需要将项目部署到Sevrvlet3.0之前的容器中,或者还没有使用Spring 3.1 或者更高的版本,那么可能就需要 CommonsMultipartResolver了。
使用Servlet3.0解析multipart
兼容Servlet3.0的StandardServletMultipartResolver没有构造器参数,也没有要设置的参数,这样,在Spring应用上下文中,将其声明为bean就会非常简单。
@Bean public MultipartResolver multipartResolver() throws IOException { return new StandardServletMultipartResolver(); }
如果我们采用Servlet初始化类的方式来配置DispatcherServlet的话,这个初始化类应该已经实现了WebApplicationInitializer,那么我们可以在ServletRegistration上调用setMultipartConfig()方法,传入一个MultipartConfigElement实例,具体的配置如下:
@Override protected void customizeRegistration(Dynamic registration) { registration.setMultipartConfig( new MultipartConfigElement("C:Temp")); } }
通过重载customizeRegistration()方法(它会得到一个Dynamic作为参数)类配置multipart的具体细节。
到目前为止,我们所使用的是只有一个参数的MultipartConfigElemenet构造器,这个参数指定的是文件系统中一个绝对目录,上传文件将会临时写入该目录,但是,我们还可以通过其他的构造器来限制上传文件的大小,除了临时路径的位置,其他的构造器可以接受的参数如下:
上传文件的最大容量(以字节为单位)。默认是没有限制的
整个multipart请求的容量。不会关心有多少个part以及每个part的大小。默认是没有限制的。
在上传的过程中,如果文件大小达到了一个指定最大容量,将会写入到临时文件路径中,默认值为0,也就是所有上传的文件都会写入磁盘上。
例如,假设我们想要限制文件的大小不超过2MB,整个请求不超过4MB,而且所有的文件都要写入磁盘,
@Override protected void customizeRegistration(Dynamic registration) { registration.setMultipartConfig( new MultipartConfigElement("C:Tempuploads",2097152, 4194304, 0)); }
如果使用更为传统的web.xml来配置MultipartConfigResolver的话,那么可以使用
appServlet org.springframework.web.servlet.DispatcherServlet 1 C:Tempuploads 2097152 4194304
配置Jakarta Commons FileUpload Multipart解析器
Spring内置了CommonsMultipartResolver,可以作为StandardServletMultipartResolver的替代方案。
7.2.2 处理multipart请求。已经配置好multipart请求的处理器,那么接下来我们就编写控制器方法来接收上传的文件。要实现这一点,最常见的方法就是在某个控制器方法参数上添加@RequestPart注解。
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/68576.html
摘要:启用安全性这个简单的默认配置指定了如何保护请求,以及客户端认证用户的方案。基于数据库进行认证用户数据通常会存储在关系型数据库中,并通过进行访问。必须经过认证其他所有请求都是允许的,不需要认证。要求用户不仅需要认证,还要具备权限。 Spring Security Spring Security 是基于Spring 应用程序提供的声明式安全保护的安全框架。Spring Sercurity ...
摘要:请求旅程的第一站是的。的任务是将请求发送控制器控制器是一个用于处理请求的组件。处理映射器根据请求携带的信息来进行决策。这样的结果就是,只能找到显示声明在配置类中的控制器。 构建Spring Web应用 说明 如果你有幸能看到。 1、本文参考了《Spring 实战》重点内容,参考了GitHub上的代码 2、本文只为记录作为以后参考,要想真正领悟Spring的强大,请看原书。 3、在一次...
摘要:是的简称,运行环境,为的运行提供了所需的环境。分割字符串,返回分割后的字符串数组。当计算的值相同时,我们称之为冲突,的做法是用链表和红黑树存储相同的值的。迭代器取代了集合框架中的,迭代器允许调用者在迭代过程中移除元素。 Java基础1.JDK和JRE有什么区别? JDK 是java development kit的简称,java开发工具包,提供java的开发环境和运行环境。JRE 是j...
摘要:是一个基于的框架。控制器将视图响应给用户通过视图展示给用户要的数据或处理结果。有了减少了其它组件之间的耦合度。 相关阅读: 本文档和项目代码地址:https://github.com/zhisheng17/springmvc 转载请注明出处和保留以上文字! 了解 Spring: Spring 官网:http://spring.io/ 一个好的东西一般都会有一个好的文档解释说明,如果你...
阅读 1309·2021-11-22 14:44
阅读 2444·2021-09-30 09:47
阅读 1220·2021-09-09 11:56
阅读 2076·2021-09-08 09:45
阅读 3952·2021-08-31 09:40
阅读 1246·2019-08-30 15:52
阅读 2043·2019-08-30 14:09
阅读 1577·2019-08-26 17:04