我们正在使用Eclipse构建一个(Java)Web项目.默认情况下,Eclipse Cp1252在Windows机器上使用编码(我们使用).
由于我们在中国也有开发人员(除了欧洲),我开始怀疑这是否真的是要使用的编码.
我最初的想法是转换为UTF-8,因为"它支持所有字符集".但是,这真的很明智吗?我们应该选择其他编码吗?我看到几个问题:
1)Web浏览器如何解释默认情况下的文件?它取决于使用的语言版本吗?我在这里说的是,我们应该详细声明所使用的编码方案:
<?xml version='1.0' encoding='UTF-8' ?>声明来详细设置编码.@CHARSET "UTF-8";.<meta http-equiv="Content-Script-Type" content="text/javascript; charset=utf-8">或<script type="text/javascript" charset="utf-8">使用特定脚本.如果我们离开CSS文件而没有@CHARSET "UTF-8";声明怎么办?浏览器如何确定它的编码方式?
2)是否明智使用UTF-8,因为它是非常灵活.通过将我们的代码锁定Cp1252(或者可能ISO-8859-1),我可以确保外国开发人员不会在文件中引入特殊字符.这有效地阻止了他们插入中文评论,例如(我们应该使用100%英语).此外,允许UTF-8有时会让开发人员意外地引入一些奇怪的角色,这些角色很难/不可能被人眼察觉.这种情况发生在人们,例如,复制粘贴文本或碰巧意外按下某些奇怪的键盘组合时.
似乎在项目中允许UTF-8只会带来问题......
3)对于国际化,我最初认为UTF-8是一件好事("如果文件编码不支持所需的字符,你如何添加翻译?").但是,事实证明,Java Resource Bundles(.properties文件)必须使用ISO-8859-1进行编码,否则它们可能会中断.相反,国际字符被转换为\uXXXX符号,例如\u0009,文件编码ISO-8859-1.所以...我们甚至无法使用UTF-8.
对于二进制文件......好吧,编码方案并不重要(我想可以说它甚至不存在).
我们该如何处理这些问题?
我们的一个产品实现了以下单向Web服务结构:
Server <--------------------- Middleware <---------------- Client
SOAP over JMS (queue) SOAP over HTTP
Run Code Online (Sandbox Code Playgroud)
在此模型中,客户端通过HTTP将SOAP消息发送到我们的中间件(Progress SonicMQ).消息被SonicMQ推送到JMS队列,我们的服务器从那里获取它们.但是,正如您所看到的,服务器不会向客户端发送响应(异步JMS).
我们希望为此模型实现响应通道.通常建议的解决方案是在中间件中创建临时replyTo-queue(动态),允许服务器向该队列发送响应.然后,客户端可以获取响应并关闭replyTo队列.这听起来很方便,但不幸的是我们的客户端通过纯HTTP而不是JMS运行,因此他们的客户端无法轻松设置replyTo队列.
在这种混合HTTP/JMS SOAP模型中实现响应通道的一种方法是配置中间件以在每个成功的SOAP接收上打开replyTo队列,将replyTo-queue和sender信息附加到SOAP消息并将消息推送到队列,服务器将获取它.在接收并处理消息之后,服务器可以向中间件中的指示的replyTo队列发送响应.最后,中间件将通过使用SOAP消息中的数据(在首次接收请求时在中间件过程中插入的数据)通过HTTP将响应(SOAP)发送回原始客户端.
虽然有可能,但这听起来有点像hacky.所以问题是:在我们的案例中实现这种请求/响应模型的任何更清晰的方法?服务器端已用Java实现.
解决方案:
Progress SonicMQ支持"内容回复发送"HTTP Acceptor,它允许轻松发送JMS回复.内容回复发送接受器以下列方式工作:
如果消费者(在我们的情况下是"服务器")失败并且没有发送回复导致超时,Sonic的HTTP Acceptor会向客户端发送HTTP消息,指示超时.这是SonicMQ中非常标准的功能.我想它也存在于其他产品中.
这允许在"服务器"端使用标准SOAP over JMS(参见skaffman的答案),避免在中间件中进行任何自定义编程.
我仍然在JMS模型中看到一些问题,但这肯定是一种改进.
更新2009-11-05:
在研究了这个问题之后,事实证明我对HTTP < - >中间件< - > JMS的怀疑是相关的.
这个模型中存在一些关键问题.具有中间件的同步异步模型简单不方便.要么两端都实现JMS连接(应该摇摆),要么两端都使用HTTP.混合它们只会导致头痛.在这两者中,SOAP-over-HTTP比SOAP-over-JMS更简单,更受支持.
再一次:如果你正在设计这种系统......不要.
我发现"集成测试"的概念令人困惑.似乎有不少解释和范围:
我开始将集成测试视为一个总括性术语(而不是在编程讲座中定义它,其中通常给出特定/严格的含义):
在Maven默认生命周期中,只有"测试"和"集成测试"阶段.这似乎将测试分为大致两类,并与这些假设一致.
一般来说,有许多现有的问题和答案正在寻找单元测试,功能测试,回归测试等之间的差异.但是,我正在寻找有关集成测试的更具体的答案:您如何对集成测试进行分类,以及您在其中包含哪些内容?另外,您是否将软件测试大致分为两类:单元测试(1个单元)与集成测试(2个单元)?
我试图控制哪些文件进入由mvn package目标创建的WAR包.具体来说,我想从src/main/resources每个包的默认文件夹中排除一些文件(我正在尝试为不同的环境进行构建/包).
我尝试使用maven-war-plugin但失败了.如果我添加此配置(用于测试):
<webResources>
<resource>
<directory>src/main/resources</directory>
<targetPath>WEB-INF/classes</targetPath>
<excludes>
<exclude>*.xml</exclude>
</excludes>
</resource>
</webResources>
Run Code Online (Sandbox Code Playgroud)
...我WEB-INF/classes仍然会包含XML文件.这是因为webResources参数似乎复制了复制过程(上面的配置实际上有效,文件不会被复制......但是它们会被复制到其他一些进程中).
所有Maven 2项目的默认资源目录是src/main/resources,它们将最终出现在目标/类和WAR中的WEB-INF/classes中.目录结构将在此过程中保留.
WAR插件还能够通过webResources参数包含默认资源目录中找不到的资源.
这有点令人困惑.这是否意味着:
webResources参数是maven-war-plugin中的一项功能,它允许文件仅包含在外部src/main/resources文件夹中?如果是这样,我们如何从内部改变复制的文件src/main/resources?webResources参数是Maven的战争插件,使文件的功能将包括也从外部src/main/resources文件夹?如果是这样,如何配置来执行此操作?我试图覆盖渲染器h:selectBooleanCheckbox(由于这里解释的原因):
但是,我发现无法注册我的渲染器.我试过在我的声明中声明faces-config.xml:
<render-kit>
<renderer>
<component-family>javax.faces.SelectBoolean</component-family>
<renderer-type>javax.faces.Checkbox</renderer-type>
<renderer-class>com.myapp.CustomCheckboxRenderer</renderer-class>
</renderer>
</render-kit>
Run Code Online (Sandbox Code Playgroud)
我抓住的价值观:
javax.faces.component.html.HtmlSelectBooleanCheckboxjavax.faces.component.html.SelectBooleanCheckboxTag但它不起作用.
我也试过详细宣布RenderKit:
<description>Custom renderers</description>
<render-kit-id>???</render-kit-id>
<render-kit-class>com.sun.faces.renderkit.RenderKitImpl</render-kit-class>
Run Code Online (Sandbox Code Playgroud)
但正如你所看到的,我真的不知道在哪里获取价值render-kit-id或者render-kit-class无论如何都是正确的.
在Mojarra包内有文件,jsf-ri-runtime.xml但它没有声明渲染器.它只声明一个RenderKitFactory,我根本不会直接找到任何感兴趣的内容.
指针?
我指的是相当深的对象层次结构,在EL中有相当神秘的名字#{myBean.configBaseStack.excludeMethodFromAccounting.method.TimeoutBehaviorEnabled}.
我想通过类似的别名指向这个相同的属性:
<x:alias name="m" value="#{myBean.configBaseStack.excludeMethodFromAccounting.method" />
<h:inputText value="#{m.TimeoutBehaviorEnabled}" />
Run Code Online (Sandbox Code Playgroud)
我想有一种方法可以在支持bean中创建这些别名,但我宁愿把它留给模板.
如何在模板/ facelet级别完成此操作?
将字典设置为ContextVar默认:
var: ContextVar[dict] = ContextVar('var', default={})
Run Code Online (Sandbox Code Playgroud)
...有点有效,因为字典默认可用,但它始终引用相同的实例,而不是为每个上下文生成一个新实例。
contextvars 是否以某种方式支持工厂(对于字典、列表等),如下所示:
var: ContextVar[dict] = ContextVar('var', default=list)
var: ContextVar[dict] = ContextVar('var', default=lambda: dict())
Run Code Online (Sandbox Code Playgroud)
或者我只需要手动完成:
var: ContextVar[Optional[dict]] = ContextVar('var', default=None)
...
if not var.get():
var.set({})
Run Code Online (Sandbox Code Playgroud) 考虑一个虚拟案例:
<h:form id="wrapperForm">
<h:panelGroup id="rowsContainer">
<h:dataTable id="rowsTable" value="#{bean.rows}" var="row" >
<h:column>
<h:commandButton value="Click me to update (#{component.parent.parent.parent.clientId})">
<f:ajax render=":#{component.parent.parent.parent.clientId}" />
</h:commandButton>
</h:column>
</h:dataTable>
</h:panelGroup>
</h:form>
Run Code Online (Sandbox Code Playgroud)
单击按钮,id=rowsContainer可以按原样成功更新.
但是,如果我在ui:repeat那里添加它,它就不再起作用了:
<h:form id="wrapperForm">
<ui:repeat id="blocksRepeat" var="block" value="#{bean.blocks}">
<h:panelGroup id="rowsWrapper">
<h:dataTable id="rowsTable" value="#{block.rows}" var="row" >
<h:column>
<h:commandButton value="Click me 2 update (#{component.parent.parent.parent.clientId})">
<f:ajax render=":#{component.parent.parent.parent.clientId}" />
</h:commandButton>
</h:column>
</h:dataTable>
</h:panelGroup>
</ui:repeat>
</h:form>
Run Code Online (Sandbox Code Playgroud)
相反,这得到:
<f:ajax> contains an unknown id ':wrapperForm:blocksRepeat:0:rowsWrapper' - cannot locate it in the context of the component j_idt363
Run Code Online (Sandbox Code Playgroud)
但是,该组件确实存在该ID,因此EL应该没问题.不知何故ui:repeat …
考虑自定义 UIComponent(仅用于测试目的):
public class UITest extends UIComponentBase {
@Override
public void encodeBegin(FacesContext context) throws IOException {
System.out.println("encodeBegin");
}
@Override
public void encodeAll(FacesContext context) throws IOException {
System.out.println("encodeAll");
}
}
Run Code Online (Sandbox Code Playgroud)
当我将它添加到复合组件内的页面时,该encodeBegin()方法被调用。但是,当将它添加到复合组件外部的页面时,该encodeAll()方法会被调用。
将它添加到其他 UIComponents 中没有区别,只有复合组件包装器似乎会改变行为。
找不到信息为什么会这样?规范的链接?
让我们有一个非常简单的复合组件:
<cc:implementation>
#{testBean.someField}
</cc:implementation>
Run Code Online (Sandbox Code Playgroud)
豆为它:
public class TestBean {
private boolean someField = false;
public boolean getSomeField() { return someField; }
@PostConstruct
public void init() {
System.out.println("PostConstruct");
}
}
Run Code Online (Sandbox Code Playgroud)
然后像往常一样调用它但不显示它:
<codeEditor:test rendered="#{false}" />
Run Code Online (Sandbox Code Playgroud)
发生的事情是组件永远不会被渲染,并且bean永远不会像人们想象的那样被启动.
但是,如果我们将组件更改为:
<cc:implementation>
<h:outputText value="#{testBean.someField}" />
</cc:implementation>
Run Code Online (Sandbox Code Playgroud)
发生的事情是组件仍然永远不会被渲染(因为rendered属性是false),但是,bean确实被实例化了.出现这种情况总是当我们用一个bean属性一些本地的JSF组件内部(h:panelGroup,h:inputHidden,等等).
为什么会这样?