ServletContext对象
web容器在启动的时候,他会为每一个web容器创建一个对应的ServletContext对象,它代表了当前的web应用
他的应用
1.共享数据:我们在这个Servlet中保存的数据可以在另外一个Servlet中使用
需要一个放置数据的类
public class Hello extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
/*
this.getInitParameter();初始化参数
this.getServletConfig();Servlet配置
获取Servlet上下文
this.getInitParameterNames();
*/
ServletContext context = this.getServletContext();
String username="九怪";//数据
context.setAttribute("username",username);//将一个数据保存在了servletcontext中
resp.setContentType("text/html");
resp.setCharacterEncoding("UTF-8");
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
super.doPost(req, resp);
}
}
建立一个获取数据的类
public class getServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
ServletContext context = this.getServletContext();
String username = (String) context.getAttribute("username");
resp.setContentType("text/html");
resp.setCharacterEncoding("UTF-8");
resp.getWriter().print(username);
}
发现可以获取到,但是想要获取那个数据,先得把存放数据的类加载出来,我们才能获取他的数据
2.获取初始化参数
<!--配置一些初始化参数-->
<context-param>
<param-name>url</param-name>
<param-value>jdbc:mysql://localhost:3060/mybatis</param-value>
</context-param>
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
ServletContext context = this.getServletContext();
String url = context.getInitParameter("url");
resp.getWriter().print(url);
}
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
ServletContext context = this.getServletContext();
String url = context.getInitParameter("url");
resp.getWriter().print(url);
}
3.请求转发
@Override
public class ServletDemo01 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
ServletContext context = this.getServletContext();
System.out.println("进入了demo01");
RequestDispatcher requestDispatcher = context.getRequestDispatcher("/s3");//转发的请求路径
requestDispatcher.forward(req,resp);//调用forward实现请求转发
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
super.doPost(req, resp);
}
}
4.获取资源文件
Properties
在Java目录下新建properties,如果没有在java下生成配置文件,就是因为资源导出现了问题
<!-- 在build中配置resources , 来防止我们资源导出失败的问题-->
<build>
<resources>
<resource>
<directory>src/main/resources</directory>
<includes>
<include>**/*.properties</include>
<include>**/*.xml</include>
</includes>
</resource>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.properties</include>
<include>**/*.xml</include>
</includes>
</resource>
</resources>
</build>
在resources目录下新建properties
发现:都被打包到同一路径:classes,我们俗称这个路径为classpath:
思路:需要一个文件流
先通过输入流读取到这个配置文件,使用load方法加载配置文件内容然后就是通过properties类中的getProperty方法获取配置文件的内容,通过输出流输出到外头,最后访问测试即可
HttpServletResponse
web服务器接收到客户端的http请求,针对这个请求,分别创建一个代表请求的HttpServletResquest对象,代表响应的一个HttpServletResponse ,
如果要获取客户端请求过来的参数:HttpServletResquest
如果给客户端响应信息:找HttpServletResponse
简单分类
向浏览器发送数据的方法
负责向浏览器发送响应头的方法
常见应用
1.向浏览器输出消息
2.下载文件
要获取下载文件的路径,下载的文件名,
想办法让浏览器支持下载我们需要的东西,
获取下载文件的输入流,
创建缓冲区,
获取outputstream对象,
使用fileoutputstream文件写入buff缓冲区,
使用OutputStream将缓冲区中的数据输出到客户端!
public class FileServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 1.要获取下载文件的路径
ServletContext context = this.getServletContext();
String path = "D:\\DAIMA\\Meavn\\javaweb\\servlet03\\src\\main\\resources\\图片.png";
System.out.println("获取到下载文件的路径"+path);
// 2.下载的文件名是啥?
String fileName = path.substring(path.lastIndexOf("\\") + 1);
// 3.设置想办法让浏览器能够支持下载我们需要的东西L
//中文文件名URLEncbder. encode(文件名,编码格式)编码。否则会出现乱码
resp.setHeader("Content-Disposition","attachment;fileName="+ URLEncoder.encode(fileName,"UTF-8"));
// 4.获取下载文件的输入流
FileInputStream fis = new FileInputStream(path);
// 5.创建缓冲区
int len=0;
byte[] buffer = new byte[1024];
// 6.获取outputStream对象
ServletOutputStream sos = resp.getOutputStream();
// 7.将FileOutputStream流 写入到buffer缓冲区,使用outputStream将缓冲区中的数据输出到客户端!
while ((len=fis.read(buffer))!=-1){
sos.write(buffer,0,len);
}
sos.close();
fis.close();
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
super.doPost(req, resp);
}
}
在这个练习代码中值得注意的点
中文文件名需要使用URLEncbder. encode(文件名,编码格式)编码。否则会出现乱码
Content-Disposition是为了让浏览器能够支持下载我们需要的东西
3.验证码功能
需要java内置实现类(用到了Random类,BufferedImage,Graphics2D)
这些中最主要的是练习响应头,这个是响应图片类型,内存不缓存
public class imgServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException {
//如何让浏览器3s自动刷新一次
resp.setHeader("refresh","3");
//在内存中创建一个图片
BufferedImage image = new BufferedImage(80,20,TYPE_INT_RGB);
//得到图片
Graphics2D g = (Graphics2D) image.getGraphics();//new一个笔
//设置图片的背景颜色
g.setColor(Color.WHITE);
g.fillRect(0,0,80,20);
//给图片写数据
g.setColor(Color.BLUE);
g.setFont(new Font(null,Font.BOLD,20));
g.drawString(makeNum(),0,20);
//告诉浏览器这个请求用图片的方式打开
resp.setContentType("image/png");
//网站存在缓存,我们不让浏览器缓存
resp.setDateHeader("expires",-1);
resp.setHeader("Cache-Control","no-cache");
resp.setHeader("Pragma","no-cache");
//把图片写给浏览器
ImageIO.write(image,"png",resp.getOutputStream());
}
//生成随机数
private String makeNum(){
Random random = new Random();
String s = random.nextInt(9999999)+"";
StringBuffer sb = new StringBuffer();
for (int i = 0; i <7-s.length(); i++) {
sb.append("0");
}
String s1 = sb.toString()+s;
return s1;
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
super.doPost(req, resp);
}
4.重定向
一个web对象收到客户端请求,他会通知客户端去访问另一个web资源,这个过程叫做重定向
常见场景 :用户登录
面试题:请你聊聊重定向和转发的区别?
相同点
●页面都会实现跳转
不同点
●请求转发的时候,url不会产生变化
●重定向时候,ur|地址栏会发生变化;
从地址栏显示来说
forward是服务器请求资源,服务器直接访问目标地址的URL,把那个URL的响应内容读取过来,然后把这些内容再发给浏览器.浏览器根本不知道服务器发送的内容从哪里来的,所以它的地址栏还是原来的地址.
redirect是服务端根据逻辑,发送一个状态码,告诉浏览器重新去请求那个地址.所以地址栏显示的是新的URL.
从数据共享来说
forward:转发页面和转发到的页面可以共享request里面的数据.
redirect:不能共享数据.
从运用地方来说
forward:一般用于用户登陆的时候,根据角色转发到相应的模块.
redirect:一般用于用户注销登陆时返回主页面和跳转到其它的网站等
从效率来说
forward:高.
redirect:低.
浅显地说就是
请求转发就是a去访问b,但是b没有这个资源,b就去c找,拿到了c的去把他交给a
重定向就是a去b访问资源,b告诉a c有资源让a去访问c。
转发和重定向的选择?
重定向的速度比转发慢,因为浏览器还得发出一个新的请求,如果在使用转发和重定向都无所谓的时候建议使用转发。
因为转发只能访问当前WEB的应用程序,所以不同WEB应用程序之间的访问,特别是要访问到另外一个WEB站点上的资源的情况,这个时候就只能使用重定向了。
六、转发和重定向的应用场景
<html>
<body>
<h2>Hello World!</h2>
<%--这里提交的路径需要寻找到项目的路径--%>
<%--${pageContext.request.ContextPath}代表当前项目--%>
<form action="${pageContext.request.contextPath}/login" method="get">
用户名:<input type="text" name="username"><br>
密码:<input type="password" name="password"><br>
<input type="submit">
</form>
</body>
</html>
public class RequestTest extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.setCharacterEncoding("UTF-8");
resp.setContentType("text/html");
System.out.println("进入这个请求了");
//处理请求
String username = req.getParameter("username");
String password = req.getParameter("password");
System.out.println(username+":"+password);
//重定向是一定要注意路径问题,否则404
resp.sendRedirect("/s/success.jsp");
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
super.doPost(req, resp);
}
}
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<h1>Success</h1>
</body>
</html>