import java.io.IOException;
import java.net.URLEncoder;
import org.apache.http.HttpEntity;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpUriRequest;
import org.apache.http.client.methods.RequestBuilder;
import org.apache.http.client.utils.HttpClientUtils;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;直接上代码。
try {
CloseableHttpClient client = HttpClients.createDefault();
HttpUriRequest getRequest = RequestBuilder.get("http://localhost:9092/test.jsp")//
.addParameter("testIn1", URLEncoder.encode("测试", "GBK"))//
.addParameter("testIn2", URLEncoder.encode("测试2", "UTF-8"))//
.addHeader("content-type", "text/html:charset=UTF-8")//
.build();
CloseableHttpResponse response = client.execute(getRequest);
HttpEntity entity = response.getEntity();
System.out.println(entity.getContentType().toString());
System.out.println(EntityUtils.toString(entity));
HttpClientUtils.closeQuietly(response);
} catch (ClientProtocolException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}注意:通过addParameter项get请求里追加参数时,要通过URLEncoder对参数进行指定字符集编码,主要是为了解决中文乱码问题,同样的,接收方要通过URLDecoder对参数进行对应字符集的解码。
附:接收jsp样例
<%@page import="java.net.URLDecoder"%>
<%@page import="java.util.HashMap"%>
<%@page import="java.nio.charset.Charset"%>
<%@page language="java" contentType="text/html; charset=GBK" pageEncoding="GBK"%>
<%
System.out.println("默认字符集:" + Charset.defaultCharset().toString());
System.out.println("请求字符集:" + request.getCharacterEncoding());
System.out.println("请求入参testIn1(utf-8):" + URLDecoder.decode(request.getParameter("testIn1"), "UTF-8"));
System.out.println("请求入参testIn1:(gbk)" + URLDecoder.decode(request.getParameter("testIn1"), "GBK") );
System.out.println("请求入参testIn1:" + request.getParameter("testIn1"));
System.out.println("请求入参testIn2(utf-8):" + URLDecoder.decode(request.getParameter("testIn2"), "UTF-8"));
System.out.println("请求入参testIn2:(gbk)" + URLDecoder.decode(request.getParameter("testIn2"), "GBK"));
System.out.println("请求入参testIn2:" + request.getParameter("testIn2"));
%>
<!DOCTYPE html>
<html>
<head>
<meta charset="GBK">
<title>这是标题</title>
</head>
<body>
这是正文部分
</body>
</html>try {
CloseableHttpClient client = HttpClients.createDefault();
HttpGet get = new HttpGet("https://www.baidu.com/img/PCfb_5bf082d29588c07f842ccde3f97243ea.png");
CloseableHttpResponse response = client.execute(get);
HttpEntity entity = response.getEntity();
FileOutputStream fos = new FileOutputStream(new File("D:/abc.png"));
entity.writeTo(fos);
fos.close();
} catch (ClientProtocolException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}下一期计划:通过HttpClient发送POST请求。
您的关注是对我莫大的支持!
. 增强HttpServletResponse对象
1. 实现一个增强的HttpServletResponse类,需要继承javax.servlet.http.HttpServletRequestWrapper类,通过重写自己需要增强的方法来实现(这种模式就叫做装饰者模式),使用该增强类在加上过滤器就可以实现无编码转换处理代码。
public class MyRequest extends HttpServletRequestWrapper{
private HttpServletRequest req;
public MyRequest(HttpServletRequest request) {
super(request);
req=request;
}
@Override
public String getParameter(String name) {
//解决编码问题,无论是post还是get请求,都不需要在业务代码中对编码再处理
String method=req.getMethod();
if("get".equalsIgnoreCase(method)){
try {
String str=req.getParameter(name);
byte[] b=str.getBytes("iso8859-1");
String newStr=new String(b, "utf-8");
return newStr;
} catch (UnsupportedEncodingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}else if("post".equalsIgnoreCase(method)){
try {
req.setCharacterEncoding("utf-8");
} catch (UnsupportedEncodingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
//绝对不能删除此行代码,因为此行代码返回的就是编码之后的数据
return super.getParameter(name);
}
}
在过滤器中应用
public class FilterTest4 implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
//生成增强的HttpServletRequest对象
HttpServletRequest req=(HttpServletRequest) request;
MyRequest myReq=new MyRequest(req);
//将增强的HttpServletRequest对象传入过滤器执行链中,在后面传入的request对象都会是增强的HttpServletRequest对象
chain.doFilter(myReq, response);
}
@Override
public void destroy() {}
}
2. 文件上传原理过程
1. JavaWeb中实现文件上传:
<html> <head> <title>My JSP 'upload.jsp' starting page</title> <meta http-equiv="pragma" content="no-cache"> <meta http-equiv="cache-control" content="no-cache"> <meta http-equiv="expires" content="0"> <meta http-equiv="keywords" content="keyword1,keyword2,keyword3"> <meta http-equiv="description" content="This is my page"> </head> <body> <form action="" method="post" enctype="multipart/form-data"> <input type="text" name="name"> 请选择文件:<input type="file" name="upload"> <input type="submit" value="上传"> </form> </body> </html>
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
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.FileUploadException;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
public class UploadServlet extends HttpServlet{
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
/**
* 1. 创建磁盘文件项工厂类 DiskFileItemFactory
* 2. 创建核心解析Request类 ServletFileUpload
* 3. 开始解析Request对象中的数据,并返回一个List集合
* 4. List中包含表单中提交的内容
* 5. 遍历集合,获取内容
*/
DiskFileItemFactory fac=new DiskFileItemFactory();
ServletFileUpload upload=new ServletFileUpload(fac);
upload.setHeaderEncoding("utf-8");//防止中文的文件名乱码
try {
List<FileItem> fileItems = upload.parseRequest(req);
for(FileItem item:fileItems){
//有可能是普通文本项,比如<input type="text">标签提交上来的字符串
//也有可能是<input type="submit" value="上传">上传的文件
//文件项与普通项有不同的API来处理
//首先判断是普通文本项还是文件项,
if(item.isFormField()){
//true表示普通文本项
//获取文本项的name属性值
String name=item.getFieldName();
//获取对应的文本
String value=item.getString("utf-8");//防止中文乱码
System.out.println(name+":"+value);
}else{
//false表示文件项
//先获取文件名称
String name=item.getName();
//获取文件项的输入流
InputStream in=item.getInputStream();
//获取服务器端文件存储的目标磁盘路径
String path=getServletContext().getRealPath("/upload");
System.out.println(path);
//获取输出流,输出到本地文件中
OutputStream out=new FileOutputStream(path+"/"+name);
//写入数据
int len=0;
byte[] b=new byte[1024];
while((len=in.read(b))!=-1){
out.write(b,0,len);
}
in.close();
out.close();
}
}
} catch (FileUploadException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
注意:在文件上传时,会将form表单的属性enctype属性值为"multipart/form-data",当提交到服务端后,无法使用 req.getParameter(name) 方法来获取到内容,只有通过上面的方法来获取文本项。
2. 文件上传相关核心类:
//改进上面的文件上传代码,添加一个临时文件
public class UploadServlet extends HttpServlet{
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
DiskFileItemFactory fac=new DiskFileItemFactory();
fac.setSizeThreshold(1024*1024);//设置缓冲区为1mb
//设置临时文件的本地磁盘存储路径
File repository=new File(getServletContext().getRealPath("/temp"));
fac.setRepository(repository);
ServletFileUpload upload=new ServletFileUpload(fac);
upload.setHeaderEncoding("utf-8");//防止中文的文件名乱码
try {
List<FileItem> fileItems = upload.parseRequest(req);
for(FileItem item:fileItems){
if(item.isFormField()){
String name=item.getFieldName();
String value=item.getString();
String value=item.getString("utf-8");//防止中文乱码
System.out.println(name+":"+value);
}else{
String name=item.getName();
InputStream in=item.getInputStream();
String path=getServletContext().getRealPath("/upload");
System.out.println(path);
OutputStream out=new FileOutputStream(path+"/"+name);
int len=0;
byte[] b=new byte[1024];
while((len=in.read(b))!=-1){
out.write(b,0,len);
}
in.close();
out.close();
}
}
} catch (FileUploadException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
3. 实现多文件上传(需要js技术):主要是更改jsp页面,通过js代码来添加多个文件进行上传,服务器代码无需更改
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8" contentType="text/html; charset=utf-8"%>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<base href="<%=basePath%>">
<title>My JSP 'upload.jsp' starting page</title>
<meta http-equiv="pragma" content="no-cache">
<meta http-equiv="cache-control" content="no-cache">
<meta http-equiv="expires" content="0">
<meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
<meta http-equiv="description" content="This is my page">
</head>
<body>
<script type="text/javascript">
function run(){
var div=document.getElementById("divId");
div.innerHTML+=
"<div><input type='file' name='upload'><input type='button' value='删除' onclick='del(this)'></div>"
}
function del(presentNode){
var div=document.getElementById("divId");
div.removeChild(presentNode.parentNode);
}
</script>
<div>
多文件上传<br/>
<form action="/Servlet/upload" method="post" enctype="multipart/form-data">
<input type="button" value="添加" onclick="run()"><br/>
<div id="divId">
</div>
<input type="submit" value="上传">
</form>
</div>
</body>
</html>
4. 关于文件上传的一些问题:
3. 文件下载
1. 传统文件下载方式有超链接下载或者后台程序下载两种方式。通过超链接下载时,如果浏览器可以解析,那么就会直接打开,如果不能解析,就会弹出下载框;而后台程序下载就必须通过两个响应头和一个文件的输入流。
2. 后台程序下载:
做网站开发时,我们有时候会获取当前页面的完整路径。在网页前端如何实现呢?
请在网页脚本代码段中粘贴如下代码。
function getRootPath() {
//获取当前网址,如: http://localhost:8083/uimcardprj/share/meun.jsp
var curWwwPath = window.document.location.href;
//获取主机地址之后的目录,如: /uimcardprj/share/meun.jsp
var pathName = window.document.location.pathname;
var pos = curWwwPath.indexOf(pathName);
//获取主机地址,如: http://localhost:8083
var localhostPath = curWwwPath.substring(0, pos);
//获取带"/"的项目名,如:/uimcardprj
var projectName = pathName.substring(0, pathName.substr(1).indexOf('/') + 1);
return localhostPath;
}
执行该脚本后可获取本网站及当前网页的完整域名加路径
*请认真填写需求信息,我们会在24小时内与您取得联系。