Java 29---JSP

导读

1.过滤器Filter
2.什么是JSP
3.JSP原理
4. jsp文件创建及编码设置
5. JSP指令
6. JSP九大隐式对象
7. JSP语法
8. JSP标签

过滤器Filter

Javaweb中的过滤器可以拦截所有访问web资源的请求或响应操作。

创建步骤

1.创建一个类实现Filter接口
2.重写接口中方法 doFilter方法是真正过滤的。
3.在web.xml文件中配置
⚠️在Filter的doFilter方法内如果没有执行chain.doFilter(request,response)
那么资源是不会被访问到的。

Filter配置

<filter>
  	<filter-name>MyFilter</filter-name>
  	<filter-class>com.oracleoaec.filter.MyFilter</filter-class>
  	<init-param>
  		<param-name>encoding</param-name>
  		<param-value>utf-8</param-value>
  	</init-param>
  </filter>
  <filter-mapping>
  	<filter-name>MyFilter</filter-name>
	<url-pattern>/*</url-pattern>  	
  </filter-mapping>

完全匹配   以”/demo1”开始,不包含通配符*
目录匹配   以”/”开始  以*结束,当前目录所有
扩展名匹配  *.xxx  不能写成/*.xxx,当前目录所有.xxx如.html

FilterChain

FilterChain 是 servlet 容器为开发人员提供的对象,它提供了对某一资源的已过滤请求调用链的视图。过滤器使用 FilterChain 调用链中的下一个过滤器,如果调用的过滤器是链中的最后一个过滤器,则调用链末尾的资源。
问题:怎样可以形成一个Filter链?
只要多个Filter对同一个资源进行拦截就可以形成Filter链
问题:怎样确定Filter的执行顺序?
<filter-mapping>来确定

package com.oracleoaec.filter;

import java.io.IOException;
import java.util.Enumeration;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;

public class MyFilter implements Filter{
	private String encoding = null;
	@Override
	public void init(FilterConfig con) throws ServletException {
		System.out.println("过滤器创建了");
		encoding = con.getInitParameter("encoding");
		/*Enumeration<String> en = con.getInitParameterNames();
		while(en.hasMoreElements()){
			String value = en.nextElement();
		}*/
	}
	@Override
	public void destroy() {
		System.out.println("过滤器销毁了");
	}

	@Override
	public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain)
			throws IOException, ServletException {
		//全局编码过滤器
		//请求及响应的乱码解决
		req.setCharacterEncoding("utf-8");
		resp.setContentType("text/html;charset=utf-8");
//		System.out.println("过滤器干活了");
//		resp.getWriter().write("我是过滤器1");
		chain.doFilter(req, resp);//放行
//		resp.getWriter().write("我是过滤器2");
	}
}

Filter生命周期

1.当服务器启动,会创建Filter对象,并调用init方法,只调用一次.
2. 当访问资源时,路径与Filter的拦截路径匹配,会执行Filter中的doFilter方法,这个方法是真正拦截操作的方法.
3. 当服务器关闭时,会调用Filter的destroy方法来进行销毁操作.

编码问题

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

什么是JSP

JSP全称是Java Server Pages,它和servle技术一样,都是SUN公司定义的一种用于开发动态web资源的技术。
JSP这门技术的最大的特点在于,写jsp就像在写html,但它相比html而言,html只能为用户提供静态数据,而Jsp技术允许在页面中嵌套java代码,为用户提供动态数据。

JSP原理

1.Web服务器是如何调用并执行一个jsp页面的?

浏览器向服务器发请求,不管访问的是什么资源,其实都是在访问Servlet,所以当访问一个jsp页面时,其实也是在访问一个Servlet,服务器在执行jsp的时候,首先把jsp翻译成一个Servlet,所以我们访问jsp时,其实不是在访问jsp,而是在访问jsp翻译过后的那个Servlet,例如下面的代码:
index.jsp

 1<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
 2 <%
 3 String path = request.getContextPath();
 4 String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
 5 %>
 6 
 7 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
 8 <html>
 9   <head>
10     <base href="<%=basePath%>">
11     
12     <title>First Jsp</title>
13     
14   </head>
15   
16   <body>
17     <%
18         out.print("Hello Jsp");
19     %>
20   </body>
21 </html>

