整合营销服务商

电脑端+手机端+微信端=数据同步管理

免费咨询热线:

JSP的前生今世

础知识,servlet是什么?

官方解释:Servlet 是运行在 Web 服务器或应用服务器上的程序,它是作为来自 Web 浏览器或其他 HTTP 客户端的请求和 HTTP 服务器上的数据库或应用程序之间的中间层

简单来说,servlet是运行在web服务器如tomcat,jetty这样应用服务器上的一段程序,他可以响应http协议的请求,并且实现用户自己的逻辑,最终将结果返回到用户的客户端(浏览器)

Java Servlet 通常情况下与使用 CGI(Common Gateway Interface,公共网关接口)实现的程序可以达到异曲同工的效果。但是相比于 CGI,Servlet 有以下几点优势:

1、性能明显更好。

2、Servlet 在 Web 服务器的地址空间内执行。这样它就没有必要再创建一个单独的进程来处理每个客户端请求。

3、Servlet 是独立于平台的,因为它们是用 Java 编写的。

4、服务器上的 Java 安全管理器执行了一系列限制,以保护服务器计算机上的资源。因此,Servlet 是可信的。

5、Java 类库的全部功能对 Servlet 来说都是可用的。它可以通过 sockets 和 RMI 机制与 applets、数据库或其他软件进行交互。

Servlet的生命周期

Servlet 生命周期可被定义为从创建直到毁灭的整个过程。以下是 Servlet 遵循的过程:

1、Servlet 通过调用 init () 方法进行初始化。

2、Servlet 调用 service() 方法来处理客户端的请求。

3、Servlet 通过调用 destroy() 方法终止(结束)。

4、最后,Servlet 是由 JVM 的垃圾回收器进行垃圾回收的

init() 方法

init 方法被设计成只调用一次。它在第一次创建 Servlet 时被调用,在后续每次用户请求时不再调用。因此,它是用于一次性初始化,就像 Applet 的 init 方法一样。

Servlet 创建于用户第一次调用对应于该 Servlet 的 URL 时,但是您也可以指定 Servlet 在服务器第一次启动时被加载。

service() 方法

service() 方法是执行实际任务的主要方法。Servlet 容器(即 Web 服务器)调用 service() 方法来处理来自客户端(浏览器)的请求,并把格式化的响应写回给客户端。

每次服务器接收到一个 Servlet 请求时,服务器会产生一个新的线程并调用服务。service() 方法检查 HTTP 请求类型(GET、POST、PUT、DELETE 等),并在适当的时候调用 doGet、doPost、doPut,doDelete 等方法。

destroy() 方法

destroy() 方法只会被调用一次,在 Servlet 生命周期结束时被调用。destroy() 方法可以让您的 Servlet 关闭数据库连接、停止后台线程、把 Cookie 列表或点击计数器写入到磁盘,并执行其他类似的清理活动。

在调用 destroy() 方法之后,servlet 对象被标记为垃圾回收。

JSP是什么?

JSP全称Java Server Pages,是一种动态网页开发技术。它使用JSP标签在HTML网页中插入Java代码。标签通常以<%开头以%>结束。

JSP是一种Java servlet,主要用于实现Java web应用程序的用户界面部分。网页开发者们通过结合HTML代码、XHTML代码、XML元素以及嵌入JSP操作和命令来编写JSP。

JSP通过网页表单获取用户输入数据、访问数据库及其他数据源,然后动态地创建网页。

JSP标签有多种功能,比如访问数据库、记录用户选择信息、访问JavaBeans组件等,还可以在不同的网页中传递控制信息和共享信息。


servlet和jsp的区别

1、Servlet在Java代码中可以通过HttpServletResponse对象动态输出HTML内容。

2、JSP是在静态HTML内容中嵌入Java代码,然后Java代码在被动态执行后生成HTML内容。

servlet和jsp各自的特点

1、Servlet虽然能够很好地组织业务逻辑代码,但是在Java源文件中,因为是通过字符串拼接的方式生成动态HTML内容,这样就容易导致代码维护困难、可读性差。

2、JSP虽然规避了Servlet在生成HTML内容方面的劣势,但是在HTML中混入大量、复杂的业务逻辑。

MVC的诞生

