我在Tomcat 7中将一个Web应用程序部署为WAR文件.该应用程序构建为一个多模块项目:
通常,我们可以将JSP文件放在webapp项目中,并相对于上下文引用它们:
/WEB-INF/jsp/someMagicalPage.jsp
Run Code Online (Sandbox Code Playgroud)
问题是我们如何处理特定于客户扩展项目的JSP文件,这些文件不应始终包含在WAR中.不幸的是,我看不到JAR文件中的JSP.尝试classpath:jsp/customerMagicalPage.jsp
在JspServlet中找不到的文件,因为它使用了ServletContext.getResource()
.
传统上,我们"解决"了maven解包客户扩展JAR,定位JSP,并在构建它时将它们放入WAR中.但理想的情况是,您只需在Tomcat中的爆炸WAR中放置JAR并发现扩展 - 这适用于除JSP之外的所有内容.
反正有没有解决这个问题?标准方式,特定于Tomcat的方式,黑客还是变通方法?例如,我一直在考虑在应用程序启动时解压缩JSP ...
我正在使用JAX WS来公开WebService.此服务的某些操作可能会生成异常.不是内部服务器异常,而是依赖于操作调用的输入参数的异常.
如果我指定我的操作抛出自定义异常,如下所示:
@WebService
@SOAPBinding(style = Style.RPC, use = Use.LITERAL)
public class MyServiceEndpointImpl implements MyServiceEndpoint {
@WebMethod
public void throwsException throws InvalidInputException;
}
Run Code Online (Sandbox Code Playgroud)
运行应用程序时,我最终得到以下堆栈跟踪:
com.sun.xml.ws.model.RuntimeModelerException: runtime modeler error: Wrapper class com.mypackage.ws.services.jaxws.InvalidInputExceptionBean is not found. Have you run APT to generate them?
at com.sun.xml.ws.model.RuntimeModeler.getClass(RuntimeModeler.java:285)
at com.sun.xml.ws.model.RuntimeModeler.processExceptions(RuntimeModeler.java:1006)
at com.sun.xml.ws.model.RuntimeModeler.processRpcMethod(RuntimeModeler.java:969)
at com.sun.xml.ws.model.RuntimeModeler.processMethod(RuntimeModeler.java:546)
at com.sun.xml.ws.model.RuntimeModeler.processClass(RuntimeModeler.java:370)
at com.sun.xml.ws.model.RuntimeModeler.buildRuntimeModel(RuntimeModeler.java:256)
at com.sun.xml.ws.server.EndpointFactory.createSEIModel(EndpointFactory.java:322)
at com.sun.xml.ws.server.EndpointFactory.createEndpoint(EndpointFactory.java:188)
at com.sun.xml.ws.api.server.WSEndpoint.create(WSEndpoint.java:467)
at org.jvnet.jax_ws_commons.spring.SpringService.getObject(SpringService.java:333)
at org.jvnet.jax_ws_commons.spring.SpringService.getObject(SpringService.java:45)
at org.springframework.beans.factory.support.FactoryBeanRegistrySupport$1.run(FactoryBeanRegistrySupport.java:121)
Run Code Online (Sandbox Code Playgroud)
添加@XmlRootEntity
到InvalidInputException
不解决问题.
如果这不是报告Web服务故障的推荐方法,那么有更好的方法吗?我的异常是应该继承RuntimeException
并依赖于传输进行错误处理(即,所有内容最终都将包含在SOAPException中)?我希望有类似Spring-WS的东西SoapFaultAnnotationExceptionResolver
.是否有类似的东西可用于JAX-WS?
我遇到了一些非常基本但今天非常困惑的事情.我需要将列表转换为数组.该列表包含String
实例.完美的使用示例List.toArray(T[])
,因为我想要一个String[]
实例.但是,如果没有明确地将结果转换为,它将无法工作String[]
.
作为测试场景,我使用了以下代码:
import java.util.Arrays;
import java.util.List;
public class MainClass {
public static void main(String args[]) {
List l = Arrays.asList("a", "b", "c");
String stuff[] = l.toArray(new String[0]);
System.err.println(Arrays.asList(stuff));
}
}
Run Code Online (Sandbox Code Playgroud)
哪个不编译.它几乎是javadoc中示例的精确副本,但编译器说如下:
MainClass.java:7: incompatible types
found : java.lang.Object[]
required: java.lang.String[]
String stuff[] = l.toArray(new String[0]);
^
Run Code Online (Sandbox Code Playgroud)
如果我添加一个强制转换String[]
它将编译并运行完美.但是当我查看toArray方法的签名时,这不是我所期望的:
<T> T[] toArray(T[] a)
Run Code Online (Sandbox Code Playgroud)
这告诉我,我不应该投.到底是怎么回事?
编辑:
奇怪的是,如果我将列表声明更改为:
List<?> l = Arrays.asList("a", "b", "c");
Run Code Online (Sandbox Code Playgroud)
它也有效.或者List<Object>
.所以它不一定List<String>
是建议的.我开始认为使用原始List
类型也会改变该类中泛型方法的工作方式.
第二次编辑:
我想我现在明白了.Tom …
将域对象用作映射(或"获取"方法)的键是一种好习惯,还是仅使用域对象的id更好?
用一个例子解释起来比较简单.假设我有Person类,Club类和Membership类(连接其他两个).也就是说,
public class Person {
private int id; // primary key
private String name;
}
public class Club {
private String name; // primary key
}
public class Membership {
private Person person;
private Club club;
private Date expires;
}
Run Code Online (Sandbox Code Playgroud)
或类似的东西.现在,我想getMembership
向Club 添加一个方法.问题是,如果此方法采用Person对象:
public Membership getMembership(Person person);
Run Code Online (Sandbox Code Playgroud)
或者,一个人的身份:
public Membership getMembership(int personId);
Run Code Online (Sandbox Code Playgroud)
哪个是最惯用的,哪个最方便,哪个最合适?
编辑:很多非常好的答案.我没有暴露id,因为"人"(你可能已经意识到,我的真实域名与人和俱乐部没有任何关系......)实例很容易获得,但现在它在内部存储一个HashMap在id上进行了哈希 - 但至少我在接口中正确地公开了它.
我在"aspectj"模式下使用Spring的声明式事务(@Transactional注释).它在大多数情况下都可以完全像它应该的那样工作,但对于其中一个它没有.我们可以称之为Lang
(因为这就是它实际上所称的).
我已经能够确定加载时间织布机的问题.通过打开aop.xml中的debug和verbose日志记录,它列出了所有正在编织的类.Lang
根本没有在日志中提到有问题的类.
然后我在顶部放置了一个断点Lang
,导致Eclipse在Lang
加载类时挂起线程.当LTW编织其他类时,这个断点被击中!所以我猜测它要么编织也要Lang
失败并且不输出,或者其他一些类有一个引用强制它Lang
在实际有机会编织它之前加载.
我不确定如何继续调试这个,因为我无法以较小的规模重现它.有关如何继续的任何建议?
更新:其他线索也欢迎.例如,LTW实际上如何运作?似乎有很多魔法发生.是否有任何选项可以从LTW获得更多的调试输出?我目前有:
<weaver options="-XnoInline -Xreweavable -verbose -debug -showWeaveInfo">
Run Code Online (Sandbox Code Playgroud)
我忘了汤姆之前提到它:弹簧剂被用来允许LTW,即InstrumentationLoadTimeWeaver
.
根据Andy Clement的建议,我决定检查AspectJ变压器是否甚至通过了这门课程.我放了一个断点ClassPreProcessorAgent.transform(..)
,看起来这个Lang
类甚至都没有到达那个方法,尽管它被与其他类(Jetty的WebAppClassLoader的一个实例)相同的类加载器加载.
然后我接着断了一个断点InstrumentationLoadTimeWeaver$FilteringClassFileTransformer.transform(..)
.甚至没有一个被击中Lang
.我相信应该为所有加载的类调用该方法,无论他们使用什么类加载器.这开始看起来像:
Lang
在Eclipse报告时没有加载接下来的线索:我打开了-verbose:class
,看起来好像Lang
是过早加载 - 可能是在变压器添加到Instrumentation之前.奇怪的是,我的Eclipse断点没有捕获到这个加载.
这意味着Spring是新的嫌疑人.在ConfigurationClassPostProcessor
负载类中似乎有一些处理来检查它们.这可能与我的问题有关.
这些行ConfigurationClassBeanDefinitionReader
导致Lang
类被读取:
else if (metadata.isAnnotated(Component.class.getName()) ||
metadata.hasAnnotatedMethods(Bean.class.getName())) {
beanDef.setAttribute(CONFIGURATION_CLASS_ATTRIBUTE, CONFIGURATION_CLASS_LITE);
return true;
}
Run Code Online (Sandbox Code Playgroud)
特别是对类的metadata.hasAnnotatedMethods()
调用getDeclaredMethods()
,它加载该类中所有方法的所有参数类.我猜这可能不是问题的结束,因为我认为这些类应该被卸载.JVM是否可以出于不可知的原因缓存类实例?
我试图相对于输入字段定位一个span元素(让我们称之为"工具提示跨度").为此,我将工具提示范围和输入字段包装在另一个span元素中(让我们称之为"包装器跨度")position: relative
.然后我设置position: absolute
工具提示跨度.这使得工具提示跨度位置本身相对于包装器跨度,但不是页面流的一部分 - 不占用任何空间.这正是我想要的.
然后,使用javascript,我设置工具提示相对于输入元素位置的位置.由于输入元件可以不同在不同的页面被成形(脚本应globablly适用),我使用其offsetTop
和offsetLeft
属性,以计算相对于所述包装跨度其位置.
但是,我注意到这里的浏览器之间存在不一致.在Firefox,IE6,7,8中,它按预期工作.但在Chrome和Safari中,报道offsetTop
似乎是错误的.
为了证明这一点,我在下面创建了测试页面:
<html>
<head>
<style type="text/css">
span { font-size: 8px; position: relative; top: 0; left: 0; border: 1px solid red }
</style>
</head>
<body>
<span id="wrapper">
<input id="foo" name="foo" type="text">
</span>
<script type="text/javascript">
document.write("<br>Offset parent: " + document.getElementById("foo").offsetParent.id);
document.write("<br>Offset top: " + document.getElementById("foo").offsetTop);
</script>
</body>
</html>
Run Code Online (Sandbox Code Playgroud)
并将其加载到Firefox和Chrome中.两个浏览器都报告包装器范围offsetParent
,但对于Firefox,它offsetTop
是-8,对于Chrome,它是2.视觉上,两个浏览器中的页面呈现相同.
这让我很头疼,因为当我有人使用Chrome时,我不能只使用不同的偏移,因为如果我改变字体大小,offsetTop
则不会改变,我的脚本会破坏.
这是一个错误吗?我能解决这个问题吗?
避免死锁的通常建议是始终以相同的顺序锁定资源.但是,对于高度满足的Oracle数据库中的行锁,您将如何实现这一点?
要了解我的意思,请考虑以下示例.一个非常简单的DAO来处理银行账户:
@Component
public class AccountDao {
@Resource
private DataSource dataSource;
public void withdraw(String account, int amount) {
modifyBalance(account, -amount);
}
public void deposit(String account, int amount) {
modifyBalance(account, amount);
}
private void modifyBalance(String account, int amount) {
try {
Connection connection = DataSourceUtils.getConnection(dataSource);
PreparedStatement statement = connection
.prepareStatement("update account set balance = balance + ? where holder = ?");
statement.setInt(1, amount);
statement.setString(2, account);
statement.execute();
}
catch (SQLException e) {
throw new RuntimeException(e);
}
}
}
Run Code Online (Sandbox Code Playgroud)
要在两个帐户之间执行传输,有某种InternalBankTransfer
类具有传输方法:
public …
Run Code Online (Sandbox Code Playgroud) 我正在使用具有贫血域模型的遗留系统.
域名具有以下实体classses: ,Car
,CarType
,.CarComponent
CarComponentType
对于其中的每一个,都有一个单独的存储库.还有许多服务可以访问这些存储库并且基本上包含所有逻辑.
我需要实现一个方法来确定CarComponentType
供应商是否可以停止使用.逻辑如下:只有当前没有现有汽车的组件才能停止组件.
最初,我在服务类中实现了它.
public boolean canBeDiscontinued(CarComponentType carComponentType) {
List<Car> cars = carRepository.getCarsWithComponent(carComponentType);
return cars.isEmpty();
}
Run Code Online (Sandbox Code Playgroud)
这有效 - 但是这个逻辑在代码中的其他几个地方使用.它可能会增长,它看起来像是适合类内的东西CarComponentType
:
public boolean canBeDiscontinued() {
List<Car> cars = carRepository.getCarsWithComponent(this);
return cars.isEmpty();
}
Run Code Online (Sandbox Code Playgroud)
但是,我不能把它放在那里,因为它需要访问存储库(据我所知,它是一个非常严重的反模式,实体要知道数据访问层).加载组件类型时,我无法加载该类型的所有汽车,因为这可能是数千个对象.我们没有使用任何ORM,所以制作一个懒惰的加载集合不仅体积大,而且非常容易出错.
像我第一次在服务类中实际使用此方法更合适吗?这不重要吗?还有另一种选择吗?我应该从另一个起点开始重构吗?
还有一个类似的问题在这里.但是我的问题与Java有关,所以我不认为这个解决方案适用于我的情况.此外,提前抱歉使用汽车和组件作为我的域模型.:)
我有一个在JBoss中运行的Java应用程序,我在其中启用了JMX远程监控.这允许我连接jconsole和visualvm等工具来监视内存使用情况,cpu利用率,mbeans等.运行我的应用程序的服务器具有限制性端口访问权限,这就是我使用JSR-262 JMX WS Connector的原因.
JSR-262实现有一个如何为jconsole启用jmx:ws协议的示例.但我想尝试使用visualvm.
我认为我必须做的是,在启动visualvm时:
有人能指出我正确的方向吗?有没有一种机制可以为visualvm提供额外的参数?它会起作用吗?还有更简单的方法吗?
java ×8
css ×2
html ×2
web-services ×2
aop ×1
arrays ×1
aspectj ×1
deadlock ×1
javascript ×1
jax-ws ×1
jdbc ×1
jmx ×1
jsp ×1
list ×1
oop ×1
oracle ×1
refactoring ×1
repository ×1
servlets ×1
spring-aop ×1
tiles ×1
tomcat ×1
visualvm ×1