当前位置:  开发笔记 > 编程语言 > 正文

如何避免JSP文件中的Java代码?

如何解决《如何避免JSP文件中的Java代码?》经验,为你挑选了23个好方法。

我是Java EE的新手,我知道类似以下三行

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

是一种旧式的编码方式,在JSP版本2中,存在一种避免JSP文件中的Java代码的方法.有人可以告诉我替代的JSP 2行,以及这种技术的名称是什么?



1> BalusC..:

使用小脚本(那些<% %>在东西)JSP确实是高度自诞生气馁标签库(如JSTL)和EL(表达式语言,那些${}东西),早在2001年.

scriptlet的主要缺点是:

    可重用性:您无法重用scriptlet.

    可替换性:您不能使scriptlet抽象化.

    OO-ability:你不能利用继承/组合.

    可调试性:如果scriptlet中途抛出异常,你得到的只是一个空白页面.

    可测试性: scriptlet不是可单元测试的.

    可维护性:每个saldo需要更多时间来维护混杂/混乱/重复的代码逻辑.

Sun Oracle本身也建议在JSP编码约定中避免在(标记)类可能的情况下使用scriptlet.以下是几个相关的引用:

从JSP 1.2规范,强烈建议JSP标准标签库(JSTL)在Web应用程序中使用,以帮助减少对JSP小脚本需要在你的页面.通常,使用JSTL的页面更易于阅读和维护.

...

尽可能在标记库提供等效功能时避免使用JSP scriptlet.这使页面更容易阅读和维护,有助于业务逻辑从表示逻辑分离,将使您的网页更容易演变成JSP 2.0风格的页面(JSP 2.0规范支持,但去强调使用脚本小程序).

...

本着采用模型 - 视图 - 控制器(MVC)设计模式以减少表示层与业务逻辑之间的耦合的精神,JSP scriptlet不应用于编写业务逻辑.相反,如果需要,可以使用JSP scriptlet将从处理客户端请求返回的数据(也称为"值对象")转换为适当的客户端就绪格式.即使这样,使用前端控制器servlet或自定义标签也可以做得更好.


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

如果要在每个请求上调用相同的 Java代码,不管请求的页面是否少于或多,例如检查用户是否已登录,则实现过滤器并在方法中相应地编写代码.例如:doFilter()

public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws ServletException, IOException {
    if (((HttpServletRequest) request).getSession().getAttribute("user") == null) {
        ((HttpServletResponse) response).sendRedirect("login"); // Not logged in, redirect to login page.
    } else {
        chain.doFilter(request, response); // Logged in, just continue request.
    }
}

当映射到适当的覆盖JSP页面时,那么你不需要在整个JSP页面中复制相同的代码片段.


如果要调用某些Java代码来预处理请求,例如,从数据库预加载某些列表以显示在某个表中,必要时根据某些查询参数,然后实现servlet并在doGet()方法中相应地编写代码.例如:

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    try {
        List products = productService.list(); // Obtain all products.
        request.setAttribute("products", products); // Store products in request scope.
        request.getRequestDispatcher("/WEB-INF/products.jsp").forward(request, response); // Forward to JSP page to display them in a HTML table.
    } catch (SQLException e) {
        throw new ServletException("Retrieving products failed!", e);
    }
}

这种处理异常的方式更容易.在JSP渲染过程中不会访问DB,但是在JSP显示之前.每当数据库访问引发异常时,您仍然可以更改响应.在上面的示例中,将显示默认错误500页面,您可以通过输入进行自定义web.xml.


如果要调用某些Java代码来处理请求,例如处理表单提交,则实现servlet并在doPost()方法中相应地编写代码.例如:

protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    String username = request.getParameter("username");
    String password = request.getParameter("password");
    User user = userService.find(username, password);

    if (user != null) {
        request.getSession().setAttribute("user", user); // Login user.
        response.sendRedirect("home"); // Redirect to home page.
    } else {
        request.setAttribute("message", "Unknown username/password. Please retry."); // Store error message in request scope.
        request.getRequestDispatcher("/WEB-INF/login.jsp").forward(request, response); // Forward to JSP page to redisplay login form with error.
    }
}

