文地址:http://blog.longjiazuo.com/archives/1389
这是对springMvc4.x相关特性的一个总结和整理,会有一系列文章,欢迎大家阅读,交流,讨论。
一. 点睛
Spring MVC提供了一个DispatcherServlet来开发Web应用。在Servlet2.5以及以下的时候只要在web.xml下配置元素即可。但下面我们采用Servlet3.0+无web.xml的配置方式,在Spring MVC里面实现WebApplicationInitializer接口便可实现等同于web.xml的配置。
下面将基于Maven搭建零配置的Spring MVC原型项目。
二. 示例
1. 快速构建Maven项目
说明:系列文章的内容有依赖关系,后面章节的内容依赖前面章节内容的配置。为了方便后面内容的讲解,所以构建的是多模块maven项目,公用的依赖配置在父工程的pom.xml文件里面,如果在当前工程的pom文件里面找不到的依赖可以查看父工程的配置,后面的章节也是如此,不再说明。
pom.xml的内容如下:
2. 日志配置
在src/main/resources目录下,新建logback.xml用来配置日志,内容如下:
代码解释:
① 将org.springframework.web包下的类的日志级别设置为DEBUG,我们开发Spring MVC经常出现和参数类型相关的4XX错误。设置此项我们将会看到更详细的错误信息。
3. 演示页面
在src/main/resources下建立views目录,再建其子目录quickStart,并在此目录下新建index.jsp,内容如下:
代码解释:
也许你会问,为什么页面不放在Maven标准的src/main/webapp/WEB-INF下,此处这样建的目的主要是让你习惯Spring Boot的页面习惯的放置方式,Spring Boot的页面就放置在src/main/resources下。
4. Spring MVC配置
代码解释:
此处无任何特别之处,只是一个普通的Spring配置类。这里我配置了JSP的ViewResolver,用来映射路径和实际页面的位置,其中,@EnableWebMvc注解会开启一些默认配置,如一些ViewResolver
或者MessageConverter等。在此处要特别解释一下Spring MVC的ViewResolver,这是Spring MVC视图(JSP下就是html)渲染的核心机制;SpringMVC里有一个接口叫做ViewResolver(所有的ViewResolver都实现该接口),实现这个接口要重写方法resolveViewName(),这个方法的返回值是接口View,而View的职责就是使用model,request,response对象,并将渲染的视图(不一定是html,可能是json,xml,pdf)返回给浏览器,在以后的文章我会介绍更多关于ViewResolver的内容。
可能你会对当前路径前缀配置为/WEB-INF/classes/views/有些奇怪,怎么和我开发的目录不一致?因为我们看到的页面效果是运行时而不是开发时候的代码,运行时代码会将我们的页面自动编译到/WEB-INF/classes/views/下,下图是运行时的目录结构,这样我们就能理解前缀为什么写成这样,在Spring Boot中,使用Thymeleaf作为模板,将不需要这样的设置。
5. Web配置
代码解释:
① WebApplicationInitializer是Spring提供用来配置Servlet3.0+配置的接口,从而实现替代web.xml的位置。实现此接口将会自动被SpringServletContainerInitializer(用来启动Servlet3.0容器)获取到。
② 新建WebApplicationContext,注册配置类,并将其和当前servletContext关联。
③ 注册Spring MVC的DispatcherServlet。
6. 简单控制器
代码解释:
① 利用@Controller注解声明是一个控制器。
② 利用@RequestMapping配置URL和方法之间的映射。
③ 通过上面ViewResolver的Bean配置,返回值为index,说明我们的页面放置的路径为/WEB-INF/classes/views/。
7.运行
将程序部署到Tomcat中,我设置的Tomcat端口是80,现在启动Tomcat,并访问http://localhost/springMvc4.x-quickStart/index,运行结果如下图所示:
三. 源代码示例:
需要阅读和下载源码的朋友请访问原文地址。
图&作者 | YourBatman,CSDN博客专家
责编 | 唐小引
出品 | CSDN(ID:CSDNnews)
前言
千呼万唤始出来!自从官方在 2020-01-20 发布了其 2020 年的 Roadmap 后,我便持续关注着、期待着 JetBrains IntelliJ IDEA 在“新 10 年”的首个版本的发布。这不,就在 4 月 9 日,发布了其“新 10 年”的首个版本 —— IntelliJ IDEA 2020.1。
按照国际惯例,作为大版本号的升级,一般都会“搞点事情”,而事实确实如此(包括了支持中文)。
说明:2020 是 JetBrains 公司成立 20 周年,小伙子是 20 岁的大男孩了。
What’s new(新特性)
IntelliJ IDEA 2020.1 添加了对 Java 14 的支持、为部分 Web 和测试框架添加新功能,通过数据流分析辅助升级了调试器,新增了 LightEdit 模式,以及支持从 IDE 直接下载和配置 JDK 等!
1、支持 Java 14
2020 年 3 月 17 日,Oracle 的 JDK/Java 14 正式 GA(General Available),这是自 Java 采用六个月一次的发布周期后的第五次发布。
“咱们”IDEA 顺序跟上,提供了支持其新特性。除了针对 record 提供完整的代码洞察支持,IDE 还允许用户快速创建新 record,生成其构造函数与组件,以及对既有错误发出警报。另外,IDE 现已支持 instanceof 运算符的模式匹配,其中包括新的检查以及快速修复,后者用简洁明了的新模式变量快速简化了冗长的 instanceof-and-cast 惯用代码。
2、从 IDE 直接下载 JDK
当你还在吐槽现在 JDK 下载起来越来越麻烦的时候,IntelliJ IDEA 此举会不会让你感动到哭?
您无需再从网络中搜索不可或缺的 JDK。从 IntelliJ IDEA 2020.1 开始,在创建并配置项目时,您可以直接从 IDE 下载并配置 JDK 构建。如果您打开下载的项目,IDE 将检查计算机是否安装了为此项目配置的 JDK。如果未安装,IDE 将提示您下载 JDK。当然你也可以自己主动下载:
下载 JDK 的 vendor 源可以有多种可选(木有官方正统的 Oracle 哟~):
3、更好的 Java 代码检查
在 IntelliJ IDEA 的每个新版本中,都会扩展其静态代码分析功能。此版本也不例外。除了上述改进外,还新增了多项代码检查。它们可以检查 SimpleDateFormat 模式中的大写字母,分析日期格式设置,搜索其他冗余方法调用,以及报告并建议消除字符串文字中多余的转义字符等。
4、LightEdit 模式
“轻编辑”模式,用意是用来作为简单的文本编辑器。IntelliJ IDEA 2020.1 增加了期待已久的 LightEdit 模式。如今,用户无需创建或加载整个项目,即可在类似文本的编辑器中快速修改独立文件。您可以从命令行,IDE 的欢迎屏幕或操作系统文件管理器中,在此新的轻量级编辑器中打开文件。此外,使用“Open File in Project” (Alt+Enter) 意图,可以从 LightEdit 模式切换至完整项目模式。
想法是好的,但我感觉有点鸡肋:还要通过命令行模式打开,并且有编辑功能的阉割~
5、Javadoc 渲染
这个小功能本人非常的喜欢,照顾到了爱好读源码一族。在编辑器中阅读 Javadoc 可能令人不胜其烦。此类文本中充斥着各种标记,在需要与参考链接和图像进行交互时,更是雪上加霜。正因如此,IDEA 在编辑器中增加了一种渲染 Javadoc 的方法。通过 Help | Find actions | Render documentation comments on file opening 可以启用此功能。
提个小建议:渲染后就不能鼠标选中 or 复制了,期望可以选中和复制,这样讲课起来做示例会方便很多。
6、改进的导航栏/面包屑栏
这个小功能我也是非常的喜欢,当然我平时使用快捷键会更多,但也还是喜欢此功能。IntelliJ IDEA 2020.1 提供了一种新选项来简化项目导航。新导航栏可以显示 Java 类和接口中的方法,用户无需滚动屏幕,即可直接跳转到需要在文件中查看的行。如果之前很少使用导航栏,那么何不体验一下这项功能。通过 View | Appearance | Navigation Bar 即可将其打开(默认就是打开的)。
7、Zen 模式(禅模式)
很高级有木有,对于快捷键控,平时工作中我个人还挺喜欢使用这种模式编码,投入度高效率就高了。
IntelliJ IDEA 2020.1 在编辑器中引入了新的 Zen 模式。这种模式有助于消除所有干扰项,使您可以专注于源代码。Zen 模式将“免打扰模式”和“全屏模式”完美融合,无需同时开启这两种模式。从主菜单中选择 View | Appearance | Enter Zen Mode,全身心沉浸在代码世界中。
禅模式下的全屏截图如下:
8、调试器:数据流分析辅助
该功能挺不错的,辅助你调试,提高调试效率。
IntelliJ IDEA 2020.1 为 JVM 调试器新增了数据流分析功能。在代码实际执行前,这项功能可对执行情况进行预测。当应用程序在断点处停止时,IDE 将根据程序的当前状态执行数据流分析,检查/预测接下来的运行结果。要在调试器中使用 DFA,请在 Settings/Preferences | Build, Execution, Deployment | Debugger | Data Views | Java 下启用该功能(默认是启用的)。
9、调试器:属性置顶
又是一个非常非常实用的小功能。简单的说,你在调试的时候呢,有些对象的字段太多了,要去找他有时候还要翻页或者下拉很多,一般 IDEA 调试可能要走好多遍代码,你现在在第一次调试后,吧这个调试的字段置顶,以免老是要去找。
10、初步支持 HProf 快照分析
.hprof 文件一般指的是内存快照文件,用于做 JVM 内存溢出分析。之前 IDEA 一般借助 jvisualvm.exe 这个好用的工具来打开/分析此文件,现在 IDEA 内置就支持啦。
IntelliJ IDEA 2020.1 可以打开 .hprof 内存转储文件,这种文件有助于识别内存泄漏,并找到优化内存使用率的方法。例如,您可以查看总体大小、实例数量以及堆栈跟踪等基本文件信息。这些文件还列出了按类分组的所有根对象、按实例数或大小排序的所有类以及带有字段值查看器的所有类实例。
使用 Demo
先使用 jmap -dump:file=test.hprof,format=b 你的 pid 拿到一份 dump 文件:test.hprof。然后使用 IDEA 的此功能把该文件读取进来:
文件读取进来后,可在其“专属视窗”看到分析结果:
需要注意的是:这项功能目前处于早期阶段,功能相对捡漏,后续的主要版本中将继续改进,加入新的功能。
11、Git 交互体验优化
此版本在 Git 的交互体验上做了优化,使得使用起来确实更得心应手了。
新 Commit 工具窗口:
可通过此页面右上角的小齿轮,switch 切换为弹窗模式:
前者若想生效,你需要配置它成为默认的 commit 窗口模式,如下截图所示:
对应的,还会衍生出 Git 其它操作中一些新的交互方式,见下图们:
这个小功能非常赞:可以搜索分支以及刷新啦。
12、改进的 HttpClient 工具
IntelliJ IDEA 2020.1 中的 HTTP 客户端更加智能。现在,它可以正确地自动补全路径变量和 URL 路径,引导用户直接从 HTTP 请求文件访问相关端点。IDEA 还为 Spring 用户提供了一项更新:Spring MVC 处理程序方法现在获得了指示 URL 映射的间距图标。使用它可以创建或打开现有的 HTTP 请求文件并导航到 HTTP 客户端。
13、统一的浅色主题
IntelliJ IDEA 2020.1 将新的浅色主题作为其在所有操作系统中统一使用的默认主题。IntelliJ 推荐你使用!但是像我用习惯了我的“自定义白色系主题”,所以我会切换回来的,看个人习惯喽~
另外它默认使用的 JetBrains Mono 字体,若你不喜欢你也可以改回自己原来的。
此字体据说评价不错,但我习惯了之前的,那就改吧。
14、小彩蛋:支持中文
这算此版本给的一个小彩蛋。需要注意的是:源生是不支持中文的,需要你额外下载 Chinese (Simplified) Language Pack 这个由官方提供的简体中文插件:
汉化后的效果如下:
感谢捷克工程师(可能是由国人实现)对我大天朝程序员的“照顾”,且不说这个必要性到底有多大,但从侧面体现了我国 IT 产业在国际上的分量越来越重了,这是一个好的信号,是我们的骄傲。
由于插件还是 EAP 版本,所以有些地方汉化不是非常彻底,不过绝大部分都是很 OK 的。程序员“老鸟”一定会觉得汉化的 IDE 很 low,但很明显这对新手是非常友好的。
15、其它
更好的框架支持
对 Spring WebFlux、Spring、JMS、RxJava、Swagger Codegen...等最主流框架均做了些许更好的支持,你使用过程中自会体会到的。
对 Docker、Kubernetes 更好支持
为了便于您从 Docke 注册表中拉取映像,此版本重新设计了 UI 并移除了弹出对话框。现在,只需点击 Service 工具窗口左侧窗格中的 Images 节点,IntelliJ IDEA 即可在右侧窗格中打开 Images Console 选项卡,您从中可以轻松拉取映像。IDE 还为映像提供了补全功能。
Kubernetes 方面:通过直接从编辑器间距调用“Apply”命令,您可以更新 Kubernetes 集群,从而匹配在本地文件中定义的状态,使用中自行体会哈。
Maven/Gradle 自动导入更加智能
使用中会体会到。
支持 Scala 3
说明:初步支持,随着 Scala 3 的发展也会逐渐提供更多支持。
拆分 Terminal 终端会话
这个小功能也非常好用。此版本新增了垂直或水平拆分终端会话的功能,便于用户并行运行多个会话。您可以从终端调用上下文菜单来创建、导航和关闭拆分的终端会话。
运行配置可存储到文件
这个小功能非常不错,特别适合团队协作。从 v2020.1 开始,运行配置可以灵活存储于项目文件夹中。为此,请打开 Run/Debug Configurations 对话框,选中右上方的 Store as project file,然后点击齿轮图标。之后将打开一个弹出窗口,您可以在其中选择运行配置的存储位置。
彻底过度到 JBR11 版本
从此版本开始,JetBrains Runtime 8 (JBR8) 已成历史,已彻底过渡到 JetBrains Runtime 11 (JBR11)。
总结
作为 2020 年的第一个版本,有点“跨时代”的意思,带来的新特性们还是可圈可点的。
升级建议:如果你不是“正经付费党”,再次提示你:升级需谨慎哦(当然喽,若纯从使用角度来说,我本人是强烈建议你使用它的)。
最后,依旧要向那些孜孜不倦为 IT 行业提供优秀工具的人们致敬!!!特别是捷克的那些创造者们,你们创造了非常好的工具提高了生产力,推动了社会某些产业的进步,功勋卓越!!!
版权声明:本文为 CSDN 博主「YourBatman」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/f641385712/article/details/105435920
?朱广权李佳琦直播掉线,1.2 亿人在线等
?“抗疫”新战术:世卫组织联合IBM、甲骨文、微软构建了一个开放数据的区块链项目!
?快速搭建对话机器人,就用这一招!
?据说,这是当代极客们的【技术风向标】...
?iPhone 12系列旗舰有望分批发布;美威胁吊销中国电信在美经营许可,外交部发言人回应;VS Code新版发布| 极客头条
今日福利:评论区留言入选,可获得价值299元的「2020 AI开发者万人大会」在线直播门票一张。 快来动动手指,写下你想说的话吧。
喜大普奔啊,果断“在看”一下!
项目中,经常用到的一个功能就是文件的上传和下载,不过大多数情况下都是通用的工具类,自己写的情况较少,这里写个通过Spring框架和ajaxFileUpload插件实现上传的小功能,做个练习和记录。
首先配置下SpringMVC的配置文件,配置支持文件上传
<!-- 配置MultipartResolver 用于文件上传 使用spring的CommosMultipartResolver
说明:
p:defaultEncoding="UTF-8":这里设置默认的文件编码为UTF-8,必须与用户JSP的默认编码一致;
p:maxUploadSize="5000000":指定文件上传大小,单位为字节;
p:uploadTempDir="fileUpload/temp":文件上传临时目录,上传完成后,就会将临时文件删除;
-->
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver"
p:defaultEncoding="UTF-8"
p:maxUploadSize="5000000"
p:uploadTempDir="fileUpload/temp"
>
</bean>
然后写个简单的JSP页面,为了方便绑定数据,引入Spring自带的Form表单标签,引入语句
<%@taglib uri="http://www.springframework.org/tags/form" prefix="form" %>
Form表单实现一个简单的注册功能,虽然说美感不好,这里还是引用了下bootstrap做了个简单的排版。因为原版的file标签的格式无法调整,所有用了其他的小标签代替,然后用按钮去触发file标签
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%
String path=request.getContextPath();
String basePath=request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
request.setAttribute("_path", path);
%>
<%@taglib uri="http://www.springframework.org/tags/form" prefix="form" %>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<base href="<%=basePath%>">
<title>My JSP 'index.jsp' starting page</title>
<meta http-equiv="pragma" content="no-cache">
<meta http-equiv="cache-control" content="no-cache">
<meta http-equiv="expires" content="0">
<meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
<meta http-equiv="description" content="This is my page">
<!--
<link rel="stylesheet" type="text/css" href="styles.css">
-->
<link rel="stylesheet" href="<%=basePath%>static/css/bootstrap.css"/>
<script type="text/javascript" src="<%=basePath%>static/js/jquery.min.js"></script>
<script type="text/javascript" src="<%=basePath%>static/js/ajaxfileupload.js"></script>
<script type="text/javascript" src="<%=basePath%>static/js/bootstrap.js"></script>
<script type="text/javascript" src="<%=basePath%>static/js/jquery.json-2.4.js" charset="UTF-8"></script>
<script type="text/javascript">
var path="${_path}";
$(function(){
/* 重置Form表单功能 */
$("#clean").click(function(){
document.getElementById("user").reset();
$("#userName").attr("value","");
$("#password").attr("value","");
$("#name").attr("value","");
$("#sex").attr("value","");
$("#file").attr("value","");
});
/* begin 附件上功能 */
$("#choose").click(function(){
$("#fileUpload").click();
});
$("#fileUpload").change(function(){
$("#file").attr("value",$("#fileUpload").val());
$.ajaxFileUpload({
type: "POST",
url: path+"/fileUpload.do",
data:{fileName:$("#fileUpload").val()},//要传到后台的参数,没有可以不写
secureuri : false,//是否启用安全提交,默认为false
fileElementId:'fileUpload',//文件选择框的id属性
dataType: 'json',//服务器返回的格式
async : false,
success: function(mes){
if(mes.message=="OK"){
alert("附件上传成功");
}
if(mes.message=="NG"){
alert("附件上传失败");
}
},
error: function (){
alert("附件上传失败");
}
});
});
/* end 附件上功能 */
});
</script>
</head>
<body>
<div class="container" style="width: 100%" >
<div> </div>
<div class="row">
<div class="col-lg-5 col-md-5 col-sm-5 col-xs-5"></div>
<div class="col-lg-1 col-md-1 col-sm-1 col-xs-1" >注册页面</div>
</div>
<div> </div>
<div class="row">
<form:form commandName="user" action="${_path }/register.do" method="post" enctype="multipart/form-data">
<div class="col-lg-4 col-md-4 col-sm-4 col-xs-4"></div>
<div class="col-lg-1 col-md-1 col-sm-1 col-xs-1" style="text-align:right">账号:</div>
<form:input path="userName" type="text" value="" class="input-large"/>
<div> </div>
<div class="col-lg-4 col-md-4 col-sm-4 col-xs-4"></div>
<div class="col-lg-1 col-md-1 col-sm-1 col-xs-1" style="text-align:right">密码:</div>
<form:input path="password" type="password" class="input-large"/>
<div> </div>
<div class="col-lg-4 col-md-4 col-sm-4 col-xs-4"></div>
<div class="col-lg-1 col-md-1 col-sm-1 col-xs-1" style="text-align:right">姓名:</div>
<form:input path="name" type="text" value="" class="input-large"/>
<div> </div>
<div class="col-lg-4 col-md-4 col-sm-4 col-xs-4"></div>
<div class="col-lg-1 col-md-1 col-sm-1 col-xs-1" style="text-align:right">性别:</div>
<form:input path="sex" type="text" value="" class="input-large"/>
<div> </div>
<div class="col-lg-4 col-md-4 col-sm-4 col-xs-4"></div>
<div class="col-lg-1 col-md-1 col-sm-1 col-xs-1" style="text-align:right">附件:</div>
<input id="fileUpload" name="fileUpload" type="file" style=" display: none">
<form:input type="text" class="input-large" path="file" />
<input id="choose" type="button" value="选择" class="btn btn-primary btn-xs"/>
<div> </div>
<div class="col-lg-4 col-md-4 col-sm-4 col-xs-4"></div>
<div class="col-lg-2 col-md-2 col-sm-2 col-xs-2" style="text-align:right">
<input id="upload" type="submit" value="提交" class="btn btn-default btn-sm"/>
<input id="clean" type="button" value="清除" class="btn btn-default btn-sm"/>
</div>
</form:form>
</div>
</div>
</body>
</html>
后台页面控制器,因为用了SpringMVC的form表单,所以在渲染的时候模型中一定要有user这个对象,所以我们用控制器跳转页面
@RequestMapping("/Login.do")
public String Login(@ModelAttribute("user") User user, Model model){
System.out.println("进入");
user.setName("小明");
user.setSex("男");
user.setUserName("叶良辰");
model.addAttribute("user", user);
return "index";
}
这里为了显示SpringMVC form的自动绑定功能,我给user对象设置了值,在JSP页面,如果form:input标签由path属性和user里的属性一样,会自动设置值
附件的js代码在上面的JSP页面中已经写好了,下面是后台控制的controller,因为我们配置了multipartResolver,所以form表单是设置了enctype="multipart/form-data,后台一样能直接取出文本值
接受文本框内容的controller
@RequestMapping("/register.do")
public String register(@ModelAttribute("user") User user, Model model){
model.addAttribute("user", user);
System.out.println(user);
return "index";
}
附件上传的controller
*请认真填写需求信息,我们会在24小时内与您取得联系。