JSP和Servlet都有自身的适用环境,那么有没有什么办法能够让它们发挥各自的优势呢?答案是肯有的,MVC模式就能够完美解决这一问题。

MVC模式,是Model-View-Controller的简称,是软件工程中的一种软件架构模式,分为三个基本部分,分别是:模型(Model)、视图(View)和控制器(Controller):

Controller——负责转发请求,对请求进行处理

View——负责界面显示

Model——业务功能编写(例如算法实现)、数据库设计以及数据存取操作实现

在JSP/Servlet开发的软件系统中,这三个部分的描述如下所示:


MVC模型

1、Web浏览器发送HTTP请求到服务端,然后被Controller(Servlet)获取并进行处理(例如参数解析、请求转发)

2、Controller(Servlet)调用核心业务逻辑——Model部分,获得结果

3、Controller(Servlet)将逻辑处理结果交给View(JSP),动态输出HTML内容

4、动态生成的HTML内容返回到浏览器显示

MVC模式在Web开发中有很大的优势,它完美规避了JSP与Servlet各自的缺点,让Servlet只负责业务逻辑部分,而不会生成HTML代码;同时JSP中也不会充斥着大量的业务代码,这样大大提高了代码的可读性和可维护性。


相关面试题



如何读取Servlet的初始化参数?

ServletConfig中定义了如下的方法用来读取初始化参数的信息:

public String getInitParameter(String name)

参数:初始化参数的名称。
返回:初始化参数的值,如果没有配置,返回null。

init(ServletConfig)方法执行次数

在Servlet的生命周期中,该方法执行一次。

service()方法的职责

service()方法为Servlet的核心方法,客户端的业务逻辑应该在该方法内执行,典型的服务方法的开发流程为:

解析客户端请求-〉执行业务逻辑-〉输出响应页面到客户端

get方式和post方式有何区别

数据携带上:

GET方式:在URL地址后附带的参数是有限制的,其数据容量通常不能超过1K。

POST方式:可以在请求的实体内容中向服务器发送数据,传送的数据量无限制。

请求参数的位置上:

GET方式:请求参数放在URL地址后面,以?的方式来进行拼接

POST方式:请求参数放在HTTP请求包中

用途上:

GET方式一般用来获取数据

POST方式一般用来提交数据

原因:

首先是因为GET方式携带的数据量比较小,无法带过去很大的数量

POST方式提交的参数后台更加容易解析(使用POST方式提交的中文数据,后台也更加容易解决)

GET方式比POST方式要快

Servlet相关 API

HttpServletRequest:封装了与请求相关的信息

HttpServletResponse:封装了与响应相关的信息


获取页面的元素的值有几种方式,分别说一下

request.getParameter() 返回客户端的请求参数的值

request.getParameterNames() 返回所有可用属性名的枚举

request.getParameterValues() 返回包含参数的所有值的数组

request.getAttribute()和request.getParameter()区别

用途上:

request.getAttribute(), 一般用于获取request域对象的数据(在跳转之前把数据使用setAttribute来放到request对象上)

request.getParameter(), 一般用于获取客户端提交的参数

存储数据上:

request.getAttribute()可以获取Objcet对象

request.getParameter()只能获取字符串(这也是为什么它一般用于获取客户端提交的参数)


forward和redirect的区别

实际发生位置不同,地址栏不同

转发是发生在服务器的

转发是由服务器进行跳转的,细心的朋友会发现,在转发的时候,浏览器的地址栏是没有发生变化的,在我访问Servlet111的时候,即使跳转到了Servlet222的页面,浏览器的地址还是Servlet111的。也就是说浏览器是不知道该跳转的动作,转发是对浏览器透明的。通过上面的转发时序图我们也可以发现,实现转发只是一次的http请求,一次转发中request和response对象都是同一个。这也解释了,为什么可以使用request作为域对象进行Servlet之间的通讯。

重定向是发生在浏览器的

重定向是由浏览器进行跳转的,进行重定向跳转的时候,浏览器的地址会发生变化的。曾经介绍过:实现重定向的原理是由response的状态码和Location头组合而实现的。这是由浏览器进行的页面跳转实现重定向会发出两个http请求,**request域对象是无效的,因为它不是同一个request对象

用法不同:

