Servlet 之jsp(上)

  jsp与Servlet本质都是一样的。jsp是在html中嵌入java代码,servlet是在java代码中嵌入html。

  tomcat在获得jsp页面后,在work目录下,会将其转换为servlet的java文件(如hello.jsp--->hello_jsp.java),而后对其进行编译,这里分析jsp各个部分功能的时候,注意它转为servlet中的代码结构。hello_jsp.hava中的_jspService(final javax.servlet.http.HttpServletRequest request, final javax.servlet.http.HttpServletResponse response)方法相当于Servlet中的service(javax.servlet.http.HttpServletRequest request, final javax.servlet.http.HttpServletResponse response)。

--------------------------------------------------------------------------------------------------->

  JSP脚本元素 

  表达式: <%= 表达式 %> 将表达式结果输出到浏览器,底层解析后 out.print(表达式);
  代码片段: <% java 代码 %> 将“java代码”完整复制到service方法体中。 service(){ java代码片段}
  脚本声明: <%! 声明内容 %> 将“声明内容”完整复制到class类体中, class hello { 脚本声明 }

<body>
    Hello again!
    <br>
    <%=i%>
    <% int i = 5; %>
    <%=i%>
    <%! int i = 10; %>
    <% i++; %>
    <%=this.i%>
</body>

这里<%! %>属于声明,所以其中i=10为hello_jsp.java代码中的成员变量,而<% int i = 5 ;%>会被直接搬到_jspService(httpServletRequest, httpServletResponse)方法体中,所以属于局部变量,而<%= %>中的内容会在搬到方法体中用out.print()进行输出。

--------------------------------------------------------------------------------------------------->

  jsp中的注释分<%-- --%>,注释部分的内容到java源码中就不存在了。

--------------------------------------------------------------------------------------------------->

  JSP指令

  jsp在web容器中被转为servlet,文件编码、依赖类、发送给浏览器输出编码、行为等等需要jsp页面与tomcat进行约定,这个依据就是jsp指令。指令的格式为:<%@指令名称  属性=值 属性=值  .....%>,指令有三,page, include, taglib。

  <%@page  属性=值 属性=值  .....%>

>使用
* 一个指令可以编写多个属性
* 相同指令可以使用多次
* 指令可以使用在任意位置
* 大部分属性只能使用一次,否则jsp将抛出异常。之后少数可以重复使用。例如:import

  >编码

pageEncoding :当前页面的编码
contentType:jsp生成servlet响应给浏览器编码
注意:一般一致
对比:
如果只有pageEncoding,设置当前编码,也可以设置响应编码
如果只有contentType,可以设置响应编码,也可以设置当前页面编码

  >缓存机制

buffer : 设置缓存大小,默认:8kb
autoFlush : 缓存如果溢出,将自动刷新,常设置为true,设置false有可能异常:java.io.IOException: Error: JSP Buffer overflow

  >常用

session : 表示当前jsp页面是否可以使用session 内置对象。 true:可以使用 jsp脚本(表达式、代码块)中 使用 session
import : jsp使用其他类,进行导包。 分别导入:java.util.List 一次性导入:java.util.List,java.util.ArrayList 星号:java.util.*
language :表示jsp支持嵌入语言(java)
info ,使用在servlet接口第5个方法,getServletInfo()

  >错误处理机制

  在每个展示页面中都设置<%@ page errorPage="error.jsp"%>,当页面出现错误时,会跳转到该jsp页面,在error.jsp中设置<%@ page isErrorPage="true" %> 就可以引用exception对象,获取到错误的原因,可以灵活处理它的内容,像<%=exception.getMessage()%>。当页面出现错误时,Chrome浏览器进行访问,可以看到它会把错误原因,以及页面内容都输出到浏览器上。但ie浏览器会出现下图显示,原因是此时服务器响应的状态码为500,ie浏览器将会给出自己的错误页面,可以利用过滤器对其进行处理。

  一般来说,我们会对其进行页面的统一配置,给整个工程进行友好错误页面。在web.xml中配置如下:

......
    <error-page>
        <exception-type></exception-type>
        <location></location>
    </error-page>
</web-app>

看error-page的说明,可以发现,这个标签需要两个内容,错误定义和位置,而错误定义又分两种:

Element : error-page
The error-page element contains a mapping between an error code or exception type to the
 path of a resource in the web application Used in: web-app

Content Model : ((error-code | exception-type), location)

这几个参数的内容分别为((错误码(状态码)|java异常类型),友好页面位置)。

  taglib指令之后专门汇总

  这里再总结一下<%@ include %>指令的用法与场景。

  在很多门户网站中,往往一个页面会被切成很多块儿,不同的开发人员会对不同的快分别进行处理,但整个网页也会有很多公共资源,例如框架,各种链接等等,同样的版面和内容会被放到很多独立的子模块中使用,如果子模块中处理这些公共内容,无疑工程量巨大,而且容易出错,不易扩展,所以我们会将其做成单独的界面,而后在每个需要的子模块中引用该界面。就相当于这个界面会与子模块的界面合并,所以这个指令主要就是做合并的工作。

  这里的合并分为两种,一种静态包含<%@include  file="" %>,另一种是动态包含<jsp:include page="">。前者的过程是A.jsp包含B.jsp,tomcat将A和Bjsp合并在一起,生成一个A_jsp.java文件,然后编译,最后运行,其结果为:AB合并(一个servlet),所以两个页面中处理变量时需要注意;后者的过程是A.jsp 包含 B.jsp ,tomcat将A生成 A_jsp.java文件,将B生成B_jsp.java文件,分别编译,在运行时将内容合并输出。结果:AB合并(两个servlet)。