这样处理不同的结果页面目标更容易:在出现错误的情况下重新显示带有验证错误的表单(在此特定示例中,您可以${message}在EL中重新显示它),或者只是在成功的情况下转到所需的目标页面.


如果要调用某些Java代码来控制请求和响应的执行计划和/或目标,则根据MVC的前端控制器模式实现servlet.例如:

protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    try {
        Action action = ActionFactory.getAction(request);
        String view = action.execute(request, response);

        if (view.equals(request.getPathInfo().substring(1)) {
            request.getRequestDispatcher("/WEB-INF/" + view + ".jsp").forward(request, response);
        } else {
            response.sendRedirect(view);
        }
    } catch (Exception e) {
        throw new ServletException("Executing action failed.", e);
    }
}

或者只是采用一个MVC框架,如JSF,Spring MVC,Wicket等,这样你最终只需要一个JSP/Facelets页面和一个JavaBean类,而不需要自定义的servlet.


如果要调用某些Java代码来控制 JSP页面内的流,那么您需要获取(现有的)流控制标记库,如JSTL核心.例如List,在表格中显示:

<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
...

        
${product.name} ${product.description} ${product.price}

使用XML样式的标签非常适合所有HTML,代码比具有各种打开和关闭括号的一堆scriptlet更好的可读性(因此更易于维护)("这个闭合括号属于哪个?").一个简单的帮助是配置您的Web应用程序,以便在仍然使用scriptlet时抛出异常,方法是将以下部分添加到web.xml:


    
        *.jsp
        true
    

在Facelets的,JSP的继任者,这是Java EE提供的MVC框架的一部分JSF,它已经能够使用小脚本.这样你就会被迫以"正确的方式"做事.


如果要调用某些Java代码来访问和显示 JSP页面中的"后端"数据,那么您需要使用EL(表达式语言)这些${}东西.例如,重新显示提交的输入值:


${param.foo}显示器的结果request.getParameter("foo").


如果要直接在JSP页面中调用某些实用程序 Java代码(通常是public static方法),则需要将它们定义为EL函数.JSTL中有一个标准函数taglib,但您也可以自己轻松创建函数.以下是JSTL如何fn:escapeXml有效防止XSS 攻击的示例.

<%@ taglib uri="http://java.sun.com/jsp/jstl/functions" prefix="fn" %>
...

请注意,XSS灵敏度绝不与Java/JSP/JSTL/EL /无关,在您开发的每个 Web应用程序中需要考虑此问题.scriptlet的问题在于它无法提供内置预防,至少不使用标准Java API.JSP的后继者Facelets已经隐式HTML转义,因此您不必担心Facelets中的XSS漏洞.

也可以看看:

JSP,Servlet和JSF有什么区别?

Servlet,ServletContext,HttpSession和HttpServletRequest/Response如何工作?

JSP,Servlet和JDBC的基本MVC示例

Java Web应用程序中的设计模式

JSP/Servlet的隐藏功能


+1很棒的答案.但是不要去教条,有时使用scriptlet是可以的,但这应该是证明规则的例外.
@svachon:我用自己的javabean类包装这些类,然后使用它们.
这是一个非常好的答案,但doGet和doPost部分是误导性的.这些方法用于处理特定请求(HEAD,GET和POST)方法,不用于"预处理"或"后处理"请求!
@svachon:Scriptlet对于快速原型设计/测试非常有用.据我所知,只有一个"合法"生产使用了一个scriptlet,即`<%response.getWriter().flush(); 在``和``之间的`>,以改善webbrowser中的网页解析性能.但是,当服务器端的输出缓冲区大小较低(1~2KB)时,这种使用又完全可以忽略不计.[另见本文](http://balusc.blogspot.com/2009/09/webapplication-performance-tips-and.html#FlushTheBufferEarly).
@BalusC有几次我一直坚持使用不遵循getter/setter模式的java类.恕我直言,这是一个scripltet完成工作的情况.
@Met:我解释的方式对于不了解HTTP如何工作的初学者来说是最明确的;)实际上,基于HTML表单的Web应用程序通常也是如此.例如,如果您正在考虑RESTful,那么我对该部分的解释当然没有意义.

2> Stefan Schub..:

作为安全措施:禁用Scriptlets for Good

