2010-02-02 2 views
32

내 JSP 페이지에서 스크립틀릿 (< % = ... %>)을 사용하는 것이 그리 좋은 방법은 아니라고 들었습니다.내 JSP 페이지에서 스크립틀릿 사용을 피하는 방법은 무엇입니까?

좀 더 많은 java/jsp 경험을 가진 사람이이 코드를 어떻게 바꿀 수 있는지에 대한 조언을 해줄 수 있습니까?

이 JSP는 실제로 내 sitemesh 메인 데코레이터 페이지입니다. 기본적으로 내 웹 디자인에는 탭 스트립과 하위 메뉴가 있으며 현재 탭을 강조 표시하고 현재 요청 URI를보고 올바른 하위 메뉴를 표시하려고합니다.

<%@ taglib uri="http://www.opensymphony.com/sitemesh/decorator" prefix="decorator" %> 

<html> 
<head> 
    <title>My Events - <decorator:title /></title> 
    <link href="<%= request.getContextPath() %>/assets/styles.css" rel="stylesheet" type="text/css" /> 
</head> 
<body> 

<div class="tabs"> 
    <a 
    <%= request.getRequestURI().contains("/events/") ? "class='selected'" : "" %> 
    href='<%= request.getContextPath() %>/events/Listing.action'>Events</a> 
    <a 
    <%= request.getRequestURI().contains("/people/") ? "class='selected'" : "" %> 
    href='<%= request.getContextPath() %>/people/Listing.action'>People</a> 
</div> 

<div class="submenu"> 
    <% if(request.getRequestURI().contains("/events/")) { %> 
    <a href="Listing.action">List of Events</a> 
    |<a href="New.action">New Event</a> 
    <% } %> 
    <% if(request.getRequestURI().contains("/people/")) { %> 
    <a href="Listing.action">List of People</a> 
    |<a href="New.action">New Person</a> 
    <% } %> 
    &nbsp; 
</div> 

<div class="body"> 
    <decorator:body /> 
</div> 

</body> 
</html> 

덕분에 모든

+0

제쳐두고 '<% = request.getContextPath() %>'는 너무 많이 싫어하는 스크립틀릿을 사용할 수 있습니까? – Chris

+0

템플릿 작성을 위해 facelets 사용을 시작해야합니다. 코드를 올바르게 작성하도록합니다. –

+0

sitemesh 대신 facelet을 사용 하시겠습니까? – Chris

답변

40

의 차이를 볼 실패 실제로는 스크립트 렛 없이는 완전히 완료 할 수 있습니다. 내가 c:set에 "캐시"를 사용주의,

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

<html> 
<head> 
    <title>My Events - <decorator:title /></title> 
    <link href="${pageContext.request.contextPath}/assets/styles.css" rel="stylesheet" type="text/css" /> 
</head> 
<body> 

<div class="tabs"> 
    <a 
    ${fn:contains(pageContext.request.requestURI, '/events/') ? 'class="selected"' : ''} 
    href="${pageContext.request.contextPath}/events/Listing.action">Events</a> 
    <a 
    ${fn:contains(pageContext.request.requestURI, '/people/') ? 'class="selected"' : ''} 
    href="${pageContext.request.contextPath}/people/Listing.action">People</a> 
</div> 

<div class="submenu"> 
    <c:if test="${fn:contains(pageContext.request.requestURI, '/events/')}"> 
    <a href="Listing.action">List of Events</a> 
    |<a href="New.action">New Event</a> 
    </c:if> 
    <c:if test="${fn:contains(pageContext.request.requestURI, '/people/')}"> 
    <a href="Listing.action">List of People</a> 
    |<a href="New.action">New Person</a> 
    </c:if> 
    &nbsp; 
</div> 

좀 더 최적화 된 재입니다 : 여기

JSTL corefunctions 태그 라이브러리 (단지 /WEB-INF/lib에서 jstl-1.2.jar 드롭) 다른 사람들의 도움으로 1 일에 재 작성의 expression 결과를 재사용하고 모든 링크에 컨텍스트 경로를 지정하는 것을 피하기 위해 HTML <base> 태그를 사용합니다 (웹 페이지의 상대적 URL은 모두 - 슬래시없이 - 슬래시없이 -!) :

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

<c:set var="isEvents" value="${fn:contains(pageContext.request.requestURI, '/events/')}" /> 
<c:set var="isPeople" value="${fn:contains(pageContext.request.requestURI, '/people/')}" /> 

