Servlet简单介绍
来源:互联网 发布:linux 3306监听命令 编辑:程序博客网 时间:2024/05/22 17:31
Servlet
注意点:
- 在
cmd
中设置servlet相关的编译路径:set classpath=%classpath%;D:\0hsx\
,然后在运行相关的servlet的Java程序。
apache-tomcat-7.0.67\lib\servlet-api.jar
手动编写Servlet过程
- 建立JavaWeb应用的目录
Hello --- 应用名称 WEB-INF --- 目录 classes --- 目录:对应的Servlet的java文件就放在这里,比如:HelloServlet.java lib --- 目录 web.xml --- 配置文件
- 在classes目录中建立HelloServlet.java文件,具体代码如下:
package com.hsx;import java.io.*;import javax.servlet.*;public class HelloServlet extends GenericServlet { public void init() throws ServletException { System.out.println("init"); } public void service(ServletRequest req, ServletResponse res) throws ServletException,java.io.IOException { //向客户端输出数据 String data = "Hello Servlet"; OutputStream out = res.getOutputStream(); out.write(data.getBytes()); } public void destroy() { System.out.println("destory"); }}
- web.xml文件的配置,代码:
<?xml version="1.0" encoding="UTf-8"?><web-app xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" version="3.0" metadata-complete="true"> <servlet> <servlet-name>HelloServlet</servlet-name> <!-- Servlet的名称 --> <servlet-class>com.hsx.HelloServlet</servlet-class> <!-- Servlet的全名-路径 --> </servlet> <servlet-mapping> <servlet-name>HelloServlet</servlet-name> <!-- Servlet的名称,与<servlet>中的<servlet-name>中的内容要一致 --> <url-pattern>/helloServlet</url-pattern> <!-- URL:用户访问的映射路径 --> </servlet-mapping></web-app>
- 编译HelloServlet.java文件,注意,编译需要用到servlet-api.jar(在Tomcat的lib目录中),在
cmd
目录中编译时,需要设置classpath的路径,命令set classpath=%classpath%;D:\0hsx\
,接着在classes目录下编译该java类,命令:
apache-tomcat-7.0.67\lib\servlet-api.jarjavac -d . HelloServlet.java
,这是可以在classes目录中查看其是否编译成功。 - 启动Tomcat。
- 在浏览器中输入:
http://localhost:8080/hello/helloServlet
,页面上回显示”Hello Servlet”。
感觉用intellij Idea开发Servlet不好。
开发servlet的三种方式
- 实现servlet接口
- 继承GenericServlet类
- 继承HttpServlet类 * 一般用这个
修改MyEclipse中的Servlet模板
MyEclipse2014:在MyEclipse的安装目录中找到这个com.genuitec.eclipse.wizards_11.5.0.me201310291746.jar文件,打开其中的templates找到Servlet.java文件(注意:需要关闭MyEclipse,修改是应该养成良好的备份习惯)
Servlet的一些细节
细节1
- 由于客户端是通过URL地址访问web服务器中的资源,所以Servlet程序若想被外界访问,必须把servlet程序映射到一个URL地址上,这个工作在web.xml文件中使用
<servlet>
元素和<servlet-mapping>
元素完成。 <servlet>
元素用于注册Servlet,它包含两个主要的子元素:<servlet-name>
:设置Servlet的注册名<servlet-class>
:设置Servlet的完整类名
<servlet-mapping>
元素用于映射一个已注册的Servlet的一个对外访问的路径,它包好两个子元素:<servlet-name>
:指定Servlet的注册名<url-pattern>
:Servlet对外访问路径
- 示例:
<servlet> <servlet-name>HelloServlet</servlet-name> <servlet-class>com.hsx.HelloServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>HelloServlet</servlet-name> <url-pattern>/hello</url-pattern> </servlet-mapping>
细节2
- 同一个Servlet可以被映射到多个URL上,即多个
<servlet-mapping>
元素的<servlet-name>
子元素的值可以相同,即同一个Servlet的注册名。 - 在Servlet映射到的URL中也可以使用*通配符,但是只能有两种固定的格式:
- 一种格式是
*.扩展名
(注:*前没有其他内容) - 另一种格式是以正斜杠(/)开头并以(/*)结尾
- 一种格式是
注:*.扩展名
的匹配优先级低。
细节3
- 如果某个Servlet的映射路径仅仅为一个正斜杠(/),那么这个Servlet就成为当前web应用程序的缺省Servlet,即默认的Servlet。
- 凡是在web.xml文件中找不到匹配的元素的URL,它们的访问请求都将交给缺省Servlet处理,也就是说,缺省的Servlet用于处理所有其他的Servlet群殴不处理的访问请求。
- 在[tomcat的安装目录]\conf\web.xml文件中,注册了一个名称为org.apache.catalina.servlets.DefaultServlet的Servlet,并将这个Servlet设置为了缺省的Servlet。
<servlet> <servlet-name>default</servlet-name> <servlet-class>org.apache.catalina.servlets.DefaultServlet</servlet-class> <init-param> <param-name>debug</param-name> <param-value>0</param-value> </init-param> <init-param> <param-name>listings</param-name> <param-value>false</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>default</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping>
即访问Tomcat服务器中某个静态HTML文件盒图片时,实际上是在访问这个缺省的Servlet。
Servlet的生命周期
- Servlet是一个供其他Java程序(Servlet引擎)调用的Java类,它不能独立运行,它的运行完全由Servlet引擎控制和调度。
- 针对客户端的多次请求,通常,服务器只会创建一个Servlet实例对象,也就说Servlet实例对象一旦创建,它就会驻留在内存中,为后继的其他请求服务,直至web容器退出,Servlet实例对象才会销毁。
- 在Servlet的整个生命周期内,Servlet的init方法只被调用一次。而对一个Servlet的每次访问请求都导致Servlet引擎调用Servlet的service方法。对于每次访问请求,Servlet引擎都会创建一个新的HttpServletRequest请求对象和一个新的HttpServletResponse响应对象,然后将这两个对象作为参数传递给他调用的Servlet的service()方法,service方法再根据请求方式调用doXXX方法。
<load-on-startup>
的取值说明这个Servlet的启动顺序。
<servlet> <servlet-name>HelloServlet</servlet-name> <servlet-class>com.hsx.HelloServlet</servlet-class> <load-on-startop>2</load-on-startup> </servlet
Servlet线程安全问题
- 当多个客户端并发访问同一个Servlet时,web服务器会为每一个客户端的访问请求创建一个线程,并在这个线程上调用Servlet的service方法,因此service方法内如果访问了同一个资源的话,就有可能引发线程安全问题。
- 如果Servlet实现了SingleThreadModel接口,那么Servlet引擎将以单线程模式来调用其service方法。
- SingleThreadModel接口中没有定义任何方法,只要在Servlet类的定义中增加实现SingleThreadModel接口的声明即可。
- 对于实现了SingleThreadModel接口的Servlet,Servlet引擎仍然支持对该Servlet的多线程并发访问,其采用的方式是产生多个Servlet实例对象,并发的每一个线程分别调用一个独立的Servlet实例对象。
- 实现SingleThreadModel接口并不能真正解决Servlet的线程安全问题,因为Servlet引擎会创建多个Servlet实例对象,而真正意义上解决多线程安全问题是指一个Servlet实例对象被多个线程同时调用的问题。
解决并发问题
- 使用Java同步机制对多线程同步:运行效率低。
- 使用SingleThreadModel接口。
- 合理决定在Servlet中定义的变量的作用域。
ServletConfig对象
- 在Servlet的配置文件中,可以使用一个或多个
<init-param>
标签为Servlet配置一些初始化参数。 - 当Servlet配置了初始化参数后,web容器在创建Servlet实例对象时,会自动将这些初始化参数封装到ServletConfig对象中,并在调用Servlet的init方法时,将ServletConfig对象传递给Servlet,从而,程序员通过ServletConfig对象就可以得到当前Servlet的初始化参数信息。
<init-param> <param-name>enconding</param-name> <param-value>utf-8</param-value></init-param><load-on-startup>1</load-on-startup>
注:要配置在的下面。
补充:
- 只能给某个Servlet配置参数,当然也只能作用于对应的Servlet。
- 是给所有的Servlet配置参数,当然要配置在所有的Servlet外面,作用于所有的Servlet。
- 示例:
<!-- web.xml --><context-param> <param-name>encoding</param-name> <param-value>UTF-8</param-value></context-param><context-param> <param-name>welcome</param-name> <param-value>hhh</param-value></context-param>//结合ServletContext对象ServletConfig servletConfig = this.getServletConfig();ServletContext servletContext = servletConfig.getServletContext();Enumeration<String> e = servletContext.getInitParameterNames();while (e.hasMoreElements()) { String name = e.nextElement(); Object value = servletContext.getInitParameter(name); System.out.println(value);}
ServletContext对象
- Web容器在启动时,它会为每一个Web应用程序都创建一个对应的ServletContext对象,它代表的是当前的Web应用。
- ServletConfig对象中维护了ServletContext对象的引用,我们在编写程序时,可以通过:
- servletConfig.getServletContext方法
this.getServletConfig().getServletContext();
获得ServletContext对象。 - 在继承HttpServlet中,直接
ServletContext sc = getServletContext();
获得ServletContext对象。
- servletConfig.getServletContext方法
- 由于一个Web应用中的所有Servlet共享同一个ServletContext对象,因此Servlet对象之间可以通过ServletContext对象实现通讯。ServletContext对象通常也被称为context域对象。
ServletContext应用
- 实现Servlet的转发示例:
//ServletContextDemo3中的代码ServletContext sc = getServletContext();RequestDispatcher rd = sc.getRequestDispatcher("/ServletContextDemo4");rd.forward(request, response);//ServletContextDemo4中的代码response.getOutputStream().write("nihao".getBytes());
- 转发的特点:
- 请求的地址栏不变。
- 转发前的Servlet和转发后的Servlet,两者之间共享request和response对象。
- 转发前的页面是不会有输出的,显示的始终是转发后的页面。示例:
ServletContext sc = getServletContext();RequestDispatcher rd = sc.getRequestDispatcher("/ServletContextDemo4");System.out.println("转发前ServletContextDemo3"); //后台会打印response.getOutputStream().write("Demo3 before".getBytes()); //页面不会显示response.getOutputStream().flush(); //强制刷新缓存 - 这是显示的Dome3的内容,而不会显示Demo4的内容//注:转发前不要刷新response输出流//转发前会清空response中输出流的内容rd.forward(request, response);System.out.println("转发后ServletContextDemo3"); //后台会打印response.getOutputStream().write("Demo3 after".getBytes()); //页面不会显示
- ServletContext读取资源配置文件,示例:
package com.hsx;import java.io.FileInputStream;import java.io.IOException;import java.io.InputStream;import java.io.OutputStream;import javax.servlet.ServletContext;import javax.servlet.ServletException;import javax.servlet.http.HttpServlet;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;/** * 读取文本中的某个资源文件,下载的方式打开 * @author hsx * */public class ServletContextDemo5 extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //1 http.png的真实路径 String httpPath = "/image/http.png"; //在web开发中"/"就代表当前web应用的根目录,本应用就是servletContext ServletContext sc = getServletContext(); String realPath = sc.getRealPath(httpPath); //得到绝对路径 System.out.println(realPath); InputStream in = new FileInputStream(realPath); OutputStream out = response.getOutputStream(); //通知客户端下载的方式 response.setHeader("Content-Disposition", "attachment;filename=http.png"); byte[] buffer = new byte[1024]; int len = -1; while ((len = in.read(buffer)) != -1) { out.write(buffer, 0, len); } in.close(); out.close(); //有没有没有什么关系,servlet容器会自动将其关闭 } public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { this.doGet(request, response); }}
注:getRealPath():获取指定相对路径资源的绝对路径,相对路径在WebRoot目录下必须以”/”开始。
- 读取WEB-INF目录下的配置文件
String realPath = sc.getRealPath("/WEB-INF/db.properties");
- 读取类目录下的配置文件
String realPath = sc.getRealPath("/WEB-INF/classes/db.properties");
- 读取类目录中的某个包中的配置文件
String realPath = sc.getRealPath("/WEB-INF/classes/com/hsx/db.properties");
- 采用类加载器读取配置文件,ClassLoader只能加载类目录中的资源(类加载不适合加载大的配置文件)
ClassLoader cl = ServletContextDemo6.class.getClassLoader(); //or this.getClass().getClassLoader();InputStream in = cl.getResourceAsStream("db.properties");Properties properties = new Properties();properties.load(in);System.out.println(properties.getProperty("name"));System.out.println(properties.getProperty("password"));
HttpURLConnection
- HttpURLConnection类的作用是通过HTTP协议向服务器发送请求,并可以获取服务器发回的数据。
- HttpURLConnection来自于jdk,它的完整名称为:java.net.HttpURLConnection。
- HttpURLConnection类没有公开的构造方法,但我们可以通过java.net.URL的openConnection方法获取一个URLConnection的实例,而HttpURLConnection是它的子类。
- 示例:
URL url = new URL("http://localhost:8080");HttpURLConnection connection = (HttpURLConnection) url.openConnection();
- 示例:简单获取服务器数据
- connection.getResponseCode() : 获取响应码
- connection.getResponseMessage() : 获取响应码描述
- connection.getHeaderField(“Server”) : 获取响应头
- connection.getInputStream(): 获取正文输入流
package com.hsx;import java.io.InputStream;import java.net.HttpURLConnection;import java.net.URL;public class HttpURLConnectionTest { public static void main(String[] args) throws Exception { URL url = new URL("http://localhost:8080/"); HttpURLConnection connection = (HttpURLConnection) url.openConnection(); // 获取响应码 int code = connection.getResponseCode(); // 获取响应码描述 String status = connection.getResponseMessage(); // 获取一个响应头 String header = connection.getHeaderField("Server"); // 获取响应正文 InputStream in = connection.getInputStream(); System.out.println("响应码" + code + "\t响应码描述" + status + "\t响应头" + header); byte[] buffer = new byte[1024]; int len = -1; while ((len = in.read(buffer)) != -1) { System.out.println(new String(buffer, 0, len)); } in.close(); connection.disconnect(); }}
- 示例:向服务器发送消息默认请求到doGet方式
URL url = new URL("http://localhost:8080/servletContext/ServletContextDemo1");HttpURLConnection connection = (HttpURLConnection) url.openConnection();connection.setDoOutput(true);//向服务器发送消息头connection.setRequestProperty("mheader", "pp");//向服务器发送请求参数OutputStream out = connection.getOutputStream();out.write("username=huang".getBytes());System.out.println(connection.getResponseCode());connection.disconnect();
- 示例:向服务器发送消息默认请求到doPost方式,只需要在上述代码中加上
connection.setRequestMethod("POST")
,默认的是doGet方式。
Servlet类图
request和response
- Web服务器收到客户端的http请求,会针对每一次请求,分别创建一个用于代表请求的request对象和代表响应的response对象。
- request和response对象既然代表请求和响应,要获取客户机提交过来的数据,只需要找request对象;要想客户机输出数据,只需要response对象。
HttpServletResponse
- HttpServletResponse对象代表服务器的响应。这个对象中封装了向客户端发送数据、发送响应头、发送响应状态码的方法。
response常见应用
向客户端输出中文数据,以字节为单位的四种方式:
package com.hsx;import java.io.IOException;import java.io.OutputStream;import java.io.PrintWriter;import javax.servlet.ServletException;import javax.servlet.http.HttpServlet;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;/** * 以字节为单位向客户端发送中文数据 * @author hsx * */public class ServletTest extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //test1(response); //test2(response); //test3(response); test4(response); } /** * 以UTF-8编码向客户端发送中文数据,并告诉客户端编码方式 * @param response * @throws IOException */ private void test4(HttpServletResponse response) throws IOException { String data = "中华"; response.setContentType("text/html;charset=UTF-8"); //实际上就是设置响应头 OutputStream out = response.getOutputStream(); out.write(data.getBytes("UTF-8")); // 告诉客户端编码方式 out.close(); } /** * 以UTF-8编码向客户端发送中文数据,并通过meta标签模拟请求头 * @param response * @throws IOException */ private void test3(HttpServletResponse response) throws IOException { String data = "中华"; OutputStream out = response.getOutputStream(); out.write("<meta http-equiv='Content-Type' content='text/html;charset=UTF-8'>".getBytes()); out.write(data.getBytes("UTF-8")); } /** * 以UTF-8编码向客户端发送中文数据,并告诉客户端编码方式 * @param response * @throws IOException */ private void test2(HttpServletResponse response) throws IOException { String data = "中华"; OutputStream out = response.getOutputStream(); out.write(data.getBytes("UTF-8")); // 告诉客户端编码方式 response.setHeader("Content-Type", "text/html;charset=UTF-8"); out.close(); } /** * 以本地平台默认编码向客户端发送中文数据 - GBK * @param response * @throws IOException */ private void test1(HttpServletResponse response) throws IOException { String data = "中华"; OutputStream out = response.getOutputStream(); out.write(data.getBytes()); //默认编码GBK out.close(); } public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { this.doGet(request, response); }}
总结:程序以什么编码输出,就要告知客户端以什么编码显示。
注:浏览器“查看”编码,再修改编码是不可取的。
注意:以字节流的方式向客户端发送1,一定要把int型的转换成String型
int i = 1; OutputStream out = response.getOutputStream(); out.write((i + "").getBytes()); out.close();
向客户端输出中文数据,以字符为单位的两种方式:
package com.hsx;import java.io.IOException;import java.io.PrintWriter;import javax.servlet.ServletException;import javax.servlet.http.HttpServlet;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;/** * 以字符为单位向客户端发送中文数据 * * @author hsx * */public class ServletTest2 extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //test1(response); test2(response); } /** * 字符流用这一种方式就可以搞定中文乱码问题response.setContentType("text/html;charset=UTF-8"); * @param response * @throws IOException */ private void test2(HttpServletResponse response) throws IOException { String data = "你好,啊打发"; response.setContentType("text/html;charset=UTF-8"); PrintWriter pw = response.getWriter(); pw.write(data); pw.close(); } /** * 制定向客户端发送的数据的编码是UTF-8,告诉客户端编码方式[即时客户端打开时显示的数据时以UTF-8编码显示的] * @param response * @throws IOException */ private void test1(HttpServletResponse response) throws IOException { String data = "你好,黄阿斯"; response.setCharacterEncoding("UTF-8"); //制定向客户端发送的数据的编码是UTF-8 PrintWriter pw = response.getWriter(); //默认的编码是ISO-8859-1(ISO-8859-1码表中没有中文) response.setHeader("Content-Type", "text/html;charset=UTF-8"); //告诉客户端编码方式 pw.write(data); pw.close(); } public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { this.doGet(request, response); }}
中文文件下载时的中文显示问题
package com.hsx;import java.io.FileInputStream;import java.io.IOException;import java.io.InputStream;import java.io.OutputStream;import java.net.URLEncoder;import javax.servlet.ServletException;import javax.servlet.http.HttpServlet;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import javax.servlet.http.HttpUtils;public class ServletTest3 extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //1 得到文件的真实路径 String realPath = getServletContext().getRealPath("/image/http请求过程.jpg"); String name = realPath.substring(realPath.lastIndexOf("\\") + 1); //文件名 System.out.println(name); //2 构建输入流 InputStream in = new FileInputStream(realPath); //3 利用response向客户端输出,告知客户端的下载方式 response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(name, "UTF-8")); //这里需要将文件的中文名进行编码,这里指定的编码是UTF-8 OutputStream out = response.getOutputStream(); byte[] buffer = new byte[1024]; int len = -1; while((len = in.read()) != -1) { out.write(buffer, 0, len); } in.close(); //out.close(); } public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { this.doGet(request, response); }}
输出随机图片
输出随机图片(CAPTCHA图像):Completely Automated Public Turing Test to Tell Computer and Humans Apart(全自动区分计算和人类的测试),相关的主要类[JDK查看API]:
- BufferedImage:内存图像
- Graphics:画笔
- ImageIO:输出图像
- 放在HTML页面上
注意:浏览器默认会缓存图片。
- 控制客户端不要缓存
response.addHeader("Pragma", "no-cache");response.setHeader("Cache-Control", "no-cache");response.setHeader("Expires", "0");
package com.hsx;import java.awt.Color;import java.awt.Font;import java.awt.Graphics;import java.awt.image.BufferedImage;import java.io.IOException;import java.io.PrintWriter;import java.util.Random;import javax.imageio.ImageIO;import javax.servlet.ServletException;import javax.servlet.http.HttpServlet;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;/** * 输出随机图像 * @author hsx * */public class ServletTest4 extends HttpServlet { private static int WIDTH = 120; private static int HIGHT = 30; public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.addHeader("Pragma", "no-cache"); response.setHeader("Cache-Control", "no-cache"); response.setHeader("Expires", "0"); //1 创建一个内存图像,并设置长和高 :BufferedImage BufferedImage image = new BufferedImage(WIDTH, HIGHT, BufferedImage.TYPE_INT_RGB); //2 得到该图像的画笔 :Graphics Graphics g = image.getGraphics(); //2.1 画边框 g.setColor(Color.BLUE); g.drawRect(0, 0, WIDTH, HIGHT); //2.2 画背景色 g.setColor(Color.GRAY); g.fillRect(1, 1, WIDTH - 2, HIGHT - 2); //2.3 画干扰线9条 Random random = new Random(); for (int i = 0; i < 9; i++) { g.setColor(Color.YELLOW); g.drawLine(random.nextInt(WIDTH), random.nextInt(HIGHT), random.nextInt(WIDTH), random.nextInt(HIGHT)); } //2.4 画验证树数字4个 int count = 5; for (int i = 0; i < 4; i++) { g.setColor(Color.RED); g.setFont(new Font("宋体", Font.BOLD, 25)); g.drawString(random.nextInt(9) + "", count, 25); count += 30; } //3 输出daoresponse的输出流中 :ImageIO ImageIO.write(image, "jpeg", response.getOutputStream()); } public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { this.doGet(request, response); }}
- js能刷新页面
<body> <form action="" method="post"> <input type="text" name="username" value=""/><br/><br/> <input type="password" name="password" value=""/><br/> <input type="text" name="code" value=""/><img id="codeImg" src="/servletContext/ServletTest4"> <a href="javascript:change()">看不清,换一张</a><br/> <input type="submit" value="登录"/> </form> <script type="text/javascript"> function change() { var imgObj = document.getElementById("codeImg"); imgObj.src = "/servletContext/ServletTest4?" + new Date().getTime(); } </script></body>
刷新页面
- 每隔3秒刷新页面(Servlet控制)
response.setHeader("Refresh", "3"); //每隔3秒中刷新一次
- 刷新到新的页面(Servlet控制)
response.getOutputStream().write("<meta http-equiv=\"Refresh\" content=\"3;URL=/servletContext/login.html\">".getBytes());
- 页面跳转到Servlet控制的页面上上去
··
<meta http-equiv="Refresh" content="0;URL=/servletContext/ServletTest5">
- 模仿注册成功,提示3秒后跳转到主页,或者点击‘这里’,直接跳转到主页
response.setContentType("text/html;charset=GBK");PrintWriter pw = response.getWriter();response.setHeader("Refresh", "3;URL=/servletContext/default.html");pw.println("注册成功!3秒后会自动转向主页。若没有发生跳转,请猛点<a href='/servletContext/default.html'>这里</a>");
控制客户端的缓存
- 设置客户端缓存一个月
// 设置客户端缓存一个月response.setContentType("text/html;charset=UTF-8"); response.setDateHeader("Expires", System.currentTimeMillis() + 30 * 24 * 60 * 60 * 1000);response.getOutputStream().write("你好".getBytes("UTF-8"));;
通过response现实请求重定向
- 请求重定向是指:一个Web资源收到客户端请求后,通知客户端去访问另外一个web资源,这称之为请求重定向。
- 地址栏会变,并发送2次请求,增加服务器负担。
- 实现方式:
- response.sendRedirect()
- 实现原理:
- 302状态码和location头即可实现重定向。
//重定向到login.html页面response.sendRedirect("/servletContext/login.html");
response细节
- getOutputStream()和getWriter()方法分别用于得到输出二进制数据、输出文本数据的ServletOutputStream、PrintWriter对象。
- getOutputStream()和getWriter()这两个方法互相排斥,调用了其中的任何有一个方法后,就不能再调用另一个方法。会抛异常。
- Servlet程序向ServletOutputStream或者PrintWriter对象中写入的数据将被Servlet引擎从response里面获取,Servlet引擎将这些数据当做响应消息的正文,然后再与响应状态行和各响应头组合后输出DOA客户端。( Servlet程序向ServletOutputStream或者PrintWriter对象将数据写到了response对象中,容器从response对象中获取响应行、响应头和正文)。
- Servlet的service()方法结束后,Servlet引擎将检查getWriter()或getOutputStream()方法返回的输出流对象是否已经调用close()方法,如果没有,Servlet引擎将调用close()方法关闭输出流对象。
HttpServletRequest
- HttpServletRequest对象代表客户端的请求,当客户端通过HTTP协议访问服务器时,HTTP请求头中的所有信息都封装在这个对象中,开发人员通过这个对象的方法,可以获取客户端这些消息。
request常用的方法
- 获取客户机 + 服务器信息
- getRequestURL方法返回客户端发出请求时的完整URL。
- getRequestURI方法返回请求行中的资源名部分。
- getQueryString方法返回请求行中的参数部分。
- getRemoteAddr方法返回发出请求的客户机的IP地址。
- getRemoteHost方法发出请求的客户机的完整主机名。
- getRemotePort方法返回客户机所使用的网络端口号。
- getLocalAddr方法返回WEB服务器的IP地址。
- getLocalName方法返回WEB服务器的主机名。
- getMethod返回客户机的请求方式。
String url = request.getRequestURL().toString();String uri = request.getRequestURI();String attr = request.getQueryString();String remoteAddr = request.getRemoteAddr();String remoteHost = request.getRemoteHost();int remotePort = request.getRemotePort();String localAddr = request.getLocalAddr();String localName = request.getLocalName();String method = request.getMethod();
- 获得客户机请求头
- getHeader(name) 获取某个请求头的值
- getHeaders(name) 获取某个请求头的值(有多个,全部返回出来)
- getHeaderNames() 获取请求头的所有的键,而不是值。
String header = request.getHeader("Accept");pw.println(header + "<br/>");pw.print("<br/>");Enumeration<String> headers = request.getHeaders("Accept");while (headers.hasMoreElements()) { String string = (String) headers.nextElement(); pw.println(string + "<br/>");}pw.print("<br/>");Enumeration<String> hh = request.getHeaderNames();while (hh.hasMoreElements()) { String key = (String) hh.nextElement(); String value = request.getHeader(key); pw.println(key + " = " + value + "<br/>");}
- 获得客户机请求参数(客户提交的数据)
- getParameter(name) 获取对应的值
- getParameteValues(name) 获取对应的值[数组]
- getParameterNames() 获取对应的键
- getParameterMap()
- getInputStream()
request处理中文乱码问题
- 浏览器是什么编码就以什么编码传送数据。
- 解决:
- request.setCharacterEncoding(“UTF-8”); //POST有效
- new String(username.getBytes(“ISO-8859-1”),”UTF-8”); //GET方式
- 超链接:cn //GET方式
- 更改Tomcat的配置解决URL编码问题:
request对象实现请求转发
- request对象实现请求转发:请求转发指一个Web资源收到客户端请求后,通知服务器去调用另外一个Web资源进行处理。
- request对象提供了一个getRequestDispatcher方法,该方法返回一个RequestDispathcher对象,调用这个对象的forword方法可以实现请求转发。
- request对象同时也是一个域对象,开发人员通过request对象在实现转发时,把数据通过request对象带给其他Web资源处理。
- setAttribute()
- getAttribute()
- removeAttribute()
- getAttributeNames()
//得到请求转发器RequestDispatcherRequestDispatcher rd = request.getRequestDispatcher("/servlet/ServletDemo");rd.forward(request, response);
转发与包含
- forward:浏览器访问Servlet1,Servlet1转发到Servlet2,Servlet2把结果返回给浏览器。
- include:浏览器访问Servlet1,Servlet1包含了Servlet2,Servlet1把结果返回给浏览器。[这里指的是动态包含]
RequestDispatcher
表示请求分发器,两个方法:
- forward(): 把请求转发给目标组件
- include(): 包含目标组件的响应结果
得到RequestDispatcher对象
- ServletContext对象的getRequestDispather(String path1),path1必须用绝对路径,即以”/”开头,若用相对路径会抛出异常。
- ServletRequest对象的getRequestDispather(String path2),path2可以使用绝对路径也可以使用相对路径。
路径的写法
- 绝对路径:ServletContext都必须用绝对路径。”/”
- 相对路径:其他的都可以使用相对路径,也可以使用绝对路径
在使用绝对路径时,要不要加”/”或者项目名:
- 是服务器调用的,不用加项目名,用”/”就可以代表了;
是客户端调用的,必须加上项目名。
转发:request.getRequestDispather(String url); – 当使用绝对路径时: “/ServletDemo” — 服务器
- 重定向:response.sendRedirect(String url); – 当使用绝对路径时: “/servlet/ServletDemo” — 客户端
- 超链接: – 当使用绝对路径时: “/servlet/ServletDemo” — 服务器
- 类加载文件的路径 – web应用中只能用相对路径,相对于classes目录的
- – 当使用绝对路径时: “/servlet/ServletDemo” — 服务器
- 页面分帧(frame) – 当使用绝对路径时: “/servlet/ServletDemo”
- ServletContext.getRealpath(url) – 当使用绝对路径时: “/servlet/ServletDemo”
- Servlet简单介绍
- Servlet的简单介绍
- servlet简单介绍
- Servlet入门简单介绍
- Servlet介绍以及简单实例
- Servlet中Filter的简单介绍
- SpringMvc和servlet简单对比介绍
- DRP总结—JSP+Servlet+JSTL简单介绍
- Servlet介绍
- Servlet介绍
- Servlet介绍
- servlet介绍
- Servlet 介绍
- Servlet介绍
- servlet介绍
- Servlet介绍
- Servlet介绍
- servlet介绍
- 区块链公司在创造历史,爱俄华州使…
- 英国五大基金公司正在探索区块链
- 比特币区块大小并不仅仅跟技术相关
- Simplex为信用卡比特币交易服务筹…
- JVM垃圾回收和内存分配策略
- Servlet简单介绍
- 联合国儿童基金会将区块链视为解决…
- 法国巴黎银行主办区块链科技开发活…
- Blockstream筹集5500万美元构建比…
- 韩国央行报告中鼓励探索区块链技术
- 日本金融巨头对比特币交易所Kraken…
- D+H报告:区块链必须做到的五件正…
- 对冲基金和区块链正走向更加高效的…
- Android双系统之基本问题研究