这是一个将在Tomcat 7.0上运行的servlet。该应用程序非常繁忙。
我们所做的是以下内容:
public void processRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//get the path {/api/login}
String requestPath = request.getRequestURI().substring(request.getRequestURI().indexOf(getServletConfig().getServletContext().getContextPath()) + getServletConfig().getServletContext().getContextPath().length());
//get the responder class {mobi.foo.base.api.login}
Class<? extends Responder> responderClass = Class.forName("mobi.foo.base"+requestPath.replaceAll("/", ".")).asSubclass(Responder.class);
//initialize a responder using reflection
Responder responder = responderClass.newInstance();
//print the response
PrintWriter out = response.getWriter();
out.write(responder.respond());
out.close();
}
所以在第一次,我倾向于接受这个,因为它不计入瓶颈。换句话说,即使它相对较慢,它的便利性也超过了它引入的相当微不足道的开销:我们正在讨论可能访问数据库的http请求!
我是对的吗?我只是想了解其他人&#39;对此有所了解。
答案 0 :(得分:2)
答:使用分析器来衡量在关注代码中花费的时间百分比。如果时间百分比很大,那么优化它。否则不要。
当然,我们无法对您进行明确的量化&#34;重要的&#34;。它实际上取决于实际成本。例如,如果你有一个webapp实例并且大部分时间都是轻载,那么性能提升1%很可能是不值得的。另一方面,如果你有成千上万的这个程序副本在数千台服务器上运行,那么性能提升1%可能是值得的......只是减少你的电费。
可以优化吗?
我认为你不太可能加速。用class.forName
查找工厂对象替换newInstance()
和HashMap
等,每次调用 1 可能会节省一些微秒的时间。那个可能相当于一个显着的加速......但我对此表示怀疑。
但我认为@JBNizet正在提出重要观点。这里存在潜在的安全问题。解决该问题将是对此代码进行大修的合理原因。
1 - 加载类的成本会随着请求类型的重复而摊销。当您为之前加载的类调用class.forName
时,类加载器只需查找并返回现有的Class
对象。
答案 1 :(得分:0)
如果你的respond()方法只使用方法变量(不是类字段),你可以创建响应者并将其放在响应者池中并重复使用它,而不是每次都创建它。
基本上是这样的:
//get the path {/api/login}
String requestPath = request.getRequestURI().substring(request.getRequestURI().indexOf(getServletConfig().getServletContext().getContextPath()) + getServletConfig().getServletContext().getContextPath().length());
//get the responder class {mobi.foo.base.api.login}
String responderName = "mobi.foo.base"+requestPath.replaceAll("/", ".");
Responder responder = responderMap.get(responderName);
if (responder == null) {
Class<? extends Responder> responderClass = Class.forName("mobi.foo.base"+requestPath.replaceAll("/", ".")).asSubclass(Responder.class);
//initialize a responder using reflection
Responder responder = responderClass.newInstance();
responderMap.put(responderName, responder);
}
//print the response
PrintWriter out = response.getWriter();
out.write(responder.respond());
out.close();
其中responderMap是保存在ServletContext中的Map<String, Responder>
类型的映射,或者作为单例提供。