Zhiqim Httpd即知启蒙WEB容器,是Zhiqim Framework面向WEB开发的多例服务,提供更简洁配置、积木式组件模块和天然的模型模板设计。
HttpResponseImpl.java14KB
/*
* 版权所有 (C) 2015 知启蒙(ZHIQIM) 保留所有权利。[遇见知启蒙,邂逅框架梦]
*
* https://zhiqim.org/project/zhiqim_framework/zhiqim_httpd.htm
*
* Zhiqim Httpd is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
package org.zhiqim.httpd;
import java.io.IOException;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import org.zhiqim.httpd.model.HttpDomainPortPath;
import org.zhiqim.kernel.util.Asserts;
import org.zhiqim.kernel.util.Validates;
/**
* HTTP响应类
*
* @version v1.0.0 @author zouzhigang 2014-3-21 新建与整理
*/
public class HttpResponseImpl implements HttpResponse
{
private HttpRequestAbs request;
private HttpSenderImpl sender;
private HttpContext context;
private List<HttpCookie> cookies;
private boolean addSessionIdToCookie;
private boolean addCookieToSender;
public HttpResponseImpl(HttpRequestAbs request)
{
this.request = request;
this.sender = (HttpSenderImpl)request.getSender();
this.context = request.getContext();
this.cookies = new ArrayList<HttpCookie>();
}
/***********************************************************************/
// 关联连接信息
/***********************************************************************/
/** 获取连接编号 */
public String getId()
{
return request.getId();
}
/** 获取当前请求 */
public HttpRequest getRequest()
{
return request;
}
/** 获取上下文环境 */
public HttpContext getContext()
{
return context;
}
/***********************************************************************/
// 状态处理和判断
/***********************************************************************/
/** 是否可编辑 */
public boolean isEditable()
{
return request != null && request.isEditable();
}
/** 是否已提交 */
public boolean isCommitted()
{
return request == null || request.isCommitted();
}
/***********************************************************************/
// 设置状态或,或重定向,或错误重定向
/***********************************************************************/
/**
* 单独设置状态,通过setStatus,write和commit完成操作
*/
public void setStatus(int code)
{
sender.setStatus(code);
}
/**
* 发生错误,返回错误码和标准的错误信息
*
* @param code 错误码
* @throws IOException 可能的异常
*/
public void sendError(int code) throws IOException
{
sendError(code, null);
}
/**
* 发生错误,返回错误状态和一句错误描述,如果描述为null,则取标准错误描述
*
* @param code 错误码
* @param message 错误信息
* @throws IOException 可能的异常
*/
public void sendError(int code, String message) throws IOException
{
sender.sendError(code, message);
}
/**
* 发送错误信息,内容为HTML格式
*
* @param code 响应码
* @throws IOException 可能的异常
*/
public void sendErrorHTML(int code) throws IOException
{
sender.sendErrorHTML(code);
}
/**
* 发送错误信息,内容为HTML格式
*
* @param code 响应码
* @param reason 响应原因
* @throws IOException 可能的异常
*/
public void sendErrorHTML(int code, String reason) throws IOException
{
sender.sendErrorHTML(code, reason);
}
/**
* 客户端重定向,将资源指身一个永久URI,采用302把URI写在location消息头中
*
* @param location 重定向连接地址
* @throws IOException 可能的异常
*/
public void sendRedirect(String location) throws IOException
{
Asserts.asState(!isCommitted()?null:"已提交不允许再提交");
this.addCookieSessionId();
this.addCookieToSender();
sender.sendRedirect(encodeURL(location));
}
/**
* 只返回消息头,如304等,会清空内容
*
* @param code 响应码,可以是200表示成功
* @throws IOException 可能的异常
*/
public void sendHeader(int code) throws IOException
{
this.addCookieSessionId();
this.addCookieToSender();
sender.sendHeader(code);
}
/**
* 一般用于返回200-207的成功码和提示的一个内容,和sendError不同的是sendError的reason=content,而sendSuccess的reason=默认值
*
* @param code 成功码
* @param content 内容
* @throws IOException 可能的异常
*/
public void sendContent(int code, String content) throws IOException
{
this.addCookieSessionId();
this.addCookieToSender();
sender.sendContent(code, content);
}
/** 编码URL,增加非useCookie时有可能的jsessionid,在URL跳转时需要 */
public String encodeURL(String url)
{
if (context == null)
return url;
HttpSessionManager sessionManager = context.getSessionManager();
if (sessionManager == null)
return url;
if (context.isCookieUse())
return url;
HttpSession session = getRequest().getSession();
if (session == null)
return url;
String sessionId = session.getId();
if (sessionId == null)
return url;
int ind = url.indexOf("?");
if (ind == -1)
url = url + "?"+sessionManager.getSessionIdName()+"=" + sessionId;
else//存在参数
url = url + "&"+sessionManager.getSessionIdName()+"=" + sessionId;
return url;
}
/** 获取响应状态码 */
public int getStatus()
{
return sender.getStatus();
}
/** 获取状态描述 */
public String getReason()
{
return sender.getReason();
}
/***********************************************************************/
// 设置头部信息
/***********************************************************************/
/** 设置头部域 */
public void setHeader(String key, Object value)
{
sender.setHeader(key, value);
}
/** 设置头部日期格式域 */
public void setDateHeader(String key, long value)
{
sender.setDateHeader(key, value);
}
/** 设置缓存控制域 */
public void setCacheControl(String value)
{
setHeader(_CACHE_CONTROL_, value);
}
/** 设置缓存控制域为私有 */
public void setCacheControlPrivate()
{
setHeader(_PRAGMA_, _PRIVATE_);
setHeader(_CACHE_CONTROL_, _PRIVATE_);
}
/** 设置头部域,增加一个属性 */
public void addHeader(String key, Object value)
{
sender.addHeader(key, value);
}
/** 设置头部日期格式域,增加一个日期类型的属性 */
public void addDateHeader(String key, long value)
{
sender.addDateHeader(key, value);
}
/** 删除头部域 */
public void removeHeader(String key)
{
sender.removeHeader(key);
}
/** 获取头部域 */
public String getHeader(String key)
{
return sender.getHeader(key);
}
/** 判断是否有头部域 */
public boolean hasHeader(String key)
{
return sender.hasHeader(key);
}
/** 设置编码格式 */
public void setCharacterEncoding(String encoding)
{
sender.setCharacterEncoding(encoding);
}
/** 获取编码格式 */
public String getCharacterEncoding()
{
String encoding = sender.getCharacterEncoding();
if (Validates.isEmptyBlank(encoding))
encoding = getRequest().getCharacterEncoding();
return Validates.isEmptyBlank(encoding)?_UTF_8_:encoding;
}
/**
* 设置内容类型,会增加默认的字符集到消息头中
*
* @param contentType 内容类型
*/
public void setContentType(String contentType)
{
sender.setContentType(contentType);
}
/**
* 设置内容类型,不设置字符集到消息头中
*
* @param contentType 内容类型
*/
public void setContentTypeNoCharset(String contentType)
{
sender.setContentTypeNoCharset(contentType);
}
/** 获取内容长度 */
public long getFlushLength()
{
return sender.getFlushLength();
}
/***********************************************************************/
// 设置Cookie
/***********************************************************************/
/** 增加cookie值,浏览器关闭即失效 */
public void addCookie(String name, String value)
{
cookies.add(new HttpCookie(name, value));
}
/**
* 增加cookie值
*
* @param name 名称
* @param value 值
* @param seconds 存活时间,单位:秒
*/
public void addCookie(String name, String value, int seconds)
{
HttpCookie cookie = new HttpCookie(name, value);
cookie.setMaxAge(seconds);
addCookie(cookie);
}
/** 增加Cookie值 */
public void addCookie(HttpCookie cookie)
{
cookies.add(cookie);
}
/** 删除Cookie值 */
public void removeCookie(String name)
{
for (Iterator<HttpCookie> it = cookies.iterator();it.hasNext();)
{
HttpCookie cookie = it.next();
if (name.equals(cookie.getName()))
it.remove();
}
addCookie(name, null, -1);
}
/** 清空Cookie */
public void clearCookie()
{
cookies.clear();
}
/** 把cookie写入到sender */
private void addCookieToSender()
{
if (addCookieToSender || cookies.isEmpty() || context == null || !context.isCookieUse())
return;
String sessionIdName = context.getSessionManager().getSessionIdName();
HttpDomainPortPath dpp = getRequest().getDomainPortPath();
String prefix = dpp.buildCookiePrefix(context.isCookieForce());
for (HttpCookie cookie : cookies)
{
sender.addMultiHeader(_SET_COOKIE_, cookie.getResponseValue(dpp.getDomain(), dpp.getPort(), dpp.getPath(), cookie.isSessionIdName(sessionIdName)?null:prefix));
}
addCookieToSender = true;
}
/** 把sessionId组装成cookie */
private void addCookieSessionId()
{
if (addSessionIdToCookie || context == null || !context.isCookieUse())
return;
HttpSessionManager sessionManager = context.getSessionManager();
if (sessionManager == null)
return;
HttpSession session = request.getSession();
if (session == null)
return;
//有会话要求维持时,放置到Cookies中
String sessionId = session.getId();
addCookie(new HttpCookie(sessionManager.getSessionIdName(), sessionId));
//如果有浸入式修改了sessionId,则清理老会话,设置新会话
String oldSessionId = session.getOldSessionId();
if (oldSessionId != null)
{
if (!sessionId.equals(oldSessionId))
sessionManager.invalidateSession(oldSessionId);
session.clearOldSessionId();
sessionManager.setSession(session);
}
addSessionIdToCookie = true;
}
/***********************************************************************/
// 数据流处理,包括写入、打印和提交等
/***********************************************************************/
/** 获取输出流 */
public OutputStream getOutputStream()
{
return sender.getOutputStream();
}
/** 写内容字节方式 */
public void write(byte[] b) throws IOException
{
addCookieSessionId();
addCookieToSender();
sender.write(b);
}
/** 写内容加回车换行 */
public void println(String str) throws IOException
{
addCookieSessionId();
addCookieToSender();
sender.println(str);
}
/** 写回车换行 */
public void println() throws IOException
{
addCookieSessionId();
addCookieToSender();
sender.println();
}
/** 写内容,无回车换行 */
public void print(String str) throws IOException
{
addCookieSessionId();
addCookieToSender();
sender.print(str);
}
/** 提交响应 */
public void commit() throws IOException
{
if (isCommitted())
return;
addCookieSessionId();
addCookieToSender();
sender.commit();
}
/***********************************************************************/
// toString
/***********************************************************************/
public String toString()
{
return sender.toString();
}
/***********************************************************************/
// 内部调用的方法,不通过HttpResponse公开
/***********************************************************************/
/** 销毁 */
void destroy()
{
if (cookies != null)
{
cookies.clear();
cookies = null;
}
//引用置空
request = null;
sender = null;
context = null;
}
byte[] buildChunkedHeader(boolean chunked)
{
return sender.buildChunkedHeader(chunked);
}
}