Servlets & JSP
java开发:
- cs(client、server)
客户端、服务器。必须安装客户端,服务端更新客户端必须更新才能应用。 如大型游戏、qq。 - bs(browser、server)。 浏览器、服务器。通过浏览器就能访问,不需要安装客户端。
bs原理
浏览器–应用程序服务器–数据库服务器
bs结构程序完全部署在应用程序服务器中,基于请求和响应,基于http协议。一次请求对应一次响应。
tomcat服务器–小型开源免费的应用程序服务器,默认端口号8080。学习、开发中应用tomcat服务器,项目上线应用收费的应用程序服务器weblogic….
Tomcat目录:
- bin 启动、关闭tomcat服务器应用的一些命令
- conf 配置文件
- lib jar包
- webapps 部署到服务器中的应用程序
- work Tomcat把由JSP生成的Servlet放于此目录下。
URL格式:
http://ip地址:tomcat的端口号/项目名/访问的路径
请求的方式:
get: 显示提交、不安全、、不能直接支持中文。
表单的method属性设置为get时(默认)
用户的输入信息会在地址栏显示
输入url
点击链接post: 隐式提交、安全、支持中文。
表单的method属性设置为post时
Servlet API
Servlet接口
└─GenericServlet抽象类
└─HttpServlet抽象类(基于http协议),我们所使用的servlet根基类。
ServletRequest、ServletResponse
└─HttpServletRequest、HttpServletResponse。基于http协议的请求、响应
javax.servlet Interface Servlet
All Known Implementing Classes:
GenericServlet
Servlet
javax.servlet
Interface Servlet
All Known Implementing Classes: GenericServlet
ServletConfig
javax.servlet
Interface ServletConfig
All Known Implementing Classes:
GenericServlet
ServletContext
javax.servlet
Interface ServletContext
ServletRequest
javax.servlet
Interface ServletRequest
All Known Subinterfaces:
HttpServletRequest
ServletResponse
javax.servlet
Interface ServletResponse
All Known Subinterfaces:
HttpServletResponse
GenericServlet
javax.servlet
Class GenericServlet
java.lang.Object
└─javax.servlet.GenericServlet
All Implemented Interfaces:
java.io.Serializable, Servlet, ServletConfig
Direct Known Subclasses:
HttpServlet
HttpServlet
javax.servlet.http
abstract Class HttpServlet
java.lang.Object
└─javax.servlet.GenericServlet
└─javax.servlet.http.HttpServlet
All Implemented Interfaces:
java.io.Serializable, Servlet, ServletConfig
HttpServletRequest
javax.servlet.http
Interface HttpServletRequest
All Superinterfaces:
ServletRequest
HttpServletResponse
javax.servlet.http
Interface HttpServletResponse
All Superinterfaces:
ServletResponse
RequestDispatcher
javax.servlet
Interface RequestDispatcher
自定义Servlet类的创建:
- 继承自HttpServlet类。
- 重写doGet()方法、doPost()方法。
- Web.xml文件中配置Servlet类(或servlet注解)。
路径问题:
- web.xml、servlet类中“/”代表当前项目的根目录。
http://localhost:8080/项目名
- HTML中action、href中,“/”代表服务器根目录。
http://localhost:8080/
tomcat默认端口号:8080,修改tomcat的端口号:
<!--tomcat--conf文件夹--server.xml中修改端口号-->
<Connector port="8080" protocol="HTTP/1.1"
connectionTimeout="20000"
redirectPort="8443" />
项目调试:
- 如果修改了web.xml 必须重新启动服务器
- 修改了java代码,需要重新部署
- 修改了页面代码,不需要重新部署
web.xml: 最先被加载的配置文件
- 配置servlet(配置访问路径)
- 配置欢迎页面,一般用于设置主页
容器如何处理请求:
- 用户点击一个链接,其URL指向一个servlet而不是静态页面。
- 容器“看出来”这个请求要的是一个servlet,所以容器创建两个对象:HTTPServletRequest和HttpServletResponse。
- 容器根据请求中的URL找到正确的servlet,为这个请求创建或分配一个线程,并把请求和相应对象传递给这个servlet线程。
- 容器调用servlet的service()方法。根据请求的不同类型,service()方法会调用doGet()或doPost()方法。
- doGet()或doPost()方法生成动态页面,并把这个页面“填入”响应对象。要记住,容器还有相应对象的一个引用。
- 线程结束,容器把响应对象转换为一个Http响应,把它发送给客户,然后删除请求和相应对象。
servlet的生命周期:
HTTP请求 → 解析请求 → 创建servlet实例 → 调用init()方法 → 调用service()方法 → 输出响应信息 → 响应 → 调用destroy()方法。
- 实例化阶段:Servlet容器调用构造函数。
- 初始化阶段:容器调用init()方法。
- 请求处理阶段:如果请求Servlet,则容器调用service()方法(service()方法根据请求的方式调用doGet()或doPost()方法)。
- 销毁阶段:销毁实例之前调用destroy()方法。
servlet采用多线程单实例的模式:
- 第一次访问servlet:实例化阶段–初始化阶段–请求处理阶段
- 第二次及以上访问servlet:请求处理阶段。
servlet中不应该自定义成员变量。
Servlet接口
定义了所有Servlet要实现的方法。
Servlet常用方法:
方法名称 | 功能描述 |
public void init(ServletConfig config) | 由servlet容器调用,用于完成Servlet对象在处理客户请求前的初始化工作 |
public void service(ServletRequest req, ServletResponse) | 由servlet容器调用,用来处理客户端的请求 |
public void destroy() | 由servlet容器调用,释放Servlet对象所使用的资源 |
public ServletConfig getServletConfig() | 返回ServletConfig对象,该对象包含此servlet的初始化和启动参数。返回的ServletConfig对象是传递给init()方法的对象 |
public String getServletInfo() | 返回有关servlet的信息,比如作者、版本和版权。返回的字符串是纯文本。 |
ServletConfig接口
在Servlet初始化过程中获取配置信息,一个Servlet只有一个ServletConfig对象。
ServletConfig常用方法:
方法名称 | 功能描述 |
public String getInitParameter(String name) | 获取web.xml中设置的以name命名的初始化参数值 |
public ServletContext getServletContext() | 返回Servlet的上下文对象引用 |
GenericServlet抽象类
提供了Servlet与ServletConfig接口的默认实现方法。
Servlet接口的常用方法:
方法名称 | 功能描述 |
public void init(ServletConfig config) | 调用Servlet接口中的init()方法。此方法还有一无参的重载方法,其功能与此方法相同 |
public String getInitParameter(Stringname) | 返回名称为name的初始化参数的值 |
public ServletContext getServletContext() | 返回ServletContext对象的引用 |
HttpServlet抽象类
继承于GenericServlet,处理HTTP协议的请求和响应。
HttpServlet的常用方法:
方法名称 | 功能描述 |
public void service(ServletRequest req, ServletResponse res) | 调用GenericServlet类中service()方法的实现 |
public void service(HttpServletRequest req, HttpServletResponse res) | 接收HTTP请求,并将它们分发给此类中定义的doXXX()方法 |
public void doXXX(HttpServletRequest req, HttpServletResponse res) | 根据请求方式的不同,分别调用相应的处理方法,例如doGet()、doPost()等 |
ServletRequest接口
获取客户端的请求数据。
ServletRequest接口常用方法:
方法名称 | 功能描述 |
public Object getAttribute(String name) | 获取名称为name的属性值 |
public void setAttribute(String name, Object object) | 在请求中保存名称为name的属性 |
public void removeAttribute(String name) | 清除请求中名字为name的属性 |
HttpServletRequest接口
除了继承ServletRequest接口中的方法,还增加了一些用于读取请求信息的方法。
HttpServletRequest的常用方法:
方法名称 | 功能描述 |
public String getContextPath() | 返回请求URI中表示请求上下文的路径,上下文路径是请求URI的开始部分 |
public Cookie[] getCookies() | 返回客户端在此次请求中发送的所有cookie对象 |
public HttpSession getSession() | 返回和此次请求相关联的session,如果没有给客户端分配session,则创建一个新的session |
public String getMethod() | 返回此次请求所使用的HTTP方法的名字,如GET、POST |
RervletResopnse接口
向客户端发送响应数据。
RervletResopnse接口的常用方法:
方法名称 | 功能描述 |
public PrintWriter getWriter() | public PrintWriter getWriter() |
public String getCharacterEncoding() | 返回在响应中发送的正文所使用的字符编码 |
public void setCharacterEncoding() | 设置发送到客户端的响应的字符编码 |
public void setContentType(String type) | 设置发送到客户端的响应的内容类型,此时响应的状态属于尚未提交 |
HttpServletResponse接口
除了继承ServletResopnse接口中的方法,还增加了新的方法。
HttpServletResopnse的常用方法:
方法名称 | 功能描述 |
public void addCookie(Cookie cookie) | 增加一个cookie到响应中,这个方法可多次调用,设置多个cookie |
public void addHeader(String name,String value) | 将一个名称为name,值为value的响应报头添加到响应中 |
public void sendRedirect(String location) | 发送一个临时的重定向响应到客户端,以便客户端访问新的URL |
public void encodeURL(String url) | 使用session ID对用于重定向的URL进行编码 |
ServletContent接口
获取Servlet上下文。
ServletContext常用方法:
方法名称 | 功能描述 |
public String getInitParameter(String name) | 获取名称为name的系统范围内的初始化参数值,系统范围内的初始化参数可以在部署描述符中使用context-param元素定义 |
public void setAttribute(String name, Object object) | 设置名称为name的属性 |
public Object getAttribute(String name) | 获取名称为name的属性 |
public String getRealPath(String path) | 返回参数所代表目录的真实路径 |
public void log(String message) | 记录一般日志信息 |
字符编码:
GBK2312、GBK、BIG5、ISO8859-1(默认采用此字符集)、UTF-8、
能读取文本框内中文内容不乱码:
request.setCharacterEnding("utf-8");
输出中文内容不乱码:
resopnse.setContentType("text/html; charset=utf-8");
每种文件都有各自的内容类型(mine-type),在servers>web.xml文件中有定义,html对应–text/html。
初始化参数:
- servlet类初始化参数:在web.xml中的servlet节点中配置,有效范围是当前servlet类。
- servlet上下文对象的初始化参数(ServletContext):在web.xml中配置,有效范围是当前项目中所有servlet类。
<!--Servlet初始化参数配置-->
<web-app>
<servlet>
<servlet-name>HelloServlet</servlet-name>
<servlet-class>org.jbit.servlet.HelloServlet</servlet-class>
<init-param>
<param-name>initParam</param-name>
<param-value>Hello Servlet</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>HelloServlet</servlet-name>
<url-pattern>/HelloServlet</url-pattern>
</servlet-mapping>
</web-app>
<!--获取Servlet初始化参数-->
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("处理请求时,doGet()方法被调用。");
String initParam = getInitParameter("initParam");
System.out.println(initParam);
}
<!--配置Servlet上下文-->
<web-app>
<context-param>
<param-name>contextParam</param-name>
<param-value>Hello Servlet</param-value>
</context-param>
<!--省略其他配置-->
</web-app>
<!--读取Servlet上下文-->
public class HelloServlet extends HttpServlet {
// …省略其他代码
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("处理请求时,doGet()方法被调用。");
String initParam = getInitParameter("initParam");
String contextParam = this.getServletContext().getInitParameter("contextParam");
System.out.println("Servlet初始化参数" + initParam);
System.out.println("系统初始化参数" + contextParam);
}
}
servlet类打印html代码输出:
resopnse.setContentType("text/html; charset=utf-8");
PrinterWriter out = request.getWriter();
out.println("<h1>HELLO WORLD</h1>");
页面跳转的两种方式:
- 请求转发:
- 转发是在服务器端发挥作用,通过forward()将提交信息在多个页面间进行传递。
- 客户端浏览器的地址栏不会显示出转向后的地址。
- 重定向:
- 重定向是在客户端发挥作用,通过请求新的地址实现页面转向,不能携带数据。
- 在地址栏中可以显示转向后的地址。
//重定向
response.sendRedirect("URL");
//请求转发
RequestDispather dispather = request.getResquestDispather("URL");
dispather.forword(request, reponse);
Cookie
web服务器保存在客户端的一系列文本信息。
//创建Cookie对象
Cookie cookie = new Coolie(String key, String value);
//写入Cookie
response.addCookie();
//读取Cookie
Coolies[] cookies = request.getCookies();
Cookie对象的常用方法:void setMaxAge(int second)、 void setValue(String key)、 String getName()、 String getValue()、 String getMaxAge()。
使用部署文件将URL映射到sevlet
将servlet部署到Web容器时,会创建一个相当简单的XML文档,这称为部署描述文件(DD),部署描述文件会告诉容器如何运行你的servlet和JSP。
部署描述文件(DD)提供了一种“声明”机制来定制Web应用,而无需修改源代码!
DD的优点:
- 尽量少改动已经测试通过的源代码。
- 即使你手上并没有源代码,也可以对应用功能进行调整。
- 不用重新编译和测试任何代码,也可以让你的应用适应不同的资源(如数据可)。
- 可以更容易地维护安全信息,如访问控制列表和安全角色。
- 非程序员也可以以修改和部署Web应用,而你可以留出精力,做出有意思的事情,比如看看你的行装是否适合夏威夷之旅。
servlet的存在就是要为客户服务。servlet的任务时得到一个客户的请求,在发出一个响应。
service()方法总是在自己的栈中调用。容器运行多个线程来处理对一个servlet的多个请求。
谁来实现HttpServletRequest和HttpServletResponse接口?这些类在API中吗?——容器、不在。他们要由开发商来实现。
HttpSession
javax.servlet.http.HttpSession接口表示一个会话,我们可以把一个会话内需要共享的数据保存到HttpSession对象中!
通常把HttpSession直接称为Session。
获取Session对象:
HttpSession session = request.getSession();
常用方法:void setAttribute(String key, Object value)、 Object getAttribute(String key)、 void invalidate()、 String getId()、 void setMaxInactiveInterval()、 int getMaxInactiveInterval()、 void removeAttribute()。
注意:存值时,key相同value会覆盖。session失效,其中的值会消失。
session的生命周期:打开浏览器session有效,关闭浏览器/调用invalidata()方法/超时session失效(销毁),默认有效时间为20分钟。
手动设置session失效:
//使用session的方法
session.setMaxInactiveInterval(int second);
//配置文件,就近有效原则,项目下的web.xml优先级高于Tomcat中的web.xml。
<seesion-config>
<session-timeout>int minutes</session-timeout>
</session-config>
session与窗口的关系:
- 每个session对象都与浏览器一一对应,重新开启一个浏览器,相当于重新创建一个session对象(版本不同可能会有差异)。
- 通过超链接打开的新窗口,新窗口的session与其父窗口的session相同。
session的应用场合:
- 登录成功后存储用户对象。
- 安全退出。
- 后台页面的访问控制。
Servlet下载
package gacl.response.study;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.URLEncoder;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* 文件下载
*/
public class ResponseDemo02 extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
downloadChineseFileByOutputStream(response);//下载中文文件
}
/**
* 下载中文文件,中文文件下载时,文件名要经过URL编码,否则会出现文件名乱码
* @param response
* @throws FileNotFoundException
* @throws IOException
*/
private void downloadChineseFileByOutputStream(HttpServletResponse response)
throws FileNotFoundException, IOException {
String realPath = this.getServletContext().getRealPath("/download/张家界国家森林公园.JPG");//获取要下载的文件的绝对路径
String fileName = realPath.substring(realPath.lastIndexOf("\\")+1);//获取要下载的文件名
//设置content-disposition响应头控制浏览器以下载的形式打开文件,中文文件名要使用URLEncoder.encode方法进行编码,否则会出现文件名乱码
response.setHeader("content-disposition", "attachment;filename="+URLEncoder.encode(fileName, "UTF-8"));
InputStream in = new FileInputStream(realPath);//获取文件输入流
int len = 0;
byte[] buffer = new byte[1024];
OutputStream out = response.getOutputStream();
while ((len = in.read(buffer)) > 0) {
out.write(buffer,0,len);//将缓冲区的数据输出到客户端浏览器
}
in.close();
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}
}
JSP
JSP内置对象
JSP内置对象是由web容器创造出来的一组对象。常用的JSP内置对象有:out、 request、 response、 session、 application。
- out 对象:用于向客户端输出信息。
- request对象:主要用于处理客服端的请求。
- response对象:用于响应客户请求并向客户端输出信息。
- session对象:用于记录会话状态的相关信息。
- application对象:实现用户之间的数据共享。
指令元素:(3个)
<%@指令元素名 属性名=”属性值” 属性名2=”属性值2”… %>
page指令
通过page指令的属性设置页面的属性信息
import 导包
contentType 内容类型、字符集
每个jsp页面第一行必须是page指令
脚本元素:三个(java代码)
小脚本<% %> java代码
表达式<%= %> 输出
声明<%! %> 方法 (不常用)
注释:
html注释 响应给用户时查看源文件可以看到
jsp注释 响应后查看源文件不可以看到
小脚本中应用java注释
jsp处理流程(执行过程)
翻译阶段 .jsp—.java (Servlet类)
编译阶段 .java—.class
运行阶段 将显示内容显示给用户
为什么第一次访问jsp页面慢,页面内容不改时再次访问速度变快?
第一次访问jsp页面时需要经历翻译-编译-运行阶段
页面内容不改时再访问 可以重用.class文件 直接运行(只经历运行阶段)
jsp与servlet的关系
实质是一个技术
jsp首先会翻译成一个Servlet类再编译、运行
jsp、servlet都能实现页面显示、处理代码
jsp显示更好
servlet处理更好
jsp和servlet搭配应用
tomcat服务器 work文件夹–jsp所翻译的.java、编译的.class文件
jsp页面报错的代码行数–.java文件行数
调错:
404 路径、run as on Server
500 语法错误,抛异常,查看异常信息,提示错误行数
应用system.out…输出
浏览器中右键查看源文件(jsp)
jsp指令元素
page
include 引入页面、包含页面
<%@include file=”页面路径”%>
jsp的作用范围
page 仅在当前页面有效
pageContext对象
request 在当前请求中有效的
点击链接、输入url、表单提交、刷新页面 请求有效(诞生)
页面跳转(路径变化了) 刷新页面 请求失效了 会产生新的请求
如果在request作用范围中存值,必须采用请求转发跳转,跳转后页面中可以获取到request中的值。
session 当前会话中有效
打开浏览器session有效
关闭浏览器、session超时、session手动卸载(session.invalidate())session失效
application 当前应用程序中有效
打开服务器时application有效
关闭服务器时application失效
作用范围从小到大
page–request–session–application
ServletContext
应用:
page 用的很少
request 一般用来存用一次的数据
session 一般用来存用户信息、购物车(跟踪)
application 范围最大的 一般用来存公有信息、计算访问人数
原则:
能用小的就不用大的
请求转发和重定向
如果在request作用范围中存值,必须采用请求转发跳转。
其他情况重定向
cookie和session的对比:
- session:在服务器端保存用户信息,session中保存的是Object类型,随会话结束而将其存储的数据销毁,保存重要信息。
- 在客户端保存用户信息,cookie中保存的是字符串,cookie可以长期保存在客户端,用来保存不重要信息。