<html> 
<head> 
    <title>My Events - <decorator:title /></title> 
    <base href="${pageContext.request.contextPath}"> 
    <link href="assets/styles.css" rel="stylesheet" type="text/css" /> 
</head> 
<body> 

<div class="tabs"> 
    <a ${isEvents ? 'class="selected"' : ''} href="events/Listing.action">Events</a> 
    <a ${isPeople ? 'class="selected"' : ''} href="people/Listing.action">People</a> 
</div> 

<div class="submenu"> 
    <c:if test="${isEvents}"> 
    <a href="Listing.action">List of Events</a>|<a href="New.action">New Event</a> 
    </c:if> 
    <c:if test="${isPeople}"> 
    <a href="Listing.action">List of People</a>|<a href="New.action">New Person</a> 
    </c:if> 
    &nbsp; 
</div> 

eventspeople과 같은 하드 코드 된 값을 모두 수집하고 응용 프로그램 범위의 Map에 텍스트를 연결하고 각 JSTL <c:forEach>에서 텍스트를 사용하여 탭을 표시하는 경우 실제로 최적화 할 수 있습니다. 당신의 실제 질문에 관해서는

을 수행 할 수 있습니다 비활성화 스크립트 릿 (및 사용에 대한 런타임 오류를 얻을) 웹 애플리케이션의 web.xml에 다음 항목을 추가하여. 그것은 전체 스크립틀릿을 찾는 데 도움이 될 수 있습니다.

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

EL에 대해 자세히 알아 보려면 Java EE tutorial part II chapter 5을 확인하십시오. ${pageContext}과 같은 암시 적 EL 객체는 here으로 설명됩니다. JSTL에 대해 자세히 알아 보려면 Java EE tutorial part II chapter 7을 확인하십시오. JSTL과 EL은 별개의 두 가지 사항입니다. JSTL은 표준 태그 라이브러리이며 EL은 프로그래밍 방식으로 백엔드 데이터에 액세스 할 수 있도록합니다. JSTL과 같은 taglib에서 일반적으로 사용되지만 템플릿 텍스트에서도 독립 실행 형으로 사용할 수 있습니다.

+5

"이전"과 "이후"템플릿을 비교해 보면 거의 동일하다는 것을 알 수 있습니다. 나는 후자가 자동적으로 (작은 비트 청소기를 보는 것 외에) 전자보다 얼마나 나은지 보지 못한다. – Ree

+3

@Ree - 솔직히 말해서 JSTL의 가장 큰 자산은 JSP에서 어떤 코드가 떠오르더라도 자유롭게 작성할 수 있다는 것입니다. JSTL은 컨트롤러, 비즈니스 로직 관리자 또는 데이터 액세스 객체가 아닌 템플릿을 작성하는 데 필요한 모든 도구를 제공합니다. – RustyTheBoyRobot

2

당신은 어떤 웹 프레임 워크를 사용해야합니다. 아니면 적어도 편리한 taglib. 또는 FreeMarker과 같은 템플릿 enginge.

광고 프레임 워크 :

당신이 코딩의 JSP 방식을 좋아한다면

, 그때 내가 Struts 2을 건의 할 것입니다.

<s:if test="%{false}"> 
    <div>Will Not Be Executed</div> 
</s:if> 
<s:elseif test="%{true}"> 
    <div>Will Be Executed</div> 
</s:elseif> 
<s:else> 
    <div>Will Not Be Executed</div> 
</s:else> 

는 다음 구성 요소 지향 JSF있다. 당신이 OOP와 자바 코딩 모든 것을 좋아하는 경우에

, Apache Wicket (내가 좋아하는) 또는 구글 웹 툴킷을 시도합니다.

+0

도움이된다면 struts2를 사용하고 있습니다. – Chris

+0

이제 빈센트 (Vincent)가 제안한 JSTL과 같은 태그 라이브러리와 결합하면 스크립틀릿이 없습니다. 여기를 참고하십시오 : http://struts.apache.org/2.1.8.1/docs/tag-reference.html 그리고 다른 것들 중에서도 http://struts.apache.org/2.1.8.1/docs를 찾을 수 있습니다. /text.html –

3

태그 라이브러리를 사용하여 시작할 수 있습니다. 표준 태그 라이브러리 JSTL을 사용하면 scriplets가 필요한 일반적인 작업을 대부분 수행 할 수 있습니다. struts2 프레임 워크 나 아파치처럼 사용되는 많은 다른 풍부한 태그 라이브러리가있다.

예컨대