当我们通过浏览器访问index.jsp时,服务器首先将index.jsp翻译成一个index_jsp.class,在Tomcat服务器的work\Catalina\localhost\项目名\org\apache\jsp目录下可以看到index_jsp.class的源代码文件index_jsp.java
index_jsp这个类是继承 org.apache.jasper.runtime.HttpJspBase这个类的,
HttpJspBase类是继承HttpServlet的,所以HttpJspBase类是一个Servlet,而index_jsp又是继承HttpJspBase类的,所以index_jsp类也是一个Servlet,所以当浏览器访问服务器上的index.jsp页面时,其实就是在访问index_jsp这个Servlet,index_jsp这个Servlet使用_jspService这个方法处理请求。

2.Jsp页面中的html排版标签是如何被发送到客户端的?

在jsp页面中编写的html排版标签都是以out.write("<html标签>\r\n");的形式输出到浏览器,浏览器拿到html代码后才能够解析执行html代码。

3.Web服务器在调用jsp时,会给jsp提供一些什么java对象?

查看_jspService方法可以看到,Web服务器在调用jsp时,会给Jsp提供如下的8个java对象:
PageContext pageContext;
HttpSession session;
ServletContext application;
ServletConfig config;
JspWriter out;
Object page = this;
HttpServletRequest request,
HttpServletResponse response
其中page对象,request和response已经完成了实例化,而其它5个没有实例化的对象通过下面的方式实例化

1 pageContext = _jspxFactory.getPageContext(this, request, response,null, true, 8192, true);
2 application = pageContext.getServletContext();
3 config = pageContext.getServletConfig();
4 session = pageContext.getSession();
5 out = pageContext.getOut();

这8个java对象在Jsp页面中是可以直接使用的,如下所示:

<%
        session.setAttribute("name", "session对象");//使用session对象,设置session对象的属性
        out.print(session.getAttribute("name")+"<br/>");//获取session对象的属性
        pageContext.setAttribute("name", "pageContext对象");//使用pageContext对象,设置pageContext对象的属性
        out.print(pageContext.getAttribute("name")+"<br/>");//获取pageContext对象的属性
        application.setAttribute("name", "application对象");//使用application对象,设置application对象的属性
        out.print(application.getAttribute("name")+"<br/>");//获取application对象的属性
        out.print("Hello Jsp"+"<br/>");//使用out对象
        out.print("服务器调用index.jsp页面时翻译成的类的名字是:"+page.getClass()+"<br/>");//使用page对象
        out.print("处理请求的Servlet的名字是:"+config.getServletName()+"<br/>");//使用config对象
        out.print(response.getContentType()+"<br/>");//使用response对象
        out.print(request.getContextPath()+"<br/>");//使用request对象
%>

4.Jsp最佳实践

Jsp最佳实践就是jsp技术在开发中该怎么去用。
  不管是JSP还是Servlet,虽然都可以用于开发动态web资源。但由于这2门技术各自的特点,在长期的软件实践中,人们逐渐把servlet作为web应用中的控制器组件来使用,而把JSP技术作为数据显示模板来使用。其原因为,程序的数据通常要美化后再输出:让jsp既用java代码产生动态数据,又做美化会导致页面难以维护。让servlet既产生数据,又在里面嵌套html代码美化数据,同样也会导致程序可读性差,难以维护。因此最好的办法就是根据这两门技术的特点,让它们各自负责各的,servlet只负责响应请求产生数据,并把数据通过转发技术带给jsp,数据的显示jsp来做。

5.Tomcat服务器的执行流程

(1)客户端通过电脑连接服务器,因为是请求是动态的,所以所有的请求交给WEB容器来处理
(2)在容器中找到需要执行的*.jsp文件
(3)之后*.jsp文件通过转换变为*.java文件
(4)*.java文件经过编译后,形成*.class文件
(5)最终服务器要执行形成的*.class文件

在这里插入图片描述

jsp文件创建及编码设置

在WebContent下new一个JSPFile
在这里插入图片描述
可以如下图在文件中设置编码
在这里插入图片描述
还有一劳永逸的方法

在这里插入图片描述
在这里插入图片描述

JSP指令

JSP指令(directive)是为JSP引擎而设计的,它们并不直接产生任何可见输出,而只是告诉引擎如何处理JSP页面中的其余部分。
  在JSP 2.0规范中共定义了三个指令:
1.page指令
2.Include指令
3.taglib指令
  JSP指令的基本语法格式:<%@ 指令 属性名="值" %>
  例如:

