第一章 servlet技术
一、servlet的简介
servlet是能够接受请求并向客户端响应的Java类,类名为java.servlet.http.HttpServlet.JSP的前身就是servlet,JSP是在HTML中编写Java程序,而servlet是使用Java程序向客户端输出HTML。
1.1、开发一个servlet需要以下步骤
- 创建类并集成Servlet类,重写doGet()或doPost()方法;
- Servlet部署;
(配置URL与Servlet的映射,可通过xml配置,也可以通过注释配置); - 通过浏览器访问Servlet.
1.2、实例1:使用servlet输出Hello Servlet
第一步:创建web项目
项目名:JavaEE
第一步:创建包
包名:servlet
第一步:创建Servlet类
类名:HelloServlet
package servlet;
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* Servlet implementation class HelloServlet
*/
//servlet部署方法1:注释配置
//@WebServlet("/HelloServlet")
public class HelloServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
/**
* @see HttpServlet#HttpServlet()
*/
public HelloServlet() {
super();
}
/**
* @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
*/
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.setContentType("text/html");
PrintWriter out = response.getWriter();
out.print("<HTML>");
out.println("<HEAD><TITLE>First Servlet</TITLE></HEAD>");
out.println("<body bgcolor='cyan' align='center'>");
out.println("Hello World !");
out.println("</body>");
out.println("</html>");
out.flush();
out.close();
}
/**
* @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse
* response)
*/
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}
}
解释:
1、定义HelloServlet类,该类继承了javax.servlet.http.HttpServlet,因此HelloServlet类是servlet,并重写doGet()和doPost()方法。
2、doGet()和doPost()方法中的参数HttpServletRequest request, HttpServletResponse response分别用于从客户端获取数据和向客户端响应数据。
第二步:Servlet部署
方法1:使用注释
详细查看HelloServlet.java类
@WebServlet("/HelloServlet")
方法2:web.xml映射
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd" version="4.0">
<display-name>JavaEE</display-name>
<servlet>
<servlet-name>HelloServlet</servlet-name>
<servlet-class>servlet.HelloServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>HelloServlet</servlet-name>
<url-pattern>/HelloServlet</url-pattern>
</servlet-mapping>
</web-app>
解释:
1、url-pattern定义访问的URL;
2、servlet-class定义servlet类的全路径;
3、url-pattern和servlet-class通过servlet-name同名建立映射关系;
4、当用户在浏览器中输入url-pattern定义的路径“/HelloServlet”时,tomcat容器会将请求映射到HelloServlet类。当用户以get方式访问时会调用servlet的doGet()方法,当用户一post方式访问时,会调用servlet的doPost()方法。
5、URL映射是指用户通过浏览器输入URL向服务器发出请求时,将请求交给那个Servlet类处理该请求。
注意:
有时创建的web项目中没有web.xml文件,可以同过以下两种方式添加:
方式1:自动添加
方式2:手动添加
效果展示
1.3、实例2:使用servlet实现登录
创建web项目
项目名:Login
创建包
包名:com.login.servlet
创建servlet类
类名:TestServlet
package com.gxd.control;
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
/**
* Servlet implementation class TestServlet
*/
//@WebServlet("/TestServlet")
public class TestServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
/**
* @see HttpServlet#HttpServlet()
*/
public TestServlet() {
super();
}
/**
* @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
*/
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doPost(request,response);
}
/**
* @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
*/
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
PrintWriter out = response.getWriter();
// 接受到请求的字符编码
request.setCharacterEncoding("utf-8");//解决中文参数乱码
// 相应中的字符编码
response.setContentType("text/html;charset=UTF-8");//GBK,GB2312,BIG5,utf-8
out.println("Hello");
// 定义变量
String userName = request.getParameter("userName");
String userPass = request.getParameter("userPass");
// 判断账户
if("Admin".equals(userName)&&"123456".equals(userPass)) {
HttpSession session = request.getSession();
session.setAttribute("userName",userName);
response.sendRedirect("/loginSuccessed.jsp");
return;
}else {
request.setAttribute("message", "输入错误!");
request.getRequestDispatcher("login.jsp").forward(request, response);
return;
}
}
}
Servlet部署
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd" id="WebApp_ID" version="4.0">
<display-name>winterCampWeb0118</display-name>
<servlet>
<servlet-name>TestServlet</servlet-name>
<servlet-class>com.login.servlet.TestServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>TestServlet</servlet-name>
<url-pattern>/TestServlet</url-pattern>
</servlet-mapping>
</web-app>
index.jsp
<%@ page language="java" contentType="text/html; charset=utf-8"
pageEncoding="ISO-8859-1"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="ISO-8859-1">
<title>index</title>
</head>
<body>
<script type="text/javascript">
window.location = "/winterCampWeb0118/login.jsp";
</script>
</body>
</html>
login.jsp
<%@ page language="java" contentType="text/html; charset=utf-8"
pageEncoding="utf-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>login</title>
<style>
body{
margin: 0px;
padding: 0px;
background-image:url("./Images/bg.jpeg");
position: absolut;
height:100%;
width:100%;
}
#bg{
width:30%;
height:25%;
top:20%;
left:35%;
position:fixed;
background-image:url(https://b-ssl.duitang.com/uploads/item/201406/28/20140628134651_sWicV.jpeg);
background-size:60%;
}
</style>
<script type="text/javascript" >
function check() {
var a=document.getElementById('username').value;
var b=document.getElementById('password').value;
var c=document.getElementById('Username').value;
var d=document.getElementById('Password').value;
if(a!=c)
alert("name error!");
else if(b!=d)
alert("password error!");
else alert("Welcome!");
}
</script>
</head>
<body>
<div id="bg">
<h1 align="center">登录</h1>
<form action="TestServle" method="post">
<table width="100%"border="1">
<tr>
<td style="text-align:right" height:"100px">
<p>姓名:</p></td>
<td>
<input type="text" name="userName" id="Username" value="张三"></td>
</tr>
<tr>
<td style="text-align:right">
<p>密码:</p></td>
<td>
<input type="password" name="userPass" id="Password" value="******"></td>
</tr>
<tr>
<td> </td>
<td><input type="submit" value="登录"></td>
<!-- <td><input type="submit" value="登录" οnclick='check()'></td> -->
</tr>
</table>
</form>
</div>
</body>
</html>
目录结构:
效果展示
二、Servlet生命周期
2.1、测试Servlet生命周期
创建web项目
项目名:TestServlet
包名:com.test.servlet
Servlet类名:LoginServlet
package com.test.servlet;
import java.io.IOException;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@WebServlet("/LoginServlet")
public class LoginServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
public LoginServlet() {
super();
}
@Override
public void init(ServletConfig config) {
System.out.println("LoginServlet已经初始化");
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doPost(request,response);
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("LoginServlet完成了服务");
}
public void destory() {
System.out.println("LoginServlet已经销毁");
}
}
解释:
通过URL访问多次LoginServlet类,观察控制台的运算结果,会发现初始化方法只调用了一次,而服务器方法每发出一次,就执行一次。当重新启动Tomcat时,会发现销毁方法被执行了一次,因此说Servlet是单例模式(程序设计模式的一种)。
结果展示:
三、Servlet加载
Servlet
默认在第一次客户端请求时加载,并初始化。在某些应用中,需要Servlet
在容器启动时加载并初始化,这时需要配置启动参数loadOnStartup
属性。启动参数作为一个非负整数时,容器启动时加载对应的Servlet
,整数越小初始化越早。当配置参数值为负数时无效。
@WebServlet(urlPatterns="/LoginServlet",loadOnStartup = 1)
四、生成验证码
- 验证码的实现原理:
- 客户端首页向服务器的Servlet发出验证码请求;
- 服务器端生成随机验证码;
- 服务器将验证码保存到session中;
- 服务器将验证码绘制到图片上;
- Servlet将验证码图片响应到客户端浏览器
客户端浏览器提交数据后,服务器先判断用户提交的验证码是否与保存到session中验证码匹配,若通过验证则继续后面的业务,若未通过验证,则重新生成验证码,终止后面的业务。
在Java中如果要开发验证码程序需要使用到java.awt包中的很多类及方法,在本例中对其中的主要类进行介绍,关于更详细的只是,查看Java的API进行学习。
创建web项目
项目名:validatecode
创建包
包名:com.test.servlet
创建首页
首页名:index.jsp
<%@ page language="java" contentType="text/html; charset=utf-8"
pageEncoding="utf-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>验证码</title>
<script type="text/javascript">
function changeValidCode(){
var d = new Date().getTime();
document.getElementById("validcode").src="<%=request.getContextPath()%>/ImageServlet?d="+d
}
</script>
</head>
<body>
<form action="checkServlet" method="post">
请输入验证码:<input type="text" name="randomCode"/>
<img src="ImageServlet" id="validcode" onclick="changeValidCode()"/><br/>
<input type="submit" value="提交">
</form>
</body>
</html>
创建类
RandomValidateCode.java
package com.test.servlet;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.Random;
import javax.imageio.ImageIO;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
public class RandomValidateCode {
// 放到Session空间的KEY
public static final String RANDOMCODEKEY = "RANDOMVALIDATECODEKEY";
private Random random = new Random();
// 验证码字符的来源
private String randString = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
private int width = 80;
private int height = 26;
private int lineSize = 100;//验证码干扰线数量,干扰线时防止验证码被破解的
private int stringNum = 4;//验证码中字符的数量
/*
* 获得字体
*/
private Font getFont() {
return new Font("Times new Roman",Font.ROMAN_BASELINE,18);
}
/*
* 获得颜色
*/
private Color getRandColor() {
int r = random.nextInt(256);
int g = random.nextInt(256);
int b = random.nextInt(256);
return new Color(r,g,b);
}
/*
* 生成随机数图片
*/
public void getRandcode(HttpServletRequest request,HttpServletResponse response) throws IOException {
// 创建HttpSession对象
HttpSession session = request.getSession();
// 在内存中创建一副指定宽度,高度,背景色的图片,验证码将会之在这副图像上
BufferedImage image = new BufferedImage(width,height,BufferedImage.TYPE_INT_RGB);
// 产生image对象的Graphics对象,该对象可在图像上进行各种绘制操作,相当于画笔
Graphics g = image.getGraphics();
// 设置画笔的边框
g.fillRect(0, 0, width, height);
// 设置画笔的颜色
g.setColor(getRandColor());
// 画笔已经设置完毕,开始绘制验证码的干扰线
for(int i = 0;i <= lineSize;i++) {
drawLine(g);
}
// 开始绘制验证码,并将验证码保存到randomString变量中
String randomString = "";
for(int i = 0;i <= stringNum;i++) {
randomString = drawString(g,randomString,i);
}
// 将完整的验证码字符串保存到session中,用于下次验证
session.removeAttribute(RANDOMCODEKEY);
session.setAttribute(RANDOMCODEKEY, randomString);
// 销毁画笔
g.dispose();
// 将验证码图片响应到输出流中,发送给浏览器
ImageIO.write(image, "JPEG", response.getOutputStream());
}
/*
* 绘制验证码到图片上
*/
private String drawString(Graphics g, String randomString, int i) {
// 设置画笔字体
g.setFont(getFont());
// 设置画笔颜色
g.setColor(new Color(random.nextInt(101),random.nextInt(111),random.nextInt(121)));
// 设置画笔子啊x方向和y方向随机变换3个像素
g.translate(random.nextInt(3), random.nextInt(3));
// 生成验证码中的一个字符
String rand = String.valueOf(getRandomString(random.nextInt(randString.length())));
// 将验证码字符连接到验证码字符串中
randomString += rand;
// 将验证码字符rand绘制到图片上,x坐标时每个字符的宽度13*个数i,y坐标是16
g.drawString(rand, 13*i, 16);
return randomString;
}
/*
* 绘制干扰线
*/
private void drawLine(Graphics g) {
int x = random.nextInt(width);
int y = random.nextInt(height);
int xl = random.nextInt(13);
int yl = random.nextInt(15);
g.drawLine(x, y, x + xl, y + yl); //参数分别为起点x,y坐标,终点x,y坐标
}
/*
* 获得随机字符
*/
private String getRandomString(int num) {
return String.valueOf(randString.charAt(num));
}
}
ImageServlet.java
package com.test.servlet;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@WebServlet("/ImageServlet")
public class ImageServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
public ImageServlet() {
super();
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.setContentType("image/jpeg");
response.setHeader("Pragma", "No-cache");
response.setHeader("Cache-Control", "no-cache");
response.setDateHeader("Expires", 0);
RandomValidateCode rc = new RandomValidateCode();
try {
rc.getRandcode(request, response);
}catch(Exception e) {
e.printStackTrace();
}
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
}
checkServlet.java
package com.test.servlet;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
@WebServlet("/checkServlet")
public class checkServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
public checkServlet() {
super();
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doPost(request,response);
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.setContentType("text/html;charset=UTF-8");
String randomCode = request.getParameter("randomCode");
HttpSession session = request.getSession();
//RandomValidateCode ranVC = new RandomValidateCode();
String sessionCode = (String)session.getAttribute(RandomValidateCode.RANDOMCODEKEY);
//String sessionCode = (String)session.getAttribute(ranVC.RANDOMCODEKEY);
if(sessionCode.equals(randomCode)) {
System.out.println("验证成功!");
System.out.println("session中存储的验证码:"+sessionCode);
System.out.println("输 入 的 的 验 证 码:"+randomCode);
}else {
System.out.println("验证失败!");
System.out.println("session中存储的验证码:"+sessionCode);
System.out.println("输 入 的 的 验 证 码:"+randomCode);
}
}
}
目录结构
效果展示