标签:long iso 简单 问控制 tin expr 6.4 AC cookies
一. 基本了解
JSP是应用最广泛的表现层技术,它和Servlet是Java EE的两个基本成员。JSP和Servlet本质是一样的,因为JSP最终编译成ServLet才能运行。
1.1 web应用和web.xml文件
对于web应用而言,WEB-INF是一个特殊的文件夹。web容器会包含该文件夹下的内容,客户端浏览器无法访问WEB-INF路径下的任何内容。
web.xml配置的管理内容
除此之外,web.xml还负责配置、管理如下常用内容
web.xml文件的根元素是<web-app.../>元素,在servlet 3.0规范中,该元素新增了如下属性。
metadata-complete:该属性接受true和false两个属性值。当该属性值为true时,web应用将不会加载注解配置的Web组件(如Servlet,Filter,Listener等)
在web.xml文件中配置首页使用welcome-file-list元素,该元素能包含多个welcome-file子元素,其中每个welcome-file子元素配置一个首页。例如
<welcome-file-list> <welcome-file>index.html</welcome-file> <welcome-file>index.htm</welcome-file> <welcome-file>index.jsp</welcome-file> </welcome-file-list>
二. JSP原理
2.1 JSP页面的内容有两部分组成
jsp的本质是servlet,使用jsp其实还是使用servlet,因为web应用中的JSP页面都会由Servlet容器生成对应的servlet,对Tomcat而言,JSP页面生成的Servlet放在work路径对应的Web应用下。当启动Tomcat后,Tomcat根据JSP页面生成对应的Servlet的Java文件和class文件。
/* * Generated by the Jasper component of Apache Tomcat * Version: Apache Tomcat/8.5.31 * Generated at: 2018-05-12 09:10:41 UTC * Note: The last modified time of this file was set to * the last modified time of the source file after * generation to assist with modification tracking. */ package org.apache.jsp; import javax.servlet.*; import javax.servlet.http.*; import javax.servlet.jsp.*; public final class index_jsp extends org.apache.jasper.runtime.HttpJspBase implements org.apache.jasper.runtime.JspSourceDependent, org.apache.jasper.runtime.JspSourceImports { private static final javax.servlet.jsp.JspFactory _jspxFactory = javax.servlet.jsp.JspFactory.getDefaultFactory(); private static java.util.Map<java.lang.String,java.lang.Long> _jspx_dependants; private static final java.util.Set<java.lang.String> _jspx_imports_packages; private static final java.util.Set<java.lang.String> _jspx_imports_classes; static { _jspx_imports_packages = new java.util.HashSet<>(); _jspx_imports_packages.add("javax.servlet"); _jspx_imports_packages.add("javax.servlet.http"); _jspx_imports_packages.add("javax.servlet.jsp"); _jspx_imports_classes = new java.util.HashSet<>(); } private volatile javax.el.ExpressionFactory _el_expressionfactory; private volatile org.apache.tomcat.InstanceManager _jsp_instancemanager; public java.util.Map<java.lang.String,java.lang.Long> getDependants() { return _jspx_dependants; } public java.util.Set<java.lang.String> getPackageImports() { return _jspx_imports_packages; } public java.util.Set<java.lang.String> getClassImports() { return _jspx_imports_classes; } public javax.el.ExpressionFactory _jsp_getExpressionFactory() { if (_el_expressionfactory == null) { synchronized (this) { if (_el_expressionfactory == null) { _el_expressionfactory = _jspxFactory.getJspApplicationContext(getServletConfig().getServletContext()).getExpressionFactory(); } } } return _el_expressionfactory; } public org.apache.tomcat.InstanceManager _jsp_getInstanceManager() { if (_jsp_instancemanager == null) { synchronized (this) { if (_jsp_instancemanager == null) { _jsp_instancemanager = org.apache.jasper.runtime.InstanceManagerFactory.getInstanceManager(getServletConfig()); } } } return _jsp_instancemanager; } public void _jspInit() { } public void _jspDestroy() { } public void _jspService(final javax.servlet.http.HttpServletRequest request, final javax.servlet.http.HttpServletResponse response) throws java.io.IOException, javax.servlet.ServletException { final java.lang.String _jspx_method = request.getMethod(); if (!"GET".equals(_jspx_method) && !"POST".equals(_jspx_method) && !"HEAD".equals(_jspx_method) && !javax.servlet.DispatcherType.ERROR.equals(request.getDispatcherType())) { response.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED, "JSPs only permit GET POST or HEAD"); return; } final javax.servlet.jsp.PageContext pageContext; final javax.servlet.ServletContext application; final javax.servlet.ServletConfig config; javax.servlet.jsp.JspWriter out = null; final java.lang.Object page = this; javax.servlet.jsp.JspWriter _jspx_out = null; javax.servlet.jsp.PageContext _jspx_page_context = null; try { response.setContentType("text/html; charset=UTF-8"); pageContext = _jspxFactory.getPageContext(this, request, response, null, false, 8192, true); _jspx_page_context = pageContext; application = pageContext.getServletContext(); config = pageContext.getServletConfig(); out = pageContext.getOut(); _jspx_out = out; out.write("\r\n"); out.write("\r\n"); out.write("\r\n"); out.write("\r\n"); out.write("\r\n"); out.write("\r\n"); out.write("\r\n"); out.write("\r\n"); out.write("<html>\r\n"); out.write("<head>\r\n"); out.write(" <meta charset=\"UTF-8\">\r\n"); out.write(" <title>首页</title>\r\n"); out.write("</head>\r\n"); out.write("<body>\r\n"); out.write("\r\n"); out.write("Java 中国\r\n"); out.write("</body>\r\n"); out.write("</html>"); } catch (java.lang.Throwable t) { if (!(t instanceof javax.servlet.jsp.SkipPageException)){ out = _jspx_out; if (out != null && out.getBufferSize() != 0) try { if (response.isCommitted()) { out.flush(); } else { out.clearBuffer(); } } catch (java.io.IOException e) {} if (_jspx_page_context != null) _jspx_page_context.handlePageException(t); else throw new ServletException(t); } } finally { _jspxFactory.releasePageContext(_jspx_page_context); } } }
可以看出,去掉前缀之后,该Java类主要包含三个方法
2.3 JSP的工作原理四个结论
2.4 JSP的4种基本语法
2.5 JSP的三个编译指令
JSP的编译指令是通知JSP的引擎的消息,它不直接生成输出。编译指令都有默认值。
常见的编译指令有如下三个。
2.5.1 page指令
page指令通常位于JSP页面的顶端,一个JSP页面可以使用多条page指令,page指令的语法格式<%@page %>
page指令的各属性值如下:
2.5.2 include 指令
使用include指令,可以将一个外部文件嵌入到当前的JSP文件中,同时解析这个页面的中的JSP语句(如果有的话),这是个静态的include语句,它会把目标页面的其他编译指令也包含进来,但动态include则不会。
include既可以包含静态的文本,也可以包含动态的JSP页面。静态的include编译指令会将被包含的页面融入本页面。因此被包含页面甚至不需要是一个完整的页面。
include编译指令的语法如下:
<%@include file="relativeURLSpec" %>
如果被嵌入的文件经常需要改变,建议使用<jsp:include>操作指令,因为他是动态的include语句。
需要指出的是,静态包含还会将被包含页面的编译指令也包含进来,如果两个页面的编译指令发生冲突,那么页面就会报错。
2.6 JSP的7个动作指令
jsp:forward 执行页面转向,将请求的处理转发到下一个页面。
jsp:param 用于传递参数,必须与其他支持参数的标签一起使用。
jsp:include 用于动态引入一个JSP页面
jsp:plugin 用于下载JavaBean或Applet到客户端执行
jsp:useBean 创建一个JavaBean的实例
jsp:setProperty 设置JavaBean实例的属性值
jsp:getProperty 输出JavaBean实例的属性值
2.6.1 forward指令
forward 指令用于将页面响应转发到另外的页面。即可以转发到静态的HTML页面,也可以转发到动态的JSP页面,或者转发到容器中的Serclet。
JSP的forward指令格式如下:
对于JSP 1.0,使用如下语法:
<jsp:forward page="{relativeURL | <%=expression%>}">
对于JSP 1.1以上规范,可使用如下语法
<jsp:forward page="{relativeURL | <%=expression%>}"> {<jsp:param.../>} </jsp:forward>
第二种语法用于转法时增加额外的参数。增加的请求参数的值可以通过HttpServletRequest类的getParameter()方法获取,看下面实例
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>Title</title> </head> <jsp:forward page="forward-result.jsp"> <jsp:param name="age" value="29"/> </jsp:forward> </body> </html>
在forward-result.jsp中,可以使用request内置对象获取请求的参数
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>forward结果页</title> </head> <body> <%=request.getParameter("age")%> </body> </html>
执行效果如图:
从图中可以看出,执行forward指令时,用户请求的地址依然没有改变,而页面内容全部被为forward目标页的内容
执行forward指令转发请求时,客户端请求参数不会丢失。实际上,重定向forward指令并没有向新页面发送请求,只是完全采用了新页面来对用户生成响应——请求依然是一次请求,所以请求参数,请求属性都不会丢失。
2.6.2 include 指令
include指令是一个动态的include指令,也用于包含页面,它不会导入被include页面的编译指令,仅仅将被导入页面的body内容插入本页面。
include动作指令的语法格式:
<jsp:include page="{relativeURL | <%=expression%>}" flush="true"/>
或者
<jsp:include page="{relativeURL | <%=expression%>}" flush="true"> <jsp:param name="parameterName" value="parameterValue"/> </jsp:include>
flush属性用于指定输出缓存是否转移到被导入文件中。如果指定为true,则包含在被导入文件中;如果指定为false,则包含在源文件中。动态导入的关键是插入目标页面的内容而不是将目标页面融入本页面中。
归纳起来,静态导入和动态导入有三点区别
实际上forward和include指令语法和作用十分相似,forward是拿目标页面代替原有页面,而include则拿目标页面插入原有页面
2.6.3 useBean,setProperty,getProperty指令
这三个指令都是与JavaBean相关的指令,其中useBean指令用于在JSP页面中初始化一个Java实例;setProperty指令用于JavaBean实例设置属性值;getProperty指令用于获取JavaBean实例的属性值。
useBean的语法格式如下:
<jsp:useBean id="name" class="classname" scope="page | request | session | application"/>
scope属性用于指定JavaBean实例的作用范围
setProperty的语法格式
<jsp:setProperty name="BeanName" property="propertyName" value="propertyValue"/>
getProperty的语法格式
<jsp:setProperty name="BeanName" property="propertyName" value="propertyValue"/>
下面的jsp页面示范了这三个动作指令的使用
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>JavaBean 测试</title> </head> <body> <jsp:useBean id="p1" class="java.Person" scope="page"/> <jsp:setProperty name="p1" property="name" value="sherman"/> <jsp:setProperty name="p1" property="age" value="23"/> <jsp:getProperty name="p1" property="name" /><br> <jsp:getProperty name="p1" property="age"/> </body> </html>
事实上,当页面使用setProperty和getProperty标签时,系统底层就是调用Bean类的setter和getter方法。上面代码可以换成Java脚本代替,如下:
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <%@page import=""%> <html> <head> <title>JavaBean 测试</title> </head> <body> <% Person p1 = new Person(); p1.setName("sherman"); p1.setAge(23); p1.getName(); p1.getAge(); %> </body> </html>
通常还需要将JavaBean放入指定的scope中
pageContext.setAttribute("p1",p1);
request.setAttribute("p1",p1);
session.setAttribute("p1",p1);
application.setAttribute("p1",p1);
2.6.4 plugin指令
plugin指令主要用于下载服务器端的JavaBean和Applet到客户端执行。由于程序在客户端执行,因此客户端必须安装虚拟机。这个指令很少使用。
2.6.5 param指令
param指令本身不能单独使用,通常与include指令,forward指令,plugin指令介个使用。
2.7 JSP脚本的九个内置对象
JSP脚本中包含9个内置对象,这九个内置对象都是Servlet API接口的实例,只是JSP规范对他们进行了初始化,也就是说它们本身就是对象,可以直接使用,它们依次如下:
JSP内置对象的实质:他们要么是_jspService()方法的形参,要么是该方法的局部变量,它们都是在_jspService()内完成初始化的,所以可以在JSP脚本中调用这些对象,无需创建它们。而且注意的是只能在JSP脚本和JSP表达式中使用这些对象,千万不能再JSP声明中使用它们,否则系统会找不到这些变量。
2.7.1 application对象
对于浏览器而言,它通常负责完成三件事情。
对于服务器而言,它的主要工作是
提示:最新版的Tomcat已经不需要对每个用户请求都启用单独的线程,使用普通I/O读取用户请求的数据,最新的Tomcat使用的是异步IO,具有更高的性能。
几乎所有的web服务器都会提供4个类似的Map结构,分别是application,session,request,page,并允许JSP,Servlet将数据保存在这4个结构中,并从这4个结构读取参数,这四个结构只是作用范围不同。JSP中的application,session,request,pageContext这四个内置对象分别用于操作这四个结构的参数。
application 对象代表web应用本身,通常有两个作用。
看如下JSP页面,该页面访问数据库,但访问数据库的驱动,URL,用户名及密码都在web.xml中给出。
%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>Title</title> </head> <body> <% String driver = application.getInitParameter("driver"); String url = application.getInitParameter("url"); String user = application.getInitParameter("user"); String password = application.getInitParameter("password"); %> </body> </html>
web应用的配置参数在web.xml文件中<context-param.../>配置,每个<context-param.../>配置一个参数,每个配置参数对整个应用有效。
2.7.2 config对象
config对应当前的JSP页面配置信息,但JSP页面通常无需配置,因此也不存在配置信息,JSP页面较少用到这个对象。但在Servlet中则用处比较大,因为Servlet需要在web.xml中进行配置,可以指定配置参数。
2.7.3 Exception 对象
exception对象代表JSP脚本中产生的错误和异常,是JSP页面异常机制的一部分。JSP脚本的代码已经处于try块中,一旦try块捕捉到JSP脚本的异常,就会为该对象处理异常。如果该页面的page指令指定了errorPage属性,则将请求forward到errorPage属性指定的页面,否则使用系统页面来输出异常信息。
在JSP的异常处理机制中,一个异常处理页面可以处理多个JSP页面脚本部分的异常。异常处理页面通过page指令的errorPage属性指定。
例如下面是个简单的异常处理页面
<%@ page contentType="text/html;charset=UTF-8" language="java" isErrorPage="true" %> <html> <head> <title>Title</title> </head> <body> <%=exception.getClass()%> <%=exception.getMessage()%> </body> </html>
可以看出,当page指令的属性isErrorPage的值为true是,该页面就会提供exception对象
2.7.4 out对象
out对象代表一个页面的输出流
2.75 pageContext对象
pageContext对象是pageContext类的实例,它提供了如下两个方法来访问page,request,seesion,application范围的变量
与getAttribute()方法对应,pageConext也提供两个setAttribute()方法来设置四个范围的变量 。
不仅如此,page_Context还可用于获取其他内置对象
2.7.6 request对象
request对象时JSP的重要对象,每个request对象都封装一个用户的请求,并且所有的请求参数都被封装在request中。
除此之外,request可代表 本次请求范围。可用于操作request范围的属性。
1.获取请求头/请求参数
HttpServletRequest提供多个方法获取请求头。
请求头和请求参数都是用户发送到服务器的数据。区别在于请求头通常由浏览器自动添加,因此一次请求总是包含若干请求头,而请求参数则通常需要开发人员控制添加,让客户端发送请求通常有两种方式
表单域和请求参数的关系
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>收集参数的表单页</title> </head> <body> <form id="form1" method="post" action="request1.jsp"> 用户名:<br/> <input type="text" name="name"/><hr/> 性别:<br> 男:<input type="radio" name="gender" value="男"/> 女:<input type="radio" name="gender" value="女"/><hr/> 喜欢的颜色:<br/> 红:<input type="checkbox" name="color" value="红"/> 绿:<input type="checkbox" name="color" value="绿"/> 蓝:<input type="checkbox" name="color" value="蓝"/><hr/> 来自的国家:<br/> <select name="county"> <option value="中国">中国</option> <option value="美国">美国</option> <option value="俄罗斯">俄罗斯</option> </select><hr/> <input type="submit" value="提交"/> <input type="reset" value="重置"/> </form> </body> </html>
上面的表单页面向request.jsp发送请求,request.jsp页面代码如下
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>获取请求头/请求参数</title> </head> <body> <% Enumeration<String> headerNames = request.getHeaderNames(); while(headerNames.hasMoreElements()){ String headerName = headerNames.nextElement(); out.println(headerName +"-->"+request.getHeader(headerName)+"<br/>"); } out.println("<hr/>"); request.setCharacterEncoding("UTF-8"); String name = request.getParameter("name"); String gender = request.getParameter("gender"); String[] color = request.getParameterValues("color"); String country = request.getParameter("country"); %> 您的名字:<%=name%><hr/> 您的性别:<%=gender%><hr/> 您喜欢的颜色:<%=gender%><hr/> 您的来自的国家:<%=country%><hr/> </body> </html>
结果图如下:
如果表单西欧字符,可借助java.net.URLDecoder的decode()方法来解码。
2.操作request范围的属性
主要依靠setAttribute(String attriName,Object attriValue)方法和Object getAttribute(String attriName)两个方法。
3.执行forward和include
例如:
getRequestDispatcher("/a.jsp").forward(request,response);
getRequestDispatcher("/a.jsp").include(request,response);
forward用户请求时,用户请求参数和request不会丢失,即forward还是原来的请求。
使用request的getDispatcher(String path)方法时,path参数必须以“/”开头
2.7.7 response对象
response代表服务器的响应。大部分时候,程序无需使用response响应客户端请求。完全有个更简单的out对象,是writer的实例,他代表输出流。但是writer是字符流。无法输出非字符内容。
还可以使用response来重定向请求,以及用于向客户端增加cookie.
1.response生成非字符响应
response对象实现了HTTPServletResponse接口,该接口提供了一个getOutputStream()方法,该方法返回响应输出字节流
<%@ page contentType="image/png" language="java" %> <%@ page import="java.awt.image.BufferedImage" %> <%@ page import="java.awt.*" %> <%@ page import="javax.imageio.ImageIO" %> <html> <head> <title>Title</title> </head> <body> <% BufferedImage image = new BufferedImage(340,160,BufferedImage.TYPE_INT_BGR); Graphics g = image.getGraphics(); g.fillRect(0,0,400,400); g.setColor(new Color(255,0,0)); g.fillArc(20,20,100,100,30,120); g.setColor(new Color(0,255,0)); g.fillArc(20,20,100,100,150,120); g.setColor(new Color(0,0,255)); g.fillArc(20,20,100,100,270,120); g.setColor(new Color(0,0,0)); g.setFont(new Font("Arial Black",Font.PLAIN,16)); g.drawString("red:climb",200,60); g.drawString("green:swim",200,100); g.drawString("blue:jump",200,140); g.dispose(); ImageIO.write(image,"png",response.getOutputStream()); %> </body> </html>
当然也可以使用img标签来显示这张图片,如下
<img src="img.jsp">
2.重定向
重定向是response另一个用处,与forward不同的是,重定向会丢失所有的请求参数和request范围的属性,因为重定向将生成第二次请求,与前一次请求不在同一个request范围内,所以发送一次的请求参数和request范围将会丢失。
HTTPServletResponse 提供了一个sendRedirect(String path)方法,该方法用于重定向到path资源,即重新向path发送请求。
执行重定向是地址栏的URL会编程目标页的URL
3.增加cookie
cookie用于网站记录用户的的某些信息,比如客户的用户名及用户的喜好等等。一旦用户下次登录,网站可以获取到用户的喜好,为客户提供更好的服务。与session不同的是:session会随浏览器的关闭而失效,但cookie会一直存放在客户端机器上,除非超出cookie的生命期限
出于安全性的原因,使用Cookie客户端浏览器必须支持cookie才可以,客户端浏览器完全可以设置禁用cookie
增加cookie也是使用response内置对象完成的,response提供了如下方法
void addCookie(Cookie cookie):增加cookie
在增加cookie之前,必须先创建cookie对象,按如下步骤:
访问客户端cookie使用request对象,request提供了getCookies()方法,该方法返回客户端机器上所有Cookie组成的数组,遍历数组,找到希望访问的cookie即可
默认情况下,Cookie不允许出现中文字符,如果需要中文字符的Cookie,可以借助于java.net.URLEncoder先对字符串编码,然后将编码后的结果设为cookie值,当成需要读取Cookie时,则应该先读取,然后使用java.net.URLEncoder对其进行解码。
<%@ page contentType="text/html;charset=UTF-8" language="java" errorPage="" %> <html> <head> <title>Title</title> </head> <body> <% Cookie c = new Cookie("cnName",java.net.URLDecoder.encode("孙悟空","gbk")); c.setMaxAge(24*3600); response.addCookie(c); Cookie[] cookies = request.getCookies(); for (Cookie cookie:cookies) { out.println(java.net.URLDecoder.decode(cookie.getValue())); } %> </body> </html>
2.7.8 session对象
session对象代表一次用户会话。一次用户会话的含义是用户客户端连接服务器开始,到客户端浏览器与服务器断开为止,这个过程就是一次会话。
session会话用于跟踪用户的会话信息,如判断用户是否登陆系统,或者在购物车应用中,用于跟踪用户购买的商品等。session范围的属性可以在多个页面跳转之间共享。一旦关闭浏览器,即Session结束,session范围内的属性将全部丢失。
session常用的方法有setAtttribute()和getAttribute();
关于session的一点还需要指出,session机制通常用于保存客户端的状态信息,这些状态信息需要保存到Web服务器的硬盘上,所以要求session里的属性值必须是可序列化的,否则引发不可序列化的异常。
标签:long iso 简单 问控制 tin expr 6.4 AC cookies
原文地址:https://www.cnblogs.com/yumiaoxia/p/9027031.html