<c:if test="${your condition}"> 
     Your Content 
    </c:if> 

은 if 문을 대체합니다.

3

스크립틀릿 대신 JSTL 표현식 언어를 사용할 수 있습니다. here 좋은 개요입니다. 당신은 너무 같은 태그 라이브러리를 추가해야합니다 :

예를 들어
<%@ taglib uri='http://java.sun.com/jsp/jstl/core' prefix='c' %> 

이, JSTL는 당신이 필요로하는 물건을주고 내장 객체의 무리를 제공한다; 원하는 사람은 pageContext.request입니다.

<%request.getRequestURI%>${pageContext.request.requestURI}으로 바꿀 수 있습니다.

<c:if> 태그를 사용하여 조건부를 수행 할 수 있습니다.

+0

JSTL! = 표현 언어. JSTL은 표준 taglib입니다. http://java.sun.com/products/jsp/jstl/1.1/docs/tlddocs/ Expression Language는 그'$ {} '것입니다. http://java.sun.com/javaee/5 /docs/tutorial/doc/bnahq.html – BalusC

+1

나중에 참조 할 수 있습니다. http : // 대신 taglib uri에서 'http://java.sun.com/jsp/jstl/core'에 대해 더 많은 행운을 빕니다. java.sun.com/jstl/core) – Chris

+0

/jsp/-less uri는 실제로 10 년 된 JSTL 1.0의 일부입니다. 사용하지 마십시오. – BalusC

9

제쳐두고, <%= request.getContextPath() %>은 너무 많이 싫어하는 스크립틀릿을 사용할 수 있습니까?

이것은 예상치 못한 의견 일 수 있지만 간단한 조건문 및 텍스트 삽입 만 수행하면 스크립틀릿 사용시 많은 오류를 찾을 수 없습니다.(일 경우)

나는 주로 JSTL과 표현 언어를 사용 하겠지만, 타이핑이 덜하고 IDE 지원이 더 좋을 수 있기 때문에 (그러나 좋은 JSP IDE는 빠진 닫는 대괄호와 그런 것들).

그러나 근본적으로 (같이하는 "템플릿에서 논리를 계속") 나는 당신이 당신의 자신으로 보면 더 도움이 생각

