我知道类似以下三行

<%= x+1 %>
<%= request.getParameter("name") %>
<%! counter++; %>

是一种老式的编码方式,在JSP版本2中存在一种避免JSP文件中出现Java代码的方法。什么是可选的JSP2行,这种技术叫什么?


当前回答

无论您如何努力避免,当您与其他开发人员合作时,他们中的一些人仍然会选择scriptlet,然后将邪恶代码插入到项目中。因此,如果您真的想要减少scriptlet代码,那么在第一个标志处设置项目是非常重要的。有几种方法可以克服这个问题(包括其他提到的几种框架)。但是,如果您喜欢纯JSP方式,那么可以使用JSTL标记文件。这样做的好处是,您还可以为项目设置母版页,这样其他页面就可以继承母版页

在WEB-INF/标记下创建一个名为base.tag的母版页,内容如下

<%@tag description=“总体页面模板”pageEncoding=“UTF-8”%><%@attribute name=“title”fragment=“true”%><html><head><标题><jsp:invokefragment=“title”></jsp:invoke></title></head><body><div id=“page header”>....</div><div id=“page body”><jsp:doBody/></div><div id=“page footer”>.....</div></body></html>

在这个主页面上,我创建了一个名为“title”的片段,这样在子页面中,我可以在主页面的这个位置插入更多代码。此外,标记<jsp:doBody/>将被子页面的内容替换

在WebContent文件夹中创建子页面(child.jsp):

<%@taglib prefix=“t”tagdir=“/WEB-INF/tags”%><t:基础><jsp:attribute name=“title”><bean:messagekey=“hello.world”/></jsp:attribute><jsp:body>[将您的孩子内容放在这里]</jsp:body></t:基础>

<t:base>用于指定要使用的母版页(此时为base.tag)。此处标记<jsp:body>中的所有内容将替换母版页上的<jsp:doBody/>。您的子页面还可以包含任何标记库,您可以像前面提到的其他页面一样正常使用它。但是,如果在这里使用任何scriptlet代码(<%=request.getParameter(“name”)%>…)并尝试运行此页面,您将得到一个JasperException,因为此处不允许脚本元素(&lt;%!,&lt;jsp:declaration,&lt!%=,&lt;jsp:expression,&lt:%,&lt,jsp:scriptlet)。因此,其他人无法将恶意代码包含到jsp文件中

从控制器调用此页面:

您可以从控制器轻松调用child.jsp文件。这也适用于struts框架

其他回答

在JSP中使用scriptlets不是一种好的做法。

相反,您可以使用:

JSTL标签EL表达式自定义标记-您可以定义自己要使用的标记。

请参考:

http://docs.oracle.com/javaee/1.4/tutorial/doc/JSTL3.html电子邮箱

JSTL为条件、循环、集合、get等提供标记。例如:

<c:if test="${someAttribute == 'something'}">
   ...
</c:if>

JSTL与请求属性一起工作——它们通常由Servlet在请求中设置,Servlet转发到JSP。

自2001年taglibs(如JSTL)和EL(表达式语言,那些${}的东西)诞生以来,在JSP中使用scriptlets(那些<%%>的东西)确实非常不受欢迎。

scriptlets的主要缺点是:

可重用性:不能重用scriptlets。可替换性:不能使scriptlets抽象。OO能力:你不能利用继承/组合。可调试性:如果scriptlet中途抛出异常,则只会得到一个空白页面。可测试性:scriptlets不是可单元测试的。可维护性:每个saldo需要更多的时间来维护混合/杂乱/重复的代码逻辑。

Sun Oracle本身也建议在JSP编码约定中避免在(标记)类可能具有相同功能时使用scriptlet。以下是几个相关的例子:

根据JSP1.2规范,强烈建议在web应用程序中使用JSP标准标记库(JSTL),以帮助减少页面中对JSP脚本的需求。通常,使用JSTL的页面更容易阅读和维护。...如果可能,只要标记库提供了等效的功能,就避免使用JSP脚本。这使得页面更易于阅读和维护,有助于将业务逻辑与表示逻辑分开,并将使您的页面更容易演变为JSP 2.0风格的页面(JSP 2.0规范支持但不强调scriptlets的使用)。...本着采用模型-视图-控制器(MVC)设计模式来减少表示层与业务逻辑之间的耦合的精神,JSP脚本不应用于编写业务逻辑。相反,如果需要,可以使用JSP脚本将处理客户端请求返回的数据(也称为“值对象”)转换为适合客户端的格式。即使这样,使用前端控制器servlet或自定义标记也会更好。


如何替换scriptlet完全取决于代码/逻辑的唯一目的。这段代码通常被放在一个完整的Java类中:

