Java Web整合开发(3) -- Servlet

时间:2023-03-08 20:39:47

Servlert基本程序架构: (FirstServlet.java + web.xml)

FirstServlet.java

package com.helloben.servlet;

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; public class FirstServlet extends HttpServlet { @Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
execute(request, response);
} @Override
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
execute(request, response);
} @Override
public String getServletInfo() {
return "Short description";
} protected void execute(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException { response.setContentType("text/html;charset=UTF-8");
response.setCharacterEncoding("UTF-8"); request.setCharacterEncoding("UTF-8"); String requestUri = request.getRequestURI();
String method = request.getMethod();
String param = request.getParameter("param"); try (PrintWriter out = response.getWriter()) { out.println("<!DOCTYPE html>");
out.println("<html>");
out.println("<head>");
out.println("<title>Servlet FirstServlet</title>");
out.println("</head>");
out.println("<body>"); out.println("<h1>FirstServlet at " + request.getContextPath() + "</h1>"); out.println("以 " + method + " 方式访问该页面。取到的 param 参数为:" + param + "<br/><br/>"); out.println("<form action='" + requestUri + "' method='get'><input type='text' name='param' value=''><input type='submit' value='以 GET 方式访问 RequestServlet'></form>");
out.println("<br/><br/>");
out.println("<form action='" + requestUri + "' method='post'><input type='text' name='param' value=''><input type='submit' value='以 POST 方式访问 RequestServlet'></form>");
out.println("<br/><br/>"); out.println("<script>document.write('本页面最后更新时间:' + document.lastModified + '<br /><br/>'); </script>");
out.println("<script>document.write('本页面URL:' + location + '<br/>' ); </script>"); out.println("</body>");
out.println("</html>");
}
}
}

web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="3.0" 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">
<servlet>
<servlet-name>FirstServlet</servlet-name>
<servlet-class>com.helloben.servlet.FirstServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>FirstServlet</servlet-name>
<url-pattern>/FirstServlet</url-pattern>
</servlet-mapping>
<session-config>
<session-timeout>
30
</session-timeout>
</session-config>
</web-app>

访问路径: http://localhost:8080/ch03servlet/FirstServlet

1. 获取request变量

        String authType = request.getAuthType();
String localAddr = request.getLocalAddr();
Locale locale = request.getLocale();
String localName = request.getLocalName();
String contextPath = request.getContextPath();
int localPort = request.getLocalPort();
String method = request.getMethod();
String pathInfo = request.getPathInfo();
String pathTranslated = request.getPathTranslated();
String protocol = request.getProtocol();
String queryString = request.getQueryString();
String remoteAddr = request.getRemoteAddr();
int port = request.getRemotePort();
String remoteUser = request.getRemoteUser();
String requestedSessionId = request.getRequestedSessionId();
String requestURI = request.getRequestURI();
StringBuffer requestURL = request.getRequestURL();
String scheme = request.getScheme();
String serverName = request.getServerName();
int serverPort = request.getServerPort();
String servletPath = request.getServletPath();
Principal userPrincipal = request.getUserPrincipal(); String accept = request.getHeader("accept");
String referer = request.getHeader("referer");
String userAgent = request.getHeader("user-agent"); String serverInfo = this.getServletContext().getServerInfo();

2.生成图片验证码(IdentityServlet.java)

package com.helloben.servlet;

import com.sun.image.codec.jpeg.JPEGCodec;
import com.sun.image.codec.jpeg.JPEGImageEncoder;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.Random;
import javax.servlet.*;
import javax.servlet.http.*; public class IdentityServlet extends HttpServlet { public static final char[] CHARS = { '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', '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(); 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());
} protected void execute(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException { response.setContentType("image/jpeg"); String randomString = getRandomString();
request.getSession(true).setAttribute("randomString", randomString); int width = 100;
int height = 30; Color color = getRandomColor();
Color reverse = getReverseColor(color); BufferedImage bufferedImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
Graphics2D g = bufferedImage.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);
} // 转成JPEG格式
ServletOutputStream out = response.getOutputStream();
JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(out);
encoder.encode(bufferedImage);
out.flush();
}
}

3. 获取初始化变量

Enumeration params = this.getInitParameterNames();
while(params.hasMoreElements()){
String usernameParam = (String)params.nextElement();
String passnameParam = this.getInitParameter(usernameParam);
}

4. 获取上下文变量

ServletContext servletContext = this.getServletConfig().getServletContext();