很多人都搞不清楚转发和重定向的时候,资源地址究竟怎么写。有的时候要把应用名写上,有的时候不用把应用名写上。很容易把人搞晕。记住一个原则: 给服务器用的直接从资源名开始写,给浏览器用的要把应用名写上

request.getRequestDispatcher("/资源名 URI").forward(request,response)

转发时"/"代表的是本应用程序的根目录【zhongfucheng】

response.send("/web应用/资源名 URI");

重定向时"/"代表的是webapps目录


能够去往的URL的范围不一样:

转发是服务器跳转只能去往当前web应用的资源

重定向是服务器跳转,可以去往任何的资源


传递数据的类型不同

转发的request对象可以传递各种类型的数据,包括对象

重定向只能传递字符串


跳转的时间不同

转发时:执行到跳转语句时就会立刻跳转

重定向:整个页面执行完之后才执行跳转


典型的应用场景:

转发: 访问 Servlet 处理业务逻辑,然后 forward 到 jsp 显示处理结果,浏览器里 URL 不变

重定向: 提交表单,处理成功后 redirect 到另一个 jsp,防止表单重复提交,浏览器里 URL 变了

SP

JSP的基础语法

简介

JSP:Java Server Page SUN 公司提供的动态网页编程技术,是 Java Web 服务器端的动态资源。

它相比 html 而言,html 只能为用户提供静态数据,而 Jsp 技术允许在页面中嵌套 java 代码,为用户提供动态数据。

相比 servlet 而言,servlet 很难对数据进行排版,而 jsp 除了可以用 java 代码产生动态数据的同时,也很容易对数据进行排版。

不管是 JSP 还是 Servlet,虽然都可以用于开发动态 web 资源。但由于这 2 门技术各自的特点,在长期的软件实践中,人们逐渐把 servlet 作为 web 应用中的控制器组件来使用, 而把 JSP 技术作为数据显示模板来使用。

其实 Jsp 就是一个 Servlet,当我们第一次访问 Jsp 的时候,Jsp 引擎都会将这个 Jsp 翻译 成一个 Servlet,这个文件存放在tomcat(源码目录) 中的 work 目录中。



准备工作

配置IDEA

这一步不是必须的,当然由于 编辑器中有些默认的配置项我们觉得不是很完美,比如"编码格式"、页面模板等。我们可以在新建 JSP 页面之前就先修改为我们需要的。

1.选择"File" —> "Settings..."



2.设置编码格式。搜索"encode",选择"File Encoding"

[

3.设置页面模板。搜索"template",选择"File and Code Templates",选择右侧的"Other",选择下方的"Jsp File"



新建JSP页面



注释

在 JSP 中支持两种注释的语法操作:

一种是显示注释,这种注释是允许客户端看见的; 另一种是隐式注释,此种注释是客户端无法看见的

① 显示注释语法:从 HTML 风格继承而来

② 隐式注释语法:从 JAVA 风格继承;JSP 自己的注释


JSP 的三种注释方式:

1) // 注释,单行注释  /* 多行注释*/ 
​
2)<!--  HTML风格的注释 -->
​
3)<%--   JSP注释  --%>


Scriptlet

在 JSP 中最重要的部分就是 Scriptlet(脚本小程序),所有嵌入在 HTML 代码中的 Java 程序

在 JSP 中一共有三种 Scriptlet 代码:都必须使用 Scriptlet 标记出来

第一种:<%    %>: java 脚本段,可以定义局部变量、编写语句
​
第二种:<%!   %>:声明,可以定义全局(成员)变量、方法、类
​
第三种:<%=  %>:表达式,数据一个变量或具体内容

通过观察解析为 java 文件的 jsp 代码理解三种小脚本

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<!DOCTYPE >
<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
        <title>Scriptlet</title>
    </head>
    <body>
        <%
            String str = "Hello JSP";
            System.out.println(str);
            response.getWriter().write(str);
        %>
        <%!
            String memberStr = "a member String";
        %>
        <%=memberStr%>
        <h1>This is a JSP page!!</h1>
    </body>
</html>


JSP的指令标签

使用包含操作,可以将一些重复的代码包含进来继续使用,从正常的页面组成来看,有时可能分为几个区域。而其中的一些区域可能是一直不需要改变的,改变的就其中的一个具体内容区域。现在有两种方法可以实现上述功能。

