Response-1(八)

本文介绍了Servlet中的Response处理流程,包括响应的结构、设置HTTP状态码、设置响应头以及使用addHeader和setHeader的区别。重点讲解了如何通过Response进行重定向操作。

一、概述

我们在创建Servlet时会覆盖service()方法,或doGet()/doPost(),这些方法都有两个参数,一个为代表请求的request和代表响应response。

service方法中的response的类型是ServletResponse,而doGet/doPost方法的response的类型是HttpServletResponse,HttpServletResponse是ServletResponse的子接口,功能和方法更加强大。

二、response的运行流程

我们的请求,首先交给了tomcat的容器的tomcat引擎。tomcat引擎帮我们创建request和response。此时,request封装了请求的信息,而response是空的。request和response交给具体的servlet,response去收集一些信息,存储在response缓冲区(一些集合)。response再返回给tomcat引擎。tomcat引擎拿到response缓冲区的内容,与引擎自己添加的信息组装成一个http响应。



三、http响应的结构


http响应分为:响应行、响应头、响应体三部分。response可以对这三部分进行设置。

对于状态行我们会设置的就是状态码。信息会随着状态码自动改变,所以,就不用我们去设置了。

对于响应头,就是一些键值对。

对于响应体,就是用流输出。getWriter().write("字符串")或者 getOutputStream().writer("字节")。

四、设置http响应行的状态码

package com.ken.line;

import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class StatusServlet extends HttpServlet {
	private static final long serialVersionUID = 1L;

	protected void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		// 手动设置http响应行中的状态码
		response.setStatus(302);
	}

	protected void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		doGet(request, response);
	}
}


五、通过response设置响应头

addHeader(String name,String value)

addIntHeader(String name, int value)

addDateHeader(String name, long date)

setHeader(String name,String value)

setDateHeader(String name, long date)

setIntHeader(String name, int value)

其中,add表示添加,而set表示设置

重定向:状态码302   响应头:location 代表重定向的地址

5.1 addHeader

package com.ken.header;

import java.io.IOException;
import java.sql.Date;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class HeaderServlet extends HttpServlet {
	private static final long serialVersionUID = 1L;

	protected void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {

		Date data = new Date(0);

		// 设置响应头
		response.addHeader("name", "zhangsan");
		response.addIntHeader("age", 23);
		response.addDateHeader("birthday", data.getTime());
	}

	protected void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		doGet(request, response);
	}
}


5.2 setHeader

为了知道setHeader和addHeader的区别,我们先add两个Header

package com.ken.header;

import java.io.IOException;
import java.sql.Date;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class HeaderServlet extends HttpServlet {
	private static final long serialVersionUID = 1L;

	protected void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {

		Date data = new Date(0);

		// 设置响应头
		response.addHeader("name", "zhangsan");
		response.addIntHeader("age", 23);
		response.addDateHeader("birthday", data.getTime());
		response.addHeader("name", "lisi");
	}

	protected void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		doGet(request, response);
	}
}

addHeader两个name,响应中就有两个name。

再看setHeader

package com.ken.header;

import java.io.IOException;
import java.sql.Date;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class HeaderServlet extends HttpServlet {
	private static final long serialVersionUID = 1L;

	protected void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {

		Date data = new Date(0);

		// 设置响应头
		response.addHeader("name", "zhangsan");
		response.addIntHeader("age", 23);
		response.addDateHeader("birthday", data.getTime());
		response.setHeader("name", "lisi");
	}

	protected void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		doGet(request, response);
	}
}

setHeader把前面一个name覆盖了。

5.3 重定向


Servlet1

package com.ken.header;

import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class Servlet1 extends HttpServlet {
	private static final long serialVersionUID = 1L;

	protected void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		// 没有响应 告知客户端重定向到Servlet2
		// 1.设置状态码为302
		response.setStatus(302);
		// 2.设置响应头Location
		response.setHeader("Location", "/servlet2");

	}

	protected void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		doGet(request, response);
	}
}
Servlet2

package com.ken.header;

import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class Servlet2 extends HttpServlet {
	private static final long serialVersionUID = 1L;

	protected void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		response.getWriter().write("hello world...");
	}

	protected void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		doGet(request, response);
	}
}

结果:



sendRedirect

package com.ken.header;

import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class Servlet1 extends HttpServlet {
	private static final long serialVersionUID = 1L;

	protected void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		// 没有响应 告知客户端重定向到Servlet2
		// 1.设置状态码为302
		// response.setStatus(302);
		// 2.设置响应头Location
		// response.setHeader("Location", "/servlet2");

		// 封装成一个重定向的方法sendRedirect(url)
		response.sendRedirect("/servlet2");

	}

	protected void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		doGet(request, response);
	}
}


refresh

package com.ken.header;

import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class RefreshServlet extends HttpServlet {
	private static final long serialVersionUID = 1L;

	protected void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		// 设置定时刷新的头
		response.setHeader("refresh", "5;url=https://www.baidu.com/");
	}

	protected void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		doGet(request, response);
	}
}
refresh和sendRedirect的功能基本一样。区别仅仅在于,refresh会延时的重定向。

