[java] JSP 파일에서 Java 코드를 피하는 방법은 무엇입니까?

Java EE를 처음 사용하고 다음 세 줄과 같은 것을 알고 있습니다.

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

JSP 버전 2에는 JSP 파일에서 Java 코드를 피하는 방법이 있습니다. 다른 JSP 2 라인을 알려주시겠습니까?



답변

의 사용 스크립틀릿 (사람 <% %>의 일) JSP는 실제로 매우의 탄생 있기 때문에 권장하지 않습니다 태그 라이브러리 (같은 JSTL 과) EL ( 표현 언어 , 그 ${}일) 2001 년 웨이 다시.

스크립틀릿 의 주요 단점 은 다음과 같습니다.

  1. 재사용 성 : 스크립틀릿을 재사용 할 수 없습니다.
  2. 교체 성 : 스크립틀릿을 추상적으로 만들 수 없습니다.
  3. OO 기능 : 상속 / 구성을 사용할 수 없습니다.
  4. 디버깅 가능성 : 스크립틀릿에서 예외가 절반 만 발생하면 빈 페이지 만 있으면됩니다.
  5. 테스트 가능성 : 스크립틀릿은 단위 테스트가 불가능합니다.
  6. 유지 보수성 : 혼합 / 정렬 / 복제 된 코드 로직을 유지 보수하려면 Saldo 당 더 많은 시간이 필요합니다.

또한 Sun Oracle 자체는 (태그) 클래스에서 동일한 기능이 가능할 때마다 스크립틀릿을 사용하지 않도록 JSP 코딩 규칙 에서 권장합니다 . 여기 몇 가지 관련성이 있습니다.

JSP 1.2 스펙에서 웹 애플리케이션에 JSP 표준 태그 라이브러리 (JSTL)를 사용 하여 페이지 에 JSP 스크립틀릿의 필요성을 줄이는 것이 좋습니다 . JSTL을 사용하는 페이지는 일반적으로 읽고 관리하기가 더 쉽습니다.

가능하면 태그 라이브러리가 동등한 기능을 제공 할 때마다 JSP 스크립틀릿을 사용하지 마십시오 . 이렇게하면 페이지를보다 쉽게 ​​읽고 유지 관리 할 수 ​​있으며 비즈니스 로직과 프리젠 테이션 로직을 분리 할 수 ​​있으며 페이지를 JSP 2.0 스타일 페이지로 쉽게 발전시킬 수 있습니다 (JSP 2.0 사양은 스크립틀릿 사용을 지원하지만 강조하지 않습니다).

비즈니스 로직에서 프리젠 테이션 티어 간의 결합을 줄이기 위해 MVC (Model-View-Controller) 디자인 패턴을 채택 한다는 개념 에서 JSP 스크립틀릿은 비즈니스 로직을 작성 하는 데 사용해서는 안됩니다 . 대신, JSP 스크립틀릿은 필요한 경우 클라이언트 요청 처리에서 리턴 된 데이터 ( “값 오브젝트”라고도 함)를 적절한 클라이언트 지원 형식으로 변환하는 데 사용됩니다. 그럼에도 불구하고 이것은 프론트 컨트롤러 서블릿 또는 사용자 정의 태그로 더 잘 수행됩니다.