方法一:在每个 JSP 页面(HTML)都包含工具栏、头部信息、尾部信息、具体内容

方法二:将工具栏、头部信息、尾部信息都分成各个独立的文件,使用的时候直接导入

很明显,第二种方法比第一种更好,第一种会存在很多重复的代码,并且修改很不方便,在 JSP 中如果要想实现包含的操作,有两种做法:静态包含动态包含,静态包含使用 include 指令即可,动态包含则需要使用 include 动作标签。


include 静态包含

<%@ include file="要包含的文件路径" %>  <!-- 相对路径 -->

例如:

<%@include file="include.jsp" %>
或
<%@include file="include.html" %>

静态包含就是将内容进行了直接的替换,就好比程序中定义的变量一样,是在 servlet 引擎转译时,就把此文件内容包含了进去(两个文件的源代码整合到一起, 全部放到_jspService 方法中),所以只生成了一个 servlet,所以两个页面不能有同名的变量。 运行效率高一点点。耦合性较高,不够灵活。


include 动态包含

动态包含在代码的编译阶段,包含和被包含部分是两个独立的部分,只有当运行时,才会动态包含进来,好比方法的调用。

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

注意:动态包含,中间不要加任何内容,包括空格,除非确认要使用参数,否则报错!

<jsp:include page="include.html"></jsp:include>
<%
    String a = "hello.jsp";
%>
<jsp:include page="<%=a %>"></jsp:include>

使用动态包含还可以通过在页面之间传参。

接收参数通过 request.getParameter(name);

<jsp:include page="hello.jsp" flush="true">
    <jsp:param name="uname" value="zhangsan"/>
</jsp:include>

hello.jsp

<!-- 接收参数 -->
<%=request.getParameter("uname")%>


JSP的四大域对象

四种属性范围

在JSP中提供了四种属性的保存范围,所谓的属性保存范围,指的就是一个设置的对象,可以再多少个页面中保存并可以继续使用

  1. page范围 pageContext : 只在一个页面中保存属性,跳转之后无效
  2. request范围 request : 只在一次请求中保存,服务器跳转后依然有效
  3. session范围 session : 在一次会话范围中,无论何种跳转都可以使用
  4. application范围 application : 在整个服务器上保存

方法类型描述public void setAttribute(String name, Object o)普通设置属性的名称及内容public Object getAttribute(String name)普通根据属性名称取属性public void removeAttribute(String name)普通删除指定的属性


验证属性范围的特点

  1. page

本页面取得,服务器端跳转(<jsp :forward>)后无效


  1. request 服务器跳转有效,客户端跳转无效如果是客户端跳转,则相当于发出了两次请求,那么第一次的请求将不存在了;如果希望不管是客户端还是服务器跳转,都能保存的话,就需要继续扩大范围。


  1. session无论客户端还是服务器端都可以取得,但是现在重新开启一个新的浏览器,则无法取得之前设置的session了,因为每一个session只保存在当前的浏览器当中,并在相关的页面取得。对于服务器而言,每一个连接到它的客户端都是一个session如果想要让属性设置一次之后,不管是否是新的浏览器打开都能取得则可以使用application


  1. application所有的application属性直接保存在服务器上,所有的用户(每一个session)都可以直接访问取得 只要是通过application设置的属性,则所有的session都可以取得,表示公共的内容,但是如果此时服务器重启了,则无法取得了,因为关闭服务器后,所有的属性都消失了,所以需要重新设置。


问:使用哪个范围呢?

答:在合理范围尽可能小


EL表达式的使用

EL表达式的语法

EL(Expression Language) 是为了使 JSP 写起来更加简单。表达式语言的灵感来自于 ECMAScript 和 XPath 表达式语言,它提供了在 JSP 中简化表达式的方法,让 Jsp 的代码更加简化。

语法结构非常简单: ${expression}

EL 表达式一般操作的都是域对象中的数据,操作不了局部变量。

域对象的概念在 JSP 中一共有四个:pageContext, request, session, application;范围依次是,本页面一次请求一次会话整个应用程序

当需要指定从某个特定的域对象中查找数据时可以使用四个域对象对应的空间对象,分别是:pageScope, requestScope, sessionScope, applicationScope。

