zoukankan      html  css  js  c++  java
  • javaWeb2之Jsp

    Java Server Page

    放在除WEB-INF(放web项目的隐私文件)外的其他任何目录中。
    Java服务器端网页,实现在HTML页面编写Java代码实现动态内容,一种简化Servlet编写的技术(不用在java里拼写html)
    本质上是一个Servlet,每个JSP页面在第一次被访问时,JSP引擎会将它翻译成一个Servlet程序(java文件),接着编译为class文件,然后由web容器(Servlet引擎,tomcat)去装载、执行。

    workspace.metadata.pluginsorg.eclipse.wst.server.core	mp0workCatalinalocalhost项目名orgapachejspxxx_jsp.java
    


    HttpJspBase看源码知,它继承了HttpServlet!

    运行tomcat后,被装载在:

    tomcat_homeworkCatalinalocalhost项目名orgapachexxx_jsp.java
    

    整个过程在Servlet容器的控制下将请求的JSP资源转变为Servlet之后,同样会经历Servlet的实例化、初始化、就绪、销毁四部分的生命周期。从图中可以看到,之所以第一次请求一个JSP页面会比之后的请求响应慢一些,就是要经过转译成Servlet,编译成class这样一个过程。

    JSP页面的隐含对象

    没有声明就可以引用的,源码:

    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;
    
    	//...
    	
    	//使用  <% %> 编写的代码会出现在此位置. 可以用到 request, response, pageContext, session
    	//application, config, out, page 这 8 个隐含对象. (实际上还可以使用一个叫 exception 的隐含对象)
        
    }
    

    1.request:HttpServletRequest,属性的作用范围仅限于同一个请求。
    2.response:HttpServletResponse,JSP页面里几乎不用。
    3.pageContext:PageContext,页面的上下文,可以从该对象中获取其他8个隐含对象和当前页面其他信息(标签),属性作业范围仅限于当前JSP页面。
    4.session:HttpSession,代表浏览器和服务器的一次会话(浏览器打开直到关闭即一次会话)
    5.application:ServletContext,代表当前Web应用,属性作业范围仅限于当前Web应用。只要在一处设置属性, 在其他各处的 JSP 或 Servlet 中都可以获取到。
    6.config:当前JSP对应的Servlet的ServletConfig对象(几乎不用)。若需访问当前JSP配置的初始化参数,需要通过映射地址(url-pattern,如果你给这个jsp文件在web.xml配了的话)。
    7.out:JspWriter对象,调用out.print(),直接把字符串打印在浏览器上。
    8.page:指向当前JSP对应的Servlet对象的引用(this),但为Object类型,只能调用Object类的方法(几乎不用)。
    9.exception:在声明了page指令的isErrorPage="true"时才可用。

    <%@ page isErrorPage="true" %>
    

    pageContext, request, session, application(对属性的作用域的范围从小到大) ,都有这些方法!这四个对象也称之为域对象:

    void setAttribute(String name, Object o): 设置属性  
    Object getAttribute(String name): 获取指定的属性
    Enumeration getAttributeNames(): 获取所有的属性的名字组成的 Enumeration 对象
    removeAttribute(String name): 移除指定的属性 
    pageContext, request, session, application 对象
    

    JSP模版元素:

    JSP页面中的静态HTML内容称 。

    JSP脚本片断(scriptlet)

    是指嵌套在<% 和 %>之中的一条或多条Java程序代码。 多个脚本片断中的代码可以相互访问。

    <% 
    	String ageStr = request.getParameter("age");
    	Integer age = Integer.parseInt(ageStr);
    	
    	if(age >= 18){
    %>
    		成人...
    <%
    	}else{
    %>
    		未成人...
    <%
    	}
    %>
    

    JSP表达式

    提供了将一个 java 变量或表达式的计算结果输出到客户端的简化方式,它将要输出的变量或表达式直接封装在<%= 和 %>之中。

    <% 
    	Date date = new Date();
    	out.print(date);
    %>
    <!--jsp表达式-->
    <%= date %>
    

    JSP 声明

    JSP 声明将 Java 代码封装在<%!和 %>之中,它里面的方法声明代码将被插入进 Servle t的 _jspService 方法的外面,不然报错!(在 JSP 页面中几乎从不这样使用)。

    JSP指令

    eclipse新建jsp文件的第一、二行,在目前的JSP 2.0中,定义了page、include 和 taglib这三种指令。

    page指令


    1). page指令用于定义JSP页面的各种属性, 无论page指令出现在JSP页面中的什么地方, 它作用的都是整个JSP页面, 为了保持程序的可读性和遵循良好的编程习惯, page指令最好是放在整个JSP页面的起始位置。

    2). page 指令常用的属性:

    ①. import 属性: 指定当前 JSP 页面对应的 Servlet 需要导入的类。
    查看jsp翻译成的servlet文件源码可知,这些包已经导入过:

    import javax.servlet.*;
    import javax.servlet.http.*;
    import javax.servlet.jsp.*;  
    
    <%@page import="java.text.DateFormat"%>
    

    ②. session 属性: 取值为 true 或 false, 指定当前页面的 session 隐藏变量是否可用, 也可以说访问当前页面时是否一定要生成 HttpSession对象.

    <%@ page session="false" %> 
    

    ③. errorPage 和 isErrorPage:
    errorPage 指定若当前页面出现错误的实际响应页面时什么. 其中 / 表示的是当前 WEB 应用的根目录.

    <%@ page errorPage="/error.jsp" %> 
    

    在响应 error.jsp 时, JSP 引擎使用的请求转发的方式!
    isErrorPage 指定当前页面是否为错误处理页面, 可以说明当前页面是否可以使用 exception 隐藏变量. 需要注意的是: error.jsp 中,若指定 isErrorPage="true", 并使用 exception 的方法了, 一般不建议能够直接访问该页面。直接访问,exception是null!只能出错情况才让看!
    那如何使客户不能直接访问某一个页面呢 ? 对于 Tomcat 服务器而言, WEB-INF 下的文件是不能通过在浏览器中直接输入地址的方式来访问的(直接访问404)。 但通过请求的转发是可以的,所以把通常它们放WEB-INF文件夹里!

    还可以在 web.xml 文件中配置错误页面:

    	<error-page>
      	<!-- 指定出错的代码: 404 没有指定的资源, 500 内部错误. -->
    	  	<error-code>404</error-code>
    	  	<!-- 指定响应页面的位置 -->
    	  	<location>/WEB-INF/error.jsp</location>
    	</error-page>
    	  
    	<error-page>
    	  	<!-- 指定异常的类型 -->
    	  	<exception-type>java.lang.ArithmeticException</exception-type>
    	  	<location>/WEB-INF/error.jsp</location>
    	</error-page>
    

    ④. contentType: 指定当前 JSP 页面的响应类型. 实际调用的是 response.setContentType("text/html; charset=UTF-8");
    通常情况下, 对于 JSP 页面而言其取值均为 text/html; charset=UTF-8. charset 指定返回的页面的字符编码是什么(服务器发送给客户端时的内容编码), 通常取值为 UTF-8。

    ⑤. pageEncoding: 指定当前 JSP 页面的字符编码(把jsp翻译成utf-8的java代码时的编码),通常情况下该值和 contentType 中的 charset 一致。
    pageencoding是规则的遵循者,chartset是规则的制定者
    ps:head标签里这里的charset的意思?

    ⑥. isELIgnored: 指定当前 JSP 页面是否可以使用 EL 表达式. 通常取值为 false,表示不忽略el表达式。

    include 指令

    1). include 指令用于通知 JSP 引擎在翻译当前 JSP 页面时将其他文件中的内容合并进当前 JSP 页面转换成的 Servlet 源文件中,这种在源文件级别进行引入的方式称之为静态引入, 当前JSP页面与静态引入的页面紧密结合为一个Servlet。

    静态引入:用于通知JSP引擎在翻译当前JSP页面时将其他文件中的内容合并进当前页面转换成的servlet源文件中。最终只有一个.java文件。
    查看原文件:

    2). file属性的设置值必须使用相对路径

    3). 如果以 / 开头,表示相对于当前WEB应用程序的根目录(注意不是站点根目录),否则,表示相对于当前文件

    taglib 指令

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

    JSP注释

    <%-- JSP 注释 --%>
    区别: JSP 注释可以阻止 Java 代码的执行.。

    JSP标签

    JSP标签可代替java代码,使JSP文件变得简洁,便于维护和代码复用。

    include标签

    <jsp:include page="b.jsp"></jsp:include>
    

    动态引入: 并不是像 include 指令生成一个 Servlet 源文件, 而是生成两个 Servlet 源文件, 然后通过一个方法的方式把目标页面包含进来:

    org.apache.jasper.runtime.JspRuntimeLibrary.include(request, response, "b.jsp", out, false);

    forward标签

    <jsp:forward page="/include/b.jsp"></jsp:forward>	   
    

    相当于.

    <% 
    	request.getRequestDispatcher("/include/b.jsp").forward(request, response);
    %>
    

    但使用 jsp:forward 可以使用 jsp:param 子标签向 b.jsp 传入一些参数. 同样 jsp:include 也可以使用 jsp:param 子标签.

    <jsp:forward page="/include/b.jsp">
    	<jsp:param value="abcd" name="username"/>
    </jsp:forward>	
    

    OR

    <jsp:include page="/include/b.jsp">
    	<jsp:param value="abcd" name="username"/>
    </jsp:include>
    

    在 b.jsp 页面可以通过 request.getParameter("username") 获取到传入的请求参数.

    自定义JSP标签

    EL表达式

    EL(Expression Language) 是为了使JSP写起来更加简单。用于给jsp标签的属性赋值,也可以直接输出。
    表达式语言的灵感来自于 ECMAScript 和 XPath 表达式语言,它提供了在 JSP 中简化表达式的方法,让Jsp的代码更加简化。
    1.访问bean的属性
    如果该属性没有被赋过值(或是null)或取值时对象绑定名写错,会输出"",而非null。但属性名写错,会报错。

    ${user.name}
    

    容器会依次从pageContext、request、session、application中查找绑定名为user的对象(getAttribute),找到之后,调用该对象的getName()方法,找不到,输出""。
    如果要查指定范围的,可以使用pageScope等xxScope,如${requestScope.user.name}

    ${user['name']}
    

    等价于上面的。

    2.读取请求参数值

    ${param.username}
    

    等价于 request.getParameter("username");

    ${paramValues.username}
    

    等价于 request.getParameterValues("username");

    jstl(java standard taglib)标签

    请求转发与重定向

    请求到达容器,容器会创建request和response对象。当响应发送完毕,容器会删除request和response对象,即request和response对象的生存时间是一次请求与响应期间。

    重定向

    浏览器发送请求访问A,A可以发送状态码302和Location消息头到浏览器,于是浏览器立即向Location发新的请求。重定向之前,容器会清空response对象上存放的数据。一件事情已经做完了,再坐下一件事。

    response.sendRedirect(path);
    

    特点:
    重定向的地址是任意的;
    重定向后浏览器地址会变为重定向地址。

    转发

    浏览器请求访问A,A通知容器去调用B,是一件事情没有做完,调用另一个组件继续做。转发涉及的各个Web组件共享一个request和response对象。

    		//请求的转发.
    		//1. 调用 HttpServletRequest 的 getRequestDispatcher() 方法获取  RequestDispatcher 对象
    		//传入要转发的地址
    		String path = "testServlet";
    		RequestDispatcher requestDispatcher = request.getRequestDispatcher("/" + path);
    		
    		//2.进行请求的转发. 
    		requestDispatcher.forward(request, response); 
    

    特点:
    发生在服务器端(由容器实现),客户端只发了一个请求,浏览器不知道转发过程,所以地址栏没有变化。
    转发的地址必须是同一个web应用内部某个地址。
    转发过程里涉及到的web组件共享同一个reqest、response
    forward之后的其他语句还是会执行。

    本质区别:

    请求的转发只发出了一次请求, 而重定向则发出了两次请求.
    ①. 请求的转发: 地址栏是初次发出请求的地址.
    请求的重定向: 地址栏不再是初次发出的请求地址. 地址栏为最后响应的那个地址

    ②. 请求转发: 在最终的 Servlet 中, request 对象和中转的那个 request 是同一个对象.
    请求的重定向: 在最终的 Servlet 中, request 对象和中转的那个 request 不是同一个对象.

    ③. 请求的转发: 只能转发给当前 WEB 应用的的资源
    请求的重定向: 可以重定向到任何资源.

    ④. 请求的转发: / 代表的是当前 WEB 应用的根目录
    请求的重定向: / 代表的是当前 WEB 站点的根目录.

    中文乱码问题

    jsp编码设置


    1). JSP 页面上有中文, 请求页面展示中文信息时不出现乱码:
    保证 contentType="text/html; charset=UTF-8", pageEncoding="UTF-8" charset 和 pageEncoding 的编码一致, 且都支持中文. 通常建议取值为UTF-8。
    另外还需保证浏览器的显示的字符编码也和请求的 JSP 页面的编码一致!

    2). 通过页面输入框获取中文参数值,再进行展示不出现乱码:
    默认参数在传输过程中使用的编码为 ISO-8859-1

    ①. 对于 POST 请求: POST请求参数在请求体中,只要在获取请求信息之前(在调用 request.getParameter 或者是 request.getReader 等), 调用 request.setCharacterEncoding("UTF-8")

    ②. 对于 GET 请求: 前面的方式对于 GET 如果无效。
    可以通过先解码后编码的方式:

       String val = request.getParameter("username");
    		String username = new String(val.getBytes("iso-8859-1"), "UTF-8");
    		out.print(username); 
    

    也可以通过修改 Tomcat 的 server.xml 文件的方式,使得前面的方式对于 GET 起效:
    参照 http://localhost:8989/docs/config/index.html 文档的 useBodyEncodingForURI 属性,
    为 Connector 节点添加 useBodyEncodingForURI="true" 属性,或者添加URIEncoding=utf-8

    <Connector connectionTimeout="20000" port="8989" protocol="HTTP/1.1" redirectPort="8443" useBodyEncodingForURI="true"/>  
    

    本地的和映射到eclipse的server的都改:

    3).浏览器以get方式提交数据时,参数有中文的情况
    (RFC3986文档规定)首先url的编码格式采用的是ASCII码,如果url包含中文,客户端浏览器会按照操作系统的字符集进行编码提交到服务器,服务器会按照配置的字符集进行解码,所以如果两者不一致就会导致乱码。解决如下:

    encodeURI函数采用UTF-8对URL进行编码。如果只进行一次encodeURI,得到的是UTF-8形式的URL,服务器端通过request.getParameter()解码查询参数(通常是iso-8859-1)就会得到乱码。
    如果进行两次encodeURI,第一次编码得到的是UTF-8形式的URL,第二次编码得到的依然是UTF-8形式的URL,但是在效果上相当于首先进行了一次UTF-8编码(此时已经全部转换为ASCII字符),再进行了一次iso-8859-1编码,因为对英文字符来说UTF-8编码和ISO-8859-1编码的效果相同。在服务器端,首先通过request.getParameter()自动进行第一次解码(可能是gb2312,gbk,utf-8,iso-8859-1等字符集,对结果无影响)得到ascii字符,然后再使用UTF-8进行第二次解码,通常使用java.net.URLDecoder("","UTF-8")方法。
    两次编码两次解码的过程为:
    UTF-8编码->UTF-8(iso-8859-1)编码->iso-8859-1解码->UTF-8解码,编码和解码的过程是对称的,所以不会出现乱码。
    参考:https://blog.csdn.net/zqd_java/article/details/53924769

    PS:
    请求出现RFC 7230 and RFC3986的错误

    路径问题

    javaWeb中的"/"

    什么情况下”/“表示当前web应用的根路径即http://localhost:8080/Dive/

    需要交由servlet容器处理的时候
    

    1)请求转发时

    request.getRequestDispatcher("/jspDir/b.jsp").forward(request,response);
    

    2)配置web.xml文件中映射servlet访问路径时

    什么情况下”/“表示表示web站点的根路径即http://localhost:8080/

    需要交由浏览器处理的时候
    1)超链接href的值;
    2)表单中的action值;
    3)请求重定向

    开发过程中,建议写“绝对路径”,"/"代表的是站点的根目录时,在后面直接加contextPath(request或application获取);
    如果不愿意写,也可以通过head元素里的base标签指定基本 URL 来解析所有的相对 URL。

  • 相关阅读:
    sprint1的个人总结及《构建之法》8、9、10章读后感
    操作系统作业----实验三
    《构建之法》第六,七章读后感
    实验二 作业调度模拟程序 报告
    参考的博客园
    复利计算器6.0
    复利计算-做汉堡,结对2.
    复利计算器5.0
    0608典型用户
    0603我的感受
  • 原文地址:https://www.cnblogs.com/xiaobingzi/p/10752555.html
Copyright © 2011-2022 走看看