스크립틀릿 을 교체하는 방법은 전적으로 코드 / 로직의 목적에 달려 있습니다. 이 코드는 자주 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.
        }
    }

    <url-pattern>관심있는 JSP 페이지를 포함 하는 적절한 맵에 맵핑되면 전체 JSP 페이지에서 동일한 코드 조각을 복사하여 붙여 넣을 필요가 없습니다.


  • 일부 Java 코드를 호출 하여 요청 을 사전 처리 하려면 ( 예 : 일부 쿼리 매개 변수를 기반으로 필요한 경우 일부 테이블에 표시 할 데이터베이스에서 일부 목록을 사전로드하여) 서블릿 을 구현하고 그에 따라 코드를 작성하십시오 doGet(). 예 :

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        try {
            List<Product> 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);
        }
    }

    이 방법으로 예외를 처리하는 것이 더 쉽습니다. DB는 JSP 렌더링 도중에 액세스되지 않지만 JSP가 표시되기 훨씬 전에 액세스됩니다. DB 액세스에서 예외가 발생할 때마다 응답을 변경할 수 있습니다. 위의 예에서 기본 오류 500 페이지가 표시되어 <error-page>in에 의해 사용자 정의 할 수 있습니다 web.xml.


  • 양식 제출 처리와 같이 요청 을 후 처리 하기 위해 일부 Java 코드를 호출하려면 서블릿 을 구현하고 그에 따라 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의 프론트 컨트롤러 패턴 에 따라 서블릿 을 구현하십시오 . 예 :

    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);
        }
    }

    또는 JSF , Spring MVC , Wicket 과 같은 MVC 프레임 워크를 채택하면 사용자 정의 서블릿이 필요하지 않고 JSP / Facelets 페이지와 JavaBean 클래스로 끝납니다.


  • JSP 페이지 내부 의 흐름제어 하기 위해 일부 Java 코드를 호출 하려면 JSTL core 와 같은 (기존) 흐름 제어 taglib를 가져와야 합니다. 예 List<Product>를 들어 표에 표시 :

    <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
    ...
    <table>
        <c:forEach items="${products}" var="product">
            <tr>
                <td>${product.name}</td>
                <td>${product.description}</td>
                <td>${product.price}</td>
            </tr>
        </c:forEach>
    </table>

    모든 HTML에 잘 맞는 XML 스타일 태그를 사용하면 다양한 여는 중괄호와 닫는 중괄호가있는 여러 스크립틀릿보다 코드를 더 잘 읽을 수 있고 유지 관리하기가 더 쉽습니다 ( 닫는 중괄호는 어디에 있습니까?” ). 다음과 같은 부분을 추가하여 스크립틀릿 을 계속 사용할 때마다 웹 응용 프로그램에서 예외가 발생하도록 구성하는 것이 가장 쉽습니다 web.xml.

    <jsp-config>
        <jsp-property-group>
            <url-pattern>*.jsp</url-pattern>
            <scripting-invalid>true</scripting-invalid>
        </jsp-property-group>
    </jsp-config>

    Java EE에 포함 된 MVC 프레임 워크 JSF의 일부인 JSP의 후속 버전 인 Facelets 에서는 이미 스크립틀릿 을 사용할 수 없습니다 . 이 방법으로 자동으로 “올바른 방법”을 수행해야합니다.


  • JSP 페이지에서 “백엔드”데이터 에 액세스하고 표시 하기 위해 일부 Java 코드를 호출 하려면 EL (Expression Language)을 사용해야 ${}합니다. 예 : 제출 된 입력 값을 다시 표시 :

    <input type="text" name="foo" value="${param.foo}" />

    ${param.foo}결과가 표시됩니다 request.getParameter("foo").


  • JSP 페이지에서 일부 유틸리티 Java 코드를 직접 호출 하려면 (일반적으로 public static메소드)이를 EL 함수로 정의해야합니다. JSTL 에는 표준 함수 taglib 가 있지만 직접 함수를 직접 작성할 수도 있습니다 . 다음 fn:escapeXmlXSS 공격 을 방지하기 위해 JSTL 이 유용한 방법의 예 입니다.

    <%@ taglib uri="http://java.sun.com/jsp/jstl/functions" prefix="fn" %>
    ...
    <input type="text" name="foo" value="${fn:escapeXml(param.foo)}" />

    XSS 감도는 Java / JSP / JSTL / EL /와는 전혀 관련이 없으며, 개발하는 모든 웹 응용 프로그램 에서이 문제를 고려해야합니다 . 스크립틀릿 의 문제점은 최소한 표준 Java API를 사용하지 않는 내장 된 예방 방법을 제공하지 않는다는 것입니다. JSP의 후속 Facelets는 이미 암시적인 HTML 이스케이프 처리를 수행하므로 Facelets의 XSS 구멍에 대해 걱정할 필요가 없습니다.

또한보십시오:


답변

보호 수단으로 : 스크립틀릿을 사용하지 않도록 설정

으로 또 다른 문제는 논의, 당신은 항상 당신의 스크립틀릿을 사용하지 않도록해야 할 web.xml웹 응용 프로그램 설명자.

나는 개발자가 스크립틀릿을 추가하는 것을 방지하기 위해, 특히 조만간 개요를 잃을 수있는 대기업에서 항상 그렇게 할 것입니다. web.xml설정은 다음과 같이 :

<jsp-config>
  <jsp-property-group>
    <url-pattern>*.jsp</url-pattern>
     <scripting-invalid>true</scripting-invalid>
  </jsp-property-group>
</jsp-config>


답변

JSTL 은 조건부, 루프, 집합, 가져 오기 등에 대한 태그를 제공합니다. 예를 들면 다음과 같습니다.

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

JSTL은 요청 속성과 함께 작동합니다 . JSP로 전달 되는 서블릿에 의해 요청에서 가장 자주 설정됩니다 .


답변

이것이 올바른지 확실하지 않습니다.

MVC에 대해 읽어야합니다. Spring MVC & Struts 2 는 가장 일반적인 두 가지 솔루션입니다.


답변

Java와 HTML 코드의 혼합을 피하기 위해 EL 표현식과 함께 JSTL 태그를 사용할 수 있습니다.

<%@ 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" %>
<html>
    <head>
    </head>
    <body>

        <c:out value="${x + 1}" />
        <c:out value="${param.name}" />
        // and so on

    </body>
</html>


답변

Wicket 과 같은 구성 요소 기반 프레임 워크도 있으므로 많은 HTML을 생성 할 수 있습니다. HTML로 끝나는 태그는 매우 기본적이고 거의 섞이지 않는 논리가 없습니다. 결과는 일반적인 HTML 요소가있는 거의 빈 HTML 페이지입니다. 단점은 Wicket API에 배울 구성 요소가 많으며 이러한 제약 조건에서 달성하기 어려운 것이 있다는 것입니다.


답변

MVC 아키텍처 패턴에서 JSP는보기 계층을 나타냅니다. JSP에 Java 코드를 포함시키는 것은 나쁜 습관으로 간주됩니다. JSP와 함께 JSTL , freeMarker , velocity 를 “template engine”으로 사용할 수 있습니다 . 해당 태그 에 대한 데이터 공급자 는 처리 중인 프레임 워크에 따라 다릅니다 . Struts 2webworkMVC 패턴의 구현으로 사용 OGNL “JSP로 콩의 속성을 노출하는 것은 매우 흥미있는 기술”.