而 EL 默认的查找方式为从小到大查找,找到即可。当域对象全找完了还未找到则返回空字符串""。


EL表达式的使用

获取数据

设置域对象中的数据

<%
    pageContext.setAttribute("uname","zhangsan"); // page作用域
    request.setAttribute("uname","lisi"); // request作用域
    session.setAttribute("uname","wangwu"); // session作用域
    application.setAttribute("uname","zaholiu"); // application
%>

获取域对象的值

<%-- 获取域对象中的数据:默认查找方式为从小到大,找到即止。若四个范围都未找到,则返回空字符串。--%>
${uname} <!-- 输出结果为:zhangsan -->

获取指定域对象的值

${pageScope.uname}          <!-- page作用域 -->
${requestScope.uname}       <!-- request作用域 -->
${sessionScope.uname}       <!-- session作用域 -->
${applicationScope.uname}   <!-- application作用域 -->

获取List

<%
    List<String> list = new ArrayList<String>();
    list.add("aaa");
    list.add("bbb");
    list.add("ccc");
    request.setAttribute("list", list);
%>
<%--
    获取List中指定下标的数据
        ${list[下标] }
    获取集合的长度
        ${list.size()}
    注:
       list代表的是存在域对象中的变量名(限域变量名)
--%>
${list[1] }  

获取Map

<%
    Map map = new HashMap();
    map.put("aaa", "111");
    map.put("bbb", 2222);
    map.put("ccc-a", 333);
    request.setAttribute("map", map);
%>
<%--
    获取Map中指定值
       ${map["key"] } 或 ${map.key }
    注:
        map代表的是存在域对象中的变量名(限域变量名)
--%>
${map.aaa }
${map["bbb"]}

获取JavaBean对象

User.java

public class User {
​
    private Integer userId;
    private String uname;
    private String upwd;
​
    public Integer getUserId() {
        return userId;
    }
​
    public void setUserId(Integer userId) {
        this.userId = userId;
    }
​
    public String getUname() {
        return uname;
    }
​
    public void setUname(String uname) {
        this.uname = uname;
    }
​
    public String getUpwd() {
        return upwd;
    }
​
    public void setUpwd(String upwd) {
        this.upwd = upwd;
    }
}
<%
    User user = new User();
    user.setUserId(1);
    user.setUname("zhangsan");
    user.setUpwd("123456");
    request.setAttribute("user",user);
%>
<%-- JavBean中的属性字段需要提供get方法 --%>
${user} <%-- 获取对象 --%>
${user.uname} <%--获取对象中的属性--%>
empty
<%--
    empty
        判断域对象是否为空。为空,返回true;不为空返回false;
            ${empty 限域变量名 }
        判断对象是否不为空。
            ${!empty 限域变量名 }
--%>
${empty uname}
${empty list}
${empty map}
${empty user}


EL运算
<%
    request.setAttribute("a", 10);
    request.setAttribute("b", 2);
    request.setAttribute("c", "aa");
    request.setAttribute("d", "bb");
%>

等值判断

<%--
    比较两个值是否相等,返回true或false
        ==  或  eq
--%>
${a == b }
${c == d }
${c eq d }
${a == 5 }
${c == 'aa' }

算术运算

<%--
    加法: +
    减法: -
    乘法: *
    除法: / 或 div
--%>
${a + b }
${a / b } 或 ${a div b }

大小比较

SP常见面试题

jsp静态包含和动态包含的区别

jsp静态包含和动态包含的区别
  • 在讲解request对象的时候,我们曾经使用过request.getRequestDispatcher(String url).include(request,response)来对页头和页尾面进行包含
  • inclue指令也是做这样的事情,我们来试验一下吧!
  • 这是页头

  • 这是页尾

  • 在1.jsp中把页头和页尾包含进来

  • 访问1.jsp

  • include指令是静态包含。静态包含的意思就是:把文件的代码内容都包含进来,再编译!,看一下jsp的源代码就知道了!

  • 上面已经提及到了,include指令是静态包含,include行为是动态包含其实include行为就是封装了request.getRequestDispatcher(String url).include(request,response)
  • include行为语法是这个样子的
