• SpringBoot HttpServletResponse Header Cookie输出问题


    问题:

    在一次Response写入header和cookie的时候,发现部分信息没有被输出

    工具类:

    CookieUtils:

    import java.io.IOException;
    import java.util.HashMap;
    import java.util.Map;
    import javax.annotation.PostConstruct;
    import javax.servlet.http.Cookie;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import org.apache.commons.lang3.StringUtils;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Component;
    
    /**
     * Created by qhong on 2018/10/15 15:46
     **/
    @Component
    public class CookieUtils {
    
    	public static final int COOKIE_MAX_AGE = 7 * 24 * 3600;
    	public static final int COOKIE_HALF_HOUR = 30 * 60;
    
    
    	private static HttpServletResponse response;
    
    	@Autowired
    	private HttpServletResponse response2;
    
    	private static HttpServletRequest request;
    
    	@Autowired
    	private HttpServletRequest request2;
    
    	@PostConstruct
    	public void beforeInit() {
    		request=request2;
    		response=response2;
    	}
    
    
    	/**
    	 * 根据Cookie名称得到Cookie对象,不存在该对象则返回Null
    	 *
    	 * @param request
    	 * @param name
    	 * @return
    	 */
    	public static Cookie getCookie(String name) {
    		Cookie[] cookies = request.getCookies();
    		if (cookies==null||cookies.length<1) {
    			return null;
    		}
    		Cookie cookie = null;
    		for (Cookie c : cookies) {
    			if (name.equals(c.getName())) {
    				cookie = c;
    				break;
    			}
    		}
    		return cookie;
    	}
    
    	/**
    	 * 根据Cookie名称直接得到Cookie值
    	 *
    	 * @param request
    	 * @param name
    	 * @return
    	 */
    	public static String getCookieValue(String name) {
    		Cookie cookie = getCookie(name);
    		if(cookie != null){
    			return cookie.getValue();
    		}
    		return null;
    	}
    
    	/**
    	 * 移除cookie
    	 * @param request
    	 * @param response
    	 * @param name 这个是名称,不是值
    	 */
    	public static void removeCookie(String name) {
    		if (null == name) {
    			return;
    		}
    		Cookie cookie = getCookie(name);
    		if(null != cookie){
    			cookie.setPath("/");
    			cookie.setValue("");
    			cookie.setMaxAge(0);
    			response.addCookie(cookie);
    		}
    	}
    
    	/**
    	 * 添加一条新的Cookie,可以指定过期时间(单位:秒)
    	 *
    	 * @param response
    	 * @param name
    	 * @param value
    	 * @param maxValue
    	 */
    	public static void setCookie(String name,
    								 String value, int maxValue) {
    		if (StringUtils.isBlank(name)) {
    			return;
    		}
    		if (null == value) {
    			value = "";
    		}
    		Cookie cookie = new Cookie(name, value);
    		cookie.setPath("/");
    		if (maxValue != 0) {
    			cookie.setMaxAge(maxValue);
    		} else {
    			cookie.setMaxAge(COOKIE_HALF_HOUR);
    		}
    		response.addCookie(cookie);
    //		try {
    //			response.flushBuffer();
    //		} catch (IOException e) {
    //			e.printStackTrace();
    //		}
    	}
    
    	/**
    	 * 添加一条新的Cookie,默认30分钟过期时间
    	 *
    	 * @param response
    	 * @param name
    	 * @param value
    	 */
    	public static void setCookie(String name,
    								 String value) {
    		setCookie(name, value, COOKIE_HALF_HOUR);
    	}
    
    	/**
    	 * 将cookie封装到Map里面
    	 * @param request
    	 * @return
    	 */
    	public static Map<String,Cookie> getCookieMap(){
    		Map<String,Cookie> cookieMap = new HashMap<>();
    		Cookie[] cookies = request.getCookies();
    		if(cookies!=null&&cookies.length>1){
    			for(Cookie cookie : cookies){
    				cookieMap.put(cookie.getName(), cookie);
    			}
    		}
    		return cookieMap;
    	}
    }
    
    

    SpringServletUtil:

    import java.io.IOException;
    import java.util.Map;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import lombok.extern.slf4j.Slf4j;
    import org.apache.commons.lang3.StringUtils;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Component;
    
    /**
     * Created by qhong on 2019/1/11 14:17
     **/
    @Component
    @Slf4j
    public class SpringHttpUtil {
    
    // /**
    //  * 获取请求体
    //  * @return
    //  */
    // private HttpServletRequest getRequest(){
    //    return ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
    // }
    //
    // /**
    //  * 获取返回体
    //  * @return
    //  */
    // private HttpServletResponse getResponse(){
    //    return ((ServletRequestAttributes)RequestContextHolder.getRequestAttributes()).getResponse();
    // }
    
       @Autowired
       private HttpServletResponse response;
    
    
       @Autowired
       private HttpServletRequest request;
    
    
       /**
        * 获取用户请求头部或者cookie中的参数
        */
       public String getParams(String name) {
          String result = getHeader(name);
          //cookie
          if (StringUtils.isBlank(result)) {
             result = CookieUtils.getCookieValue(name);
          }
          return result;
       }
    
       public String getHeader(String name) {
          String result= request.getHeader(name);
          if(StringUtils.isBlank(result)){
             result=request.getParameter(name);
          }
          return result;
       }
    
       public void setHeader(Map<String, String> map) {
          if (map == null || map.isEmpty() || map.size() == 0)
             return;
          map.entrySet().stream().forEach(x -> {
             response.setHeader(x.getKey(), x.getValue());
          });
    
       }
    
       public void setCookie(Map<String, String> map) {
          if (map == null || map.isEmpty() || map.size() == 0)
             return;
          map.entrySet().stream().forEach(x -> {
             CookieUtils.setCookie(x.getKey(), x.getValue());
          });
       }
    }
    

    使用:

    Map<String, String> map = new HashMap<>();
    map.put("aaaaa","aaa");
    map.put("bbbbb","bbb");
    springHttpUtil.setHeader(map);
    springHttpUtil.setCookie(map);
    

    很简单的测试使用 ,但是发现cookie只能输出一个

    查看源码:

    orgapache omcatembed omcat-embed-core8.5.15 omcat-embed-core-8.5.15.jar

    ResponseFacade:

    @Override
    public void addCookie(Cookie cookie) {
    
        if (isCommitted()) {
            return;
        }
    
        response.addCookie(cookie);
    
    }
    
      @Override
        public void setHeader(String name, String value) {
    
            if (isCommitted()) {
                return;
            }
    
            response.setHeader(name, value);
    
        }
    
    
        @Override
        public void addHeader(String name, String value) {
    
            if (isCommitted()) {
                return;
            }
    
            response.addHeader(name, value);
    
        }
    

    我也断点调试了,发现除了第一次isCommitted是false,其他的true,所以其他的参数才没有输出

    刷新输出流

    response内部的输出流有8KB的缓冲区,如果缓冲区满了的话,那么response会自动去提交,即把缓冲区内容输出给客户端。这时调用response的isCommited()方法返回的就是true,表示response已经提交过至少一次了。
    也可以在缓冲区没有装满时调用response.flushBuffer()方法刷新输出流,把缓冲区中的数据发送到客户端去。同样,这也会导致response的isCommited()方法返回的就是true,表示response已经提交过至少一次了。
    其实也可以调用response.getWirter().flush()方法达到与调用response.flushBuffer()相同的效果。这两种方式基本相同!
    一旦response的isCommited()方法返回true,这说明服务器已经至少把状态码、响应头等数据发送给客户端了,也就是说已经开始向客户响应了。

    错误原因:

    错误的地方就是CookieUtils中被我注释掉的地方,这里对response进行了flushBuffer,所以isCommitted为true,后面的参数才会无效。

    response.flushBuffer最好是只对返回主体内容使用,对于头部信息除非确定是最后了,否则不要使用,使用的话,后续对头部信息的任何操作都无效。

    参考:

    HttpServletResponse的输出问题

  • 相关阅读:
    Java遍历Map键、值。获取Map大小的方法
    Oracle CASE WHEN 用法介绍
    JS动态改变select选择变更option的index值
    js对select动态添加和删除OPTION
    在js中使用createElement创建HTML对象和元素
    清空select标签中option选项的3种不同方式
    json-lib包笔记
    异常:javax.el.PropertyNotFoundException: Property 'id' not found on ..........
    golang struct的使用
    golang多维数组的切片
  • 原文地址:https://www.cnblogs.com/hongdada/p/10259378.html
Copyright © 2020-2023  润新知