我目前正在使用servlet开发一个网站&spring框架。像往常一样,它包含许多文件(jsp, js, css,图像,各种资源等)。我试图避免在任何文件中写入任何硬编码路径或域…
例如,你可能知道当一个请求被处理时,你把它"转发"到一个jsp页面(它的路径可能是硬编码的)。其他的例子是导入图像/css/js等在jsp文件…
有没有什么通用的方法(或工具)来避免硬编码路径/url,这样任何重构都不会造成麻烦?
编辑
我使用netbeans 7.1.2…不幸的是,netbeans只对纯java代码有帮助。当使用jsp文件时,事情是有限的,如果您添加自定义标记文件和jsp 2.0 EL就像在控制台模式下编程:p
在JSP文件本身中,您可以通过使用JSTL
例如,当创建到另一个页面的链接时,您可以这样做:
<a href="<c:url value="/referrals/send.html"/>" target="_blank">Refer an Entrepreneur!</a>
这意味着,无论你的web应用在哪里,链接总是有正确的url。例如,在我的开发框中,该链接将是:
http://localhost:8080/accounts/referrals/send.html
但是在我的生产服务器上,它正确地解析为:
http://wwww.mydomain.com/referrals/send.html
你可以看到,在我的开发服务器中,webapp上下文在/accounts下,但在生产机器中,它只是在/下,因为webapp在根上下文下。
你可以在这里阅读一个小教程
属性文件总是一个很好的选择,这样您只需要在一个点上进行更改。
如果您引用任何静态内容(js, images, css等),则不必硬编码整个文件路径。相反,你可以这样做:-
<img src="${pageContext.request.contextPath}/resources/images/test.jpg"/>
其余的文件路径(Hibernate域映射,Spring控制器中转发的页面等)应该与你的项目结构相关,大多数ide都足够聪明,可以毫无问题地重构它们。或者至少在我的情况下,IntelliJ似乎为我处理了所有这些。
在某些时候,你需要问自己,多少硬编码是可以接受的,多少是不可接受的?此外,我不会试图偏离Spring/Hibernate推荐的解决方案太远。如果你把每件事都做得太抽象,你就会有一组不同的问题需要处理,这会对将来可能继承你的项目的其他同事产生反效果。其实我刚想到一个主意。由于netbeans会分析并显示对java代码的依赖关系,因此最好处理所有路径&域作为Java变量。
我已经在我的项目上创建了一个名为FileResolver的包,并且在我的项目中有一个类用于每个文件类型(例如一个类用于Jsp文件,一个用于Css文件等)。在这些文件中,我会记录&在public static final String变量中硬编码所有文件的所有路径。示例:
public class Jsps {
public class layouts{
public static final String main = "layouts/main.jsp";
}
public class pages{
public static final String error = "pages/error.jsp";
public static final String login = "pages/login.jsp";
public static final String register = "pages/register.jsp";
}
...
}
在我的项目中,我应该使用变量而不是路径。然后,每当我重构一个文件时,我只需要更改一个文件,即这些变量中的映射值……如果我需要更改变量,netbeans将在项目中立即重构所有这些变量……我认为这将工作得很好,因为我保持我的项目干净的文件路径,我唯一要担心的是映射在该文件的变量到适当的文件路径。
编辑
我将编写一个简单的解析器来创建这些java文件,而不是手工编写所有文件…我完成后会更新
更新
这是我的FileResolverGenerator
public class FileResolverGenerator {
private static final String newFilePath = "C:/Users/Foo/Desktop/Jsps.java";
private static final String scanRootFolder = "C:/Users/Foo/Desktop/myProject/web/WEB-INF/jsp";
private static final String varValueReplaceSource = "C:/Users/Foo/Desktop/myProject/web/WEB-INF/jsp/";
private static final String varValueReplaceTarget = "";
private static final boolean valueAlign = true;
private static final int varNameSpaces = 15;
public static void main(String[] args){
try {
// Create file and a writer
File f = new File(newFilePath);
f.createNewFile();
bw = new BufferedWriter( new FileWriter(f) );
// Execute
filesParser( new File(scanRootFolder) );
// 'Burn' file
bw.close();
} catch (FileNotFoundException ex) {
Logger.getLogger(ResolverGenerator.class.getName()).log(Level.SEVERE, null, ex);
} catch (IOException ex) {
Logger.getLogger(ResolverGenerator.class.getName()).log(Level.SEVERE, null, ex);
}
}
// ================================================================================================ //
// ============================================= WORK ============================================= //
// ================================================================================================ //
private static void filesParser(File rootFolder) throws FileNotFoundException, IOException{
folderIn(rootFolder);
// Files first
if(!rootFolder.exists()) throw new FileNotFoundException();
for(File f : rootFolder.listFiles()){
if(f==null){ return; }
if(f.isDirectory()){ continue; }
else if(f.isFile()){ writeFileVariable(f); }
}
// Folders next
for(File f : rootFolder.listFiles()){
if(f==null){ return; }
if(f.isDirectory()){ filesParser(f); }
else if(f.isFile()){ continue; }
}
folderOut(rootFolder);
}
// ================================================================================================ //
// ============================================ PRINTS ============================================ //
// ================================================================================================ //
private static BufferedWriter bw;
private static int tabCount = 0;
private static void folderIn(File f) throws IOException{
bw.append("nn");
for(int i=0; i<tabCount; i++)
bw.append("t");
bw.append("public class "+f.getName()+"{n");
tabCount++;
}
private static void folderOut(File f) throws IOException{
tabCount--;
for(int i=0; i<tabCount; i++)
bw.append("t");
bw.append("}n");
}
private static void writeFileVariable(File f) throws IOException{
String varName = f.getName().split("\.")[0].replaceAll("-", "");
String varValue = f.getPath().replaceAll("\\","/")
.replace(varValueReplaceSource.replaceAll("\\","/"),varValueReplaceTarget.replaceAll("\\","/"));
for(int i=0; i<tabCount; i++)
bw.append("t");
bw.append("public static final String "+varName+" = ");
if(valueAlign){
for(int i=0; i<varNameSpaces-varName.length(); i++) bw.append(" ");
bw.append("t"); }
bw.append("""+varValue+"";n");
}
}
只是为了具体…这将扫描"/WEB-INF/jsp/"下的所有文件,并创建一个java文件,其中所有jsp文件"注册"到每个路径的公共静态final String变量…我们的想法是使用生成的java文件作为项目中所有jsp的参考。总是使用这些变量而不是硬编码的路径。这与项目或任何项目无关。它只是一个拯救你的工具
我还创建了另一个类ResolverConsistencyChecker,它接受所有变量并检查文件路径是否正确(文件存在)…因为我们没有对文件名和文件路径做任何改变,所以所有的测试都通过了。
此方法应在测试项目是否存在"错误"
public class ResolverConsistencyChecker {
private static Class checkClass = Jsps.class;
private static String fullPathPrefix = "C:/Users/Foo/Desktop/myProject/web/WEB-INF/jsp/";
public static void main(String[] args){
try {
filesChecker( checkClass );
System.out.println( "Tests passed. All files locations are valid" );
} catch (FileNotFoundException ex) {
Logger.getLogger(ResolverConsistencyChecker.class.getName()).log(Level.SEVERE, null, ex);
} catch (IOException ex) {
Logger.getLogger(ResolverConsistencyChecker.class.getName()).log(Level.SEVERE, null, ex);
}
}
// ================================================================================================ //
// ============================================= WORK ============================================= //
// ================================================================================================ //
private static void filesChecker(Class rootClass) throws FileNotFoundException, IOException{
// Check file paths in current class depth
for(Field f : rootClass.getFields()){
try {
String fullFilePath = fullPathPrefix+f.get(f.getName()).toString();
File file = new File( fullFilePath );
if( !file.exists() )
throw new FileNotFoundException("Variable: '"+f.getName()+"'nFile "+fullFilePath);
} catch (IllegalArgumentException ex) {
Logger.getLogger(ResolverConsistencyChecker.class.getName()).log(Level.SEVERE, null, ex);
} catch (IllegalAccessException ex) {
Logger.getLogger(ResolverConsistencyChecker.class.getName()).log(Level.SEVERE, null, ex);
}
}
// Check for embedded classes
for(Class c : rootClass.getClasses()){
filesChecker(c);
}
}
}