Java tutorial
/* * Copyright (C) 2008 feilong * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.sunchenbin.store.feilong.servlet.http; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.io.PrintWriter; import java.util.Date; import javax.servlet.RequestDispatcher; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.sunchenbin.store.feilong.core.date.DateExtensionUtil; import com.sunchenbin.store.feilong.core.io.FileUtil; import com.sunchenbin.store.feilong.core.io.IOWriteUtil; import com.sunchenbin.store.feilong.core.io.MimeType; import com.sunchenbin.store.feilong.core.io.MimeTypeUtil; import com.sunchenbin.store.feilong.core.io.UncheckedIOException; import com.sunchenbin.store.feilong.core.lang.CharsetType; import com.sunchenbin.store.feilong.core.lang.StringUtil; import com.sunchenbin.store.feilong.core.net.URIUtil; import com.sunchenbin.store.feilong.core.util.Validator; import com.sunchenbin.store.feilong.servlet.http.entity.HttpHeaders; /** * {@link javax.servlet.http.HttpServletResponse HttpServletResponse} . * * <h3> {@link RequestDispatcher#forward(javax.servlet.ServletRequest, javax.servlet.ServletResponse) RequestDispatcher.forward} * {@link HttpServletResponse#sendRedirect(String) HttpServletResponse.sendRedirect}</h3> * * <blockquote> * <table border="1" cellspacing="0" cellpadding="4"> * <tr style="background-color:#ccccff"> * <th align="left">{@link RequestDispatcher#forward(javax.servlet.ServletRequest, javax.servlet.ServletResponse) RequestDispatcher.forward} * </th> * <th align="left">{@link HttpServletResponse#sendRedirect(String) HttpServletResponse.sendRedirect}</th> * </tr> * <tr valign="top"> * <td>???Web</td> * <td>????</td> * </tr> * <tr valign="top" style="background-color:#eeeeff"> * <td>???URL??</td> * <td>URL?</td> * </tr> * <tr valign="top"> * <td>???? ????????</td> * <td>???????URL</td> * </tr> * <tr valign="top" style="background-color:#eeeeff"> * <td>?request?response?</td> * <td>?request?response</td> * </tr> * <tr> * <td>?Web??????? ??Web?? {@link HttpServletRequest#setAttribute(String, Object)}??</td> * <td>??Web???</td> * </tr> * </table> * </blockquote> * * * <h3> {@link HttpServletResponse#sendRedirect(String)}:</h3> * * <blockquote> * <p> * ?302??Location??Location?URL * </p> * * <p> * {@link HttpServletResponse#sendRedirect(String)}?<span style="color:red">?return;</span> <br> * ? {@link HttpServletResponse#sendRedirect(String)}??????????<br> * ????????? * </p> * </blockquote> * * @author feilong * @version 1.0 2011-11-3 ?02:26:14 * @see javax.servlet.http.HttpServletResponse * @since 1.0.0 */ public final class ResponseUtil { /** The Constant LOGGER. */ private static final Logger LOGGER = LoggerFactory.getLogger(ResponseUtil.class); /** Don't let anyone instantiate this class. */ private ResponseUtil() { //AssertionError?. ?????. ???. //see Effective Java 2nd throw new AssertionError("No " + getClass().getName() + " instances for you!"); } /** * ( contentType=application/force-download) . * * @param saveFileName * ???, Content-Disposition header * @param inputStream * ??? * @param contentLength * ????? * @param request * ? ?request? log * @param response * response * @see IOWriteUtil#write(InputStream, OutputStream) * @see "org.springframework.http.MediaType" */ public static void download(String saveFileName, InputStream inputStream, Number contentLength, HttpServletRequest request, HttpServletResponse response) { //? String contentType = null; String contentDisposition = null; download(saveFileName, inputStream, contentLength, contentType, contentDisposition, request, response); } /** * . * * @param saveFileName * ???, Content-Disposition header * @param inputStream * ??? * @param contentLength * ????? * @param contentType * the content type * @param contentDisposition * the content disposition * @param request * ? ?request? log * @param response * response * @see IOWriteUtil#write(InputStream, OutputStream) * @see "org.springframework.http.MediaType" * @see "org.apache.http.HttpHeaders" * @see "org.springframework.http.HttpHeaders" * @see com.sunchenbin.store.feilong.core.io.MimeTypeUtil#getContentTypeByFileName(String) * @see javax.servlet.ServletContext#getMimeType(String) */ public static void download(String saveFileName, InputStream inputStream, Number contentLength, String contentType, String contentDisposition, HttpServletRequest request, HttpServletResponse response) { setDownloadResponseHeader(saveFileName, contentLength, contentType, contentDisposition, response); //**********************************?******************************************************************** downLoadData(saveFileName, inputStream, contentLength, request, response); } /** * Down load data. * * @param saveFileName * the save file name * @param inputStream * the input stream * @param contentLength * the content length * @param request * the request * @param response * the response */ private static void downLoadData(String saveFileName, InputStream inputStream, Number contentLength, HttpServletRequest request, HttpServletResponse response) { Date beginDate = new Date(); if (LOGGER.isInfoEnabled()) { LOGGER.info("begin download~~,saveFileName:[{}],contentLength:[{}]", saveFileName, FileUtil.formatSize(contentLength.longValue())); } try { OutputStream outputStream = response.getOutputStream(); //? //inputStream.read(buffer); //outputStream = new BufferedOutputStream(response.getOutputStream()); //outputStream.write(buffer); IOWriteUtil.write(inputStream, outputStream); if (LOGGER.isInfoEnabled()) { Date endDate = new Date(); LOGGER.info("end download,saveFileName:[{}],contentLength:[{}],time use:[{}]", saveFileName, FileUtil.formatSize(contentLength.longValue()), DateExtensionUtil.getIntervalForView(beginDate, endDate)); } } catch (IOException e) { /* * ? ClientAbortException ????? * ?? ?? * ??????? * ? KILL? ?? ClientAbortException */ //ClientAbortException: java.net.SocketException: Connection reset by peer: socket write error final String exceptionName = e.getClass().getName(); if (StringUtil.contains(exceptionName, "ClientAbortException") || StringUtil.contains(e.getMessage(), "ClientAbortException")) { LOGGER.warn( "[ClientAbortException],maybe user use Thunder soft or abort client soft download,exceptionName:[{}],exception message:[{}] ,request User-Agent:[{}]", exceptionName, e.getMessage(), RequestUtil.getHeaderUserAgent(request)); } else { LOGGER.error("[download exception],exception name: " + exceptionName, e); throw new UncheckedIOException(e); } } } /** * download response header. * * @param saveFileName * the save file name * @param contentLength * the content length * @param contentType * the content type * @param contentDisposition * the content disposition * @param response * the response */ private static void setDownloadResponseHeader(String saveFileName, Number contentLength, String contentType, String contentDisposition, HttpServletResponse response) { //********************************************************************************************** // response //getResponsegetWriter()?????response.resetresetBuffer //getOutputStream() has already been called for this response //jsp??,response.getOutputStream()??java.lang.IllegalStateException:getOutputStream() has already been called for this response,Exception response.reset(); // ===================== Default MIME Type Mappings =================== --> //See tomcat web.xml //When serving static resources, Tomcat will automatically generate a "Content-Type" header based on the resource's filename extension, based on these mappings. //Additional mappings can be added here (to apply to all web applications), or in your own application's web.xml deployment descriptor. --> if (Validator.isNullOrEmpty(contentType)) { contentType = MimeTypeUtil.getContentTypeByFileName(saveFileName); if (Validator.isNullOrEmpty(contentType)) { //contentType = "application/force-download";//,phpapplication/force-download,??HTTP ???? //application/x-download //.* ??? application/octet-stream contentType = MimeType.BIN.getMime(); //The HTTP specification recommends setting the Content-Type to application/octet-stream. //Unfortunately, this causes problems with Opera 6 on Windows (which will display the raw bytes for any file whose extension it doesn't recognize) and on Internet Explorer 5.1 on the Mac (which will display inline content that would be downloaded if sent with an unrecognized type). } } //?????????????? if (Validator.isNotNullOrEmpty(contentType)) { response.setContentType(contentType); } //?:??,?,.??? //???????? //response.setBufferSize(10240); //see org.apache.commons.io.IOUtils.copyLarge(InputStream, OutputStream) javadoc //This method buffers the input internally, so there is no need to use a BufferedInputStream //**************************************************************************************************** //Content-Disposition takes one of two values, `inline' and `attachment'. //'Inline' indicates that the entity should be immediately displayed to the user, //whereas `attachment' means that the user should take additional action to view the entity. //The `filename' parameter can be used to suggest a filename for storing the bodypart, if the user wishes to store it in an external file. if (Validator.isNullOrEmpty(contentDisposition)) { // ? contentDisposition = "attachment; filename=" + URIUtil.encode(saveFileName, CharsetType.UTF8); } //TODO ? httpcomponents httpcore org.apache.http.HttpHeaders response.addHeader(HttpHeaders.CONTENT_DISPOSITION, contentDisposition); response.setContentLength(contentLength.intValue()); } /** * ?. * <p> * {@link HttpServletResponse#sendRedirect(String)}?302??Location??Location?URL * </p> * <p> * {@link HttpServletResponse#sendRedirect(String)}?<span style="color:red">?return;</span> <br> * ? {@link HttpServletResponse#sendRedirect(String)}??????????<br> * ????????? * </p> * * @param response * HttpServletResponse * @param url * * @see #setNoCacheHeader(HttpServletResponse) * @see #sendRedirect(HttpServletResponse, String) */ public static void setNoCacheAndRedirect(HttpServletResponse response, String url) { setNoCacheHeader(response); sendRedirect(response, url); } /** * . * <p> * {@link HttpServletResponse#sendRedirect(String)}?302??Location??Location?URL * </p> * <p> * {@link HttpServletResponse#sendRedirect(String)}?<span style="color:red">?return;</span>; <br> * ? {@link HttpServletResponse#sendRedirect(String)}??????????<br> * ????????? * </p> * * @param response * the response * @param url * the redirect location URL * @see HttpServletResponse#sendRedirect(String) * @since 1.2.2 */ public static void sendRedirect(HttpServletResponse response, String url) { try { response.sendRedirect(url); } catch (IOException e) { throw new UncheckedIOException(e); } } /** * ??. * * @param response * HttpServletResponse */ public static void setNoCacheHeader(HttpServletResponse response) { // HTTP1.1? CacheControl = no-cache?? // ? HTTP1.0 ?? Cache-Control // ?? HTTP1.0 ?IEPragma:no-cache HTTP??? // (https://)/??? Pragma:no-cache Internet Explorer?? // ?Pragma:no-cache ???? Expires:-1?? response.setHeader(HttpHeaders.PRAGMA, "No-cache"); // Cache-controlno-cache???Internet? response.setHeader(HttpHeaders.CACHE_CONTROL, "no-cache"); //In other wordsExpires: 0not always leads to immediate resource expiration, //therefore should be avoided andExpires: -1orExpires: [some valid date in the past]should be used instead. response.setDateHeader(HttpHeaders.EXPIRES, -1); } // [start] PrintWriter /** * json?. * * @param response * HttpServletResponse * @param json * json * @see #write(HttpServletResponse, Object, String, String) * @since 1.0.9 */ public static void writeJson(HttpServletResponse response, Object json) { writeJson(response, json, CharsetType.UTF8); } /** * json?. * * @param response * HttpServletResponse * @param json * json * @param characterEncoding * the character encoding * @see #write(HttpServletResponse, Object, String, String) * @since 1.0.9 */ public static void writeJson(HttpServletResponse response, Object json, String characterEncoding) { String contentType = MimeType.JSON.getMime() + ";charset=" + characterEncoding; write(response, json, contentType, characterEncoding); } /** * . * * @param response * HttpServletResponse * @param content * * @see javax.servlet.ServletResponse#getWriter() * @see java.io.PrintWriter#print(Object) * @see java.io.PrintWriter#flush() * @see #write(HttpServletResponse, Object, String, String) */ public static void write(HttpServletResponse response, Object content) { String contentType = null; String characterEncoding = null; write(response, content, contentType, characterEncoding); } /** * . * * @param response * HttpServletResponse * @param content * * @param contentType * the content type * @param characterEncoding * the character encoding * @see javax.servlet.ServletResponse#getWriter() * @see java.io.PrintWriter#print(Object) * @see java.io.PrintWriter#flush() * @since 1.0.9 */ public static void write(HttpServletResponse response, Object content, String contentType, String characterEncoding) { try { //? ? getWriter? if (Validator.isNotNullOrEmpty(contentType)) { response.setContentType(contentType); } if (Validator.isNotNullOrEmpty(characterEncoding)) { response.setCharacterEncoding(characterEncoding); } PrintWriter printWriter = response.getWriter(); printWriter.print(content); printWriter.flush(); //http://www.iteye.com/problems/56543 //tomcatjetty?? printWriter.close(); } catch (IOException e) { throw new UncheckedIOException(e); } } // [end] }