已导入页面中的Jsp页面导入:路径问题

时间:2013-11-21 15:32:16

标签: java-ee import jstl

我正在使用JavaEE开发一个Web应用程序,我使用JSTL来呈现我的观点;因为有很多视图和大页面(由ajax加载的Bootstrap样式内容),我决定将我的视图清楚地分成单独的文件夹。我还包括对最大页面模板的部分视图,以保持我的代码可供人阅读。 ;)

所以,这就是问题所在;假设我的文件夹架构看起来像这样:

  • WEB-INF
    • 应用
      • view1.jsp
      • 菜单
        • menu1.jsp
        • menu2.jsp

这是“规则”:

  • menu1.jsp正在导入menu2.jsp
  • view1.jsp正在导入menu1.jsp

目前,使用这种代码一切都很好:

view1.jsp

<c:import url="menus/menu1.jsp" />

menu1.jsp

<c:import url="menus/menu2.jsp" />

我被迫在第二次导入中添加menus/,因为我发现路径实际上是相对于第一个被调用的页面,所以 view1.jsp

问题在于:menu1.jsp正在定义菜单的结构,可以从页面的第一次加载(当我将响应转发到view1.jsp时)加载,或者通过AJAX。

在第二种情况下(使用ajax),我直接将我的请求转发给menu1.jsp,而不从view1.jsp导入;所以导入的路径(对于menu2.jsp)不正确,因为在这种情况下它应该是<c:import url="menu2.jsp" />

我可以放置一个conditionnal语句,并将另一个属性传递给我定义实际页面并更改导入路径的视图,但我不确定这是否是最佳解决方案。有没有办法在WEB-INF指令中定义相对于根文件夹的路径(例如c:import)?例如,我希望能够做到这一点:

view1.jsp

<c:import url="./application/menus/menu1.jsp" />

menu1.jsp

<c:import url="./application/menus/menu2.jsp" />

这会导致更长的网址,但会确保路径的有效性; JSTL documentation声明它可以导入an absolute or relative URL,但它似乎仅用于外部资源。

有什么想法吗?

1 个答案:

答案 0 :(得分:0)

我试图复制你上面解释的问题,但我没有得到相同的结果。我从应用程序根目录中的JSP导入文件view1.jsp,并且必须为它提供view1.jsp文件的完整路径:<c:import url="/WEB-INF/application/view1.jsp" />同样我必须对其他import语句执行相同的操作。< / p>

无论如何,我认为您最好使用前端控制器实现MVC模式,然后可以负责指导应用程序对资源的所有请求。

我想它的工作方式如下:

前端控制器映射到所有路径“/ *”,因此所有请求(无论路径如何)都将通过控制器。控制器servlet可以检索请求的servlet路径,并在此基础上直接调用适当的资源。使用MVC模式的优点很多,但在您的特定情况下,您将不再需要担心文件的位置,只需专注于提供资源。

例如:控制器接收菜单JSP的AJAX请求。控制器可以确定它是一个AJAX请求,因为它将检索请求的servlet路径,并根据先前配置的操作将请求重定向到菜单。

AJAX请求来自URL www.example.com/resources/ajax/menu,servlet路径为:resources / ajax / menu,因此您提供了menu1.jsp,但是来自页面的请求将类似于www .example.com / resources / menu和servlet路径将是:resources / menu,因此你可以提供view1.jsp。

以下是前端控制器的代码:

    @WebServlet({"/*"})
    public class FrontController extends HttpServlet {

        public FrontController() {
            super();      
        }

        private void processRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException{

            try {
                Action action = AbstractActionFactory.getInstance().getAction(request);
                String view = action.execute(request, response);
                request.getRequestDispatcher(view).forward(request, response);                     
            } catch (Exception e) {
                throw new ServletException("Executing action failed.", e);
            }       

        }

        /**
         * Delegate processing of GET/POST requests to the processRequest method.
         */ 
        protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            processRequest(request, response);
        }

        protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            processRequest(request, response);
        }

以下是操作的代码。您可以在此定义每个资源的切割方式。

public class ActionFactory {

    private Map<String, Action> actions = new HashMap<String, Action>();
    private Action action;

    public ActionFactory() {            
        actions.put("GET/resources/ajax/menu/", new MenuAjaxAction());  
        actions.put("GET/resources/menu/",  new MenuAction());
    }

    public synchronized Action getAction(HttpServletRequest request) throws ActionFactoryException {        
        String path = request.getServletPath();     
        if (path != null || path.length() > 0){ 
            String actionKey = request.getMethod() + path;
            System.out.println(actionKey);
            action = actions.get(actionKey);
            if(action == null){
                action = actions.get("LoginRedirect");
            }
        } else {
            throw new ActionFactoryException();
        }

        return action;      
    }
}

您需要操作界面:

public interface Action {       
    public String execute(HttpServletRequest request, HttpServletResponse response) throws Exception;       
}

抽象行动工厂:

public class AbstractActionFactory {        
    private final static ActionFactory instance = new ActionFactory();  
    private AbstractActionFactory() {}  
    public static ActionFactory getInstance() { 
        return instance;
    }
}

为AJAX菜单提供的操作如下所示:

public class MenuAjaxAction implements Action {
    public String execute(HttpServletRequest request, HttpServletResponse response) throws Exception {
        return "/menuajax.jasp";
    }
}

此操作的目的是让您有机会在转发菜单之前对菜单进行任何预处理。例如,您可以查询数据库,检索一些数据并将其传递给menuajax.jsp视图。如果不需要,则只返回导入菜单文件的JSP的名称。

和menuajax.jsp一样:

<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix ="c" %>
<c:import url="/WEB-INF/application/view1.jsp" />

这似乎有些过分,但MVC模式的优点是通过使用控制器将视图与模型分开。

您可能希望直接从操作servlet(将其从WEB-INF中取出)重定向到menu.jsp。

使用此结构,对应用程序的所有页面/资源的所有请求都将通过前端控制器。无需从HTML页面直接引用服务器上的任何资源。所有这些都将通过前端控制器,前端控制器将根据请求URL的URL(servlet路径)从动作工厂类中选择页面或任何资源,这使得交换资源非常容易,因为所有控制器都在一个中心类文件,而不是1000多个HTML / JSP文件。