Servlet
Response
使用步骤:
- 获取输出流
* 字符输出流:PrintWriter getWriter()
* 字节输出流:ServletOutputStream getOutputStream() - 使用输出流,将数据输出到客户端浏览器:response.getWriter().println(“xxxx”);
public class _01_ResponseAPI_01 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//单独设置编码,需要在获取流之前,默认编码为ISO-8859-1
resp.setCharacterEncoding("utf-8");
//相应类型和编码
resp.setContentType("text/html;charset=utf-8");
//获取字符流,输出数据
PrintWriter pw = resp.getWriter();
pw.write("你好");
pw.print("你好呀");
}
}
public class _02_ResponseAPI_02 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//单独设置编码,需要在获取流之前,默认编码为ISO-8859-1
resp.setCharacterEncoding("utf-8");
//相应类型和编码
resp.setContentType("text/html;charset=utf-8");
//获取字节流
ServletOutputStream sos = resp.getOutputStream();
sos.write(97);
//设置状态
//resp.setStatus(404);
}
}
初始化数据init
Init方法,最先执行,并且执行只执行一次,默认是第一次请求的时候执行
但是可以通过load-on-startup来设置执行时机
- -1 是第一次请求
- 0和正整数 是启动tomcat的时候执行
结合init的执行时机,所以比较适合做一些数据初始化的工作
- 初始化java中对象或其他
- 初始化xml中的数据:局部和全局
局部和全局:
<!-- 这种参数 可以让所有的servlet都访问 -->
<context-param>
<param-name>age</param-name>
<param-value>18</param-value>
</context-param>
<servlet>
<servlet-name>init</servlet-name>
<servlet-class>com.tledu.zrz.controller._04_init</servlet-class>
<!-- 这种参数 只能让当前这个_04_init 使用 , 其他servlet是用不了的 -->
<init-param>
<param-name>username</param-name>
<param-value>张三</param-value>
</init-param>
</servlet>
public void init(ServletConfig servletConfig) throws ServletException {
//局部参数获取,使用config对象调用getInitParameter(key)获取
String username = servletConfig.getInitParameter("username");
//全局参数需要使用servletContext获取,而servletContext被封装在servletConfig中
ServletContext servletContext = servletConfig.getServletContext();
String age = servletContext.getInitParameter("age");
System.out.println(username +" : "+age);
}
作用域
常用方法:
- getAttribute
- setAttribute
- removeAttribute
以上三个方法是request,session,servletContext都有的,用来向对应的作用域中保存数据,获取数据,删除数据
request:当前请求有效,如果向request中保存数据,那么仅在当前请求中可以获取。一般用于页面和后端交互是需要进行的数据传递
session:当前会话有效,建立的持续通信,一般是浏览器打开到浏览器关闭,是一次会话,不过也是可以设置会话时间的。一般用于保存登陆的用户信息。
servletContext:全局有效,只要服务器不关闭,永久存储,服务器关闭,数据消失。
跳转方式
请求转发
- 通过request对象获取请求转发器对象:RequestDispatcher getRequestDispatcher(String path)
- 使用RequestDispatcher对象来进行转发:forward(ServletRequest request, ServletResponse response)
特点:
- 浏览器地址栏路径不发生变化
- 只能转发到当前服务器内部资源中。
- 转发是一次请求
客户无感知跳转,跳转方和被跳转方数据共享(request)
注意:
- 通过servletContext对象中的getRequestDispatcher进行跳转,url地址必须加/,因为根目录就是WebContent
- 直接通过request进行跳转
* 加/表示根目录
* 不加/表示相对目录,相对于请求
public class _08_forward extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//通过servletContext对象中的getRequestDispatcher进行跳转
//url地址必须加/,因为根目录就是WebContent
//req.getServletContext().getRequestDispatcher("/test.jsp").forward(req,resp);
//直接通过request进行跳转
//加/表示根目录
//不加/表示相对目录,相对于请求
req.getRequestDispatcher("test.jsp").forward(req,resp);
}
}
重定向
response.sendRedirect("/day15/responseDemo2");
特点:
- 地址栏发生变化
- 重定向可以访问其他站点(服务器)的资源
- 重定向是两次请求。不能使用request对象来共享数据
注意:
- 不加/表示相对定位,与forward相同
- 加/表示绝对定位,定位到当前服务器,必须写项目名。
如:
public class _09_sendRedirect extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//加/是绝对:绝对定位到当前服务器
//不加/是相对:同forward的相对
//resp.sendRedirect("test.html");
//使用绝对需要注意
//需要写项目名
//resp.sendRedirect("/Servlet_02/test.html");
String name = req.getContextPath();
resp.sendRedirect(name+"/test.html");
}
}
区别
Forward是服务器内部跳转,两个页面中数据互通,使用同一个request对象,但是地址栏中依然显示第一次请求的url地址,用户感觉不到页面进行了跳转,也只会发送一次请求。
sendRedirect是重定向,两个页面数据不互通,使用的不是同一个request对象,地址栏中显示的是第二个请求的url地址,会发送两次请求
应用场景
- 比如登陆失败,或者被拦截到登陆页面,只要是需要用户输入之后,进行跳转的,一般使用重定向,如果此时使用forward跳转,则地址栏不变,那么此时如果刷新页面(重新请求地址栏),就会弹框,提示是否重复发送。
- 比如去后端获取数据,一般请求转发(因为request共享),查询相关,都是forward。比如: 搜索,用户列表。搜索比较特殊,需要传递数据(提交数据),一般搜索肯定使用get请求
如果是post请求,后端大部分使用重定向(一般发送数据使用post)
如果是get请求,后端大部分使用forward(一般获取数据使用get)