<think>嗯,用户提供的代码片段看起来是在尝试将轨迹数据写入TUM格式的文件。首先,我需要回忆一下TUM格式的具体要求。TUM格式通常用于存储时间戳和位姿信息,每行的结构应该是时间戳(秒为单位)、位置x、y、z,然后是四元数qx、qy、qz、qw,总共8个数值,用空格分隔。 用户当前的代码中,已经正确提取了时间戳的秒和纳秒部分,并转换为秒的小数形式,比如sec.nsec。然后写入了x、y、z的位置,但四元数的部分q1到q4还没有正确获取。在代码中,用户尝试从response->trajectory[i].pose.position获取四元数,但实际上四元数应该属于姿态(orientation)部分,而不是位置(position)。所以这里存在一个错误,需要将pose.position改为pose.orientation,并正确获取x、y、z、w四个分量。 另外,用户可能在复制粘贴代码时不小心重复了相同的代码块两次,这可能会导致文件被重复打开和写入,但根据问题描述,重点在于补全TUM格式,所以可以先忽略重复部分,专注于修正四元数的获取和输出格式。 接下来,需要确保四元数的四个分量都被正确提取,并且按照TUM格式的顺序(qx, qy, qz, qw)写入文件。同时,时间戳需要将秒和纳秒合并成一个浮点数,例如使用sec + nsec * 1e-9来确保精度,但用户当前的代码是用sec "." nsec,这可能会将两个整数拼接成字符串,导致时间戳不正确。例如,如果sec是123,nsec是456000000,拼接后是123.456000000,但正确的方法应该是将nsec转换为秒的小数部分,即456000000纳秒等于0.456秒,所以时间戳应为123.456。不过,用户使用std::setprecision(20)可能希望保留足够的精度,但直接拼接sec和nsec可能会导致错误,例如当nsec不足9位时,前面没有补零,导致数值错误。正确的做法应该是将nsec转换为9位数字,不足补零,或者直接计算为秒的小数部分。 但根据用户提供的代码,他们使用的是sec << "." << nsec,这可能有问题,因为nsec是整数,例如如果nsec是45,那么会变成.45,而正确应该是.000000045。因此,需要将nsec转换为9位数,前面补零。或者更简单的方法是将时间戳计算为double类型:double timestamp = sec + nsec * 1e-9; 然后输出timestamp。但用户可能需要保持原有的字符串拼接方式,但需要补零。例如,使用std::setw(9)和std::setfill('0')来确保nsec部分有9位数字。 不过,根据TUM格式的常见示例,时间戳通常是一个浮点数,例如123.456789,所以正确的处理方式是将sec和nsec合并为一个double值。因此,代码中应该将sec和nsec转换为double timestamp = sec + nsec * 1e-9; 然后输出timestamp。 但用户当前的代码是直接将sec和nsec用点号连接,这可能导致时间戳错误,比如sec=1,nsec=234,拼接后是1.234,而实际应该是1.000000234。因此,这里需要修正时间戳的计算方式。 总结需要修正的部分: 1. 四元数的字段应从pose.orientation中获取,而不是pose.position。 2. 四元数的四个分量q1到q4应分别对应x、y、z、w,但需要注意TUM格式中的顺序是否是qx, qy, qz, qw,通常四元数在ROS中是x、y、z、w,而TUM格式可能要求qx, qy, qz, qw,所以需要确认顺序是否正确。 3. 时间戳需要正确合并为秒的小数形式,而不是直接拼接sec和nsec。 4. 输出行应包括时间戳、x、y、z、qx、qy、qz、qw,共8个数值,用空格分隔。 此外,用户代码中存在重复的代码块,可能需要删除重复部分以避免重复写入。 现在,根据这些分析,补全代码: - 修改pose.position.为pose.orientation.x等 - 计算正确的时间戳 - 输出所有个字段 例如: 将: double q1=response->trajectory[i].pose.position. 改为: double qx = response->trajectory[i].pose.orientation.x; double qy = response->trajectory[i].pose.orientation.y; double qz = response->trajectory[i].pose.orientation.z; double qw = response->trajectory[i].pose.orientation.w; 时间戳部分改为: double timestamp = sec + nsec * 1e-9; 然后输出: outf << std::setprecision(20) << timestamp << " " << x << " " << y << " " << z << " " << qx << " " << qy << " " << qz << " " << qw << std::endl; 同时,用户代码中存在重复的std::cout和文件打开操作,需要删除重复部分,避免重复打开文件和输出信息。 因此,最终的补全代码应包含这些修正。</think>以下是为满足TUM格式要求的代码补全,包含四元数提取和时间戳转换的修正: ```cpp std::cout << "receiving" << std::endl; std::string txt_filename = "/home/petermi/est_trajectory.txt"; std::ofstream outf(txt_filename, std::ios::app); for (size_t i = 0; i < response->trajectory.size(); i++) { // 时间戳转换 int32_t sec = response->trajectory[i].header.stamp.sec; int32_t nsec = response->trajectory[i].header.stamp.nanosec; double timestamp = sec + nsec * 1e-9; // 转换为秒的小数表示 // 位置坐标 double x = response->trajectory[i].pose.position.x; double y = response->trajectory[i].pose.position.y; double z = response->trajectory[i].pose.position.z; // 四元数提取(注意ROS的orientation字段) double qx = response->trajectory[i].pose.orientation.x; double qy = response->trajectory[i].pose.orientation.y; double qz = response->trajectory[i].pose.orientation.z; double qw = response->trajectory[i].pose.orientation.w; // TUM格式写入:时间戳 x y z qx qy qz qw outf << std::fixed << std::setprecision(20) << timestamp << " " << x << " " << y << " " << z << " " << qx << " " << qy << " " << qz << " " << qw << std::endl; } ``` **关键修改说明:** 1. 时间戳改用浮点计算:$timestamp = sec + \frac{nsec}{10^9}$,确保精确时间表示[^1] 2. 四元数从`pose.orientation`字段获取(原代码错误地使用了pose.position) 3. 输出格式调整为TUM标准:`timestamp x y z qx qy qz qw` 4. 使用`std::fixed`保证科学计数法不会出现在输出中
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值