第3章 深入Servlet技术
请求-响应模式就是典型的Web应用程序访问过程,Java Web应用程序中,处理请求并发送响应的过程是由一种叫做Servlet的程序来完成的。
请求request,响应response,与HTTP协议
Telnet演示HTTP协议
默认telnet关闭的,控制面板中,program and feathers,找到telnet client进行开启。
GET方式查询:常用来查询信息
HTTP头数据:
User-Ageent:Mozilla/4.0(...) 浏览器信息
Accept:text/html; */* 浏览器支持的格式
cookie: account-Helloween 记录用户当前的状态
Referer: http://www.baidu.com 指从哪个页面单击链接进入的
POST方式提交数据
GET提交数据不能超过256字符,POST提交,数据不在浏览器地址中显示,常用来提交表单数据
其他访问方式
HEAD,DELETE,TRACE,PUT,OPTIONS
Servlet概述
Java Web应用程序中所有的请求-响应都是Servlet完成的,没有main之类的方法,当用户访问服务器的时候,Tomcat通过调用Servlet的某些方法完成整个处理过程的。
Servlet工作流程
HttpServeltRequest/HttpServletResponse
Servlet接口
GET/POST/HEAD/PUT/DELETE/TRACE
一般为 doGet()/doPost() .../getLastModified(request)返回文档的最后修改时间
Java Web目录结构
Web程序部署在Tomcat的/webapps下面,用 http://localhost:8080/web1
编写Servlet
javax.servlet.* javax.servlet.http.*
一般直接继承HttpServlet,覆盖方法即可,一般只覆盖doGet(),doPost()
3.3.1 实现Servlet
编写Web Project,FirstServlet.java,覆盖常用三个方法
本书使用的是java EE5,新建项目时需要注意
新建web Project-> 新建servlet,
FirstServlet.java
/**
* The doGet method of the servlet.
*
* This method is called when a form has its tag value method equals to get.
*
* @param request the request send by the client to the server
* @param response the response send by the server to the client
* @throws ServletException if an error occurred
* @throws IOException if an error occurred
*
* GET方式访问页面执行该函数 执行doGet之前会执行getLastModified,如果发现返回的数值与上次访问是相同,
* 则认为文档没有更新,浏览器采用缓存而不执行,如果返回 -1,则认为最新,总是执行该函数
*/
public void doGet(HttpServletRequest request , HttpServletResponse response )
throws ServletException, IOException {
this.log("执行doGet方法..." );// 控制台日志输出信息
this.execute(request , response );// 处理doGet
}
/**
* The doPost method of the servlet.
*
* This method is called when a form has its tag value method equals to post.
*
* @param request the request send by the client to the server
* @param response the response send by the server to the client
* @throws ServletException if an error occurred
* @throws IOException if an error occurred
*
* 以post方式访问页面时执行该函数,执行前不会调用getLastModified
*/
public void doPost(HttpServletRequest request , HttpServletResponse response )
throws ServletException, IOException {
this.log("执行doPost方法" );
this.execute(request , response );
}
@Override
protected long getLastModified(HttpServletRequest req) {
// TODO Auto-generated method stub
this.log("执行 getLastModified 方法" );
return -1;
}
// 执行方法
private void execute(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
response.setCharacterEncoding( "UTF-8");
request.setCharacterEncoding( "UTF-8");
String requestURI = request.getRequestURI();
String method = request.getMethod();
String param = request.getParameter("param" );// 客户端提交的参数 param值
response.setContentType( "text/html");// 文档类型为HTML类型
PrintWriter out = response.getWriter();
out.println( "");
out.println( "");
out.println( " A Servlet");
out.println( " ");
out.println( " 以" + method + " 方式访问该页面。取到的param参数为:" + param + "
" );
out.println( " " );
out.println( " " );
//客户端浏览器读取该文档的更新时间
out.println( " " );
out.println( " ");
out.println( "");
out.flush();
out.close();
}
3.3.2 配置
首先名称及类名:
FirstServlet
servlet.FirstServlet
message
welcome to FisrtServlet
encoding
utf-8 param-value>
配置一个初始化参数
配置Servlet的加载方式。0和1,1启动加载,否则,Tomcat会在有人第一次请求加载
FirstServlet
/ servlet/FirstServlet
配置该Servlet的访问方式:这里即http://localhost:8080/servlet /servlet/FirstServlet
如果配置为/servlet/FirstServlet.* 使用http://localhost:8080/servlet /servlet/FirstServlet.XXX访问
通配符试了好像不行,还是支持多个映射,把需要的映射加进去吧
一个完整的servlet包括servlet类,配置,配置。利用myeclipse向导自动完成配置。
???部署到Tomcat6.0系统,然后启动,发现超时,可以使用:
部署的时候出现Server Tomcat v6.0 Server at localhost was unable to start within 45 seconds. If the server requires more time, try increasing the timeout in the server editor?
我们找到当前工程的workplace目录,然后按下面的操作:
找到workspace\.metadata\.plugins\org.eclipse.wst.server.core\servers.xml文件。
把其中的start-timeout="45" 改为 start-timeout="100" 或者更长,根据不同同学的工程大小来设置。
最后重启eclipse就可以了。
3.4 请求与响应
获取request变量
客户端浏览器发出的请求被封装HttpServletRequest对象,包含所有的信息。
在servlet项目中新建servlet,
RequestServlet.java:
public class RequestServlet extends HttpServlet {
/**
* Constructor of the object.
*/
public RequestServlet() {
super();
}
/**
* Destruction of the servlet.
*/
public void destroy() {
super.destroy(); // Just puts "destroy" string in log
// Put your code here
}
// 返回客户端浏览器接受的文件类型
private String getAccept(String accept) {
StringBuffer buffer = new StringBuffer();
if (accept .contains("image/gif"))
buffer.append( "GIF文件,");
if (accept .contains("image/x-xbitmap"))
buffer.append( "BMP文件,");
if (accept .contains("image/jpeg"))
buffer.append( "JPG文件,");
if (accept.contains("application/vnd.ms-execel" ))
buffer.append( "EXCEL文件," );
if (accept.contains("application/vnd.ms-powerpoint" ))
buffer.append( "PPT文件,");
if (accept .contains("application/vnd.msword"))
buffer.append( "Word文件," );
return buffer .toString().replaceAll(", $", "");
}
// 返回客户端的语言环境
private String getLocale(Locale locale) {
if (Locale.SIMPLIFIED_CHINESE.equals(locale))
return "简体中文" ;
if (Locale.TRADITIONAL_CHINESE.equals(locale))
return "繁体中文" ;
if (Locale.ENGLISH.equals(locale))
return "英文" ;
if (Locale.JAPANESE.equals(locale))
return "日文" ;
return "未知语言环境" ;
}
// 返回IP地址对应的物理地址
// private String getAddress(String ip){
// return IpUtil.getIpAddress(ip);
// }
// 返回客户端浏览器信息
private String getNavigatior(String userAgent) {
if (userAgent .indexOf("TencentTraveler") > 0)
return "腾讯浏览器" ;
if (userAgent .indexOf("Maxthon") > 0)
return "Maxthon浏览器" ;
if (userAgent .indexOf("MyIE2") > 0)
return "MyIE2浏览器" ;
if (userAgent .indexOf("Firefox") > 0)
return "Firefox浏览器" ;
if (userAgent .indexOf("MSIE") > 0)
return "IE浏览器" ;
return "未知浏览器" ;
}
// 返回客户端操作系统
private String getOS(String userAgent) {
if (userAgent .indexOf("Windows NT 5.1") > 0)
return "Windows XP" ;
if (userAgent .indexOf("Windows 98") > 0)
return "Windows 98" ;
if (userAgent .indexOf("Windows NT 5.0") > 0)
return "Windows 2000" ;
if (userAgent .indexOf("Linux") > 0)
return "Linux" ;
if (userAgent .indexOf("Unix") > 0)
return "Unix" ;
return "未知" ;
}
/**
* The doGet method of the servlet.
*
* This method is called when a form has its tag value method equals to get.
*
* @param request
* the request send by the client to the server
* @param response
* the response send by the server to the client
* @throws ServletException
* if an error occurred
* @throws IOException
* if an error occurred
*/
public void doGet(HttpServletRequest request , HttpServletResponse response )
throws ServletException, IOException {
request.setCharacterEncoding( "UTF-8");
response.setCharacterEncoding( "UTF-8");
response.setContentType( "text/html");//文档类型为HTML
String authType = request .getAuthType();
String localAddr = request .getLocalAddr();//本地IP,服务器IP
String localName = request .getLocalName();//本地名称,服务器名称
int localPort = request .getLocalPort();//本地端口,Tomcat端口
Locale locale = request.getLocale(); //用户的语言环境
String contextPath = request .getContextPath();
String method = request .getMethod();//get还是post
String pathInfo = request .getPathInfo();
String pathTranslated = request.getPathTranslated();
String protocol = request.getProtocol(); //协议,这里指HTTP协议
String queryString = request.getQueryString();//查询字符串,即?后面的字符串
String remoteAddr = request .getRemoteAddr();//远程IP,客户端IP
int port = request .getRemotePort();//远程端口,客户端端口
String remoteUser = request .getRemoteUser();//远程用户
String requestedSessionId = request.getRequestedSessionId();//客户端session的ID
String requestURI = request .getRequestURI();//用户请求的URI
StringBuffer requestURL = request.getRequestURL();//用户请求的URL
String scheme = request.getScheme(); //协议头,这里为 http
String serverName = request .getServerName();//服务器名称
int serverPort = request .getServerPort();//服务器端口
String servletPath = request.getServletPath();// servlet的路径
Principal userPrincipal = request.getUserPrincipal();
String accept = request.getHeader( "accept");//浏览器支持的格式
String referer = request.getHeader("referer" );//从哪个页面单击到本页
//user-agent 包括操作系统类型、版本号、浏览器类型、版本号
String userAgent = request.getHeader("user-agent" );
String serverInfo = this.getServletContext().getServerInfo();
PrintWriter out = response.getWriter();
out.println( "");
out.println( "");
out.println( " Request Servlet");
out.println( " ");
out.println( " ");
out.println( "您的IP为" + remoteAddr + ",位于:空 "
+ "; 您使用" + getOS(userAgent) + "操作系统,"
+ getNavigatior( userAgent) + ",您使用 " + getLocale(locale)
+ "。
");
out.println( "服务器IP为" + localAddr + ",位于:空 "
+ "; 服务器使用" + serverPort + "端口,您的浏览器使用了," + port
+ "端口访问本网页。
" );
out.println( "服务器软件为" + serverInfo + "服务器名称为 "
+ localName + "。
" );
out.println( "您的浏览器接受" + getAccept(accept) + "。
" );
out.println( "您从" + referer + "访问到该页面。
" );
out.println( "使用的协议为" + protocol + "。URL协议头" + scheme
+ ",服务器名称" + serverName + ",您访问的URI为"
+ requestURI + "。
" );
out.println( "该servlet的路径为" + servletPath + ", 该servlet类名为" + this.getClass().getName()
+ "。
");
out.println( "本应用程序在硬盘的根目录为" + this.getServletContext().getRealPath("" ) + ", 网络的相对路径为" + contextPath + "。
" );
out.println( "
");
out.println( "
单击刷新本页面" );
out.println( " ");
out.println( "");
out.flush();
out.close();
}
/**
* Initialization of the servlet.
*
* @throws ServletException
* if an error occurs
*/
public void init() throws ServletException {
// Put your code here
}
}
结果:
3.4.2 response生成图片验证码
通过HttpServletResponese获取的PrintWrite对象只能写字符型数据。
这里使用Servlet输出图片验证码,原理:
服务器生成一个包含随机字符串的图片发给客户端,客户端提交数据时需要填写字符串作为验证。
Servlet输出图片时,需要调用getOutputStream.
IdentityServlet.java
public class IdentityServlet extends HttpServlet {
// 随机字典 不包括男人的0,O,1,I
public static final char[] CHARS = { '2', '3', '4', '5', '6' , '7' , '8' ,
'9', 'A', 'B', 'C', 'D', 'D', 'E', 'F', 'G', 'H' , 'J' , 'K' , 'L' ,
'M', 'N', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W' , 'X' , 'Y' , 'Z' };
public static Random random = new Random();
// 获取6位随机数
public static String getRandomstring() {
StringBuffer buffer = new StringBuffer();// 字符串缓存
for (int i = 0; i < 6; i++) {
buffer.append( CHARS[random .nextInt(CHARS. length)]);
}
return buffer .toString();
}
// 获取随机的颜色
public static Color getRandomColor() {
return new Color(random.nextInt(255), random.nextInt(255),
random.nextInt(255));
}
// 返回某颜色的反色
public static Color getReverseColor(Color c ) {
return new Color(255 - c.getRed(), 255 - c.getGreen(),
255 - c.getBlue());
}
/**
* Constructor of the object.
*/
public IdentityServlet() {
super();
}
/**
* Destruction of the servlet.
*/
public void destroy() {
super.destroy(); // Just puts "destroy" string in log
// Put your code here
}
/**
* The doGet method of the servlet.
*
* This method is called when a form has its tag value method equals to get.
*
* @param request
* the request send by the client to the server
* @param response
* the response send by the server to the client
* @throws ServletException
* if an error occurred
* @throws IOException
* if an error occurred
*/
public void doGet(HttpServletRequest request , HttpServletResponse response )
throws ServletException, IOException {
response.setContentType( "image/jpeg");// 设置输出类型
String randomString = getRandomstring();
// 放到session中
request.getSession( true).setAttribute("randomString" , randomString);
// 图片高度和宽度
int width = 100;
int height = 30;
// 随机颜色 背景色
Color color = getRandomColor();
Color reverse = getReverseColor(color);
// 创建彩色图片
BufferedImage bi = new BufferedImage(width , height,
BufferedImage. TYPE_INT_RGB);
// 获取绘图对象
Graphics2D g = bi.createGraphics();
g.setFont( new Font(Font.SANS_SERIF, Font.BOLD, 16));
g.setColor( color);
g.fillRect(0, 0, width, height); // 绘制背景
g.setColor( reverse); // 设置颜色
g.drawString( randomString, 18, 20);// 绘制随机字符
for (int i = 0, n = random.nextInt(100); i < n; i++) {
g.drawRect( random.nextInt(width ), random.nextInt(height ), 1, 1);
}
ServletOutputStream out = response.getOutputStream();
JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(out);
encoder.encode(bi);
out.flush();
}
/**
* The doPost method of the servlet.
*
* This method is called when a form has its tag value method equals to
* post.
*
* @param request
* the request send by the client to the server
* @param response
* the response send by the server to the client
* @throws ServletException
* if an error occurred
* @throws IOException
* if an error occurred
*/
public void doPost(HttpServletRequest request , HttpServletResponse response )
throws ServletException, IOException {
response.setContentType( "text/html");
PrintWriter out = response.getWriter();
out.println( "");
out.println( "");
out.println( " A Servlet");
out.println( " ");
out.print( " This is ");
out.print( this.getClass());
out.println( ", using the POST method");
out.println( " ");
out.println( "");
out.flush();
out.close();
}
/**
* Initialization of the servlet.
*
* @throws ServletException
* if an error occurs
*/
public void init() throws ServletException {
// Put your code here
}
}
注意
JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(out);
encoder.encode(bi);
需要导入头文件:
import com.sun.image.codec.jpeg.JPEGCodec;
import com.sun.image.codec.jpeg.JPEGImageEncoder;
生成的结果如下:
我们可以html.文件引用这个图片,identity.html
注意html中的路径问题;