正如另一个问题所讨论的那样,您可以并且始终应该在web.xmlWeb应用程序描述符中禁用scriptlet .

我总是这样做是为了防止任何开发人员添加scriptlet,特别是在大型公司中,您迟早会丢失概述.该web.xml设置是这样的:


  
    *.jsp
     true
  


@MrSpoon找到了你的答案.根据[此答案+评论](http://stackoverflow.com/questions/5890192/what-are-the-effects-of-disabling-scripting-in-a-jsp#comment6776514_5890208),这将关闭scriptlet"< %%>`,scriptlet表达式`<%!%>`和scriptlet声明`<%=%>`.这意味着指令`<%@%>`和注释`<% - - %>`保持启用和可用,因此您仍然可以执行注释和包含.
这是否也会禁用scriptlet注释?:`<% - 在最终的HTML中我不想要的注释 - %>`.我发现使用这些而不是HTML注释很有用.
禁用scriptlet指令会很糟糕 - 修剪空白对于与遗留额外空格的遗留系统进行交互是非常宝贵的.

3> Bozho..:

JSTL为条件,循环,集合,获取等提供标签.例如:


   ...

JSTL使用请求属性 - 它们通常由Servlet设置在请求中,Servlet 转发到JSP.


为什么你说JSTL与请求属性一起工作?他们可以在任何范围内使用属性,不是吗?

4> tzim..:

我不确定我是否正确.

你应该阅读一些关于MVC的内容.Spring MVC和Struts 2是两种最常见的解决方案.


使用上述许多技术,没有Spring或Struts,可以使用servlets/jsp实现MVC.
它如何回答这个问题?

5> Lambda..:

您可以将JSTL标记与EL表达式一起使用,以避免混合使用Java和HTML代码:

<%@ 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" %>

    
    
    

        
        
        // and so on

    



6> 小智..:

还有基于组件的框架,如Wicket,可以为您生成大量的HTML.最终在HTML中的标签非常基本,并且几乎没有混合的逻辑.结果几乎是空的HTML页面,具有典型的HTML元素.缺点是Wicket API 中有很多组件需要学习,有些事情在这些限制条件下很难实现.



7> 小智..:

在MVC架构模式中,JSP表示View层.在JSP中嵌入Java代码被认为是一种不好的做法.您可以将JSTL,freeMarker,velocity用JSP作为"模板引擎".这些标记的数据提供者取决于您正在处理的框架.Struts 2并且webwork作为MVC Pattern的实现使用OGNL "非常有趣的技术将Beans Properties暴露给JSP".



8> Thorbjørn Ra..:

经验表明,JSP有一些缺点,其中一个难以避免将标记与实际代码混合在一起.

如果可以的话,请考虑使用专门的技术来完成您的工作.在Java EE 6有JSF 2.0,它提供了很多不错的功能,包括通过JSF页面粘合的Java bean在一起#{bean.method(argument)}的方法.


旧的答案,但我不禁要说JSF是Java空间中最恐怖的发明之一。尝试建立单个(类似于HTTP GET)链接,您将了解原因。

9> tomasb..:

学习使用JSTL自定义和编写自己的标签

请注意,EL是EviL(运行时异常,重构)
Wicket也可能是邪恶的(性能,对于小应用程序或简单视图层来说很难)

来自java2s的示例,

必须将其添加到Web应用程序的web.xml中


    /java2s
    /WEB-INF/java2s.tld

在/ WEB-INF /中创建File:java2s.tld





    1.0
    1.2
    Java2s Simple Tags

    
    
        bodyContentTag
        com.java2s.BodyContentTag
        JSP
        
          howMany
        
    

将以下代码编译为WEB-INF\classes\com\java2s

package com.java2s;

import java.io.IOException;
import javax.servlet.jsp.JspWriter;
import javax.servlet.jsp.tagext.BodyContent;
import javax.servlet.jsp.tagext.BodyTagSupport;

public class BodyContentTag extends BodyTagSupport{
    private int iterations, howMany;

    public void setHowMany(int i){
        this.howMany = i;
    }

    public void setBodyContent(BodyContent bc){
        super.setBodyContent(bc);
        System.out.println("BodyContent = '" + bc.getString() + "'");
    }

    public int doAfterBody(){
        try{    
            BodyContent bodyContent = super.getBodyContent();
            String bodyString  = bodyContent.getString();
            JspWriter out = bodyContent.getEnclosingWriter();

            if ( iterations % 2 == 0 ) 
                out.print(bodyString.toLowerCase());
            else
                out.print(bodyString.toUpperCase());

            iterations++;
            bodyContent.clear(); // empty buffer for next evaluation
        }
        catch (IOException e) {
            System.out.println("Error in BodyContentTag.doAfterBody()" + e.getMessage());
            e.printStackTrace();
        } // end of catch

        int retValue = SKIP_BODY;

        if ( iterations < howMany ) 
            retValue = EVAL_BODY_AGAIN;

        return retValue;
    }
}

启动服务器并在浏览器中加载bodyContent.jsp

<%@ taglib uri="/java2s" prefix="java2s" %>

    
        A custom tag: body content
    
    
        This page uses a custom tag manipulates its body content.Here is its output:
        
  1. java2s.com



10> dipu..:

如果您只是想避免JSP中Java编码的缺点,即使使用scriplet也可以这样做.只需遵循一些规则,在JSP中使用最少的Java,而在JSP页面中几乎没有计算和逻辑.

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%//instantiate a JSP controller
MyController clr = new MyController(request, response);

//process action if any
clr.process(request);

//process page forwaring if necessary

//do all variable assignment here
String showMe = clr.getShowMe();%>


    
    
    
        

<%= showMe %>

<% for(String str : clr.listOfStrings()) { %>

<%= str %><% } %> // and so on



11> msj121..:

Wicket也是一种将java与html完全分离的替代方案,因此设计人员和程序员可以在不同的代码集上协同工作,彼此之间几乎没有相互理解.

看看Wicket.



12> Dmitriy R..:

你提出了一个很好的问题,虽然你得到了很好的答案,但我建议你摆脱JSP.它是过时的技术,最终会死亡.使用现代方法,如模板引擎.您将非常清楚地分离业务层和表示层,当然模板中没有Java代码,因此您可以直接从Web演示文稿编辑软件生成模板,在大多数情况下可以利用WYSIWYG.

当然,远离过滤器以及前后处理,否则您可能会遇到支持/调试困难,因为您始终不知道变量获取值的位置.


JSP本身就是一个模板引擎

13> mahesh..:

为了避免JSP文件中的java代码,java现在提供了像JSTL这样的标记库,java也提出了JSF,你可以用标签的形式编写所有编程结构



14> Thai Tran..:

无论你试图避免多少,当你与其他开发人员合作时,他们中的一些人仍然会喜欢scriptlet,然后将邪恶的代码插入到项目中.因此,如果您真的想减少scriptlet代码,那么在第一个符号设置项目非常重要.有几种技术可以克服这个问题(包括其他提到的几个框架).但是,如果您更喜欢纯JSP方式,那么请使用JSTL标记文件.关于这一点的好处是您还可以为项目设置母版页,因此其他页面可以继承母版页

在WEB-INF/tags下创建一个名为base.tag的母版页,其中包含以下内容

<%@tag description="Overall Page template" pageEncoding="UTF-8"%>

<%@attribute name="title" fragment="true" %>


  
      
       <jsp:invoke fragment="title"></jsp:invoke>
    

  
  
    
    

在这个mater页面上,我创建了一个名为"title"的片段,这样在子页面中,我可以在母版页的这个位置插入更多代码.此外,标记将被子页面的内容替换

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

<%@ taglib prefix="t" tagdir="/WEB-INF/tags" %>


     
        
    

    
    [Put your content of the child here]
       

用于指定要使用的母版页(此时为base.tag).此处标记内的所有内容都将替换您母版页上的内容.您的子页面还可以包含任何标记库,您可以像通常提到的那样使用它.但是,如果您在此处使用任何scriptlet代码(<%= request.getParameter("name") %>...)并尝试运行此页面,您将获得一个JasperException because Scripting elements ( <%!, <jsp:declaration, <%=, <jsp:expression, <%, <jsp:scriptlet ) are disallowed here.因此,其他人无法将恶意代码包含在jsp文件中

从您的控制器调用此页面:

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



15> Chandra Sekh..:

JSTL Tag libraries在JSP中使用,这将是完美的.



16> 小智..:

只需使用JSTL标记和EL表​​达式.



17> CsBalazsHung..:

如果有人真的反对使用多种语言编程,我建议GWT,理论上你可以避免所有的JS和HTML元素,因为Google Toolkit将所有客户端和共享代码转换为JS,你不会有问题,所以你有一个没有任何其他语言编码的网络服务.即使你可以使用某些默认的CSS,因为它是由扩展(smartGWT或Vaadin)提供的.您不需要学习几十个注释.

当然,如果你愿意,你可以深入了解代码的深度并注入JS并丰富你的HTML页面,但实际上如果你愿意,你可以避免使用它,结果会很好,因为它是在任何其他框架中编写的.我说值得一试,基本的GWT已经有了很好的记录.

当然,许多其他程序员在此描述或推荐了其他几种解决方案.GWT适用于那些真正不想处理Web部件或将其最小化的人.



18> Tobias..:

来自Python世界的一个巧妙的想法是模板属性语言 ; TAL由Zope引入(因此也称为"Zope页面模板",ZPT)并且是标准的,并且还实现了PHP,XSLT和Java(我使用了Python/Zope和PHP版本).在这类模板语言中,上面的一个示例可能如下所示:

Example product A nice description 1.23

代码看起来像普通的HTML(或XHTML)以及XML命名空间中的一些特殊属性; 它可以通过浏览器查看,并由设计师安全地进行调整.支持宏和i18n:

Our special offers

Example product A nice description 1.23

如果内容的翻译可用,则使用它们.

不过,我对Java实现不太了解.



19> kapil das..:

在JSP中使用scriptlet不是一个好习惯.

相反,你可以使用:

    JSTL标签

    EL表达式

    自定义标签 - 您可以定义自己的标签.

请参阅:

    http://docs.oracle.com/javaee/1.4/tutorial/doc/JSTL3.html

    EL



20> 小智..:

当然,替换<%! counter++; %>为事件生产者 - 消费者体系结构,其中业务层被通知有关递增计数器的需要,它会相应地做出反应,并通知演示者以便他们更新视图.涉及到许多数据库事务,因为将来我们需要知道计数器的新旧值,它已经增加了它并且考虑了什么目的.显然涉及序列化,因为这些层完全是分离的.您将能够通过RMI,IIOP,SOAP递增计数器.但是只需要HTML,这是你没有实现的,因为它是如此平凡的情况.您的新目标是在新的闪亮E7,64GB RAM服务器上每秒达到250个增量.

我有超过20年的编程经验,大多数项目在六重奏之前都失败了:可重用性可替换性OO能力可调试性可测性甚至还需要可维护性.由仅关心功能的人经营的其他项目非常成功.此外,在项目中过早实施的僵硬对象结构使得代码无法适应规范中的剧烈变化(也称为敏捷).

因此,我认为拖延是在项目早期或非特别需要时定义"层"或冗余数据结构的活动.  



21> mel3kings..:

从技术上讲,JSP在运行时都会转换为Servlet.JSP最初是为了按照MVC模式解耦业务逻辑和设计逻辑而创建的.所以JSP在运行时在技术上都是java代码.但回答这个问题,Tag Libraries通常用于将逻辑(删除Java代码)应用于JSP页面.



22> Ajay Takur..:

如果我们在java Web应用程序中使用以下内容,则可以从JSP的前台中删除java代码.

    将MVC架构用于Web应用程序

    使用JSP标记

    一个.标准标签

    湾 自定义标签

    表达语言



23> Yster..:

如何避免JSP文件中的Java代码?

除了表达式语言(EL)之外,您还可以使用JSTL等标签库标签.但是EL与JSP不兼容.所以最好完全删除JSP并使用Facelets.

Facelets是第一个为JSF(Java Server Faces)设计的非JSP页面声明语言,与JSP相比,它为JSF开发人员提供了更简单,更强大的编程模型.它解决了JSP中用于Web应用程序开发的不同问题.

在此输入图像描述

资源

推荐阅读
Life一切安好
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有