消除Web开发中的硬编码文件路径和URL

时间:2013-01-14 12:27:58

标签: java file jsp path hardcoded

我目前正在开发一个使用servlets& amp;弹簧框架。像往常一样,它包含大量文件(jsp,js,css,图像,各种资源等)。 我试图避免在任何文件中编写任何硬编码路径或域...

例如,您可能知道何时处理请求,您将其“转发”到jsp页面(它的路径可能会被硬编码)。其他示例是在jsp文件中导入images / css / js等...

是否有任何通用方法(或工具)来避免硬编码路径/网址,因此任何重构都不会造成麻烦?

修改
我使用netbeans 7.1.2 ...不幸的是netbeans只对纯java代码有帮助。当使用jsp文件时,事情是有限的,如果你添加自定义标记文件和Jsp 2.0 EL就像在控制台模式下编程:p

4 个答案:

答案 0 :(得分:1)

在JSP文件本身中,您可以使用JSTL

来避免几乎所有硬编码的域/网址

例如,在创建指向其他页面的链接时,您可以这样做:

<a href="<c:url value="/referrals/send.html"/>" target="_blank">Refer an Entrepreneur!</a>

这意味着,无论您的webapp在哪里,链接都将始终具有正确的URL。例如,在我的开发框中,此链接将是:

http://localhost:8080/accounts/referrals/send.html

但是在我的生产服务器上,它正确解析为:

http://wwww.mydomain.com/referrals/send.html

你可以看到,在我的开发服务器中,webapp上下文位于/ accounts下,但是在生产机器上,它位于/根据webapp在根上下文中。

您可以阅读一个小教程here

答案 1 :(得分:1)

如果要引用任何静态内容(js,images,css等),则不必对整个文件路径进行硬编码。相反,你可以这样做: -

<img src="${pageContext.request.contextPath}/resources/images/test.jpg"/>

其余的文件路径(Hibernate域映射,Spring控制器中的转发页面等)应该与您的项目结构相关,并且大多数IDE都足够聪明,可以毫无问题地重构它们......或者至少在我的情况下,IntelliJ似乎为我处理了所有这些。

在某些时候,您需要问自己,有多少硬编码是可以接受的而不是可接受的?此外,我不会试图偏离Spring / Hibernate推荐的解决方案。如果你使一切都过于抽象,你就会遇到一系列不同的问题,这对于将来可能继承你的项目的其他同行来说会适得其反。

答案 2 :(得分:1)

属性文件始终是一个不错的选择,因此您只需要在一个点上进行更改。

答案 3 :(得分:0)

其实我刚想出了一个主意。由于netbeans进行分析并显示对java代码的依赖性,因此可能最好处理所有路径&amp;域作为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("\n\n");
        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文件'已注册'为公共静态最终字符串变量与每个路径...的想法是使用生成的java文件作为项目中所有jsps的参考...总是使用这些变量而不是硬编码路径.. 这与项目或任何项目无关。它只是一个拯救你的工具 时间,而不是手动为项目中的每个文件执行此操作。

我还创建了另一个类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);
        }
    }

}