Java Server Page

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

workspace\.metadata\.plugins\org.eclipse.wst.server.core\tmp0\work\Catalina\localhost\项目名\org\apache\jsp\xxx_jsp.java

javaWeb2之Jsp 随笔 第1张

SRE实战 互联网时代守护先锋,助力企业售后服务体系运筹帷幄!一键直达领取阿里云限量特价优惠。

运行tomcat后,被装载在:

tomcat_home\work\Catalina\localhost\项目名\org\apache\xxx_jsp.java

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

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)。
7.out:JspWriter对象,调用out.print(),直接把字符串打印在浏览器上。
8.page:指向当前JSP对应的Servlet对象的引用,但为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这三种指令。

javaWeb2之Jsp 随笔 第3张

page指令

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

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

①. import 属性: 指定当前 JSP 页面对应的 Servlet 需要导入的类.

<%@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 隐藏变量. 需要注意的是: 若指定 isErrorPage="true", 并使用 exception 的方法了, 一般不建议能够直接访问该页面.,那如何使客户不能直接访问某一个页面呢 ? 对于 Tomcat 服务器而言, WEB-INF 下的文件是不能通过在浏览器中直接输入地址的方式来访问的. 但通过请求的转发是可以的,所以把通常它们放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 页面的字符编码. 通常情况下该值和 contentType 中的 charset 一致。

⑥. isELIgnored: 指定当前 JSP 页面是否可以使用 EL 表达式. 通常取值为 false.

include 指令

1). include 指令用于通知 JSP 引擎在翻译当前 JSP 页面时将其他文件中的内容合并进当前 JSP 页面转换成的 Servlet 源文件中,这种在源文件级别进行引入的方式称之为静态引入, 当前JSP页面与静态引入的页面紧密结合为一个Servlet。
javaWeb2之Jsp 随笔 第5张
静态引入:用于通知JSP引擎在翻译当前JSP页面时将其他文件中的内容合并进当前页面转换成的servlet源文件中。最终只有一个.java文件。
查看原文件:
javaWeb2之Jsp 随笔 第6张

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") 获取到传入的请求参数.

javaWeb2之Jsp 随笔 第7张

自定义JSP标签

javaWeb2之Jsp 随笔 第8张

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)标签

javaWeb2之Jsp 随笔 第9张

请求转发与重定向

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

重定向

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

response.sendRedirect(path);

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

转发

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

        //请求的转发.
        //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 站点的根目录.

javaWeb2之Jsp 随笔 第12张

中文乱码问题

jsp编码设置

javaWeb2之Jsp 随笔 第13张
1). 在 JSP 页面上输入中文, 请求页面后不出现乱码: 保证 contentType="text/html; charset=UTF-8",
pageEncoding="UTF-8" charset 和 pageEncoding 的编码一致, 且都支持中文. 通常建议取值为UTF-8

    还需保证浏览器的显示的字符编码也和请求的 JSP 页面的编码一致. 
    

2). 获取中文参数值: 默认参数在传输过程中使用的编码为 ISO-8859-1

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

②. 对于 GET 请求: 前面的方式对于 GET 无效. 可以通过修改 Tomcat 的 server.xml 文件的方式.
参照 http://localhost:8989/docs/config/index.html 文档的 useBodyEncodingForURI 属性.
为 Connector 节点添加 useBodyEncodingForURI="true" 属性即可.

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

本地的和eclipse的都改:
javaWeb2之Jsp 随笔 第14张
javaWeb2之Jsp 随笔 第15张

路径问题

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获取);

扫码关注我们
微信号:SRE实战
拒绝背锅 运筹帷幄