<% if(request.getRequestURI().contains("/events/")) { %> 

${fn:contains(pageContext.request.requestURI, '/events/') 
+3

좋습니다. 나는이 의견이있는 유일한 사람이라고 생각했습니다! – Chris

+0

여기있는 컨텍스트는 템플릿을 개발하거나 유지 관리하는 유일한 사람이 아닌 경우 더 많은 역할을하는 모범 사례 중 하나라고 생각합니다. 기능적으로는 예제에 차이가 없지만 스크립틀릿을 사용하는 우선 순위를 설정하고 잘 모르는 사람은 모델의 상태를 변경하는 임의의 Java 코드를 드롭 할 수 있습니다. 고려해야 할 것. 나는 위에서 언급 한 BalusC로 그들을 무능하게하는 아이디어를 좋아합니다. –

6

이 귀하의 질문에 직접 대답하지 않습니다 (거기에 이미 여러 좋은 것들, 그래서 그것에 추가하려고하지 않습니다)하지만 한 언급 :

수있는 사람과 함께 조금 더 java/jsp 경험이 코드를 변경하는 방법에 관해서는 포인터를 더 많은 '우수 사례'가 무엇이든 일 수 있습니다. 일 수 있습니까? 제 생각에는

는 가장 좋은 방법은, JSP 관련하여, 그것이 템플릿 엔진으로 엄격하게 사용되어야한다는 것입니다 더 이상 (즉, 어떤 비즈니스 로직에있다).많은 사람들이 지적한대로 JSTL을 사용하면 분명히 거기에 도달하는 데 도움이되지만 JSTL을 사용하더라도 JSP로 많은 일을하기가 쉽습니다.

나는 개인적으로 JSP로 개발할 때 Terence Parr이 Enforcing Strict Model-View Separation in Templating Engines에 제시 한 규칙을 따르기를 좋아합니다. 이 논문은 템플릿 엔진 (모델과 뷰 분리)의 목적과 훌륭한 템플릿 엔진의 특성에 대해 언급합니다. JSP를 잘 살펴보고 좋은 템플릿 엔진이 아닌 방법을 지적합니다. 당연히 JSP는 기본적으로 너무 강력하므로 개발자가 너무 많은 작업을 수행 할 수 있습니다. 나는이 백서를 읽기를 강력히 권장하며, JSP의 "좋은"부분을 제한하는 데 도움이 될 것이다.

  1. 뷰가 직접 모델 데이터 객체를 변경하거나 호출하여 두 모델을 수정할 수 없습니다 :

    당신이 그 종이에 하나 개의 섹션을 읽을 경우, 다음과 같은 규칙을 포함 7 장을 읽고, 메서드를 부작용의 원인이되는 모델 . 즉, 템플릿은 모델에서 데이터에 액세스 할 수 있고 메소드를 호출 할 수 있지만 이러한 참조는 부작용 이어야합니다. 이 규칙은 부분적으로 으로 발생합니다. 데이터 참조는 순서를 구분하지 않으므로 이어야합니다. 섹션 7.1을 참조하십시오.

  2. 뷰는 데이터에 의존하는 연산을 수행 할 수 값 때문에 계산 수도 미래 변화들이 깔끔하게 어쨌든 모델에 캡슐화한다. 예를 들어 도서 판매 가격을 "$ 가격 * .90"으로 계산할 수 없습니다. 모델과 독립적 이도록보기에서는 데이터의 의미에 대한 가정을 으로 만들 수 없습니다.
  3. 종속 데이터 값과 비교 할 수는 없지만 이러한 다치 데이터 값 존재/부재 또는 길이 데이터 특성을 테스트 할 수있다. 의사가 최대 수축기 혈압을 으로 줄이기 위해 $ bloodPressure< 120과 같은 테스트를 모델로 이동해야합니다. 뷰에서 표현식 이 $ bloodPressureOk 같은 부울을 보내고 simulat- 값의 존재에 대한 테스트로 교체해야합니다! = null의 템플릿 출력 은 가 가지고있는 조건, 모델 데이터 및 -이 계산을 조건으로 할 수있다 모델에서 계산됩니다. 심지어 음수 값을 만드는 간단한 테스트 빨간색 모델에서 계산되어야합니다; 추상화의 적절한 수준이 usu-입니다 동맹 뭔가 더 높은 수준과 같은 "부서 x는 돈을 잃고있다."
  4. 데이터 유형 가정을 만들 수 없습니다보기를. 의 프로 문법이 하지을 수 템플릿을 가정하면 $의 사용자 ID는 정수 : 뷰는 데이터 값이 예를 들어, 날짜입니다 가정하지만, 더 미묘한 형태의 가정 AP-배 때 일부 유형의 가정은 분명 있습니다 템플릿을 위반하지 않고이 값을 모델의 이 아닌 숫자가 아닌 값으로 변경하십시오.이 규칙은 과 같은 인덱싱을 금지합니다. (정적 또는 동적으로) 인수가있는 메서드를 호출 할 수 없으므로 이 아닌 것으로 가정합니다. 하나의 은 모델 메서드 을 단순히 개체로 처리하도록 보장 할 수 있습니다. 그래픽 디자이너 외에 프로그래머가 아닙니다. 그들에게 메서드를 호출하고 무엇을 전달할지를 알면 비현실적입니다.
  5. 모델의 데이터에는 표시 또는 레이아웃 정보가 없어야합니다. 모델은 데이터 값으로 위장한보기에 디스플레이 정보를 전달할 수 없습니다. 여기에는 다른 데이터 값에 적용 할 템플릿의 이름을 전달하지 않는 것이 포함됩니다.

덧붙여, 테렌스는 자신의 템플릿 엔진이 가정이 규칙을 적용하는 정말 좋은 일을 String Template라고 만들었습니다. 나는 개인적인 경험이 없지만 다음 프로젝트에서 그것을 확인하고 싶다.

6

스크립틀릿은 세계에서 가장 나쁜 것이 아닙니다. 중요한 고려 사항은 누가 코드를 유지할 것인지에 대해 생각하는 것입니다. Java 경험이별로없는 웹 디자이너라면 태그 라이브러리를 사용하는 것이 좋습니다. 그러나 Java 개발자가 유지 관리를 수행하는 경우 스크립틀릿을 사용하는 것이 더 쉬울 수 있습니다.

태그 라이브러리와 JSTL을 사용하게되면 관리자는 태그 라이브러리를 배우고 JSTL을 알아야합니다. 몇몇 개발자들은 원하는 기술을 가지고 있기 때문에 문제가 없지만, 몇 달에 한 번씩 JSP를 처리해야하는 개발자에게는 멋진 스크립트로 작성해야합니다. 익숙한 자바.