我正在使用JavaEE
开发一个Web应用程序,我使用JSTL
来呈现我的观点;因为有很多视图和大页面(由ajax加载的Bootstrap样式内容),我决定将我的视图清楚地分成单独的文件夹。我还包括对最大页面模板的部分视图,以保持我的代码可供人阅读。 ;)
所以,这就是问题所在;假设我的文件夹架构看起来像这样:
这是“规则”:
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
,但它似乎仅用于外部资源。
有什么想法吗?
答案 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文件。