JavaScriptのテンプレートリテラルはJSPファイルの中では使えないのでその解決策
ふと気になったので実験してみました。
JavaScriptのテンプレートリテラルとJSPのELはどちらも同じ表記(${})を使いますね。
正確には、
JavaScriptのテンプレートリテラルでは${変数名}
JSPのELでは${式}
でちょっと違うのですが、式は変数名で構成されることもあるので同じと考えたいと思います。
もしも、変数名が衝突したらどうなるのか?
気になったので実験してみました。
すると、JSPファイルではJavaScriptのテンプレートリテラルが無効のようですね。
一つ賢くなりました。
考えてみればJSPはServletに変換されて実行されるので当然と言えるかもしれません。
<HTMLの中ではテンプレートリテラルは有効>
<!DOCTYPE html>
<html>
<head>
<title>HTML page</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
</head>
<body>
<script>
let age = 19;
alert(`I am ${age} years old.`);
</script>
</body>
</html>
<JSPの中ではテンプレートリテラルは無効>
<%@page contentType="text/html" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>JSP Page</title>
</head>
<body>
<script>
let age = 19;
alert(`I am ${age} years old.`);
</script>
</body>
</html>
念のためJSPをサーブレットに変換して確かめてみます。
例えば56行目を見ると${age}の部分をELとして評価しようとしているのが見て取れます。
package org.apache.jsp;
import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.jsp.*;
public final class newjsp_jsp extends org.apache.jasper.runtime.HttpJspBase
implements org.apache.jasper.runtime.JspSourceDependent {
private static final JspFactory _jspxFactory = JspFactory.getDefaultFactory();
private static java.util.List<String> _jspx_dependants;
private org.glassfish.jsp.api.ResourceInjector _jspx_resourceInjector;
public java.util.List<String> getDependants() {
return _jspx_dependants;
}
public void _jspService(HttpServletRequest request, HttpServletResponse response)
throws java.io.IOException, ServletException {
PageContext pageContext = null;
HttpSession session = null;
ServletContext application = null;
ServletConfig config = null;
JspWriter out = null;
Object page = this;
JspWriter _jspx_out = null;
PageContext _jspx_page_context = null;
try {
response.setContentType("text/html;charset=UTF-8");
response.setHeader("X-Powered-By", "JSP/2.3");
pageContext = _jspxFactory.getPageContext(this, request, response,
null, true, 8192, true);
_jspx_page_context = pageContext;
application = pageContext.getServletContext();
config = pageContext.getServletConfig();
session = pageContext.getSession();
out = pageContext.getOut();
_jspx_out = out;
_jspx_resourceInjector = (org.glassfish.jsp.api.ResourceInjector) application.getAttribute("com.sun.appserv.jsp.resource.injector");
out.write("\n");
out.write("<!DOCTYPE html>\n");
out.write("<html>\n");
out.write(" <head>\n");
out.write(" <meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\">\n");
out.write(" <title>JSP Page</title>\n");
out.write(" </head>\n");
out.write(" <body>\n");
out.write(" <script>\n");
out.write(" let age = 19;\n");
out.write(" alert(`I am ");
out.write((java.lang.String) org.apache.jasper.runtime.PageContextImpl.evaluateExpression("${age}", java.lang.String.class, (PageContext)_jspx_page_context, null));
out.write(" years old.`);\n");
out.write(" </script>\n");
out.write(" </body>\n");
out.write("</html>");
} catch (Throwable t) {
if (!(t instanceof SkipPageException)){
out = _jspx_out;
if (out != null && out.getBufferSize() != 0)
out.clearBuffer();
if (_jspx_page_context != null) _jspx_page_context.handlePageException(t);
else throw new ServletException(t);
}
} finally {
_jspxFactory.releasePageContext(_jspx_page_context);
}
}
}
解決策
この問題を解決するには、JavaScriptのテンプレートリテラル内でEL式を適切にエスケープします。
以下のコードの19行目の\${age}がそうです。(Windows環境ではバックスラッシュが円マークで表示されます)
<%@page contentType="text/html" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>JSP Page</title>
</head>
<body>
<script>
let age = 19;
alert(`I am \${age} years old.`);
</script>
</body>
</html>