首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >已导入页面中的Jsp页面导入:路径问题

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

Stack Overflow用户
提问于 2013-11-21 15:32:15
回答 1查看 983关注 0票数 0

我正在用JavaEE开发一个web应用程序,我正在使用JSTL来呈现我的视图;因为有很多视图和大页面(由ajax加载的引导带样式的内容),所以我决定将我的视图清楚地分离到不同的文件夹中。我还将部分视图包含到最大的页面模板中,以保持代码的可读性。;)

所以,问题来了,假设我的文件夹体系结构是这样的:

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

​

​

​

以下是“规则”:

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

就目前而言,这类代码一切都很好:

view1.jsp

代码语言:javascript
复制
<c:import url="menus/menu1.jsp" />

menu1.jsp

代码语言:javascript
复制
<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" />。

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

view1.jsp

代码语言:javascript
复制
<c:import url="./application/menus/menu1.jsp" />

menu1.jsp

代码语言:javascript
复制
<c:import url="./application/menus/menu2.jsp" />

它将导致更长的URL,但确保路径的有效性;JSTL文档声明它可以导入an absolute or relative URL,但它似乎只用于外部资源。

知道吗?

EN

回答 1

Stack Overflow用户

发布于 2013-11-21 19:53:47

我试图复制你上面解释过的问题,但我没有得到相同的结果。我是从应用程序根目录中的JSP导入文件view1.jsp,必须给它提供view1.jsp文件的完整路径:同样,我也必须对其他导入语句执行相同的操作。

无论如何,我认为您最好使用一个前端控制器来实现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提供服务。

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

代码语言:javascript
复制
    @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);
        }

这是操作的代码。这是定义每个资源如何被切断的地方。

代码语言:javascript
复制
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;      
    }
}

您需要操作界面:

代码语言:javascript
复制
public interface Action {       
    public String execute(HttpServletRequest request, HttpServletResponse response) throws Exception;       
}

抽象动作工厂:

代码语言:javascript
复制
public class AbstractActionFactory {        
    private final static ActionFactory instance = new ActionFactory();  
    private AbstractActionFactory() {}  
    public static ActionFactory getInstance() { 
        return instance;
    }
}

服务AJAX菜单的操作如下所示:

代码语言:javascript
复制
public class MenuAjaxAction implements Action {
    public String execute(HttpServletRequest request, HttpServletResponse response) throws Exception {
        return "/menuajax.jasp";
    }
}

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

menuajax.jsp是这样的:

代码语言:javascript
复制
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix ="c" %>
<c:import url="/WEB-INF/application/view1.jsp" />

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

您可能希望直接从动作servlet (将其从WEB文件中删除)重定向到menu.jsp。

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

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/20125112

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档