<jsp:include page=""/>
  • 我们先来使用一下把,在1.jsp页面中也将页头和页尾包含进来

  • 访问1.jsp页面看一下效果:

  • 使用jsp行为来包含文件,jsp源文件是这样子的:

  • jsp行为包含文件就是先编译被包含的页面,再将页面的结果写入到包含的页面中(1.jsp)
  • 当然了,现在有静态包含和动态包含,使用哪一个更好呢?答案是:动态包含
  • 动态包含可以向包含的页面传递参数(用处不大),并且是分别处理两个页面的(将被包含页面编译后得出的结果再写进包含页面)【如果有相同名称的参数,使用静态包含就会报错!】
  • 模拟一下场景吧,现在我的头页面有个名为s的字符串变量

  • 我的页尾也有个名为s的字符串变量

  • 现在我使用静态包含看看会发生什么,出现异常了。

  • 出现异常的原因很简单,就是同一个文件中有两个相同的变量s

  • 使用动态包含就可以避免这种情况

总结

  1. <%@include file="xxx.jsp"%>为jsp中的编译指令,其文件的包含是发生在jsp向servlet转换的时期,而<jsp:include page="xxx.jsp">是jsp中的动作指令,其文件的包含是发生在编译时期,也就是将java文件编译为class文件的时期
  2. 使用静态包含只会产生一个class文件,而使用动态包含会产生多个class文件
  3. 使用静态包含,包含页面和被包含页面的request对象为同一对象,因为静态包含只是将被包含的页面的内容复制到包含的页面中去;而动态包含包含页面和被包含页面不是同一个页面,被包含的页面的request对象可以取到的参数范围要相对大些,不仅可以取到传递到包含页面的参数,同样也能取得在包含页面向下传递的参数

jsp有哪些内置对象?作用分别是什么?

jsp有哪些内置对象?作用分别是什么?

九个内置对象:

  • pageContext
  • page
  • config
  • request
  • response
  • session
  • application
  • exception
  • out

其中,request、response、session、application、config这五个对象和Servlet的API是一样的。这5个对象我就不解释了。

在JSP中,尤其重要的是pageContext对象。

pageContext是内置对象中最重要的一个对象,它代表着JSP页面编译后的内容(也就是JSP页面的运行环境)!

pageContext对象
  • 既然它代表了JSP页面编译后的内容,理所当然的:它封装了对其他8大内置对象的引用!,也就是说,通过pageContext可以获取到其他的8个内置对象!

  • 看下效果:

pageContext作为域对象
  • 类似于request,session,ServletContext作为域对象而言都有以下三个方法
  • setAttribute(String name,Objcet o)
  • getAttribute(String name)
  • removeAttribute(String name)
  • 当然了,pageContext也不例外,pageContext也有这三个方法
  • pageContext本质上代表的是当前JSP页面编译后的内容,作为域对象而言,它就代表着当前JSP页面(也就是page)!也就是说:pageContext域对象只在page范围内有效,超出了page范围就无效了
  • 首先来看看在page范围内能不能使用

  • 效果如下:

  • 我们现在来试验一下是不是超出了page范围就无效了!
  • 在2.jsp中request域对象设置属性

  • 企图在1.jsp中pageContext取出request存进去的属性

  • 效果如下:



  • pageContext本质上代表着编译后JSP的内容,pageContext还可以封装了访问其他域的方法
  • 上面的pageContext默认是page范围的但pageContext对象重载了set、get、removeAttribute这三个方法
  • getAttribute(String name,int scope)
  • setAttribute(String name,Object value,int scope)
  • removeAttribute(String name,int scope)
  • 多了一个设置域范围的一个参数,如果不指定默认就是page。当然了,pageContext把request、session、application、page这几个域对象封装着了静态变量供我们使用
  • PageContext.APPLICATION_SCOPE
  • PageContext.SESSION_SCOPE
  • PageContext.REQUEST_SCOPE
  • PageContext.PAGE_SCOPE
  • 刚才我们没有使用重载方法的时候,使用pageContext是无法获取到request域对象设置的属性的。现在我们使用重载后的方法看一下能不能获取得到

  • 效果:



  • pageContexst还有这么一个方法:
  • findAttribute(String name)

  • 该方法会查找各个域的属性,从小到大开始寻找!也就是page—>request->session->application。
  • 我们用此方法看能不能查找出request域对象的属性吧!

  • 效果如下:

