JSP考点 42问42答
JSP Servlet介绍
如何创建Sevlet类以及创建Servlet类的三种方式
实现Servlet接口,继承GenericServlet类,继承HTTPServlet
如何注册Servlet(web.xml和注解方式)
xml方式
<servlet>
<servlet-name>MyServlet</servlet-name>
<servlet-class>net.biancheng.www.MyServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>MyServlet</servlet-name>
<url-pattern>/MyServlet</url-pattern>
</servlet-mapping>
注解方法
@WebServlet("/MyServlet")
在Servlet中获取请求参数(如何获取一个参数的单个值和一个参数的多个值)
public String getParameter(String paramName); //获取一个参数
public String[] getParameterVValues(String paramName); //获取多个参数
Servlet的工作原理
当Web服务器接收到一个HTTP请求时,它会先判断请求内容——如果是静态网页数据,Web服务器将会自行处理,然后产生响应信息;如果牵涉到动态数据,Web服务器会将请求转交给Servlet容器。此时Servlet容器会找到对应的处理该请求的Servlet实例来处理,结果会送回Web服务器,再由Web服务器传回用户端。
Servlet生命周期方法、每个方法的作用、调用次数等
GET和POST请求的区别,对于GET请求,要重写doGet()方法,对于POST请求,要重写doPost()方法
GET | POST | |
---|---|---|
后退按钮/刷新 | 无害 | 数据会被重新提交(浏览器应该告知用户数据会被重新提交)。 |
书签 | 可收藏为书签 | 不可收藏为书签 |
缓存 | 能被缓存 | 不能缓存 |
编码类型 | application/x-www-form-urlencoded | application/x-www-form-urlencoded 或 multipart/form-data。为二进制数据使用多重编码。 |
历史 | 参数保留在浏览器历史中。 | 参数不会保存在浏览器历史中。 |
对数据长度的限制 | 是的。当发送数据时,GET 方法向 URL 添加数据;URL 的长度是受限制的(URL 的最大长度是 2048 个字符)。 | 无限制。 |
对数据类型的限制 | 只允许 ASCII 字符。 | 没有限制。也允许二进制数据。 |
安全性 | 与 POST 相比,GET 的安全性较差,因为所发送的数据是 URL 的一部分。在发送密码或其他敏感信息时绝不要使用 GET ! | POST 比 GET 更安全,因为参数不会被保存在浏览器历史或 web 服务器日志中。 |
可见性 | 数据在 URL 中对所有人都是可见的。 | 数据不会显示在 URL 中。 |
Servlet API和线程模型
ServletConfig对象和ServletContext对象的使用和对比
-
使用ServletContext对象表示WEB应用程序
- 在一个WEB应用程序中,只能存在一个ServletContext对象
- 每个WEB应用程序,都有他自己所对应的ServeltContext对象
- 在WEB容器启动的时候,会为每个WEB应用程序创建一个单独的ServletContext对象
- ServletContext是接口,此接口的实现类是Tomcat容器提供的
-
Web容器会为每个Servlet都创建一个对应的ServletConfig对象,ServletConfig代表的是Servlet初始化参数的的对象。
获取ServletConfig:
ServletConfigconfig=this.getServletConfig();
API
方法 返回值 描述 getInitParameter String 获取WEB应用程序的初始化参数
定义和获取上下文参数以及Servlet的初始化参数(web.xml中如何定义,Servlet中如何获取)
获取ServletContext
1.通过ServletConfig接口
//通过ServletConfig对象获取
ServletConfigconfig=this.getServletConfig();
ServletContextcontext2=config.getServletContext();
2.通过继承GenericServlet获取
//获取ServletContext对象
ServletContextcontext=this.getServletContext();
获取初始化参数
定义:
<!--配置WEB应用程序的初始化参数-->
<context-param>
<param-name>bdit</param-name>
<param-value>java</param-value>
</context-param>
<context-param>
<param-name>version</param-name>
<param-value>V1.0</param-value>
</context-param>
获取:
//获取ServletContext对象
ServletContextcontext=this.getServletContext();
//获取WEB应用程序的初始化参数
Stringbdit=context.getInitParameter("bdit");
Stringversion=context.getInitParameter("version");
System.out.println(bdit);
System.out.println(version);
如何使用单线程模型
实现SingleThreadModel接口
管理会话和处理错误
四种会话技术
- 隐藏表单字段
- URL重写
- Cookie
- Session
使用隐藏字段提交数据
<input name="id" value="123" type="hidden"/>
如何使用URL重写实现追加参数
url重写的优点在于:
- 缩短url,隐藏实际路径提高安全性
- 易于用户记忆和键入。
- 易于被搜索引擎收录
使用步骤
1.下载jar urlrewritefilter
2.配置web.xml
<filter>
<filter-name>UrlRewriteFilter</filter-name>
<filter-class>org.tuckey.web.filters.urlrewrite.UrlRewriteFilter</filter-class>
<!--<init-param>
<param-name>confReloadCheckInterval</param-name>
<param-value>60</param-value>
</init-param>
<init-param>
<param-name>confPath</param-name>
<param-value>/WEB-INF/urlrewrite.xml</param-value>
</init-param>-->
</filter>
<filter-mapping>
<filter-name>UrlRewriteFilter</filter-name>
<url-pattern>/*</url-pattern>
<dispatcher>REQUEST</dispatcher>
<dispatcher>FORWARD</dispatcher>
</filter-mapping>
3.配置urlrewrite.xml
<urlrewrite>
<rule>
<note>.../book/1234 instead of .../book.jsp?id=1234</note>
<from>/book/([0-9]+)$</from>
<to>/book.jsp?id=$1</to>
</rule>
</urlrewrite>
实现Cookie:创建、发送和存储、删除以及如何获取Cookie
创建
public Cookie(String Name,String value)
发送
resp.addCookie(Cookie cookie);
删除
Cookie cookie[] = req.getCookies();
获取
cookie.setMaxAge(0);
使用Session对象实现会话管理:如何获取会话对象、添加属性、在servlet和jsp页面获取会话属性。
获取对象
req,getSession();
获取属性
public Object getAttribute(String name)
添加
public void setAttribute(String name, Object value)
如何结束会话
public void invalidate()
如何配置会话的超时时间,超时时间为负值、0、正值表示什么,单位是什么。
public int getMaxInactiveInterval()
//该方法返回 Servlet 容器在客户端访问时保持 session 会话打开的最大时间间隔,以秒为单位。
public void setMaxInactiveInterval(int interval)
//该方法在 Servlet 容器指示该 session 会话无效之前,指定客户端请求之间的时间,以秒为单位。
负值:永不失效
0:立即失效
正值:……
如何针对错误代码和异常类型配置错误页面
<error-page>
<exception-type>java.lang.Throwable</exception-type >
<location>/ErrorHandler</location>
</error-page>
如何发送自定义的错误状态码:调用sendError()方法
public void sendError(int status);
public void sendError(int status,String message);
常用状态码(三位置数字代码和常量名):200、400、404、410、500等
代码 | 消息 | 描述 |
---|---|---|
100 | Continue | 只有请求的一部分已经被服务器接收,但只要它没有被拒绝,客户端应继续该请求。 |
101 | Switching Protocols | 服务器切换协议。 |
200 | OK | 请求成功。 |
201 | Created | 该请求是完整的,并创建一个新的资源。 |
202 | Accepted | 该请求被接受处理,但是该处理是不完整的。 |
203 | Non-authoritative Information | |
204 | No Content | |
205 | Reset Content | |
206 | Partial Content | |
300 | Multiple Choices | 链接列表。用户可以选择一个链接,进入到该位置。最多五个地址。 |
301 | Moved Permanently | 所请求的页面已经转移到一个新的 URL。 |
302 | Found | 所请求的页面已经临时转移到一个新的 URL。 |
303 | See Other | 所请求的页面可以在另一个不同的 URL 下被找到。 |
304 | Not Modified | |
305 | Use Proxy | |
306 | Unused | 在以前的版本中使用该代码。现在已不再使用它,但代码仍被保留。 |
307 | Temporary Redirect | 所请求的页面已经临时转移到一个新的 URL。 |
400 | Bad Request | 服务器不理解请求。 |
401 | Unauthorized | 所请求的页面需要用户名和密码。 |
402 | Payment Required | 您还不能使用该代码。 |
403 | Forbidden | 禁止访问所请求的页面。 |
404 | Not Found | 服务器无法找到所请求的页面。. |
405 | Method Not Allowed | 在请求中指定的方法是不允许的。 |
406 | Not Acceptable | 服务器只生成一个不被客户端接受的响应。 |
407 | Proxy Authentication Required | 在请求送达之前,您必须使用代理服务器的验证。 |
408 | Request Timeout | 请求需要的时间比服务器能够等待的时间长,超时。 |
409 | Conflict | 请求因为冲突无法完成。 |
410 | Gone | 所请求的页面不再可用。 |
411 | Length Required | “Content-Length” 未定义。服务器无法处理客户端发送的不带 Content-Length 的请求信息。 |
412 | Precondition Failed | 请求中给出的先决条件被服务器评估为 false。 |
413 | Request Entity Too Large | 服务器不接受该请求,因为请求实体过大。 |
414 | Request-url Too Long | 服务器不接受该请求,因为 URL 太长。当您转换一个 “post” 请求为一个带有长的查询信息的 “get” 请求时发生。 |
415 | Unsupported Media Type | 服务器不接受该请求,因为媒体类型不被支持。 |
417 | Expectation Failed | |
500 | Internal Server Error | 未完成的请求。服务器遇到了一个意外的情况。 |
501 | Not Implemented | 未完成的请求。服务器不支持所需的功能。 |
502 | Bad Gateway | 未完成的请求。服务器从上游服务器收到无效响应。 |
503 | Service Unavailable | 未完成的请求。服务器暂时超载或死机。 |
504 | Gateway Timeout | 网关超时。 |
505 | HTTP Version Not Supported | 服务器不支持"HTTP协议"版本。 |
Servlet之间通信、过滤器和监听器
理解过滤器
servlet过滤器是一种截取客户机与服务器之间的请求和相应的对象。过滤器能够修改Web客户端所发送的请求的标头和内容,并将其转发给目标servlet。
优点:
- 请求识别
- 请求拦截
- 验证用户
- 类型转换
- 资源通信
实现过滤器:创建、注册和使用过滤器,以及过滤器的合法url模式
void init(FilterConfig config);//用于完成Filter的初始化。
void destory();//用于Filter销毁前,完成某些资源的回收。
void doFilter(ServletRequest request,ServletResponse response,FilterChain chain);//实现过滤功能
部署:
-
filter
<filter> <display-name></display-name> <!-- 0或1个 --> <description></description> <!-- 0或1个 --> <icon> <!-- 0或1个 --> <small-icon></small-icon> <!-- 0或1个 --> <large-icon></large-icon> <!-- 0或1个 --> </icon> <filter-name></filter-name> <!-- 1个 --> <filter-class></filter-class> <!-- 1个 --> <init-param> <!-- 0或多个 --> <description></description> <!-- 0或1个 --> <param-name></param-name> <!-- 1个 --> <param-value></param-value> <!-- 1个 --> </init-param> </filter>
-
filterMapping
<filter-mapping> <!-- 1或多个 --> <filter-name></filter-name> <!-- 1个 --> <url-pattern></url-pattern> <!-- <url-pattern>和<servlet-name>任选一个 --> <servlet-name></servlet-name> <dispatcher></dispatcher> <!-- 0或多个 --> </filter-mapping>
请求转发和响应重定向的特点和区别,以及如何实现重定向和请求转发
请求转发(RequestDispatcher):服务器收到请求后,从一个资源跳转到另一个资源的操作。
响应重定向(Redirect):客户端给服务器发请求,然后服务器发送重定向的状态码给客户端,同时客户端向服务器重新请求指定的地址。
请求转发 RequestDispatcher | 响应重定向 Redirect |
---|---|
浏览器地址栏不发生改变,不会变为目标地址 | 浏览器地址栏发生改变,变为目标地址 |
请求转发是服务器的行为,整个转发的过程在服务器中完成 | 重定向是浏览器的行为,通过响应对象HttpServletResponse来执行 |
整个过程是一次请求,一次响应 | 整个过程是两次请求,两次响应 |
各个资源共享Request域中的数据 | 不共享Request域中数据 |
可以转发到WEB-INF目录下 | 不能访问WEB-INF目录下的资源 |
不可以访问工程以外的资源 | 可以访问工程外的资源 |
响应重定向、forward在转发和include转发特点和区别,sendRedirect()和forward()以及include()方法的路径写法。
- RequestDispatcher
- forward:不包含原来页面的内容,同一个请求,跳转到全新的、单独的页面,地址不变
- include:包含原来页面的内容,同一个请求,还是原来的页面,包含进了新的东西,地址不变
- Redirect
- redirect:不包含原来页面的内容,不同个请求,跳转到全新的、单独的页面,地址改变
ServletContextListener:实现该接口可创建上下文监听器,监听上下文对象的创建(或初始化)和摧毁,也就是程序的启动和停止。
in web.xml
<listener>
<listener-class>ServletContextTest.ServletContextLTest</listener-class>
</listener>
java
public class ServletContextLTest implements ServletContextListener{
// 实现其中的销毁函数
public void contextDestroyed(ServletContextEvent sce) {
System.out.println("this is last destroyeed");
}
// 实现其中的初始化函数,当有事件发生时即触发
public void contextInitialized(ServletContextEvent sce) {
System.out.println("======listener test is beginning=========");
}
}
JSP介绍
JSP工作原理:第一次请求的时候转换为Servlet,并编译,后续请求不再转换和编译。
jspInit();//servlet 初始化时调用
jspService();//收到请求时调用
jspDestroy();//从服务中删除servlet之前调用
JSP隐式对象:有哪些隐式对象,以及四个域对象如何添加和获取属性。
SP隐式对象是JSP容器为每个页面提供的Java对象,开发者可以直接使用它们而不用显式声明。JSP隐式对象也被称为预定义变量。
JSP所支持的九大隐式对象:
对象 | 描述 |
---|---|
request | HttpServletRequest 接口的实例。request对象提供了一系列方法来获取HTTP头信息,cookies,HTTP方法等等。 |
response | HttpServletResponse 接口的实例。response对象也定义了处理HTTP头模块的接口。通过这个对象,开发者们可以添加新的cookies,时间戳,HTTP状态码等等。 |
out | JspWriter类的实例,用于把结果输出至网页上。 |
session | HttpSession类的实例。 |
application | ServletContext类的实例,与应用上下文有关。 |
config | ServletConfig类的实例。 |
pageContext | PageContext类的实例,提供对JSP页面所有对象以及命名空间的访问。 |
page | 类似于Java类中的this关键字。 |
Exception | Exception类的对象,代表发生错误的JSP页面中对应的异常对象。 |
四大域对象:
类名 | 域名 | 功能 |
---|---|---|
ServletContext | context域 | 在整个服务器上保存,所有用户都可使用。 重启服务器后无效JSP内置对象 |
HttpSession | session域 | 再一次会话中有效。服务器跳转、客户端跳转都有效。 网页关闭重新打开无效 |
HttpServletRequet | request域 | 只在一次请求中有效,服务器跳转之后有效。 客户端跳无效 |
PageContext | page域 | 只在一个页面中保存属性。 跳转之后无效。 |
application.setAttribute("application","application");
session.setAttribute("session","session");
request.setAttribute("request","request");
pageContext.setAttribute("pageContext","pageContext");
application.getAttribute("application");
session.getAttribute("session");
request.getAttribute("request");
pageContext.getAttribute("pageContext");
JSP脚本元素:表达式、Scriptlet(代码段)和声明
<%!
int a=0;
String s="w31q2";
//声明:定义变量和方法
%>
<%= expression %>
<%-- 表达式:直接将值插入到输出中 --%>
<%
//直接写Java代码
%>
自定义标记
如何创建自定义标记,包括空标记和带属性的标记
public class ClassName extends BodyTagSupport{
int doAfterBody()
int doEndTag()
void doInitBody()
int doStartTag()
BodyContent getBodyContent()
JspWriter getPreviousOut()
void release()
void setBodyContent(BodyContent b)
}
TLD文件中如何描述标记库和标记以及标记的属性
<?xml version="1.0" encoding="ISO-8859-1" ?>
<!—XML的版本及其字符集-->
<!DOCTYPE taglib
PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.1//EN"
"http://java.sun.com/j2ee/dtds/web-jsptaglibrary_1_1.dtd">
<!—文档类型定义-->
<taglib>
<!—此标记说明我们开始描述一个标记库-->
<tlibversion>1.0</tlibversion>
<!—标记库的版本-->
<jspversion>1.1</jspversion>
<!—所使用的JSP的版本-->
<shortname>tagclass</shortname>
<!—缺省的名称-->
<tag>
<name>login</name>
<!—标记的名称-->
<tagclass>
tagclass.login.login
<!—处理这个Tag的相应的类的名称-->
</tagclass>
<info>
<!—对本标记符的描述-->
</info>
<attribute>
<!—开始定义标记的属性-->
<name>height</name>
<!—属性的名称-->
<required>true</required>
<!—表示这个属性是不是必须的-->
<rtexprvalue>true</rtexprvalue>
<!—表示这个属性是否可以用JSP的程序段的结果输出-->
</attribute>
<attribute>
<name>width</name>
<required>true</required>
<rtexprvalue>true</rtexprvalue>
</attribute>
</tag>
</taglib>
在JSP页面引入标记库和使用标记
<%@ taglib uri="URIToTagLibrary" prefix="tagPrefix" %>
<%@ taglib uri="/tlds/taglib.tld" prefix="tagclass" %>
<html>
<head>
<title>login</title>
</head>
<body>
<tagclass:login width="200" height= "100" >
</tagclass:login>
</body>
</html>
doStartTag()、doAfterBody()方法和doEndTag()方法的返回值
如何使用标记文件/标签文件创建自定义标记,创建自定义标记后如何使用自定义标记
在目录:’Web服务器\WEB-INF\tags‘ 下创建存放xxx.tag的tag文件
wel.tag
<%@ tag language="java" pageEncoding="UTF-8"%>
<p>这是一个Tag文件,负责计算1~100内的奇数之和:</p>
<%-- 在这里写属性 --%>
<%@attribute name="message" required="true" %>
<h3>{message}<h3>
.jsp
<%@page contentType="text/html" pageEncoding="UTF-8"%>
<!--
使用<taglib>指令标记引入该Web服务目录下的标记库,只有这样,JSP页面才可以使用Tag标记调用相应的Tag文件。<taglib>指令的格式如下:
<%@ taglib tagdir="自定义标记库的位置" prefix="前缀">
-->
<%@taglib tagdir="/WEB-INF/tags" prefix="my" %>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>JSP Page</title>
</head>
<body bgcolor="cyan">
<h3>以下是调用Tag文件的效果:</h3>
<my:/>
</body>
</html>
<jsp:doBody>动作的作用
doBody
动作元素只能在tag file
中使用,它用来调用一个标签的标签体中的内容
doBody
动作元素也可以有属性。你可以通过这些属性来指定某个变量来接收标签体中的内容,如果不使用这些指令,那么**doBody
动作元素会把标签体之中的内容写到JSP
页面的JspWriter
上**。
属性 | 描述 |
---|---|
var | 用于保存标签体内容的变量值,标签体内容会以java.lang.String 类型保存到这个var 变量内。var 和varReader 属性只能出现一个 |
varReader | 用于保存标签体内容的变量值,标签体内容会以java.io.Reader 类型保存到这个varReader 变量内。var 和varReader 属性只能出现一个 |
scope | 变量保存到的作用域 |
设计模式和 JDBC API 介绍
理解Dao设计模式
Dao模式将对象持久性和数据库访问逻辑或持久化机制API分离。此设计模式可以让您随时修改数据库访问代码而无需修改应用程序代码
理解MVC设计模式:全称、各个组件以及其作用
模型层(Model):指从现实世界中抽象出来的对象模型,是应用逻辑的反应;它封装了数据和对数据的操作,是实际进行数据处理的地方(模型层与数据库才有交互)
视图层(View):是应用和用户之间的接口,它负责将应用显示给用户 和 显示模型的状态。
控制器(Controller):控制器负责视图和模型之间的交互,控制对用户输入的响应、响应方式和流程;它主要负责两方面的动作,一是把用户的请求分发到相应的模型,二是吧模型的改变及时地反映到视图上。
开发无脚本的JSP页面
使用EL表达式获取请求参数
${request.param}
使用EL表达式获取Cookie的值
${cookie.param.value}
使用EL表达式获取上下文参数
${context.param}
EL表达式如何处理空值
一般情况:视为“”
算术表达式:视为0
逻辑表达式:视为false
使用功能EL表达式获取域对象中的属性
EL表达式会根据id去User类里寻找这个id的get方法,此时会自动把id首字母大写并加上get前缀,一旦找到与之匹配的方法,El表达式就会认为这就是要访问的属性,并返回属性的值。
JSTL核心标记库:c:set, c:if, c:when, c:choose, c:otherwise, c:forEach标记的使用和属性。
c:set
<c:set
var="<string>"
value="<string>"
target="<string>"
property="<string>"
scope="<string>"/>
<c:set>标签有如下属性:
属性 | 描述 | 是否必要 | 默认值 |
---|---|---|---|
value | 要存储的值 | 否 | 主体的内容 |
target | 要修改的属性所属的对象 | 否 | 无 |
property | 要修改的属性 | 否 | 无 |
var | 存储信息的变量 | 否 | 无 |
scope | var属性的作用域 | 否 | Page |
c:if
<c:if test="<boolean>" var="<string>" scope="<string>">
...
</c:if>
<c:if>标签有如下属性:
属性 | 描述 | 是否必要 | 默认值 |
---|---|---|---|
test | 条件 | 是 | 无 |
var | 用于存储条件结果的变量 | 否 | 无 |
scope | var属性的作用域 | 否 | page |
c:when && c:choose $$ c:otherwish
<c:choose>
<c:when test="<boolean>">
...
</c:when>
<c:when test="<boolean>">
...
</c:when>
...
...
<c:otherwise>
...
</c:otherwise>
</c:choose>
<c:when>标签的属性如下:
属性 | 描述 | 是否必要 | 默认值 |
---|---|---|---|
test | 条件 | 是 | 无 |
c:forEach
<c:forEach
items="<object>"
begin="<int>"
end="<int>"
step="<int>"
var="<string>"
varStatus="<string>">
<c:forEach>标签有如下属性:
属性 | 描述 | 是否必要 | 默认值 |
---|---|---|---|
items | 要被循环的信息 | 否 | 无 |
begin | 开始的元素(0=第一个元素,1=第二个元素) | 否 | 0 |
end | 最后一个元素(0=第一个元素,1=第二个元素) | 否 | Last element |
step | 每一次迭代的步长 | 否 | 1 |
var | 代表当前条目的变量名称 | 否 | 无 |
varStatus | 代表循环状态的变量名称 | 否 | 无 |
JSTL格式化标记库的常用标记:formatNumber
<fmt:formatNumber
value="<string>"
type="<string>"
pattern="<string>"
currencyCode="<string>"
currencySymbol="<string>"
groupingUsed="<string>"
maxIntegerDigits="<string>"
minIntegerDigits="<string>"
maxFractionDigits="<string>"
minFractionDigits="<string>"
var="<string>"
scope="<string>"/>
fmt:formatNumber标签有如下属性:
属性 | 描述 | 是否必要 | 默认值 |
---|---|---|---|
value | 要显示的数字 | 是 | 无 |
type | NUMBER,CURRENCY,或 PERCENT类型 | 否 | Number |
pattern | 指定一个自定义的格式化模式用与输出 | 否 | 无 |
currencyCode | 货币码(当type="currency"时) | 否 | 取决于默认区域 |
currencySymbol | 货币符号 (当 type="currency"时) | 否 | 取决于默认区域 |
groupingUsed | 是否对数字分组 (TRUE 或 FALSE) | 否 | true |
maxIntegerDigits | 整型数最大的位数 | 否 | 无 |
minIntegerDigits | 整型数最小的位数 | 否 | 无 |
maxFractionDigits | 小数点后最大的位数 | 否 | 无 |
minFractionDigits | 小数点后最小的位数 | 否 | 无 |
var | 存储格式化数字的变量 | 否 | Print to page |
scope | var属性的作用域 | 否 | page |