- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
谁能解释一下在 Tomcat 中对 ServletContext getRealPath() 的以下两次调用之间的区别是什么:
context.getRealPath("/") + "\\songModified.wav";
context.getRealPath("/"+ "\\songModified.wav");
我在服务器上有一个非常简单的 GET 方法,它读取服务器上的文件并将字节复制到上述调用返回的位置的新文件中。
在客户端,我有一个引用服务器上音频文件的音频标签,调用此方法创建一个新文件并将音频标签的引用更改为这个新文件。问题是,在 javascript 回调中,如果我将文件存储到从上述 getRealPath 调用的第二种情况返回的路径,则不能立即引用这个新文件。基本上它返回一个 404。如果我将它存储到第一个调用案例的返回路径中,那么它立即可引用并且音频标签通常引用新文件。
这两个对 getRealPath() 的调用都返回完全相同的字符串:
C:\Users\Mihael\apache-tomcat-9.0.31\wtpwebapps\AudioSimulator\songModified.wav
我将这个返回的字符串进一步传递给代码中的 FileOutputStream 构造函数。
这里要注意的是,在调用 getRealPath() 时该文件不存在,所以我很困惑为什么在调用的第二种情况下它根本不返回任何内容。
我知道这不是推荐的文件存储方式,所以我是从纯粹的教育角度提问的。如果第二次调用此方法都向其余代码返回完全相同的字符串,怎么会破坏我的功能?
编辑:
这是一个非常简单的 Javascript 和 Java 代码,供任何想要测试它的人使用。
Javascript:
<body>
<script>
function modifyRequest() {
var xhttp = new XMLHttpRequest();
xhttp.onload = function() {
var audio = document.getElementById("player");
var currentTime = audio.currentTime;
audio.src = "http://localhost:8080/AudioSimulator/bluesModified.wav";
audio.currentTime = currentTime;
audio.play();
};
xhttp.open("GET", "http://localhost:8080/AudioSimulator/rest/Test/testPath");
xhttp.send();
}
</script>
<audio id="player" src="http://localhost:8080/AudioSimulator/blues.wav"
controls>
Your browser does not support the
<code>audio</code> element.
</audio>
<button onclick="modifyRequest()">Test</button>
</body>
java :
@Path("/Test")
public class Test {
@Context
ServletContext context;
@GET
@Path("/testPath")
public Response testPath() {
File fileIn = new File(context.getRealPath("/") + "\\blues.wav");
File fileOut = new File(context.getRealPath("/" + "\\bluesModified.wav"));
//if i write it like this it would work
//File fileOut = new File(context.getRealPath("/") + "\\bluesModified.wav");
FileInputStream fis = null;
FileOutputStream fos = null;
try {
fis = new FileInputStream(fileIn);
fos = new FileOutputStream(fileOut);
byte[] inArray = new byte[(int) fileIn.length()];
try {
fis.read(inArray);
fos.write(inArray);
} catch (IOException e) {
e.printStackTrace();
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} finally {
try {
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
try {
fis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return Response
.ok()
.entity("Success")
.header("Access-Control-Allow-Origin", "null")
.build();
}
}
最佳答案
我已花时间深入 Tomcat 源代码以找出造成这种情况的原因。事实证明,getRealPath
除了为给定的虚拟 路径检索系统路径外,还可以与 Tomcat 缓存一起使用。
注意:
我知道我的文件分隔符使用不当,但 Tomcat 足够聪明,可以验证上述调用以生成 /bluesModified.wav
。因此,即使我像评论中提到的 @rickz 那样调用它,结果也是一样的,因此这不是问题所在。
在以下调用的情况下我无法引用该文件的问题
context.getRealPath("/" + "\\bluesModified.wav")
事实上,在这种情况下,我们将文件路径传递给方法,而在可行的情况下,我们将传递目录路径。
调用 getRealPath()
首先检查缓存中是否存在由 webapppath /bluesModified.wav
标识的资源。由于在调用时它不存在,Tomcat 将创建一个 EmptyResource
类的实例,它基本上是 File
类的包装器,代表一个不存在的文件存在,然后它会将对该文件的引用存储在其缓存中。
这里的问题是,即使我创建了一个具有正确虚拟路径的文件,Tomcat 仍然会在其缓存中拥有代表不存在文件的空资源。换句话说,如果我像这样从客户端引用文件
http://localhost:8080/AudioSimulator/bluesModified.wav
Tomcat 将返回表示空文件的缓存资源,这实际上意味着一个404
给客户端,即使该文件存在。
等待 5 秒,这是 Tomcat 缓存条目的生存时间,然后尝试引用该文件将重新验证缓存条目并生成 FileResource
而不是 EmptyResource
在这种情况下引用将正常工作。
在这种情况下有效
context.getRealPath("/") + "\\bluesModified.wav"
因为被缓存的路径是一个目录,文件名只是简单地连接在一起。所以我这里的字符串只是我要创建的文件的绝对路径,没有缓存条目与之冲突。
我的错误是假设 getRealPath()
只是一些“纯”方法,它将返回一个字符串,我可以用它来创建文件,但实际上它有一些副作用。这些副作用没有记录在案,即使我可能做错了一些事情,但底线是这种方法在执行文件 IO 时使用起来并不那么可预测。
关于java - 上下文 getRealPath() 用于不存在的文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60554328/
出现以下错误 Network access for Distributed Transaction Manager (MSDTC) has been disabled. Please enable D
在调试应用程序时出现以下错误。 The CLR has been unable to transition from COM context 0x3b2d70 to COM context 0x3b2
在 GAE Go 中,为了记录,我们需要使用 appengine.NewContext(r) 创建一个新的上下文,它返回 context.Context。 如何使用此上下文在请求范围内设置/获取变量?
我想使用 Puppeteer 从放置在页面上 iframe 内的选择器中获取数据,该页面在与其父框架域不同的域上运行。因此,我不是任何域的所有者 - 无法使用 frame.postMessage。 试
我正在尝试获取可用的应用程序上下文并想切换到 webview 上下文,但 appium 仅获取 Navive App。 应用程序还启用了 WebView。 Appium 版本:1.10.1 Chrom
这个问题在这里已经有了答案: How to fix this nullOk error when using the flutter_svg package? (7 个回答) 7 个月前关闭。 当我尝
我观看了关于 Core Data 的 2016 WWDC 视频并查看了各种教程。我见过使用 Core Data Framework 创建对象以持久保存到 managedObjectContext 中的
这是代码 obj = { a: 'some value'; m: function(){ alert(this.a); } } obj.m(); 结果是'som
我正在尝试做类似的事情 $(".className").click(function() { $(this).(".anotherClass").css("z-index","1");
var User = { Name: "Some Name", Age: 26, Show: function() { alert("Age= "+this.Age)}; }; fun
我目前正在使用我见过的常见 Context 模式,它允许子组件通过传递修饰函数来更新父组件的状态(即 Provider)通过共享的 Context。 我遇到的问题是,修改函数只引用原始状态,不引用最新
有没有办法让 React Context类型安全与流类型? 例如: Button.contextTypes = { color: React.PropTypes.string }; 最佳答案 不幸
我想知道是否有一种方法可以为不同的功能使用不同的上下文类。 我希望有一个功能使用 MinkExtensions 进行浏览器测试,另一个功能使用和 HTTP 客户端(如 Guzzle)进行 API 测试
我有这个配置文件 apiVersion: v1 clusters: - cluster: server: [REDACTED] // IP of my cluster name: stag
我在实现非抢先式调度时遇到了用于初始化TCB的代码。 typedef struct TCB_t { struct TCB_t *next; struct TCB_t
我想将一个函数设置为数组中每个元素的属性,但使用不同的参数调用它。我想我会使用匿名函数来解决它: for ( var i = 0; i < object_count; i++ ) { obje
这个问题已经有答案了: How to access the correct `this` inside a callback (15 个回答) 已关闭 7 年前。 我正在做一些练习,但我在管道方法中丢
我正在尝试通过 Java 和 Android Studio 学习和制作 Android 应用程序。我对Java的了解程度是两年前几个小时的youtube学习和大学基础类(class)。不过我确实知道如
我在(这个)上遇到了问题。错误ImageView无法应用。我在 fragment 类中执行此代码。 ViewFlipper v_flipper; @Nullable @Override public
我想使用 openGL 的某些功能,但与渲染视觉内容无关。有没有办法在没有任何依赖性的情况下创建它(不是对 Windows,也不是某些包[SDL,SFML,GLUT])?只允许使用没有外部库的库,就像
我是一名优秀的程序员,十分优秀!