1

我目前正在使用 servlet 和 spring 框架开发一个网站。像往常一样,它包含很多文件(jsp、js、css、图像、各种资源等)。我试图避免在任何文件中写入任何硬编码路径或域......

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

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

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

4

4 回答 4

1

在 JSP 文件本身中,您可以通过使用来避免几乎所有硬编码的域/urlJSTL

例如,当创建指向另一个页面的链接时,您可以这样做:

<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 位于根上下文下。

你可以在这里阅读一个小教程

于 2013-01-14T12:47:58.917 回答
1

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

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

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

在某个时间点,您需要问自己,有多少硬编码是可以接受的,多少是不可接受的?此外,我不会试图偏离 Spring/Hibernate 推荐的解决方案太远。如果你把所有的东西都弄得太抽象,你就会有一组不同的问题需要处理,而且对于将来可能继承你项目的其他同行来说,这会适得其反。

于 2013-01-14T12:49:00.547 回答
1

属性文件始终是一个不错的选择,因此您必须在某一点进行更改(如果有的话)。

于 2013-01-14T12:52:45.193 回答
0

其实我只是想出了一个主意。由于 netbeans 会分析并显示对 java 代码的依赖关系,因此将所有路径和域作为 java 变量处理可能会更好。

我在我的项目上创建了一个名为 FileResolver 的包,在里面我为项目中的每种文件类型都有一个类(例如,一个类用于 Jsp 文件,一个用于 Css 文件等)。在这些文件中,我将在公共静态最终字符串变量中记录和硬编码所有文件的所有路径。样本:

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);
        }
    }

}
于 2013-01-14T13:19:25.713 回答