String uploadFolder = servletContext.getInitParameter("upload folder");
String allowedFileType = servletContext.getInitParameter("allowed file type");

5. 资源注入(InjectionServlet.java)

@Resource(name="hello")
private String hello; @Resource(name="i")
private int i; @Resource(name="persons")
private String persons;

web.xml

<env-entry>
<env-entry-name>persons</env-entry-name>
<env-entry-type>java.lang.String</env-entry-type>
<env-entry-value>HelloBen, Tony, Rose, Alix</env-entry-value>
</env-entry>

6. 使用JNDI获取资源

Context ctx = new InitialContext();
String hello = (String)ctx.lookup("hello");
Integer i = (Integer)ctx.lookup("i");
String persons = (String)ctx.lookup("person");

7. 注射数据源

@Resource
javax.sql.DataSource datasource; public Connection getConnection() throws SQLException{
Connection conn = datasource.getConnection();
return conn;
}

8. GET方式提交表单(search.jsp)

<form action='SearchServlet' method='get'>
<input type="radio" name="type" value="web" checked/>网页
<input type="text" name="word" value="" style="width:300px; "/>
<input type="submit" value="用雅虎搜索" style="width:100px; "/>
</form>

URL: http://server:8080/webapp/SearchServlet?type=web&word=wbsn

SearchServlet.java

String word = request.getParameter("word");
String type = request.getParameter("type");

9. POST方式提交表单(postPersonInfo.jsp)

<form action="PostServlet" method="POST">
<input type="text" name="name" class="text" />
<input type="password" name="password" class="text" />
</form>

PostServlet.java

String name = request.getParameter("name");
String password = request.getParameter("password");
String sex = request.getParameter("sex"); int age = 0;
try {
age = Integer.parseInt(request.getParameter("age"));
}
catch (Exception e) {
} Date birthday = null;
try {
DateFormat format = new SimpleDateFormat("yyyy-MM-dd");
birthday = format.parse(request.getParameter("birthday"));
}
catch (Exception e) {
} String[] interesting = request.getParameterValues("interesting");
String area = request.getParameter("area");
String description = request.getParameter("description");
String btn = request.getParameter("btn");

10. 上传文件

Web文件上传也采用POST方式。(upload.jsp)

<form action="UploadServlet" method="post" enctype="multipart/form-data">
<input type="file" name="file1" class="text">
</form>

上传文件时,浏览器以二进制方式发送数据。解析二进制数据需要类库,如SmartUpload与Apache Commons Fileupload。SmatUpload是商业类库,解析过程中数据存放在内存中,因此比较快,但是大文件时会内存溢出。

UploadServlet.java

File file1 = null;
File file2 = null;
String description1 = null;
String description2 = null; // 使用 DiskFileUpload 对象解析 request
DiskFileUpload diskFileUpload = new DiskFileUpload();
try {
// 将 解析的结果 放置在 List 中
List<FileItem> list = diskFileUpload.parseRequest(request);
out.println("遍历所有的 FileItem ... <br/>");
// 遍历 list 中所有的 FileItem
for(FileItem fileItem : list){
if(fileItem.isFormField()){
// 如果是 文本域
if("description1".equals(fileItem.getFieldName())){
// 如果该 FileItem 名称为 description1
out.println("遍历到 description1 ... <br/>");
description1 = new String(fileItem.getString().getBytes(), "UTF-8");
}
if("description2".equals(fileItem.getFieldName())){
// 如果该 FileItem 名称为 description2
out.println("遍历到 description2 ... <br/>");
description2 = new String(fileItem.getString().getBytes(), "UTF-8");
}
}
else{
// 否则,为文件域
if("file1".equals(fileItem.getFieldName())){
// 客户端文件路径构建的 File 对象
File remoteFile = new File(new String(fileItem.getName().getBytes(), "UTF-8"));
out.println("遍历到 file1 ... <br/>");
out.println("客户端文件位置: " + remoteFile.getAbsolutePath() + "<br/>");
// 服务器端文件,放在 upload 文件夹下
file1 = new File(this.getServletContext().getRealPath("attachment"), remoteFile.getName());
file1.getParentFile().mkdirs();
file1.createNewFile(); // 写文件,将 FileItem 的文件内容写到文件中
InputStream ins = fileItem.getInputStream();
OutputStream ous = new FileOutputStream(file1); try{
byte[] buffer = new byte[1024];
int len = 0;
while((len=ins.read(buffer)) > -1) {
ous.write(buffer, 0, len);
}
out.println("已保存文件" + file1.getAbsolutePath() + "<br/>");
}
finally{
ous.close();
ins.close();
}
}
if("file2".equals(fileItem.getFieldName())){
// 客户端文件路径构建的 File 对象
File remoteFile = new File(new String(fileItem.getName().getBytes(), "UTF-8"));
out.println("遍历到 file2 ... <br/>");
out.println("客户端文件位置: " + remoteFile.getAbsolutePath() + "<br/>");
// 服务器端文件,放在 upload 文件夹下
file2 = new File(this.getServletContext().getRealPath("attachment"), remoteFile.getName());
file2.getParentFile().mkdirs();
file2.createNewFile(); // 写文件,将 FileItem 的文件内容写到文件中
InputStream ins = fileItem.getInputStream();
OutputStream ous = new FileOutputStream(file2); try{
byte[] buffer = new byte[1024];
int len = 0;
while((len=ins.read(buffer)) > -1) {
ous.write(buffer, 0, len);
}
out.println("已保存文件" + file2.getAbsolutePath() + "<br/>");
}
finally{
ous.close();
ins.close();
}
}
}
}
out.println("Request 解析完毕");
}
catch (FileUploadException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}