<%@ page contentType="text/html;charset=utf-8"%>
<%@ page import="java.util.Date"%>

<%@ page contentType="text/html;charset=utf-8" import="java.util.Date"%>

JSP 2.0规范中定义的page指令的完整语法:

<%@ page 
    [ language="java" ] 
    [ extends="package.class" ] 
    [ import="{package.class | package.*}, ..." ] 
    [ session="true | false" ] 
    [ buffer="none | 8kb | sizekb" ] 
    [ autoFlush="true | false" ] 
    [ isThreadSafe="true | false" ] 
    [ info="text" ] 
    [ errorPage="relative_url" ] 
    [ isErrorPage="true | false" ] 
    [contentType="mimeType [ ;charset=characterSet ]" | "text/html ; charset=ISO-8859-1" ] 
    [ pageEncoding="characterSet | ISO-8859-1" ] 
    [ isELIgnored="true | false" ] 
%>

page指令的import属性

在Jsp页面中,Jsp引擎会自动导入下面的包

java.lang.*
javax.servlet.*
javax.servlet.jsp.*
javax.servlet.http.*

page指令的errorPage属性

errorPage属性的设置值必须使用相对路径,如果以“/”开头,表示相对于当前Web应用程序的根目录(注意不是站点根目录),否则,表示相对于当前页面
可以在web.xml文件中使用<error-page>元素为整个Web应用程序设置错误处理页面。
<error-page>元素有3个子元素,<error-code>、<exception-type>、<location>
<error-code>子元素指定错误的状态码,例如:<error-code>404</error-code>
<exception-type>子元素指定异常类的完全限定名,例如:<exception-type>java.lang.ArithmeticException</exception-type>
<location>子元素指定以“/”开头的错误处理页面的路径,例如:<location>/ErrorPage/404Error.jsp</location>
如果设置了某个JSP页面的errorPage属性,那么在web.xml文件中设置的错误处理将不对该页面起作用。

方式一:

<%@ page language="java" import="java.util.*" errorPage=" error.jsp" pageEncoding="UTF-8"%>

方式二:

<!-- 针对404错误的处理页面 -->
  <error-page>
      <error-code>404</error-code>
      <location>404Error.jsp</location>
  </error-page>
<!-- 5秒钟后自动跳转回首页 -->
<meta http-equiv="refresh" content="5;url=${pageContext.request.contextPath}/index.jsp">
5秒钟后自动跳转回首页,如果没有跳转,请点击
<a href="${pageContext.request.contextPath}/index.jsp">这里</a>

使用page指令的的isErrorPage属性显式声明页面为错误页面

如果某一个jsp页面是作为系统的错误处理页面,那么建议将page指令的isErrorPage属性(默认为false)设置为"true"来显式声明这个Jsp页面是一个错误处理页面。
例如:将error.jsp页面显式声明为错误处理页面。
将error.jsp页面显式声明为错误处理页面后,有什么好处呢,好处就是Jsp引擎在将jsp页面翻译成Servlet的时候,在Servlet的 _jspService方法中会声明一个exception对象,然后将运行jsp出错的异常信息存储到exception对象中
如:调用exception.getMessage();

include指令

@include可以包含任意的文件,当然,只是把文件的内容包含进来。
  include指令用于引入其它JSP页面,如果使用include指令引入了其它JSP页面,那么JSP引擎将把这两个JSP翻译成一个servlet。所以include指令引入通常也称之为静态引入。
语法:<%@ include file="relativeURL"%>,其中的file属性用于指定被引入文件的路径。路径以“/”开头,表示代表当前web应用。
include指令细节注意问题:

被引入的文件必须遵循JSP语法。
被引入的文件可以使用任意的扩展名,即使其扩展名是html,JSP引擎也会按照处理jsp页面的方式处理它里面的内容,为了见明知意,JSP规范建议使用.jspf(JSP fragments(片段))作为静态引入文件的扩展名。
由于使用include指令将会涉及到2个JSP页面,并会把2个JSP翻译成一个servlet,所以这2个JSP页面的指令不能冲突(除了pageEncoding和导包除外)。

新建head.jspf页面和foot.jspf页面,分别作为jsp页面的头部和尾部,存放于WebRoot下的jspfragments文件夹中,三个文件代码如下:

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<h1 style="color:red;">网页头部</h1>

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<h1 style="color:blue;">网页尾部</h1>

<%@include file="head.jspf" %>
<h1>网页主体内容</h1>
<%@include file="foot.jspf" %>

