文章目录
从容器到HttpServlet
之前是如何开发JSP程序以及部署和开发一个Servlet,没有将二者结合起来使用,本章将详细地介绍如何将JSP与Servlet结合起来使用。
Servlet中的service()方法有多种方法:doGet()、doPost()、doHead()等。当Method是POST时,请求会调用doPost()方法;当Method是GET时,请求会调用doGet()方法。
HttpServletRequest对象
请求封装对象,由Web容器生成。使用该对象可以取得HTTP请求中的信息。在Servlet中,也是使用该对象进行请求的处理。
使用getReader()、getInputStream()读取Body内容
新建一个Java工程、配置相对应的Tomcat、导入Tomcat模块包:
在src文件夹下建立com.eshore包,该包下建立一个GetReaderBody.java文件。在Web下面建立getReaderBody.jsp文件。现在通过action来连接Servlet的GetReaderBody.java文件。
package com.eshore;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.PrintWriter;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.servlet.annotation.WebServlet;
//给当前文件的路径设置为根目录下的GetReaderBody
@WebServlet(
urlPatterns = { "/GetReaderBody" },
name = "getReaderBody"
)
public class GetReaderBody extends HttpServlet {
//采用HttpServletRequest
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
BufferedReader br = request.getReader();//获取BufferedReader对象
String input ="";
String body = "";
while((input = br.readLine())!=null){//遍历body内容
body+=input+"<br/>";
}
response.setContentType("text/html;charset=UTF-8");//设置响应的类型和编码
PrintWriter out = response.getWriter();//获取PrintWriter()对象
out.println("<!DOCTYPE HTML>");
out.println("<HTML>");
out.println(" <HEAD><TITLE>A Servlet</TITLE></HEAD>");
out.println(" <BODY>");
out.print(body);
out.println(" </BODY>");
out.println("</HTML>");
out.flush();
out.close();
}
}
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<!DOCTYPE HTML>
<html>
<head>
<title>获取body内容</title>
</head>
<body>
<%--"<%=request.getContextPath()%>获得request对象的地址--%>
<form action="<%=request.getContextPath()%>/GetReaderBody" method="POST">
用户名:<input name="username"/><br/>
密 码:<input name="password" type="password"/><br/>
<input type="submit" name="user_submit" value="提交" />
</form>
</body>
</html>
一堆乱码就是上传文件的内容,显然这不是想要的结果,可以使用getInputStream()读取Body内容。
package com.eshore;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.servlet.annotation.WebServlet;
//给当前文件的路径设置为根目录下的GetReaderBody2
@WebServlet(
urlPatterns = { "/GetReaderBody2" },
name = "getReaderBody2"
)
public class GetReaderBody2 extends HttpServlet {
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
//获取请求Body
byte[] body = readBody(request);
//将内容统一编码
String textBody = new String(body,"UTF-8");
//获得文件的名字
String filename = getFilename(textBody);
//写到指定位置
writeToFile(filename, body);
//返回页面消息
response.setContentType("text/html;charset=UTF-8");//设置响应的类型和编码
PrintWriter out = response.getWriter();//取得PrintWriter()对象
out.println("<!DOCTYPE HTML>");
out.println("<HTML>");
out.println(" <HEAD><TITLE>A Servlet</TITLE></HEAD>");
out.println(" <script>alert(\"上传成功\")</script><BODY>");
out.println(" </BODY>");
out.println("</HTML>");
out.flush();
out.close();
}
//获取请求的输入流
private byte[] readBody(HttpServletRequest request)
throws IOException{
//获取请求内容长度
int len = request.getContentLength();
//获取请求的输入流
InputStream is = request.getInputStream();
//新建一个字节数组
byte b[] = new byte[len];
int total = 0;
while(total<len){//获取字节流
int bytes = is.read(b, total, len);
total += bytes;
}
return b;
}
//获取文件的名称
private String getFilename(String bodyText){
String filename = bodyText.substring(bodyText.indexOf("filename=\"")+10);
filename = filename.substring(filename.lastIndexOf("\\")+1,filename.indexOf("\""));
return filename;
}
//写入到指定文件
private void writeToFile(String filename,byte[] body)
throws FileNotFoundException,IOException{
//写到指定的文件地址
FileOutputStream fileOutputStream =
new FileOutputStream("d:/file/"+filename);
fileOutputStream.write(body);
fileOutputStream.flush();
fileOutputStream.close();//注意关闭输出流
}
}
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<!DOCTYPE HTML>
<html>
<head>
<title>获取上传文件body内容</title>
</head>
<body>
<form action="<%=request.getContextPath()%>/GetReaderBody2"
method="POST" enctype="multipart/form-data">
选择文件:<input type="file" name="filename"/>
<input type="submit" name="file_submit" value="提交" />
</form>
</body>
</html>
使用getPart()、getParts()取得上传文件
getPart()用于处理单文件,getParts()用于处理多文件。在使用getPart()和getParts()方法时,必须使用MultipartConfig注解,这样Servlet才能获得Part对象。
package com.eshore;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.servlet.annotation.WebServlet;
//给当前文件的路径设置为根目录下的GetReaderBody2
@WebServlet(
urlPatterns = { "/GetReaderBody2" },
name = "getReaderBody2"
)
public class GetReaderBody2 extends HttpServlet {
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
//获取请求Body
byte[] body = readBody(request);
//将内容统一编码
String textBody = new String(body,"UTF-8");
//获得文件的名字
String filename = getFilename(textBody);
//写到指定位置
writeToFile(filename, body);
//返回页面消息
response.setContentType("text/html;charset=UTF-8");//设置响应的类型和编码
PrintWriter out = response.getWriter();//取得PrintWriter()对象
out.println("<!DOCTYPE HTML>");
out.println("<HTML>");
out.println(" <HEAD><TITLE>A Servlet</TITLE></HEAD>");
out.println(" <script>alert(\"上传成功\")</script><BODY>");
out.println(" </BODY>");
out.println("</HTML>");
out.flush();
out.close();
}
//获取请求的输入流
private byte[] readBody(HttpServletRequest request)
throws IOException{
//获取请求内容长度
int len = request.getContentLength();
//获取请求的输入流
InputStream is = request.getInputStream();
//新建一个字节数组
byte b[] = new byte[len];
int total = 0;
while(total<len){//获取字节流
int bytes = is.read(b, total, len);
total += bytes;
}
return b;
}
//获取文件的名称
private String getFilename(String bodyText){
String filename = bodyText.substring(bodyText.indexOf("filename=\"")+10);
filename = filename.substring(filename.lastIndexOf("\\")+1,filename.indexOf("\""));
return filename;
}
//写入到指定文件
private void writeToFile(String filename,byte[] body)
throws FileNotFoundException,IOException{
//写到指定的文件地址
FileOutputStream fileOutputStream =
new FileOutputStream("d:/file/"+filename);
fileOutputStream.write(body);
fileOutputStream.flush();
fileOutputStream.close();//注意关闭输出流
}
}
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<!DOCTYPE HTML>
<html>
<head>
<title>getPart()获取上传文件body内容</title>
</head>
<body>
<form action="<%=request.getContextPath()%>/upload.do"
method="POST" enctype="multipart/form-data">
选择文件:<input type="file" name="filename"/>
<input type="submit" name="file_submit" value="提交" />
</form>
</body>
</html>
package com.eshore;
import java.io.IOException;
import java.io.PrintWriter;
import jakarta.servlet.ServletException;
import jakarta.servlet.annotation.MultipartConfig;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.servlet.http.Part;
import org.apache.commons.lang.StringUtils;
@MultipartConfig(location = "D:/tmp/", maxFileSize = 1024 * 1024 * 10)
@WebServlet(name = "getPartsBodyContentServlet", urlPatterns = { "/uploads.do" }, loadOnStartup = 0)
public class GetPartsBodyContent extends HttpServlet {
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
//设置处理编码
request.setCharacterEncoding("UTF-8");
request.getParts();
for(Part part:request.getParts()){
//只处理上传文件,因为提交按钮也被当作一个Part对象
if(part.getName().startsWith("filename")){
// 获得文件名字
String filename = getFilename(part);
String[] filenameArray = filename.split("\\\\");
filename = filenameArray[filenameArray.length-1];
part.write(filename);
}
}
//返回页面信息
response.setContentType("text/html;charset=UTF-8");//设置相应的类型和编码
PrintWriter out = response.getWriter();//取得PrintWriter()对象
out.println("<!DOCTYPE HTML>");
out.println("<HTML>");
out.println(" <HEAD><TITLE>A Servlet</TITLE></HEAD>");
out.println(" <script>alert(\"�ϴ��ɹ�\")</script><BODY>");
out.println(" </BODY>");
out.println("</HTML>");
out.flush();
out.close();
}
//取得文件名称
private String getFilename(Part part) {
if (part == null)
return null;
String fileName = part.getHeader("content-disposition");
if (StringUtils.isBlank(fileName)) {
return null;
}
return StringUtils.substringBetween(fileName, "filename=\"", "\"");
}
}
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<!DOCTYPE HTML>
<html>
<head>
<title>getPart()获取上传文件body内容</title>
</head>
<body>
<form action="<%=request.getContextPath()%>/uploads.do"
method="POST" enctype="multipart/form-data">
选择文件1:<input type="file" name="filename1"/><br/>
选择文件2:<input type="file" name="filename2"/><br/>
选择文件3:<input type="file" name="filename3"/><br/>
<input type="submit" name="file_submit" value="提交" />
</form>
</body>
</html>
使用RequestDispatcher调派请求
调用时指定跳转的URL地址即可完成跳转动作。RequestDispatcher有两种方法实现跳转Servlet:include()和forward()。
import jakarta.servlet.RequestDispatcher;
import jakarta.servlet.ServletException;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
@WebServlet(
name = "getDispatcherDemo",
urlPatterns = { "/include.do" },
loadOnStartup = 0)
public class GetRequestDispatcherDemo extends HttpServlet {
private static final long serialVersionUID = 1L;
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException{
doPost(request,response);
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
//返回页面消息
response.setContentType("text/html;charset=UTF-8");//设置相应的类型和编码
PrintWriter out = response.getWriter();//取得PrintWriter()对象
out.println("<!DOCTYPE HTML>");
out.println("<HTML>");
out.println(" <HEAD><TITLE>A Servlet</TITLE></HEAD>");
out.println(" <BODY>");
out.println(" The First Servlet<br/>");
//获取RequestDispatcher对象
RequestDispatcher dispatcher =
request.getRequestDispatcher("/includeSeconde.do");
dispatcher.include(request, response);
out.println(" Including Servlet<br/>");
out.println(" </BODY>");
out.println("</HTML>");
out.close();
}
}
package com.eshore;
import java.io.IOException;
import java.io.PrintWriter;
import jakarta.servlet.ServletException;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
@WebServlet(name = "getDispatcherSecondeDemo",
urlPatterns = { "/includeSeconde.do" },
loadOnStartup = 0)
public class GetRequestDispatcherSecondeDemo extends HttpServlet {
private static final long serialVersionUID = 1L;
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doPost(request, response);
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
//返回页面消息
response.setContentType("text/html;charset=UTF-8");//设置响应的类型和编码
PrintWriter out = response.getWriter();//取得PrintWriter()对象
out.println(" The seconcde Servlet<br/>");
}
}
forward()方法是RequestDispatcher中的另一种Servlet跳转方法,只是它的含义是跳转到其他的Servlet,而不会跳转到前的Servlet。
HttpServletResponse对象
HttpServletResponse是对浏览器做出响应的操作对象,可以设置相应类型,也可以直接输出HTML内容。
使用getWriter()输出字符
package com.eshore;
import java.io.IOException;
import java.io.PrintWriter;
import jakarta.servlet.ServletException;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
@WebServlet(
name = "starSurvey",
urlPatterns = { "/diaocha.do" })
public class StarSurvey extends HttpServlet{
private static final long serialVersionUID = 1L;
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException{
doPost(request,response);
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
//设置请求的编码类型
request.setCharacterEncoding("UTF-8");
String username = request.getParameter("username");
String email = request.getParameter("email");
String[] starname = request.getParameterValues("starname");
//设置相应的类型和编码
response.setContentType("text/html;charset=UTF-8");
//输出页面内容
PrintWriter out = response.getWriter();
out.println("<!DOCTYPE HTML>");
out.println("<HTML>");
out.println(" <HEAD><TITLE>感谢你的调查</TITLE></HEAD>");
out.println(" <BODY>");
out.println("联系人:<a href='"+email+"'>"+username+"</a>");
out.println("<br/>喜欢的明星:");
String str = "";
for(int i=0;i<starname.length;i++){
str +=starname[i]+", ";
}
str = str.substring(0, str.length()-1);
out.println(str);
out.println(" </BODY>");
out.println("</HTML>");
out.close();
}
}
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<!DOCTYPE HTML>
<html>
<head>
<title>明星调查</title>
</head>
<body>
<div style="text-align: center;">
调查问卷
<form action="<%=request.getContextPath()%>/diaocha.do" method="POST">
姓名:<input name="username"/><br/>
邮箱:<input name="email"/><br/>
你喜欢的明星:<br/>
<select name="starname" multiple="multiple">
<option value="成龙">成龙</option>
<option value="李连杰">李连杰</option>
<option value="邓超">邓超</option>
<option value="元彪">元彪</option>
<option value="洪金宝">洪金宝</option>
<option value="周润发">周润发</option>
</select>
<input type="submit" value="提交"/>
</form>
</div>
</body>
</html>
使用getOutputStream()输出二进制字符
对于上传文件和下载文件则需要用到字节输出流
package com.eshore;
import java.io.IOException;
import java.io.InputStream;
import jakarta.servlet.ServletException;
import jakarta.servlet.ServletOutputStream;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
@WebServlet(name = "downloadServlet", urlPatterns = { "/download.do" })
public class DownloadServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doPost(request,response);
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
//设置相应的内容的类型
response.setContentType("application/msword");
//设置响应的标头内容
response.addHeader("Content-disposition","attachment;filename=test.doc");
//获取资源文件
InputStream in = getServletContext().getResourceAsStream("/doc/test.doc");
//输出到浏览器中
ServletOutputStream os = response.getOutputStream();
byte[] bytes = new byte[1024];
int len = -1;
while((len=in.read(bytes))!=-1){
os.write(bytes, 0, len);
}
//关闭输出输入流
in.close();
os.close();
}
}
使用sendRedirect(),sendError()方法
RequestDispatcher跳转,该动作是不会被浏览器所知的,因此地址栏也不会发生变化。而sendRedirect()方法会在响应中设置HTTP状态码和Location标头,当客户端接收到这个表头时,会重新请求指定的URL,所以地址栏上的地址会发生改变。
package com.eshore;
import java.io.IOException;
import java.io.PrintWriter;
import jakarta.servlet.ServletException;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
@WebServlet(name = "responseRedirectDemo",
urlPatterns = { "/redirect.do" })
public class ResponseRedirectDemo extends HttpServlet {
private static final long serialVersionUID = 1L;
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException{
doPost(request,response);
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/html;charset=UTF-8");// ������Ӧ�����ͺͱ���
PrintWriter out = response.getWriter();// ȡ��PrintWriter()����
out.println(" Redirect跳转页面的第一个页面<br/>");
response.sendRedirect(request.getContextPath()+"/redirSeconde.do");
out.println(" Redirect Servlet<br/>");
out.close();
}
}
package com.eshore;
import java.io.IOException;
import java.io.PrintWriter;
import jakarta.servlet.ServletException;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
@WebServlet(name = "responseRedirectSecodDemo",
urlPatterns = { "/redirSeconde.do" })
public class ResponseRedirectSecondeDemo extends HttpServlet {
private static final long serialVersionUID = 1L;
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException{
doPost(request,response);
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
//返回页面消息
response.setContentType("text/html;charset=UTF-8");//设置响应的类型和编码
PrintWriter out = response.getWriter();//取得PrintWriter()对象
out.println(" Redirect跳转页面的第二个页面<br/>");
}
}
sendError()方法如果在处理请求时发生错误,就可以用sendError()方法传递服务器的状态和错误。