11. 带进度条的文件上传

实时显示上传进度的原理是服务器在处理上传文件的同事,将上传进度的信息如文件总长度、已上传多少,传输速率等写入Session中。客户端浏览器利用Ajax技术再新开一个独立的线程从Session中获取上传进度信息,并实时显示。Session可以看做是服务器内存。

uploadprogress.jsp

<%@page language="java" contentType="text/html" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>上传文件</title>
<style type="text/css">
body, td, div {
font-size: 12px;
font-familly: 宋体;
} #progressBar {
width: 400px;
height: 12px;
background: #FFFFFF;
border: 1px solid #000000;
padding: 1px;
} #progressBarItem {
width: 30%;
height: 100%;
background: #FF0000;
}
</style>
<script type="text/javascript">
var _finished = true; function $(obj){
return document.getElementById(obj);
} function showStatus(){
_finished = false;
$('status').style.display = 'block';
$('progressBarItem').style.width = '1%';
$('btnSubmit').disabled = true; setTimeout("requestStatus()", 1000);
} function requestStatus(){ if(_finished) {
return;
} var req = createRequest(); req.open("GET", "ProgressUploadServlet");
req.onreadystatechange = function(){
callback(req);
}
req.send(null); setTimeout("requestStatus()", 1000);
} function createRequest()
{
if(window.XMLHttpRequest)//ns
{
return new XMLHttpRequest();
}
else//IE
{
try{
return new ActiveXObject("Msxml2.XMLHTTP");
}
catch(e){
return new ActiveXObject("Microsoft.XMLHTTP");
}
}
return null;
} function callback(req){ if(req.readyState == 4) {
if(req.status != 200){
_debug("发生错误。 req.status: " + req.status + "");
return;
} _debug("status.jsp 返回值:" + req.responseText); var ss = req.responseText.split("||"); // 格式:百分比||已完成数(M)||文件总长度(M)||传输速率(K)||已用时间(s)||估计总时间(s)||估计剩余时间(s)||正在上传第几个文件
$('progressBarItem').style.width = '' + ss[0] + '%';
$('statusInfo').innerHTML = '已完成百分比: ' + ss[0] + '% <br />已完成数(M): ' + ss[1] + '<br/>文件总长度(M): ' + ss[2] + '<br/>传输速率(K): ' + ss[3] + '<br/>已用时间(s): ' + ss[4] + '<br/>估计总时间(s): ' + ss[5] + '<br/>估计剩余时间(s): ' + ss[6] + '<br/>正在上传第几个文件: ' + ss[7]; if(ss[1] == ss[2]){
_finished = true;
$('statusInfo').innerHTML += "<br/><br/><br/>上传已完成。";
$('btnSubmit').disabled = false;
}
}
} function _debug(obj){
var div = document.createElement("DIV");
div.innerHTML = "[debug]: " + obj;
document.body.appendChild(div);
}
</script>
</head>
<body>
<iframe name=upload_iframe width=0 height=0></iframe> <form action="ProgressUploadServlet" method="post" enctype="multipart/form-data" target="upload_iframe" onsubmit="showStatus()">
<input type="file" name="file1" style="width: 350px; "> <br />
<input type="file" name="file2" style="width: 350px; "> <br />
<input type="file" name="file3" style="width: 350px; "> <br />
<input type="file" name="file4" style="width: 350px; ">
<input type="submit" value=" 开始上传 " id="btnSubmit"></form> <div id="status" style="display: none; ">
上传进度条:
<div id="progressBar">
<div id="progressBarItem"></div>
</div>
<div id="statusInfo"></div>
</div>
</form>
</body>
</html>