JSP九大隐式对象

认识九个隐式对象

在这里插入图片描述
request,response,session,application,config这些对象在前面都已经作了详细的介绍,这里重点介绍一下剩下的pageContext对象,out对象,page对象。

page对象

page对象表示当前一个JSP页面,可以理解为一个对象本身,即:把一个JSP当作一个对象来看待。page对象在开发中几乎不用,了解一下即可

out对象

out对象用于向客户端发送文本数据。
out对象是通过调用pageContext对象的getOut方法返回的,其作用和用法与ServletResponse.getWriter方法返回的PrintWriter对象非常相似。
JSP页面中的out对象的类型为JspWriter,JspWriter相当于一种带缓存功能的PrintWriter,设置JSP页面的page指令的buffer属性可以调整它的缓存大小,甚至关闭它的缓存。
只有向out对象中写入了内容,且满足如下任何一个条件时,out对象才去调用ServletResponse.getWriter方法,并通过该方法返回的PrintWriter对象将out对象的缓冲区中的内容真正写入到Servlet引擎提供的缓冲区中:
设置page指令的buffer属性关闭了out对象的缓存功能
out对象的缓冲区已满
整个JSP页面结束

pageContext对象

pageContext对象是JSP技术中最重要的一个对象,它代表JSP页面的运行环境,这个对象不仅封装了对其它8大隐式对象的引用,它自身还是一个域对象(容器),可以用来保存数据。并且,这个对象还封装了web开发中经常涉及到的一些常用操作,例如引入和跳转其它资源、检索其它域对象中的属性等。

getException方法返回exception隐式对象
getPage方法返回page隐式对象
getRequest方法返回request隐式对象
getResponse方法返回response隐式对象
getServletConfig方法返回config隐式对象
getServletContext方法返回application隐式对象
getSession方法返回session隐式对象
getOut方法返回out隐式对象

pageContext封装其它8大内置对象的意义

如果在编程过程中,把pageContext对象传递给一个普通java对象,那么这个java对象将可以获取8大隐式对象,此时这个java对象就可以和浏览器交互了,此时这个java对象就成为了一个动态web资源了,这就是pageContext封装其它8大内置对象的意义,把pageContext传递给谁,谁就能成为一个动态web资源,那么什么情况下需要把pageContext传递给另外一个java类呢,什么情况下需要使用这种技术呢,在比较正规的开发中,jsp页面是不允许出现java代码的,如果jsp页面出现了java代码,那么就应该想办法把java代码移除掉,我们可以开发一个自定义标签来移除jsp页面上的java代码,首先围绕自定义标签写一个java类,jsp引擎在执行自定义标签的时候就会调用围绕自定义标签写的那个java类,在调用java类的时候就会把pageContext对象传递给这个java类,由于pageContext对象封装了对其它8大隐式对象的引用,因此在这个java类中就可以使用jsp页面中的8大隐式对象(request,response,config,application,exception,Session,page,out)了,pageContext对象在jsp自定义标签开发中特别重要。
从域中获取数据

public java.lang.Object findAttribute(java.lang.String name)

findAttribute方法按照查找顺序"page→request→session→application"在这四个对象中去查找,只要找到了就返回属性值,如果四个对象都没有找到要查找的属性,则返回一个null。
EL表达式语句在执行时,会调用pageContext.findAttribute方法,用标识符为关键字,分别从page、request、 session、application四个域中查找相应的对象,找到则返回相应对象,找不到则返回”” (注意,不是null,而是空字符串)。
pageContext对象中封装了访问其它域的方法

1 .public java.lang.Object getAttribute(java.lang.String name,int scope)
2 .public void setAttribute(java.lang.String name, java.lang.Object value,int scope)
3. public void removeAttribute(java.lang.String name,int scope)

代表各个域的常量

1 PageContext.APPLICATION_SCOPE
2 PageContext.SESSION_SCOPE
3 PageContext.REQUEST_SCOPE
4 PageContext.PAGE_SCOPE 

PageContext引入和跳转到其他资源

PageContext类中定义了一个forward方法(用来跳转页面)和两个include方法(用来引入页面)来分别简化和替代RequestDispatcher.forward方法和include方法。
方法接收的资源如果以“/”开头, “/”代表当前web应用。

JSP语法

