让Servlet创建实例的时机 提前

本文介绍如何通过配置load-on-startup属性使Servlet在服务器启动时自动加载,而非首次访问时加载,以此来优化应用启动过程中的初始化操作。通过设置合适的值可以有效调整不同Servlet的加载顺序。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1. 默认情况下,只有在初次访问servlet的时候,才会执行init方法。 有的时候,我们可能需要在这个方法里面执行一些初始化工作,甚至是做一些比较耗时的逻辑。 

2. 那么这个时候,初次访问,可能会在init方法中逗留太久的时间。 那么有没有方法可以让这个初始化的时机提前一点。 

3. 在配置的时候, 使用load-on-startup元素来指定, 给定的数字越小,启动的时机就越早。 一般不写负数, 从2开始即可。 


        <servlet>
              <servlet-name>HelloServlet04</servlet-name>
              <servlet-class>com.itheima.servlet.HelloServlet04</servlet-class>
              <load-on-startup>2</load-on-startup>
          </servlet>

     <servlet-mapping>
            <servlet-name>HelloServlet04</servlet-name>
            <url-pattern>/HelloServlet04</url-pattern>
    </servlet-mapping>

### 错误原因分析 `java.lang.IllegalStateException: Cannot call sendRedirect() after the response has been committed` 是一种常见的异常,通常发生在尝试在响应已经被提交的情况下再次修改 HTTP 响应头或重定向时。HTTP 协议规定,在服务器向客户端发送数据之后,不能再更改响应的状态码或头部信息。 此问题可能由以下几个因素引起: - **过滤器链中的顺序不当**:如果 `sendRedirect()` 被调用前已经有部分响应被写入到输出流中,则会抛出该异常[^1]。 - **拦截器逻辑错误**:Spring MVC 的拦截器方法(如 `preHandle` 或 `postHandle`)可能会因为不恰当的操作导致响应提前结束[^4]。 - **Session 创建时机不对**:某些情况下,开发者试图在已经完成的部分响应后再创建 Session 或执行其他操作,这也会引发类似的异常[^3]。 --- ### 解决方案 #### 方法一:调整代码逻辑以避免过早提交响应 确保所有的业务逻辑都在响应未提交之前处理完毕。可以通过以下方式实现: ```java @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { HttpServletResponse httpResponse = (HttpServletResponse) response; HttpServletRequest httpRequest = (HttpServletRequest) request; // 验证逻辑 String registrationKey = httpRequest.getParameter("registrationKey"); boolean isValid = validateRegistrationCode(registrationKey); if (!isValid) { // 如果验证失败,立即跳转并终止后续流程 httpResponse.sendRedirect(httpRequest.getContextPath() + "/alert/macError"); return; // 终止进一步的请求处理 } // 只有当验证通过时才继续执行后续逻辑 chain.doFilter(request, response); } ``` 在此示例中,`sendRedirect()` 和 `chain.doFilter()` 不会被同时触发,从而防止响应冲突。 --- #### 方法二:延迟创建 Session 有时,开发人员会在 `sendRedirect()` 后再尝试获取或创建新的 Session 对象,这种做法会导致异常。因此建议尽早创建 Session 并将其存储起来供后续使用。 以下是改进后的代码片段: ```java if (!result) { HttpSession session = request.getSession(false); // 尝试获取现有session而不强制创建新session if (session == null) { session = request.getSession(true); // 显式创建一个新的session对象 } response.sendRedirect("/alert/macError"); // 执行重定向 } else { chain.doFilter(request, response); // 正常放行请求 } ``` 这里的关键在于先判断是否存在有效的 Session 实例;如果没有则显式地创建它,而不是等到后面再去访问。 --- #### 方法三:自定义缓冲区大小控制 默认情况下,Tomcat 等容器会对每个请求分配一定大小的缓冲区来暂存输出内容。一旦超出这个限制就会自动刷新缓存并将部分内容写出给客户端。此时即使尚未完全构建好整个页面也可能被认为已提交了相应的一部分数据而无法再做任何改变。 可以考虑增加服务端配置项或者设置更大的初始缓冲容量: ```xml <Connector port="8080" protocol="HTTP/1.1" connectionTimeout="20000" redirectPort="8443" buffer_size="65536"/> <!-- 设置较大的buffer size --> ``` 另外也可以直接编程设定 Response Buffer Size : ```java response.setBufferSize(65536); // 设定较大数值作为预设缓冲空间 ``` 这种方法适用于那些确实存在大量动态生成 HTML 数据场景下减少频繁刷盘次数提高性能的同时也间接降低了因超限而导致提前commit的风险[^1]. --- ### 总结 以上三种策略分别针对不同层面进行了优化——从程序设计角度出发重新梳理业务流程确保不会发生重复操作;合理安排资源申请次序规避潜在风险以及适当调节底层参数提升整体稳定性。具体采用哪种取决于实际项目需求和个人偏好。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值