ProgressUploadServlet.java

package com.helloben.servlet.upload;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.util.Iterator;
import java.util.List;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload; public class ProgressUploadServlet extends HttpServlet { @Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException { response.setHeader("Cache-Control", "no-store");
response.setHeader("Pragrma", "no-cache");
response.setDateHeader("Expires", 0); UploadStatus status = (UploadStatus) request.getSession(true).getAttribute("uploadStatus"); if (status == null) {
response.getWriter().println("没有上传信息");
return;
} long startTime = status.getStartTime();
long currentTime = System.currentTimeMillis(); long time = (currentTime - startTime) / 1000 + 1;
double velocity = ((double) status.getBytesRead()) / (double) time;
double totalTime = status.getContentLength() / velocity;
double timeLeft = totalTime - time;
int percent = (int) (100 * (double) status.getBytesRead() / (double) status.getContentLength());
double length = ((double) status.getBytesRead()) / 1024 / 1024;
double totalLength = ((double) status.getContentLength()) / 1024 / 1024; // 格式:百分比||已完成数(M)||文件总长度(M)||传输速率(K)||已用时间(s)||估计总时间(s)||估计剩余时间(s)||正在上传第几个文件
String value = percent + "||" + length + "||" + totalLength + "||"
+ velocity + "||" + time + "||" + totalTime + "||" + timeLeft + "||" + status.getItems(); response.getWriter().println(value);
} @Override
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException { UploadStatus status = new UploadStatus();
UploadListener listener = new UploadListener(status); request.getSession(true).setAttribute("uploadStatus", status); // Apache 上传工具
ServletFileUpload upload = new ServletFileUpload(new DiskFileItemFactory());
upload.setProgressListener(listener); try {
List itemList = upload.parseRequest(request); for (Iterator it = itemList.iterator(); it.hasNext();) {
FileItem item = (FileItem) it.next();
if (item.isFormField()) {
System.out.println("FormField: " + item.getFieldName() + " = " + item.getString());
}
else {
System.out.println("File: " + item.getName()); // 统一 Linux 与 windows 的路径分隔符
String fileName = item.getName().replace("/", "\\");
fileName = fileName.substring(fileName.lastIndexOf("\\")); File saved = new File("C:\\upload_test", fileName);
saved.getParentFile().mkdirs(); InputStream ins = item.getInputStream();
OutputStream ous = new FileOutputStream(saved); byte[] tmp = new byte[1024];
int len = -1; while ((len = ins.read(tmp)) != -1) {
ous.write(tmp, 0, len);
} ous.close();
ins.close(); response.getWriter().println("已保存文件:" + saved);
}
}
}
catch (Exception e) {
e.printStackTrace();
response.getWriter().println("上传发生错误:" + e.getMessage());
}
} @Override
public String getServletInfo() {
return "Short description";
}
}

UploadListener.java

package com.helloben.servlet.upload;

import org.apache.commons.fileupload.ProgressListener;

public class UploadListener implements ProgressListener {

    private UploadStatus status;

    public UploadListener(UploadStatus status) {
this.status = status;
} @Override
public void update(long bytesRead, long contentLength, int items) {
status.setBytesRead(bytesRead);
status.setContentLength(contentLength);
status.setItems(items);
}
}

UploadStatus.java

package com.helloben.servlet.upload;

class UploadStatus {
private long bytesRead;
private long contentLength;
private int items;
private long startTime = System.currentTimeMillis(); public long getBytesRead() {
return bytesRead;
}
public void setBytesRead(long bytesRead) {
this.bytesRead = bytesRead;
} public long getContentLength() {
return contentLength;
}
public void setContentLength(long contentLength) {
this.contentLength = contentLength;
} public int getItems() {
return items;
}
public void setItems(int items) {
this.items = items;
} public long getStartTime() {
return startTime;
}
public void setStartTime(long startTime) {
this.startTime = startTime;
}
}

12. Servlet生命周期(init() --> service() --> destroy())

13. web.xml文件详解 (http://www.cnblogs.com/hellojava/archive/2012/12/28/2835730.html)