Java Web中使用HttpServletRequest和HttpServletResoponse来封装客户端发来的请求和返回给客户端的响应。整个流程大致如下图:
servlet-step.jpgHttpServletRequest
HttpServletRequest对象代表客户端的请求,开发人员通过这个对象的方法,可以获得客户的这些信息。
获取客户机信息
通过HttpServletRequest对象可以获取客户端的信息。
方法 | 说明 |
---|---|
getRequestURL() | 返回客户端发出请求时的完整URL |
getRequestURI() | 返回请求行中的资源名部分 |
getQueryString() | 返回请求行中的参数部分(参数名+值) |
getRemoteAddr() | 返回发出请求的客户机的IP地址 |
getRemoteHost() | 返回发出请求的客户机的完整主机名 |
getRemotePort() | 返回发出请求的客户机的网络端口号 |
getLocalPort() | 返回web服务器所使用的网络端口号 |
getLocalAddr() | 返回web服务器的IP地址 |
getLocalName() | 返回web服务器的主机名 |
getPathInfo() | 返回请求URL中的额外路径信息。额外路径信息是请求URL中的位于Servlet的路径之后和查询参数之前的内容,它以"/"开头 |
下面看一个例子,编写一个Servlet,获取客户机信息并展示出来。
public class HttpServletRequestDemo1 extends HttpServlet{
private static final long serialVersionUID = -5563851992272269782L;
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setHeader("content-type", "text/html;charset=UTF-8");
PrintWriter out = response.getWriter();
out.write("<hr/>");
out.write("请求的URL地址: " + request.getRequestURL().toString() + "<br/>");
out.write("请求的资源: " + request.getRequestURI() + "<br/>");
out.write("请求的URL地址中附带的参数: " + request.getQueryString() + "<br/>");
out.write("客户端的IP地址: " + request.getRemoteAddr() + "<br/>");
out.write("客户端的主机名: " + request.getRemoteHost() + "<br/>");
out.write("客户端的端口号: " + request.getRemotePort() + "<br/>");
out.write("客户端的用户: " + request.getRemoteUser() + "<br/>");
out.write("请求的方法: " + request.getMethod() + "<br/>");
out.write("请求的路径信息: " + request.getPathInfo() + "<br/>");
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}
}
在web.xml中添加配置。
<servlet>
<servlet-name>requestDemo1</servlet-name>
<servlet-class>web.HttpServletRequestDemo1</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>requestDemo1</servlet-name>
<url-pattern>/requestDemo1</url-pattern>
</servlet-mapping>
运行程序,在浏览器中可以查看结果。
request-client.jpg获取客户机请求首部
通过HttpServletRequest可以获取请求报文的首部信息,获取客户机请求首部的方法包括:
- getHeader(string name)方法:String
- getHeaders(String name)方法:Enumeration
- getHeaderNames()方法:Enumeration
同样编写一个简单的例子,创建一个Servlet。
public class HttpServletRequestDemo2 extends HttpServlet{
private static final long serialVersionUID = 2156815314653251842L;
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setHeader("content-type", "text/html;charset=UTF-8");
PrintWriter out = response.getWriter();
// 获取所有请求首部的字段名
Enumeration<String> reqHeaders = request.getHeaderNames();
while(reqHeaders.hasMoreElements()) {
String headName = reqHeaders.nextElement();
String headValue = request.getHeader(headName);
out.write(headName + ":" + headValue + "<br/>");
}
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}
}
然后在web.xml中进行配置。
<servlet>
<servlet-name>requestDemo2</servlet-name>
<servlet-class>web.HttpServletRequestDemo2</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>requestDemo2</servlet-name>
<url-pattern>/requestDemo2</url-pattern>
</servlet-mapping>
运行程序,在浏览器中查看结果。
request2.jpg获取客户机请求参数
通过HttpServletRequest可以获取前台提交的请求参数,获取客户机请求参数的方法包括:
- getParameter(String)方法,获取请求参数。
- getParameterValues(String name)方法,用来获取数组型的参数。
- getParameterMap()方法 该方法在编写框架时经常使用
- getParameterNames()方法 该方法不经常使用,获取参数名。
下面看一个通过前台提交表单的例子。首先编写页面info.jsp。
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>个人信息</title>
</head>
<body>
<fieldset style="width:500px;">
<legend>个人信息填写</legend>
<form action="requestDemo3" method="post">
<!-- 文本框 -->
编号:<input type="text" name="userid" value="NO." size="2" maxlength="2" /><br>
<!-- 文本框 -->
用户名:<input type="text" name="username" placeholder="请输入用户名" /><br>
<!-- 密码框 -->
密码:<input type="password" name="userpasswd" placeholder="请输入密码" /><br>
<!-- 单选框 -->
性别:<input type="radio" name="sex" value="男" checked />男
<input type="radio" name="sex" value="女">女<br>
<!-- 下拉框 -->
职业:<select name="job">
<option value="战士">战士</option>
<option value="法师">法师</option>
<option value="牧师">牧师</option>
</select><br>
<!-- 复选框 -->
爱好:
<input type="checkbox" name="inst" value="游戏">游戏
<input type="checkbox" name="inst" value="编程" checked>编程
<input type="checkbox" name="inst" value="读书">读书
<input type="checkbox" name="inst" value="跑步">跑步
<!-- 文本域 -->
备注:<textarea name="note" cols="34" rows="5"></textarea> <br>
<!-- 隐藏域 -->
<input type="hidden" name="hiddenField" value="你看不到我"/>
<!-- 提交按钮 -->
<button type="submit">提交</button>
<!-- 重置按钮 -->
<button type="reset">重置</button>
</form>
</fieldset>
</body>
</html>
然后编写后台的Servlet。
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException{
request.setCharacterEncoding("UTF-8");
//根据表单中标签的name读取表单提交的参数
String userid = request.getParameter("userid");
String username = request.getParameter("username");
String userpasswd = request.getParameter("userpasswd");
String sex = request.getParameter("sex");
String userjob = request.getParameter("job");
String note = request.getParameter("note");
String hiddenField = request.getParameter("hiddenField");
// 获取数组
String[] insts = request.getParameterValues("inst");
String instStr = String.join(",", insts);
//将内容写入html
String html = "<table>" +
"<tr><td>填写的编号:</td><td>{0}</td><tr>" +
"<tr><td>填写的用户:</td><td>{1}</td><tr>" +
"<tr><td>填写的密码:</td><td>{2}</td><tr>" +
"<tr><td>选中的性别:</td><td>{3}</td><tr>" +
"<tr><td>选中的职业:</td><td>{4}</td><tr>" +
"<tr><td>选中的爱好:</td><td>{5}</td><tr>" +
"<tr><td>填写的备注:</td><td>{6}</td><tr>" +
"<tr><td>隐藏的内容:</td><td>{7}</td><tr>" +
"</table>";
html = MessageFormat.format(html, userid, username, userpasswd, sex,
userjob, instStr, note, hiddenField);
response.setCharacterEncoding("UTF-8");
response.setContentType("text/html;charset=UTF-8");
response.getWriter().write(html);
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}
}
同样在web.xml中进行配置。
<servlet>
<servlet-name>requestDemo3</servlet-name>
<servlet-class>web.HttpServletRequestDemo3</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>requestDemo3</servlet-name>
<url-pattern>/requestDemo3</url-pattern>
</servlet-mapping>
运行程序,首先打开表单所在的页面。
request-info.jpg填写完表单后点击提交。
request3.jpgrequest中文参数乱码问题
在前文的代码中可以看到,我们在接收POST请求的参数的时候进行了如下设置:
response.setHeader("content-type", "text/html;charset=UTF-8");
该方式通过将服务端的编码设置为和客户端一致来解决乱码问题。
GET请求由于是直接把参数放到URL中,需要获取request对象以ISO8859-1字符编码接收到的原始数据的字节数组,然后通过字节数组以指定的编码构建字符串,解决乱码问题:
String name = request.getParameter("name");//接收数据
name =new String(name.getBytes("ISO8859-1"), "UTF-8");
请求转发
请求转发指一个web资源收到客户端请求后,通知服务器去调用另外一个web资源进行处理。
在Servlet中实现请求转发的方式是通过ServeltContext或者HttpServletRequest的getRequestDispatcher(String path)方法,该方法返回RequestDispatcher对象,调用这个对象的forward方法可以实现请求转发。
看一个例子,编写一个简单的登陆页面login.jsp。
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>登录</title>
</head>
<body>
<form action="loginServlet" method="post">
用户名:<input type="text" name="username" /><br>
密码:<input type="text" name="password" /><br>
<input type="submit" value="登录"><br>
</form>
</body>
</html>
编写登录的Servlet,会转发到另一个Servlet。
public class LoginServlet extends HttpServlet {
private static final long serialVersionUID = 8467143275313331548L;
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
request.setCharacterEncoding("utf-8");
String name = request.getParameter("username");
request.setAttribute("name", name);
request.getRequestDispatcher("/servlet2").forward(request, response);
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}
}
编写转发到的Servlet。
public class LoginServlet extends HttpServlet {
private static final long serialVersionUID = 8467143275313331548L;
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
request.setCharacterEncoding("utf-8");
String name = request.getParameter("username");
request.setAttribute("name", name);
request.getRequestDispatcher("/servlet2").forward(request, response);
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}
}
在web.xml中注册Servlet。
<servlet>
<servlet-name>loginServlet</servlet-name>
<servlet-class>web.LoginServlet</servlet-class>
</servlet>
<servlet>
<servlet-name>servlet2</servlet-name>
<servlet-class>web.Servlet2</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>loginServlet</servlet-name>
<url-pattern>/loginServlet</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>servlet2</servlet-name>
<url-pattern>/servlet2</url-pattern>
</servlet-mapping>
运行程序,在登陆界面随便输个名字,点击提交。
request-login.jpg可以看到成功跳转。
request-forward.jpg文件上传
要实现文件上传,在客户端表单的提交方法必须是post并且设置表单的enctype="multipart/form-data",其中还要包含一个文件上传组件。
在服务器中,在Servlet3.0以后只需要添加@MultipartConfig注解即可。
@MultipartConfig注解
@MultipartConfig可以带有以下属性,均为可选的:
- maxFileSize:表示最多可以上传的文件的容量,超过设定值的文件将会遭到拒绝,默认值为-1,表示无限制。
- maxRequestSize:表示允许多部分HTTP请求的最大容量,默认值为-1,意味着它是不受限制的。
- location:将上传的文件保存在服务器中项目的指定位置,调用Part的write方法会使用,但是,只有write中填写为相对路径,那么意味着是相对于location的路径,如果是填写为绝对路径,则与location无关。
- fileSizeThreshold:设定溢出大小,超过这个值那么上传的文件就会被写入磁盘。
Part类
其中表单的每一个域都会转换为Part。可以同通过HttpServletRequest的getParts()或getPart(String name)方法获取Part。
Part类中包含如下方法:
- String getName() 获取这部分的名称,例如相关表单域的名称
- String getContentType() 如果Part是一个文件,那么将返回Part的内容类型,否则返回null(可以利用这一方法来识别是否为文件域)
- Collection<String> getHeaderNames() 返回这个Part中所有标头的名称
- String getHeader(String headerName) 返回指定标头名称的值
- void write(String path) 将上传的文件写入服务器中项目的指定地址下,如果path是一个绝对路径,那么将写入指定的路径,如果path是一个相对路径,那么将被写入相对于location属性值的指定路径。
- InputStream getInputStream() 以inputstream的形式返回上传文件的内容
如果HTML的输入是一个文件域,那么Part将返回这些标头:
- content-type:contentType
- content-disposition:form-data; name="filedName"; filename="fileName"
如果是一个普通文本域,那么:
- content-disposition:form-data; name="filedName"
如果是文件域,但没有上传文件,那么:
- content-type:application/octet-stream
- content-disposition:form-data; name="filedName"; filename=""
实战
下面编写一个上传图片并显示的例子。
编写上传文件的servlet。
@MultipartConfig
public class FileUploadDemo extends HttpServlet {
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// 创建目录
File path = new File(getServletContext().getRealPath("/upload") );
System.out.print("文件目录: " + path);
if(!path.exists()) {
path.mkdir();
}
// 获取文件
Part img = request.getPart("file1");
// 获取上传的文件名
String cd = img.getHeader("Content-Disposition");
String filename = cd.substring(cd.lastIndexOf("=")+2, cd.length()-1);
// 文件全路径
String filePath = path.getPath() + File.separator + filename;
// 写入文件
img.write(filePath);
System.out.println("File Upload: " + filePath);
// 跳转页面
request.setAttribute("filename", filename);
request.getRequestDispatcher("filedome.jsp").forward(request, response);
}
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doPost(request, response);
}
}
编写上传文件的页面index.jsp。
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>登录首页</title>
</head>
<body>
<form action="FileUploadServlet" enctype="multipart/form-data" method="post">
<input type="file" name="file1" /><br>
<input type="submit" value="提交">
</form>
</body>
</html>
然后编写显示图片的JSP。
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>展示图片内容</title>
</head>
<body>
<img alt="go" src="upload/<%= (String)request.getAttribute("filename")%>" />
</body>
</html>
编写配置文件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">
<display-name>Archetype Created Web Application</display-name>
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
<servlet>
<servlet-name>FileUploadServlet</servlet-name>
<servlet-class>com.wyk.servletdemo.web.FileUploadDemo</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>FileUploadServlet</servlet-name>
<url-pattern>/FileUploadServlet</url-pattern>
</servlet-mapping>
</web-app>
运行程序,打开浏览器访问首页。
fileupload.jpg上传图片,点击提交,会跳转到显示图片的界面。
img-show.jpg
网友评论