如果您希望在每个请求中调用相同的Java代码,无论请求的页面是多少,例如,检查用户是否登录,那么实现一个过滤器并在doFilter()方法中相应地编写代码。例如。:public void doFilter(ServletRequest请求、ServletResponse响应、FilterChain链)抛出ServletException、IOException{if(((HttpServletRequest)请求).getSession().getAttribute(“user”)==null){((HttpServletResponse)响应).sendRedirect(“登录”);//未登录,重定向到登录页面。}其他{chain.doFilter(请求,响应);//已登录,请继续请求。}}当映射到覆盖感兴趣的JSP页面的适当的<url模式>时,就不需要复制粘贴整个JSP页面的同一段代码。如果您想调用一些Java代码来处理GET请求,例如,从数据库中预加载一些列表以显示在某个表中,如果需要,可以基于一些查询参数,然后实现一个servlet并在doGet()方法中相应地编写代码。例如。:protected void doGet(HttpServletRequest请求,HttpServletResponse响应)throws ServletException,IOException{尝试{List<Product>products=productService.List();//获取所有产品。request.setAttribute(“products”,products);//将产品存储在请求范围内。request.getRequestDispatcher(“/WEB-INF/products.jsp”).forward(请求,响应);//转发到JSP页面以在HTML表中显示它们。}catch(SQLException e){抛出新的ServletException(“检索产品失败!”,e);}}这种处理异常的方法更容易。数据库不是在JSP呈现过程中访问的,而是在显示JSP之前访问的。您仍然可以在DB访问引发异常时更改响应。在上面的示例中,将显示默认的错误500页面,您可以通过web.xml中的<errorpage>自定义该页面。如果您想调用一些Java代码来处理POST请求,例如从提交的HTML表单中收集数据并使用它进行一些业务处理(转换、验证、保存在DB中等),那么就实现一个servlet并在doPost()方法中相应地编写代码。例如。:protected void doPost(HttpServletRequest请求,HttpServletResponse响应)throws ServletException,IOException{字符串username=request.getParameter(“username”);字符串密码=request.getParameter(“password”);用户User=userService.find(用户名、密码);if(用户!=空){request.getSession().setAttribute(“user”,用户);//登录用户。response.sendRedirect(“home”);//重定向至主页。}其他{request.setAttribute(“message”,“未知用户名/密码。请重试。”);//将错误消息存储在请求范围中。request.getRequestDispatcher(“/WEB-INF/login.jsp”).forward(请求,响应);//转发到JSP页面以重新显示出现错误的登录表单。}}这种处理不同结果页目的地的方法更容易:在出现错误时重新显示带有验证错误的表单(在这个特定的示例中,您可以使用EL中的${message}重新显示它),或者在成功时只需转到所需的目标页。如果您想调用一些Java代码来控制执行计划和/或请求和响应的目标,那么根据MVC的Front Controller Pattern实现servlet。例如。:受保护的void服务(HttpServletRequest请求、HttpServletResponse响应)引发ServletException、IOException{尝试{Action Action=ActionFactory.getAction(请求);字符串视图=action.execute(请求,响应);if(view.equals(request.getPathInfo().substring(1)){request.getRequestDispatcher(“/WEB-INF/”+view+“.jsp”).forward(请求,响应);}其他{response.sendRedirect(视图);}}catch(异常e){抛出新ServletException(“执行操作失败。”,e);}}或者只是采用一个MVC框架,如JSF、Spring MVC、Wicket等,这样您最终只需要一个JSP/Facelets页面和一个JavaBean类,而不需要定制servlet。如果您想调用一些Java代码来控制JSP页面内的流,那么需要获取一个(现有的)流控制标记库,如JSTL核心。例如,在表格中显示列表<产品>:<%@taglib uri=“http://java.sun.com/jsp/jstl/core“prefix=”c“%>”...<表><c:forEach items=“${products}”var=“product”><tr><td>${product.name}</td><td>${product.description}</td><td>${product.price}</td></tr></c:forEach></table>由于XML样式的标记非常适合所有HTML,因此代码的可读性(因此可维护性更好)比带有各种大括号和大括号(“这个大括号到底属于哪里?”)的一堆scriptlet要好。一个简单的帮助是,通过向web.xml添加以下部分,配置web应用程序,以便在仍然使用scriptlet时抛出异常:<jsp配置><jsp属性组><url模式>*.jsp</url模式><脚本无效>true</脚本无效></jsp属性组></jsp配置>在Facelets(JSP的继承者)中,它是JavaEE提供的MVC框架JSF的一部分,已经不可能使用scriptlets。这样你就自动被迫以“正确的方式”做事。如果您想调用一些Java代码来访问和显示JSP页面中的“后端”数据,那么您需要使用EL(表达式语言),这些${}的东西。例如,重新显示提交的输入值:<input-type=“text”name=“foo”value=“${param.foo}”/>${param.foo}显示request.getParameter(“foo”)的结果。如果您想直接在JSP页面中调用一些实用程序Java代码

另请参见:

JSP、Servlet和JSF之间有什么区别?Servlet、ServletContext、HttpSession和HttpServletRequest/Response是如何工作的?使用JSP、Servlet和JDBC的基本MVC示例Java web应用程序中的设计模式JSP/Servlet的隐藏特性

通过将JSTL标记与EL表达式一起使用,可以避免这种情况。在JSP页面中放置以下内容:

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt" %>

为了避免JSP文件中的Java代码,Java现在提供了标记库,如JSTL。

此外,Java还推出了JSF,您可以将所有编程结构以标记的形式写入其中。