任何语言都有自己的语法,JAVA中有,JSP虽然是在JAVA上的一种应用,但是依然有其自己扩充的语法,而且在JSP中,所有的JAVA语句都可以使用。

一、JSP模版元素

JSP页面中的HTML内容称之为JSP模版元素。
  JSP模版元素定义了网页的基本骨架,即定义了页面的结构和外观。

二、JSP表达式

JSP脚本表达式(expression)用于将程序数据输出到客户端

 语法:<%= 变量或表达式 %>
  举例:输出当前系统时间:
 <%= new java.util.Date() %> 

JSP引擎在翻译脚本表达式时,会将程序数据转成字符串,然后在相应位置用out.print(…) 将数据输给客户端。
JSP脚本表达式中的变量或表达式后面不能有分号(;)。

三、JSP脚本片断

JSP脚本片断(scriptlet)用于在JSP页面中编写多行Java代码。语法:
    <% 
        多行java代码 
    %>

在<% %>中可以定义变量、编写语句,不能定义方法。

范例:在Scriptlet中定义变量、编写语句
<%
    int sum=0;//声明变量
    /*编写语句*/
    for (int i=1;i<=100;i++){
        sum+=i;
    }
    out.println("<h1>Sum="+sum+"</h1>");
%>

Ps:多个多个脚本片断中的代码可以相互访问

四、JSP声明

JSP页面中编写的所有代码,默认会翻译到servlet的service方法中, 而Jsp声明中的java代码被翻译到_jspService方法的外面。语法:

 	<%! 
    java代码
    %>

所以,JSP声明可用于定义JSP页面转换成的Servlet程序的静态代码块、成员变量和方法 。
多个静态代码块、变量和函数可以定义在一个JSP声明中,也可以分别单独定义在多个JSP声明中。
  JSP隐式对象的作用范围仅限于Servlet的_jspService方法,所以在JSP声明中不能使用这些隐式对象。

<%!
static { 
    System.out.println("loading Servlet!"); 
}

private int globalVar = 0;

public void jspInit(){
    System.out.println("initializing jsp!");
}
%>

<%!
public void jspDestroy(){
    System.out.println("destroying jsp!");
}
%>

五、JSP注释

在JSP中,注释有两大类:

   显式注释:直接使用HTML风格的注释:<!- - 注释内容- ->
   隐式注释:直接使用JAVA的注释://、/*……*/
 JSP自己的注释:<%- - 注释内容- -%>
Ps: JAVA注释和JSP注释在浏览器中查看源文件时是看不到注释的内容的

JSP标签

一、JSP标签介绍
  JSP标签也称之为Jsp Action(JSP动作)元素,它用于在Jsp页面中提供业务逻辑功能,避免在JSP页面中直接编写java代码,造成jsp页面难以维护。
二、JSP常用标签
  jsp的常用标签有以下三个

<jsp:include>标签 
<jsp:forward>标签
<jsp:param>标签

2.1、jsp:include标签
  jsp:include标签用于把另外一个资源的输出内容插入进当前JSP页面的输出内容之中,这种在JSP页面执行时的引入方式称之为动态引入。
语法:

    <jsp:include page="relativeURL | <%=expression%>" flush="true|false" />
  page属性用于指定被引入资源的相对路径,它也可以通过执行一个表达式来获得。
  flush属性指定在插入其他资源的输出内容时,是否先将当前JSP页面的已输出的内容刷新到客户端。 
范例:使用jsp:include标签引入资源
<jsp:include page="head.jsp"/>
<h1>网页主体内容</h1>
<jsp:include page="foot.jsp"/>

2.2、jsp:include标签与include指令的区别
  jsp:include标签是动态引入, jsp:include标签涉及到的2个JSP页面会被翻译成2个servlet,这2个servlet的内容在执行时进行合并。
  而include指令是静态引入,涉及到的2个JSP页面会被翻译成一个servlet,其内容是在源文件级别进行合并。
2.3、jsp:forward标签
  jsp:forward标签用于把请求转发给另外一个资源。
  语法:

      <jsp:forward page="relativeURL | <%=expression%>" /> 
  page属性用于指定请求转发到的资源的相对路径,它也可以通过执行一个表达式来获得。
范例:使用<jsp:forward>标签转发页面

a.jsp
<jsp:forward page="/a.jsp"/>
<jsp:include page="a.jsp">
    <jsp:param name="parm1" value="hello" />
    <jsp:param name="parm2" value="gacl" />
</jsp:include>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值