JSP tags + scriptlet. How to enable scriptlet?
I have a page which uses a tag template. My web.xml is very basic.
I simply want to run some code in the page.
And no, I'm not interested in tags or other alternative. I want to use the bad-practice scriptlet haha.So far I'm getting this "HTTP ERROR 500" error:
Scripting elements ( %!, jsp:declaration, %=, jsp:expression, %, jsp:scriptlet ) are disallowed here.
While my files look like:
/WEB-INF/web.xml
<?xml version="1.0" encoding="utf-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
version="2.5">
<welcome-file-list>
<welcome-file>index.html</welcome-file>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
</web-app>
/WEB-INF/tags/wrapper.tag
<%@tag description="Simple Wrapper Tag" pageEncoding="UTF-8"%>
<%@ attribute name="title" required="true" type="java.lang.String"%>
<!DOCTYPE html PUBLIC "-//W3C//开发者_开发问答DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html>
<head>
<title>${title}</title>
</head>
<body>
<jsp:doBody />
</body>
</html>
index.jsp
<%@page contentType="text/html" pageEncoding="UTF-8"%>
<%@taglib prefix="t" tagdir="/WEB-INF/tags"%>
<t:wrapper>
<jsp:attribute name="title">My nice title</jsp:attribute>
<jsp:body>
<h1><%="some code generated text"%></h1>
</jsp:body>
</t:wrapper>
I have tried to modify web.xml to explicitly enable it, like this (not working):
<jsp-config>
<jsp-property-group>
<url-pattern>*.jsp</url-pattern>
<scripting-invalid>false</scripting-invalid>
</jsp-property-group>
<jsp-property-group>
<url-pattern>*.tag</url-pattern>
<scripting-invalid>false</scripting-invalid>
</jsp-property-group>
</jsp-config>
So, how do I use pure scriptlets within my tag'ed JSP?
EDIT #1:
An ideal code would look like this, inside a page that uses my template ('wrapper' as the above):
<%@page import="java.util.Calendar"%>
<%@page contentType="text/html" pageEncoding="UTF-8"%>
<%@taglib prefix="t" tagdir="/WEB-INF/tags"%>
<t:wrapper>
<jsp:attribute name="title">My nice title</jsp:attribute>
<%
final int day_of_week = Calendar.getInstance().get(
Calendar.DAY_OF_WEEK);
if (day_of_week == Calendar.SATURDAY)
{
%>
<jsp:body>
<h1>Have a nice Saturday (<%=Integer.toString(day_of_week)%>)!</h1>
</jsp:body>
<%
}
else
{
%>
<jsp:body>
<h1>Have a nice rest-of-the-week (<%=Integer.toString(day_of_week)%>)!</h1>
</jsp:body>
<%
}
%>
</t:wrapper>
See? Scriptlets between & inside the '' tags. That's exactly what I'm trying to achieve.
In this case, the container doesn't care about the value of scripting-invalid
in web.xml because its looking at the tag meta-data for jsp:body
which has a body-content value of scriptless
. So when you see:
Scripting elements ( %!, jsp:declaration, %=, jsp:expression, %, jsp:scriptlet ) are disallowed here.
The container is complaining about the contents of jsp:body which must be scriptless. If you want to render scriptlet content in the body, you can set it as a page attribute outside of the jsp:body tag using a scriptlet and then render it using EL inside the body like so:
<% request.setAttribute("stuff", object); %>
<jsp:body>
${stuff}
</jsp:body>
Kind of late answer, but this should work:
<t:wrapper>
<jsp:attribute name="title">My nice title</jsp:attribute>
<c:set var="bodyContent">
<%
final int day_of_week = Calendar.getInstance().get(Calendar.DAY_OF_WEEK);
if (day_of_week == Calendar.SATURDAY)
{
%>
<h1>Have a nice Saturday (<%=Integer.toString(day_of_week)%>)!</h1>
<%
}
else
{
%>
<jsp:body>
<h1>Have a nice rest-of-the-week (<%=Integer.toString(day_of_week)%>)!</h1>
</jsp:body>
<%
}
%>
</c:set>
<jsp:body>
${bodyContent}
</jsp:body>
</t:wrapper>
Simply put, as mentioned, you can't do that. There is no "fix" to it, it can't be done. Tag Files are basically "Simple Tags" in JSP parlance. Simple Tags are just that, Simpler tags that don't offer all of the options of a normal JSP Tag, and that included handling Scriptlets.
So, they're not constraining what you can do, rather you can't use tag files to do it. What you've found is that you're one of the few that seems to enjoy using scriptlets in JSP when most of the community has avoided them.
What I've found is that if I need to resort to scriptlet code, I encase that code in to it's own tag file, and then invoke the tag from the JSP. For my purposes this has worked quite well, and I've made some quite sophisticated tags using only tag files (rather than conventional Java).
This probably won't work for you, as I get the feeling you're using scriptlets as a rule, rather than as an exception.
Based on the answer of @bjarnij, I found this to be the best solution for me:
myJSP.jsp
<%@page contentType="text/html" pageEncoding="UTF-8"%>
<%@taglib prefix="t" tagdir="/WEB-INF/tags" %>
<c:set var="bodyContent">
<%
//Your content with scriplets and everything
%>
</c:set>
<t:wrapper>
<jsp:body>
${bodyContent}
</jsp:body>
</t:wrapper>
Almost the same as bjarnij's, but I had to put c:set
outside of the wrapper. Works like a charm for me :)
I'm looking to find a real solution for this problem, but the workaround I'm using is to create an old style tld tag to save scriptlet fragment in page context and then print it inside a tag.
public class PushTag extends BodyTagSupport {
private String key;
public int doStartTag() throws JspException {
return EVAL_BODY_BUFFERED;
}
@Override
public int doAfterBody() throws JspException {
pageContext.setAttribute(PREFIX + key, getBodyContent().getString());
return SKIP_BODY;
}
public String getKey() {
return key;
}
public void setKey(String key) {
this.key = key;
}
private static final String PREFIX = PushTag.class.getPackage().getName()
+ ".";
private static final long serialVersionUID = 1L;
}
public class PopTag extends BodyTagSupport {
private String key;
@Override
public int doStartTag() throws JspException {
try {
String bc = (String) pageContext.getAttribute(PREFIX + key);
if (bc != null) {
pageContext.getOut().write(bc);
}
} catch (Exception e) {
throw new JspException("Error:" + e.getMessage());
}
return super.doStartTag();
}
public String getKey() {
return key;
}
public void setKey(String key) {
this.key = key;
}
private static final String PREFIX = PopTag.class.getPackage().getName()
+ ".";
private static final long serialVersionUID = 1L;
}
pushpop.tld
<taglib>
<tlib-version>1.2</tlib-version>
<jsp-version>2.1</jsp-version>
<short-name>q</short-name>
<uri>http://dev.example.com/jsp/taglib/</uri>
<tag>
<name>push</name>
<tag-class>x.web.PushTag</tag-class>
<body-content>JSP</body-content>
<attribute>
<name>key</name>
<required>true</required>
<type>java.lang.String</type>
</attribute>
</tag>
<tag>
<name>pop</name>
<tag-class>x.web.PopTag</tag-class>
<body-content>JSP</body-content>
<attribute>
<name>key</name>
<required>true</required>
<type>java.lang.String</type>
</attribute>
</tag>
</taglib>
Use it in jsp:
<%@ taglib prefix="x" uri="http://example.com/jsp/taglib/" %>
<x:push key="scriptful"><%= "We Love SCRIPTLETS!" %></x:push>
<t:wrapper><x:pop key="scriptful"/></t:wrapper>
@Poni
If you want to use the simple if condition we can use the following instead of scriptlet
<c:if test="${!empty flashMsg}">
<p>your content</p>
</c:if>
Below is the code which I used to add scriplet like coding in JSPX pages.
Code also works while editing template pages created by Spring-Roo.
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<div xmlns:c="http://java.sun.com/jsp/jstl/core"
xmlns:fn="http://java.sun.com/jsp/jstl/functions"
xmlns:jsp="http://java.sun.com/JSP/Page"
xmlns:spring="http://www.springframework.org/tags"
xmlns:util="urn:jsptagdir:/WEB-INF/tags/util" id="footer" version="2.0">
<jsp:directive.page contentType="text/html;charset=UTF-8" />
<jsp:output omit-xml-declaration="yes" />
<jsp:declaration> String t; </jsp:declaration>
<jsp:scriptlet>
<![CDATA[
t="Declared and Initialized From Scriplet";
]]>
</jsp:scriptlet>
<jsp:scriptlet>
<![CDATA[
for(int i=0;i<3;i++){
]]>
</jsp:scriptlet>
<jsp:expression>t+i</jsp:expression> <![CDATA[ iteration <br/>]]>
<jsp:scriptlet>
<![CDATA[
}
]]>
</jsp:scriptlet>
</div>
Note: Proper combination of <jsp:declaration>,</jsp:declaration>
and <jsp:expression>
along with <![CDATA[... ]]>
does the trick.
Following are reference links:
- How to produce valid HTML with JSPX? (not XHTML)
- https://docs.oracle.com/javaee/1.4/tutorial/doc/JSPX3.html
精彩评论