--------------------------------------------------------------------------------------------------->

  JSP内置对象

  所谓的内置对象,即可以直接在<%= %>与<% %>中可以直接使用的变量,即_jspService(httpServletRequest, httpServletResponse)中提供的变量,看代码:

  public void _jspService(final javax.servlet.http.HttpServletRequest request, final javax.servlet.http.HttpServletResponse response)
        throws java.io.IOException, javax.servlet.ServletException {

    final javax.servlet.jsp.PageContext pageContext;
    javax.servlet.http.HttpSession session = null;
    java.lang.Throwable exception = org.apache.jasper.runtime.JspRuntimeLibrary.getThrowable(request);
    if (exception != null) {
      response.setStatus(javax.servlet.http.HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
    }
    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;

  ......

page 表示当前页,this引用。
config 表示 servlet配置,类型:ServletConfig
application 表示 web 应用上下文,类型:ServletContext

request 表示一次请求,类型:HttpServletRequest
response 表示一次响应:类型:HttpServletResponse

session 表示一次会话,类型HttpSession
out 表示输出响应体,类型JspWriter

exception 表示发生异常,类型 Throwable
pageContext 表示 jsp页面上下文(jsp管理者) 类型:PageContext

  其中,page 指代当前页面(一个页);request,一次请求(默认就一个页,如果使用请求转发可以多个页面);session,一次会话(可以有多次请求);application,一个应用(可以多次会话)。这里主要查看JspWriter与pageContext。我们将out对象打印出来,可知:

[email protected]

到tomcat中找到源码,查看该方法中的write(),最后查看到initOut():

    private void initOut() throws IOException {
        if (out == null) {
            out = response.getWriter();
        }
    }

所以这里底层使用了response.getWriter()获取out对象,在之前的servlet中已经解释过该方法的详细用法,这里略过。

  另外,有个缓存的问题。看页面中的代码:

......
    <br>
    <%= out %>
    <%
        out.print("111");
        out.print("2222");
        response.getWriter().print("3333");
    %>
</body>

这块代码会直接放入到hello_jap.java中然后统一在页面按照代码逻辑输出,但实际上,我们看页面源码:

3333
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
    Hello again!
    <br>
    10

    5

    10
    <br>
    [email protected]
    1112222
</body>

</html>

request.getWriter().print()中的内容被放到了页面最前面。原因在于,jsp与servlet缓存并不一致(JspWriter<->response.getWriter()),各自有各自的缓存,out的内容会首先被放到jsp缓存中,而request.getWriter()输出在servlet缓存里,等到最后,servlet会将自己缓存与jsp缓存内容结合输出到页面,造成上述情况。知道了这个原理,我们就可以当jsp将request.getWriter()之前所有内容刷到缓存中时,用out.flush()将jsp缓存中的内容刷新到servlet缓存中,而后再直接向servlet中存放3333,再输出就是代码逻辑顺序的展示了。

......
    <br>
    <%= out %>
    <%
        out.print("111");
        out.print("2222");
        out.flush();
        response.getWriter().print("3333");
    %>
</body>

  pageContext是jsp页面的管理者,可以用getXXX()获得其它8个对象的引用;可以对指定作用域属性的值进行快捷操作:

默认作用域属性进行操作:page
    getAttribute(name)  获得 page作用域数据
    setAttribute(name ,value )    给page作用域设置内容
    removeAttribute(name )  移除所有作用域的内容(page/request/session/application)
指定作用域
    getAttribute(name ,scope)  获得 指定作用域数据
    setAttribute(name ,value ,scope )    给指定作用域设置内容
    removeAttribute(name ,scope)  移除指定作用域的内容(page/request/session/application)
提供作用域常量
    PageContext.PAGE_SCOPE  page
    PageContext.REQUEST_SCOPE  request
    PageContext.SESSION_SCOPE  session
    PageContext.APPLICATION_SCOPE  application

--------------------------------------------------------------------------------------------------->

  JSP动作标签

  这里给出实际场景中的代码,看懂即可:

<jsp:include page="" />  动态包含
<jsp:forward />  转发
    <jsp:param/>  处理请求参数的 , 可以将中文内容进行 URL编码,类似  <form enctype="application/x-www-form-urlencoded">

<jsp:include page="/error.jsp">
    <jsp:param value="uservalue" name="username"/>
</jsp:include>

<jsp:useBean id="user" class="com.itheima.User"></jsp:useBean>
<%-- User user = new User();  pageContext.setAttribute("user",user)--%>

<jsp:setProperty property="username" name="user" value="jack"/>
<%--  user.setUsername("jack") --%>

<jsp:getProperty property="username" name="user"/>
<%-- user.getUsername() --%>
时间: 2024-11-02 19:35:55

Servlet 之jsp(上)的相关文章

修改MyEclipse默认的Servlet和jsp代码模板

一.修改Servlet的默认模板代码 使用MyEclipse创建Servlet时,根据默认的Servlet模板生成的Servlet代码如下: 1 package gacl.servlet.study; 2 3 import java.io.IOException; 4 import java.io.PrintWriter; 5 6 import javax.servlet.ServletException; 7 import javax.servlet.http.HttpServlet; 8 i

servlet和Jsp生命周期解读

一.servlet的工作工程 Servlet是运行在Servlet容器(有时候也叫Servlet引擎,是web服务器和应用程序服务器的一部分,用于在发送的请求和响应之上提供网络服务,解码基于MIME的请求,格式化基于MIME的响应.常用的tomcat.jboss.weblogic都是Servlet容器)中的,其生命周期是由容器来管理. 二.Servlet生命周期 Servlet是运行在Servlet容器(有时候也叫Servlet引擎,是web服务器和应用程序服务器的一部分,用于在发送的请求和响应

Servlet,jsp,JSP技术 ,JSP编程

 一.Servlet 思考 1 浏览器可以直接打开JAVA/class文件吗? 不可以 2浏览器可以打开HTML.JS 文件吗? 可以 3 JAVA程序可以生成HTML文件吗?可以的,用IO流. 4 浏览器解析的时候是需要HTTP协议的,JAVA普通类有没有HTTP协议呢? 普通类没有. JAVA-(class)浏览器如何访问呢? 浏览器---HTML A   JAVA通过IO流生成HTML--->浏览器 B   JAVA 需要加入HTTP协议 解决上面2个问题可以通过 Servlet C  如

Servlet 和 JSP 概述

说到Java web开发,就不得不提Servlet 和 JSP.这两者是java web开发技术.虽然现在有这么多的web框架,公司中很少会用这两个技术来直接开发项目,但是理解了这两个技术,一则会让你对web的基础知识要很深的了解,二则学其他的相比来说要更好理解点. 一.Servlet 1. 什么是servlet? servlet是运行在Web服务器上的java程序.是一个中间层,负责连接来自Web浏览器或其他Http请求和Http服务器上的数据库或应用程序. 2. Servlet的作用是什么?

基于Servlet、JSP、JDBC、MySQL的一个简单的用户注冊模块(附完整源代码)

近期看老罗视频,做了一个简单的用户注冊系统.用户通过网页(JSP)输入用户名.真名和password,Servlet接收后通过JDBC将信息保存到MySQL中.尽管是个简单的不能再简单的东西,但麻雀虽小,五脏俱全,在此做一归纳和整理.以下先上源代码: 一.index.jsp <%@ page language="java" import="java.util.*" pageEncoding="utf-8"%> <% String

初识Servlet和JSP

一.简介Servlet和JSP sun首先推出了Servlet规范,它是一种小型的Java程序,全部是由java写成并且生成HTML,扩展了web服务器的功能,是位于Web服务器内部的服务器端的Java应用程序. 后来,sun就推出了类似于ASP的镶嵌型的JSP,JSP页面由HTML代码和嵌入其中的Java代码所组成.服务器在页面被客户端所请求以后对这些Java代码进行处理,然后将生成的HTML页面返回给客户端浏览器. 二.Servlet和JSP的关系 Serlet是一个早期的不完善的产品,写b

关于servlet和jsp 乱码的问题

一.表单提交时出现乱码: 在进行表单提交的时候,经常提交一些中文,自然就避免不了出现中文乱码的情况,对于表单来说有两种提交方式:get和post提交方式.所以请求的时候便有get请求和post请求.以前我一直以为get请求和post请求方式出现的乱码的解决方式是一样的,但是今天才知道两种请求方式所产生的乱码的解决方式是不同的.每种方式都有着不同的解决方法,之所以出现乱码,原因就在于get请求时,其传递给服务器的数据是附加在URL地址之后的:而post的请求时,其传递给服务器的数据是作为请求体的一

基于Servlet、JSP、JDBC、MySQL的登录模块(含过滤器的使用和配置)

接前文的注册模块,本篇是登录模块.主要包括登录主界面,和登录相关编写的LoginAction.LoginDao和LoginService.以及配置的Filter.下面按逻辑顺序记录详细过程和代码: 一.在前文的index目录点击登录按钮后,通过javascript跳转至LoginAction. <script type="text/javascript"> function login(){ var th = document.form1; if(th.username.v

servlet与jsp

Servlet生命周期 一.初始化阶段   当WEB客户第一次请求访问某个Servlet的时候,WEB容器将创建这个Servlet的实例.调用init()方法进行Servlet的初始化 一.响应客户请求阶段 调用service()方法,service()方法根据收到的客户端请求类型,决定调doGet()还是doPost()还是其他的doXXX()方法. 二.终止阶段 当WEB应用被终止,或Servlet容器终止运行,web容器调用destroy()方法释放掉Servlet所占用的资源. JSP与

Servlet+JavaBean+JSP真假分页技术详解

说明:分页技术分为真分页和假分页,具体采用哪种技术需要根据需求自我抉择.其实两者之间实现区别并不是太大.在分页之前我们需要搞明白对谁进行分页,一般情况是将数据封装到一个list集合中,明白这这一点问题基本上就已经解决了.(编写匆促如有错误请联系我) 下面首先介绍真分页. 方法一: 为了大家学习起来方便, 我将在项目中用到的内容都放在这个文档中,所以可能会比较萝莉啰嗦. 1.构建数表,字段如下 goods goodid int goodname varchar(45) price flaot 2,