Servlet学习
1.servlet原理图
- 一、浏览器向Web容器发出HTTP请求。
- 二、首次访问时,会向web.xml查询相应的路径。
- 三、在web.xml中找到相映射的servlet类。
- 四、HttpServlet的父类GenericServlet中有service方法的实现,这会将请求的类型分类处理,如GET、POST等。
- 五、Web容器会将处理结果Response处理后返回到用户浏览器中。
2.Servlet映射配置
-
在web.xml文件下配置Servlet
-
将Servlet类映射到web访问路径
<!--Forexmaple
一个Servlet可以映射多个路径
-->
<servlet>
<servlet-name>Thanks</servlet-name>
<servlet-class>com.gu_ppy.servlet.HttpThanks</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>Thanks</servlet-name>
<url-pattern>/Thanks</url-pattern>
</servlet-mapping>
3.默认映射路径
- 此映射会在所有的访问路径下访问该Servlet
<servlet>
<servlet-name>Thanks</servlet-name>
<servlet-class>com.gu_ppy.servlet.HttpThanks</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>Thanks</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
4.指定一些前缀或后缀(*为通配符)
<servlet-mapping>
<servlet-name>Thanks</servlet-name>
<url-pattern>*.gu-ppy</url-pattern>
<!--后缀为.gu-ppy-->
<!--*为通配符,可以匹配任何相似格式的请求,如果web.xml中有规定格式的则认为请求详细路径-->
</servlet-mapping>
- 有固有路径的映射就走,没有就走默认路径
4.ServletContext的作用
- ServletContext:Servlet上下文,是为不同Servlet之间提供桥梁的工具,类似于Session
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-qQRasM9R-1583916335251)(C:\Users\gu-ppy\AppData\Roaming\Typora\typora-user-images\image-20200217230853121.png)]
1.共享数据
- 存放数据以及取数据
//存
context.setAttribute("name","Hello");
//取
Object name = context.getAttribute("name");
2.重定向与请求转发
请求转发代码:
this.getServletContext().getRequestDispatcher("/s1").forward(req,resp);
/**
*分组转发
*作用:请求转发,将请求转向另一个链接
*s1为目标链接
*/
重定向见下:重定向链接
- 区别
3.读取资源文件
Properties文件
- 在java目录下创建的 .properties文件
- 在resoureces目录下创建的 .properties文件
它们在Build后,发现它们都在classes路径下,俗称classpath。
- 可以使用ServletContext得到指向该配置文件的流,再新建一个Properties类以此来完成加载该配置文件。
ServletContext context = this.getServletContext();
//获取流
InputStream stream = context.getResourceAsStream("/WEB-INF/classes/db.properties");
Properties pr = new Properties();
pr.load(stream);
String driver = pr.getProperty("driver");
String name = pr.getProperty("username");
String pass = pr.getProperty("password");
4.获取初始化web配置
- 这是在web.xml中用于初始化web应用的配置代码(下方参数演示无实义)
<!--用于初始化web应用的配置-->
<context-param>
<param-name>url</param-name>
<param-value>jdbc:mysql://localhost:3306/s</param-value>
</context-param>
-
我们可以用ServletContext来获取web.xml中的自定义初始化配置信息
ServletContext context = this.getServletContext(); String url = context.getInitParameter("url"); resp.getWriter().print("Url:"+url);
5.HttpServletResponse的使用
Web服务器收到用户从浏览器发出的Http请求后,它会针对这个请求创建两个部分,一个是HttpServletRequest另一个是HttpServletResponse。
- HttpServletRequest:包含用户请求的一些列信息
- HttpServletResponse:包含将要返回给浏览器的信息
1.Response源码解析
- Http请求以及响应分为两个部分
- 请求体/响应体
- 请求状态码/响应状态码
1、用于向浏览器发送数据的方法
ServletOutputStream getOutputStream() throws IOException;
PrintWriter getWriter() throws IOException;
2、响应头的操作的方法
- 响应的头部操作
void setDateHeader(String var1, long var2);
void addDateHeader(String var1, long var2);
void setHeader(String var1, String var2);
void addHeader(String var1, String var2);
void setIntHeader(String var1, int var2);
void addIntHeader(String var1, int var2);
3、状态
Response和Request类似,都有自身的状态,代表在请求或者响应时的处理状态,在HttpServletResponse中有相应的状态常数,如下,
int SC_CONTINUE = 100;
int SC_SWITCHING_PROTOCOLS = 101;
int SC_OK = 200;//一般为成功
int SC_CREATED = 201;
int SC_ACCEPTED = 202;
int SC_NON_AUTHORITATIVE_INFORMATION = 203;
int SC_NO_CONTENT = 204;
int SC_RESET_CONTENT = 205;
int SC_PARTIAL_CONTENT = 206;
int SC_MULTIPLE_CHOICES = 300;
int SC_MOVED_PERMANENTLY = 301;
int SC_MOVED_TEMPORARILY = 302;
int SC_FOUND = 302;
int SC_SEE_OTHER = 303;
int SC_NOT_MODIFIED = 304;
int SC_USE_PROXY = 305;
int SC_TEMPORARY_REDIRECT = 307;
int SC_BAD_REQUEST = 400;
int SC_UNAUTHORIZED = 401;
int SC_PAYMENT_REQUIRED = 402;
int SC_FORBIDDEN = 403;
int SC_NOT_FOUND = 404;//找不到资源
int SC_METHOD_NOT_ALLOWED = 405;
int SC_NOT_ACCEPTABLE = 406;
int SC_PROXY_AUTHENTICATION_REQUIRED = 407;
int SC_REQUEST_TIMEOUT = 408;
int SC_CONFLICT = 409;
int SC_GONE = 410;
int SC_LENGTH_REQUIRED = 411;
int SC_PRECONDITION_FAILED = 412;
int SC_REQUEST_ENTITY_TOO_LARGE = 413;
int SC_REQUEST_URI_TOO_LONG = 414;
int SC_UNSUPPORTED_MEDIA_TYPE = 415;
int SC_REQUESTED_RANGE_NOT_SATISFIABLE = 416;
int SC_EXPECTATION_FAILED = 417;
int SC_INTERNAL_SERVER_ERROR = 500;//服务端错误
int SC_NOT_IMPLEMENTED = 501;
int SC_BAD_GATEWAY = 502;//网关错误
int SC_SERVICE_UNAVAILABLE = 503;
int SC_GATEWAY_TIMEOUT = 504;
int SC_HTTP_VERSION_NOT_SUPPORTED = 505;
2.常见应用
1、向浏览器发送消息
-
如常见的text/html文本
resp.setContentType("text/html"); resp.setCharacterEncoding("utf-8"); ServletContext context = this.getServletContext(); context.setAttribute("name","Hello"); PrintWriter writer = resp.getWriter(); writer.print("<html><head><title>Welcome</title></head><body><h1>欢迎进入Web世界</h1><hr/>Hello word</body></html>");
2、下载文件
要解决的问题:
1.获取下载文件的路径是多少
2.下载文件名是多少
3.浏览器支持 & 获取输出流OutputStream
4.获取下载文件的输入流
5.创建缓冲区 & 发送文件
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//设置输入流读取文件
String realPath = this.getServletContext().getRealPath("/resources/阅读.txt");
System.out.println("路径:"+realPath);
String fileName = realPath.substring(realPath.lastIndexOf("\\") + 1);
System.out.println("文件名:"+fileName);
FileInputStream in = new FileInputStream(realPath);
//获取输出流并设置响应头信息,中文乱码使用的MimeUtility.encodeWord()来解决
ServletOutputStream out = resp.getOutputStream();
resp.setHeader("Content-Disposition","attachment;fileName="+ MimeUtility.encodeWord(fileName));
//设置缓存区并发送
int len=0;
byte[] buffer = new byte[1024];
while((len=in.read(buffer))>-1){
out.write(buffer,0,len);
}
in.close();out.close();
}
**注意:**在ServletContext取得资源的路径中,资源尽量不要放到web根目录wbapp目录下和java目录下的reources文件夹下,它很有可能发生资源读取问题,最好自己在webapp下自建一个类似image、downlist、music等资源文件夹。
3、验证码
验证码在我们web应用中是一种很常见且对服务器减负的很有效的方法,这里用一个Servlet做一个小例子,并以此来学习Response。
- 设置响应头信息
- 创建image
- 绘制image & 生成随机数
- 发送image
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//告诉浏览器,5秒刷新一次
resp.setHeader("refresh","8");
//在内存中创建80x20的图片
BufferedImage image = new BufferedImage(80, 20, BufferedImage.TYPE_INT_RGB);
Graphics2D g = (Graphics2D) image.getGraphics();//创建一支绘笔
g.setColor(Color.white);
g.fillRect(0,0,80,20);//填充矩形
g.setColor(Color.blue);
g.setFont(new Font("微软雅黑",Font.PLAIN,20));
g.drawString(makeNum(),5,20);
resp.setContentType("image/jpg");//设置文件信息
resp.setHeader("expires","0");//缓存存在时间
resp.setHeader("cache-control","no-cache");//缓存禁用上下三局
resp.setHeader("pragma","no-cache");
//图片发送的方法,涨知识了
ImageIO.write(image,"jpg",resp.getOutputStream());
}
- 生成随机数字符串
/**
* 生成随机数字符串
* @return
*/
private String makeNum(){
Random random = new Random();
String num = random.nextInt(999999)+"";
StringBuffer buffer = new StringBuffer();
for(int i=0 ;i<6-num.length();i++){ //保证验证码总为6位
buffer.append("0");
}
return buffer + num;
}
4、重定向
重定向:一个web服务器在收到一个请求后,它通知浏览器访问另外一个网址。
//接口
resp.sendRedirect("/web_01_war_exploded/s");
//解析
resp.setHeader("Location","/web_01_war_exploded/s");
resp.setStatus(302);
6.HttpServletRequest的使用
- 用户通过http访问服务器,可以获取客户端的信息。
备注:
1.@Deprecated注解
- 为建议不使用的方法或对象,可以用其他方法替代。
@Deprecated
String encodeRedirectUrl(String var1);
2.Response的setHeader()
1、一秒刷新页面一次
response.setHeader(“refresh”,“1”);
2、五秒跳到其他页面
response.setHeader("refresh","5;URL=otherPagename");
3、设置禁用缓存:
response.setHeader("expires", "0");
response.setHeader("cache-control", "no-cache");
response.setHeader("pragma", "no-cache");
4、设置过期的时间期限
response.setDateHeader("Expires",System.currentTimeMillis()+自己设置的时间期限);
5、访问别的页面:
response.setStatus(302);
response.setHeader("location","url");
esponse.setHeader(“refresh”,“5;URL=otherPagename”);
3、设置禁用缓存:
```java
response.setHeader("expires", "0");
response.setHeader("cache-control", "no-cache");
response.setHeader("pragma", "no-cache");
4、设置过期的时间期限
response.setDateHeader("Expires",System.currentTimeMillis()+自己设置的时间期限);
5、访问别的页面:
response.setStatus(302);
response.setHeader("location","url");