4/3/2020
第八节:请求转发
请求转发介绍和使用
问题:
一次请求的处理需要多个Servlet的联动操作,第一个Servlet需要用到其他的Servlet已经声明的逻辑处理代码,这时候怎么办?
解决:
使用请求转发
解释:其实就是在一个Servlet中调用其他的Servlet。
使用:req.getRequestDispatcher("转发的路径").forward(req, res);
请求转发的特点
- 降低Servlet之间的代码冗余
- 一次请求转发内的Servlet共享此次请求的request和response对象
- 浏览器地址信息不改变,一次请求
request的作用域
一次请求转发内的Servlet
作用:request可以作为数据流转的载体
使用:request下有setAttribute()/getAttribute()两个方法,用来设置自定义的属性传入。
我们在转发的Servlet中设置request的setAttribute()然后再转发,那么被转发的Servlet可以使用getAttribute()来得到设置的自定义属性。
req.setAttrbute("str","密码错误!")
小问题:在接收自定义属性的时候默认是Object类型,我们需要强转成String,还是那个问题,强转本身不存在问题但是如果str自定义属性不纯在那么得到的结果是null强转就会报空指针。
解决:很简单做判断就好了,使用三目运算来解决
String str = req.getAttribute("str") == null ? "" : req.getAttribute("str")
重定向
请求转发的小问题
请求转发有一个特点就是浏览器地址不变,那么每次刷新就又走了一遍转发流程,如果是比较重要的服务,如银行转账,就会出现问题。
问题的解决:重定向
使用
使用方式很简单
res.sendRedirect("重定向路径");
特点:
两次请求:当前Servlet处理完问题后剩下的问题需要另一个Servlet处理,现在只告诉浏览器一个新的Servlet的地址就好了,浏览器只需要再发起一次请求和服务器建立连接,这时候浏览器地址也会发生变化,处理掉了请求转发的小问题。
新的小问题:但是也带来了新的问题,重定向是发起了新的请求连接,那么就不共享request对象了,两个Servlet之间就无法进行交互。
解决:使用cookie和session
第九节:cookie和session
Cookie
介绍和特点:
问题:不同的请求使用相同的请求数据,但是请求只要结束数据就被销毁了,替他请求需要将公共的数据重新书写发送。
解决:使用Cookie技术
特点
浏览器端的数据存储技术
哪些数据需要被存储是在服务器端进行声明,以响应的方式告诉浏览器进行存储
不适合大量数据的存储
作用:实现了不同请求之间数据共享的问题
代码实现Cookie
创建两个Servlet,Servlet1中请求响应一个a和b,Servlet2中请求响应一个b和c。b就是重复的数据了,使用Cookie存储。在Servlet2中只请求一个c,b获取a里面请求过的。
Servlet1
public class MyServlet extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 设置请求编码格式
req.setCharacterEncoding("utf-8");
// 设置响应编码格式
resp.setContentType("text/html;charset=utf-8");
// 获取请求信息
String a = req.getParameter("a");
String b = req.getParameter("b");
// 处理请求信息
System.out.println(a + ":" + b);
// 响应处理结果
// 创建Cookie数据
Cookie ck = new Cookie("b", b);
// 响应Cookie数据
resp.addCookie(ck);
// 直接响应
resp.getWriter().write("我是MyServlet1,处理完毕。");
// 请求转发
// 重定向
}
}
Servlet2
public class MyServlet2 extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 设置请求编码格式
req.setCharacterEncoding("utf-8");
// 设置响应编码格式
resp.setContentType("text/html;charset=utf-8");
// 获取请求信息
// String b = req.getParameter("b");
// 获取Cookie数据
String b = null;
Cookie[] cookies = req.getCookies();
for (Cookie ck : cookies) {
if ("b".equals(ck.getName())) {
b = ck.getValue();
}
}
String c = req.getParameter("c");
// 处理请求信息
System.out.println(b + ":" + c);
// 响应处理结果
// 直接响应
resp.getWriter().write("我是MyServlet2,处理完毕。");
// 请求转发
// 重定向
}
}
使用方法总结:
存储:
- 创建Cookie类的对象,构造器传两个参数,相当于键值对
- 使用resp里面的addCoodie()方法再响应是添加Cookie数据
获取:
- 使用req下的getCookies()方法获取Cookies数组
- 遍历数组得到想要的键值对
Cookie的有效期和有效路径设置
小问题:
- 设置的Cookie关闭浏览器就会消失
- 设置的Cookie不论是什么请求都会附带上
原因:没有设置Cookie信息
设置Cookie信息:
- 设置cookie的有效期
ck.setMaxAge(3600 * 24 * 3);
- 设置有效路径
ck.setPath("/my2");
Cookie使用特点
- 如果不设置有效期则会默认存储在浏览器的内存里,浏览器关闭即失效
- 如果设置了有效期则存储到客户端的硬盘里,到期后自动销毁
- 如果不设置有效路径则任意项目路径的请求都会附带存储的Cookie信息
- 如果设置了有效路径,则只有在该路径下的请求才会附带设置的Cookie信息
Session
Session流程介绍
为了解决两次请求之间的交互。
先创建一个对象用来存储需要交互的数据,然后这个对象有一个唯一标识的ID,想要获取这个对象数据的只需要得到这个ID就可以了。使用之前介绍的Cookie技术在两个请求之间传输这个ID就可以做到两个请求之间的交互。
这个对象就是指的Session对象。
Session使用流程
传输方:
- 创建Session对象,
HttpSession session = req.getSession();
- 设置数据setAttribute()方法```session.setAttribute("uname","张三");
接受方:
- 创建Session对象,
HttpSession session = req.getSession();
- 获取数据getAttribute()方法
String uname = (String) session.getAttribute("uname");
第二步里面的强转纯在空指针问题
细节:
Session内底层已经把存储Cookie和获取Cookie封装好了不用我们再去使用Cookie
创建Session对象时候如果之前有就不会再进行创建只会获取。
特点:
Session解决了同一个用户不同请求的数据共享问题。
Session的作用域:浏览器不关闭,Session不失效,则同一用户的任意请求获取的都是同一个Session
Session有效期设置和强制销毁
有效期设置:
session.setMaxInactiveInterval(int n);
n的单位是秒
没设置的默认是30分钟销毁
强制销毁
session.invalidate()
6/3/2020
第十节:ServletContext
ServletContext介绍
问题:Request解决了一次请求内的数据共享问题,session解决了用户不同请求的数据共享问题,那么不同的用户的数据共享该怎么办?
解决:使用ServletContext对象
作用:解决了不同用户的数据共享问题
原理:ServletContext对象由服务器创建,一个项目只有一个对象,不管在项目的任何位置进行获取到的都是同一个对象,那么不同用户夫妻的请求获取到的也就是同一个对象了,该对象由用户共同拥有。
特点:
- 服务器进行创建
- 用户共享
- 一个项目只有一个
生命周期:服务器启动到服务器关闭
作用域:项目内
使用:
获取ServletContext对象
使用作用域进行共享数据流转
获取web.xml中的全局配置
获取webroot下的项目资源流对象
获取webroot下资源绝对路径
使用ServletContext进行不同用户之间数据流转
- 获取ServletContext对象,三种方式获取的都是同一个对象
this.getServletContext()
this.getServletConfig().getServletContext()
req.getServletContext()
- 设置自定义属性,就和之前设置Session或者req的属性差不多
servletContext.setAttribute(key,value)
- 获取自定义属性
servletContext.getAttribute(key)
- 删除自定义属性
servletContext.removeAttribute(key)
注意:获取的时候强转的空指针异常
使用ServletContext获取web配置文件全局属性
- 设置web.xml文件
<context-param>
<param-name>flag</param-name>
<param-value>false</param-value>
</context-param>
- 获取属性
获取ServletContext对象
servletContext.getInitParameter("flag")
返回一个字符串
使用ServletContext获取webroot下的资源流
getResourceAsStream(url)
返回的是一个InputStream流
使用ServletContext获取webroot下的资源绝对路径
getRealPath(path)
返回的是资源的绝对路径字符串
7/3/2020
第十一节:ServletConfig对象
问题
使用ServletContext可以读取web.xml全局配置文件
每一个单独的Servlet也有独立的配置,该怎么访问呢
解决
ServletConfig对象
作用
ServletConfig是Servlet的专属配置对象,每一个Servlet都有一个ServletConfig对象,用来获取web.xml里面的配置信息。
使用
- 配置web.xml配置文件
<context-param>
<param-name>flag</param-name>
<param-value>false</param-value>
</context-param>
和全局的一样,不过要写在独立的Servlet里面
2. 获取
获取ServletConfig对象
config = this.getServletConfig()
获取配置信息
config.getInitParameter(key)
获取配置信息的枚举
config.getInitParameterNames()
Servlet基础内容完结
撒花QAQ
接下来是JSP了
Q.E.D.