out对象:
  • out对象用于向浏览器输出数据,与之对应的是Servlet的PrintWriter对象。然而这个out对象的类型并不是PrintWriter,是JspWriter

  • 我们可以简单理解为:JspWriter就是带缓存的PrintWrieter
  • out对象的原理如下:

  • 只有向out对象中写入了内容,且满足如下任何一个条件时,out对象才去调用ServletResponse.getWriter方法,并通过该方法返回的PrintWriter对象将out对象的缓冲区中的内容真正写入到Servlet引擎提供的缓冲区中
  • 设置page指令的buffer属性关闭了out对象的缓存功能
  • out对象的缓冲区已满
  • 整个JSP页面结束
  • 一般我们在JSP页面输出都是用表达式(<%=%>),所以out对象用得并不是很多
page对象

内置对象page是HttpJasPage对象,其实page对象代表的就是当前JSP页面,是当前JSP编译后的Servlet类的对象。也就是说:page对象相当于普通java类的this

exception对象
  • 内置对象exception是java.lang.Exception类的对象,exception封装了JSP页面抛出的异常信息。exception经常被用来处理错误页面
  • 前面我们已经讲过了怎么设置错误页面了,下面我们就来简单使用一下exception对象吧
  • 1.jsp页面

  • error.jsp页面

  • 效果:

总结:

  1. request 用户端请求,此请求会包含来自GET/POST请求的参数
  2. response 网页传回用户端的回应
  3. pageContext 网页的属性是在这里管理,代表的编译后JSP内容
  4. session 与请求有关的会话期
  5. application servlet 正在执行的内容
  6. out 用来传送回应的输出
  7. config servlet的构架部件
  8. page JSP网页本身
  9. exception 针对错误网页,未捕捉的例外

jsp和servlet的区别、共同点、各自应用的范围?

jsp和servlet的区别、共同点、各自应用的范围?
  1. JSP是Servlet技术的扩展,本质上就是Servlet的简易方式。JSP编译后是“类servlet”。
  2. Servlet和JSP最主要的不同点在于:Servlet的应用逻辑是在Java文件中,并且完全从表示层中的HTML里分离开来。而JSP的情况是Java和HTML可以组合成一个扩展名为.jsp的文件。
  3. JSP侧重于视图,Servlet主要用于控制逻辑。


属性作用域范围

属性作用域范围
  1. page【只在一个页面中保存属性,跳转页面无效】
  2. requet【只在一次请求中保存属性,服务器跳转有效,浏览器跳转无效】
  3. session【在一个会话范围中保存属性,无论何种跳转均有效,关闭浏览器后无效】
  4. application【在整个服务器中保存,所有用户都可以使用】

应用场景:

  1. request:如果客户向服务器发请求,产生的数据,用户看完就没用了,像这样的数据就存在request域,像新闻数据,属于用户看完就没用的
  2. session:如果客户向服务器发请求,产生的数据,用户用完了等一会儿还有用,像这样的数据就存在session域中,像购物数据,用户需要看到自己购物信息,并且等一会儿,还要用这个购物数据结帐
  3. servletContext:如果客户向服务器发请求,产生的数据,用户用完了,还要给其它用户用,像这样的数据就存在servletContext域中,像聊天数据


写出5种JSTL常用标签

写出5种JSTL常用标签
<c:if>,<c:item>,<c:foreach>,<c:out>,<c:set>


写一个自定义标签要继承什么类

写一个自定义标签要继承什么类

我们可以有两种方式来实现自定义标签:

  • 传统方式,实现Tag接口(老方法)
  • 简单方式,继承SimpleTagSupport类


SimpleTagSupport类的执行顺序(原理):

  • ①WEB容器调用标签处理器对象的setJspContext方法,将代表JSP页面的pageContext对象传递给标签处理器对象
  • ②WEB容器调用标签处理器对象的setParent方法,将父标签处理器对象传递给这个标签处理器对象。【注意,只有在标签存在父标签的情况下,WEB容器才会调用这个方法】
  • ③如果调用标签时设置了属性,容器将调用每个属性对应的setter方法把属性值传递给标签处理器对象。如果标签的属性值是EL表达式或脚本表达式,则WEB容器首先计算表达式的值,然后把值传递给标签处理器对象。
  • ④如果简单标签有标签体,容器将调用setJspBody方法把代表标签体的JspFragment对象传递进来
  • ⑤执行标签时:容器调用标签处理器的doTag()方法,开发人员在方法体内通过操作JspFragment对象,就可以实现是否执行、迭代、修改标签体的目的。

总结

SimpleTagSupport,一般调用doTag方法或者实现SimpleTag接口

JSP是如何被执行的?执行效率比SERVLET低吗?

JSP是如何被执行的?执行效率比SERVLET低吗?
  • 当客户端向一个jsp页面发送请求时,Web Container将jsp转化成servlet的源代码(只在第一次请求时),然后编译转化后的servlet并加载到内存中执行,执行的结果response到客户端
  • jsp只在第一次执行的时候会转化成servlet,以后每次执行,web容器都是直接执行编译后的servlet,所以jsp和servlet只是在第一次执行的时候不一样,jsp慢一点,以后的执行都是相同的


如何避免jsp页面自动生成session对象?为什么要这么做?

如何避免jsp页面自动生成session对象?为什么要这么做?

可以使用页面指令显式关掉,代码如下:

<%@ page session="false" %>

jsp的缺点?

jsp的缺点?
  • 1)不好调试
  • 2)与其他脚本语言的交互(可读性差)


说出Servlet和CGI的区别?

说出Servlet和CGI的区别?
  • Servlet处于服务器进程中,只会有一个servlet实例,每个请求都会产生一个新的线程,而且servlet实例一般不会销毁
  • CGI:来一个请求就创建一个进程,用完就销毁,效率低于servlet


简述JSP的设计模式。

简述JSP的设计模式。

在Web开发模式中,有两个主要的开发结构,称为模式一(Mode I)和模式二(Mode II)

首先我们来理清一些概念吧:

  • DAO(Data Access Object):主要对数据的操作,增加、修改、删除等原子性操作。
  • Web层:界面+控制器,也就是说JSP【界面】+Servlet【控制器】
  • Service业务层:将多个原子性的DAO操作进行组合,组合成一个完整的业务逻辑
  • 控制层:主要使用Servlet进行控制
  • 数据访问层:使用DAO、Hibernate、JDBC技术实现对数据的增删改查
  • JavaBean用于封装数据,处理部分核心逻辑,每一层中都用到!

模式一指的就是在开发中将显示层、控制层、数据层的操作统一交给JSP或者JavaBean来进行处理

模式一有两种情况:

完全使用JSP做开发:

  • 优点:
  • 开发速度贼快,只要写JSP就行了,JavaBean和Servlet都不用设计!
  • 小幅度修改代码方便,直接修改JSP页面交给WEB容器就行了,不像Servlet还要编译成.class文件再交给服务器!【当然了,在ide下开发这个也不算是事】

  • 缺点:
  • 程序的可读性差、复用性低、代码复杂!什么jsp代码、html代码都往上面写,这肯定很难阅读,很难重用!

使用JSP+JavaBean做开发:

  • 优点:
  • 程序的可读性较高,大部分的代码都写在JavaBean上,不会和HTML代码混合在一起,可读性还行的
  • 可重复利用高,核心的代码都由JavaBean开发了,JavaBean的设计就是用来重用、封装,大大减少编写重复代码的工作!

  • 缺点:
  • 没有流程控制,程序中的JSP页面都需要检查请求的参数是否正确,异常发生时的处理。显示操作和业务逻辑代码工作会紧密耦合在一起的!日后维护会困难

Mode II 中所有的开发都是以Servlet为主体展开的,由Servlet接收所有的客户端请求,然后根据请求调用相对应的JavaBean,并所有的显示结果交给JSP完成!,也就是俗称的MVC设计模式!

MVC设计模式:

  • 显示层(View):主要负责接受Servlet传递的内容,调用JavaBean,将内容显示给用户
  • 控制层(Controller):主要负责所有用户的请求参数,判断请求参数是否合法,根据请求的类型调用JavaBean,将最终的处理结果交给显示层显示!
  • 模型层(Mode):模型层包括了业务层,DAO层。

总结

  • (1)ModelI,JSP+JavaBean设计模式。
  • (2)ModelII,MVC设计模式。


原文地址:https://dwz.cn/NhBjgHRk作者:Java3y