6. Servlet
6.1 Servlet简介
Servlet就是sun公司开发动态web的一门技术
sun在这些API中提供一个接口叫做Servlet,如果想开发一个Servlet程序,只需要完成两个小步骤
-
编写一个类,实现Servlet接口
-
把开发好的Java类部署到web服务器中
把实现了Servlet接口的Java程序叫做Servlet
6.2 HelloServlet
-
构建一个普通的maven项目,删掉里边的src目录,以后学习就要在这个项目内建立Model,这个空的工程就是Maven的主工程;
-
关于Maven父子工程的理解
父项目中会有
<modules> <module>Servlet</module> </modules>
子项目会有
<parent> <artifactId>JavaWeb-Servlet</artifactId> <groupId>com.zhou</groupId> <version>1.0-SNAPSHOT</version> </parent>
父项目中的Java子项目可以直接使用
son extends father
-
Maven环境优化
-
修改web.xml为最新版本,此后在此处进行Servlet类class的注册,确定相应的Servlet类(Servlet-class)对应的相应域名映射(Servlet-mapping)
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd" version="4.0" metadata-complete="true"> </web-app>
-
将maven的结构搭建完整
-
-
编写一个Servlet程序
-
编写一个普通类
-
实现Servlet接口,直接继承HttpServlet
-
1 package Servlet; 2 3 import javax.servlet.ServletException; 4 import javax.servlet.http.HttpServlet; 5 import javax.servlet.http.HttpServletRequest; 6 import javax.servlet.http.HttpServletResponse; 7 import java.io.IOException; 8 import java.io.PrintWriter; 9 10 public class HelloServlet extends HttpServlet { 11 @Override 12 protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { 13 PrintWriter writer = resp.getWriter();//响应流 14 writer.print("Hello,Servlet"); 15 } 16 17 @Override 18 protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { 19 doGet(req, resp); 20 } 21 }
-
编写Servlet的映射
为什么需要映射?
写的是Java程序,但是要通过浏览器访问,而浏览器需要连接web服务器,所以需要在web服务器中注册写的Servlet,还续给它一个浏览器能够访问的路径
<!-- 注册Servlet--> <servlet> <servlet-name>hello</servlet-name> <servlet-class>Servlet.HelloServlet</servlet-class> </servlet> <!-- Servlet的请求路径--> <servlet-mapping> <servlet-name>hello</servlet-name> <url-pattern>/hello</url-pattern> </servlet-mapping>
-
配置Tomcat
注意:配置项目发布的路径
和5.7类似,可能没有Artifact,有解决方法:
idea配置 Tomcat Deployment添加时没有Artifact...选择的解决方案
-
启动测试
点击启动按钮,即可弹出浏览器,选择合适的网址查看效果

后台控制台:

6.3 Servlet原理
Servlet是由Web服务器调用,web服务器在收到浏览器请求之后

6.4 Mapping问题
-
一个Servlet可以指定一个映射路径
<servlet-mapping> <servlet-name>hello</servlet-name> <url-pattern>/hello</url-pattern> </servlet-mapping>
-
一个Servlet可以指定多个映射路径
1 <servlet-mapping> 2 <servlet-name>hello</servlet-name> 3 <url-pattern>/hello</url-pattern> 4 </servlet-mapping> 5 <servlet-mapping> 6 <servlet-name>hello</servlet-name> 7 <url-pattern>/hello1</url-pattern> 8 </servlet-mapping> 9 <servlet-mapping> 10 <servlet-name>hello</servlet-name> 11 <url-pattern>/hello2</url-pattern> 12 </servlet-mapping> 13 <servlet-mapping> 14 <servlet-name>hello</servlet-name> 15 <url-pattern>/hello3</url-pattern> 16 </servlet-mapping> 17 <servlet-mapping> 18 <servlet-name>hello</servlet-name> 19 <url-pattern>/hello4</url-pattern> 20 </servlet-mapping> 21 <servlet-mapping> 22 <servlet-name>hello</servlet-name> 23 <url-pattern>/hello5</url-pattern> 24 </servlet-mapping>
-
一个Servlet可以指定通用映射路径
<servlet-mapping> <servlet-name>hello</servlet-name> <url-pattern>/hello/*</url-pattern> </servlet-mapping>
-
默认请求路径
<servlet-mapping> <servlet-name>hello</servlet-name> <url-pattern>/*</url-pattern> </servlet-mapping>
-
指定一些后缀或者前缀等等
<!-- 可以自定义后缀实现请求映射 注意点:*前面不能加项目映射的路径--> <servlet-mapping> <servlet-name>hello</servlet-name> <url-pattern>*.xxx</url-pattern> </servlet-mapping>
-
优先级问题
指定了固有的映射路径优先级最高,如果找不到就会走默认的处理请求
<!-- 404--> <servlet> <servlet-name>error</servlet-name> <servlet-class>Servlet.ErrorServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>error</servlet-name> <url-pattern>/*</url-pattern> </servlet-mapping>

/*表示在加入/Servlet之后的默认(后边输入什么都一样)打开执行ErrorServlet程序
1 package Servlet; 2 3 import javax.servlet.ServletException; 4 import javax.servlet.http.HttpServlet; 5 import javax.servlet.http.HttpServletRequest; 6 import javax.servlet.http.HttpServletResponse; 7 import java.io.IOException; 8 import java.io.PrintWriter; 9 10 public class ErrorServlet extends HttpServlet { 11 @Override 12 protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { 13 resp.setContentType("text/html"); 14 resp.setCharacterEncoding("utf-8"); 15 PrintWriter writer = resp.getWriter(); 16 writer.print("<h1>404</h1>"); 17 } 18 19 @Override 20 protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { 21 doGet(req,resp); 22 } 23 }
6.5 ServletContext对象
web容器在启动的时候,它会为每个web程序都创建一个对应的ServletContext对象,它代表了当前的web应用。
1. 共享数据
-
在这个Servlet中保存的数据,可以在另外一个Servlet中拿到
首先创建一个键值对setAttribute
1 package com.zhou.servlet; 2 3 import javax.servlet.ServletContext; 4 import javax.servlet.ServletException; 5 import javax.servlet.http.HttpServlet; 6 import javax.servlet.http.HttpServletRequest; 7 import javax.servlet.http.HttpServletResponse; 8 import java.io.IOException; 9 10 public class HelloServlet extends HttpServlet { 11 @Override 12 protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { 13 // this.getInitParameter(); 初始化参数 14 // this.getServletConfig(); Servlet配置 15 // this.getServletContext(); Servlet上下文 16 ServletContext context = this.getServletContext(); 17 18 String username = "zhou";//数据 19 context.setAttribute("username",username);//设置键值对,将一个数据保存在ServletContext中,名字为username,值为username 20 21 System.out.println("Hello"); 22 } 23 }
然后进行读取
1 package com.zhou.servlet; 2 3 import javax.servlet.ServletContext; 4 import javax.servlet.ServletException; 5 import javax.servlet.http.HttpServlet; 6 import javax.servlet.http.HttpServletRequest; 7 import javax.servlet.http.HttpServletResponse; 8 import java.io.IOException; 9 10 public class GetServlet extends HttpServlet { 11 @Override 12 protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { 13 ServletContext context = this.getServletContext(); 14 String username = (String) context.getAttribute("username"); 15 16 resp.setContentType("text/html"); 17 resp.setCharacterEncoding("utf-8"); 18 resp.getWriter().print("名字"+username); 19 } 20 21 @Override 22 protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { 23 super.doPost(req, resp); 24 } 25 }
然后配置xml
<servlet> <servlet-name>getServlet</servlet-name> <servlet-class>com.zhou.servlet.GetServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>getServlet</servlet-name> <url-pattern>/getServlet</url-pattern> </servlet-mapping>
测试访问结果:先访问/hello,然后访问/getServlet,可以将数据读取

控制台Services变中文的方法:Tomcat文件夹的conf文件夹中找到logging.properties文件打开,UTF-8换成GBK
再创建一个Module和HelloServlet类,测试后台输出程序
package com.zhou.servlet; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; public class HelloServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { System.out.println("Hello"); } }
在web.xml中注册
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd" version="4.0" metadata-complete="true"> <!-- 新添加注册信息--> <servlet> <servlet-name>hello</servlet-name> <servlet-class>com.zhou.servlet.HelloServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>hello</servlet-name> <!-- 新添加后缀/hello后可访问hello指代的HelloServlet类--> <url-pattern>/hello</url-pattern> </servlet-mapping> </web-app>
运行Tomcat前添加Servlet组件Artifact,同6.2.6
之后运行,在地址后缀添加/hello
可在后台输出看到打印的Hello

2. 初始化参数InitParameter
package com.zhou.servlet; import javax.servlet.ServletContext; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; public class ServletDemo extends HttpServlet { @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 doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { super.doPost(req, resp); } }
<servlet> <servlet-name>gp</servlet-name> <servlet-class>com.zhou.servlet.ServletDemo</servlet-class> </servlet> <servlet-mapping> <servlet-name>gp</servlet-name> <url-pattern>/gp</url-pattern> </servlet-mapping>

3. 请求转发
重定向与转发的区别
A要拿C的资源,B没有,B做转发
A要拿C的资源,B没有,B告诉A去找C,重定向
package com.zhou.servlet; import javax.servlet.RequestDispatcher; import javax.servlet.ServletContext; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; public class ServletDemo02 extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { System.out.println("进入了ServletDemo02"); ServletContext context = this.getServletContext(); RequestDispatcher requestDispatcher = context.getRequestDispatcher("/gp");//转发的请求路径 requestDispatcher.forward(req,resp);//调用forward实现请求转发 //转发跳转到了/gp页面 } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { super.doPost(req, resp); } }
<servlet> <servlet-name>s02</servlet-name> <servlet-class>com.zhou.servlet.ServletDemo02</servlet-class> </servlet> <servlet-mapping> <servlet-name>s02</servlet-name> <url-pattern>/s02</url-pattern> </servlet-mapping>

转发跳到了/gp的页面
4. 读取资源文件
Properties
-
在java目录下新建properties
-
在resource目录下新建properties
都被打包到了同一个路径下:classes,这个路径为classpath
思路:需要一个文件流
package com.zhou.servlet; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.io.InputStream; import java.util.Properties; public class ServletDemo03 extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { InputStream is = this.getServletContext().getResourceAsStream("/WEB-INF/classes/db.properties"); Properties prop = new Properties(); prop.load(is); String user = prop.getProperty("username"); String pwd = prop.getProperty("password"); resp.getWriter().print(user+":"+pwd); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { super.doPost(req, resp); } }
<servlet> <servlet-name>s03</servlet-name> <servlet-class>com.zhou.servlet.ServletDemo03</servlet-class> </servlet> <servlet-mapping> <servlet-name>s03</servlet-name> <url-pattern>/s03</url-pattern> </servlet-mapping>
db.properties
username=root
password=123456
进行访问测试

6.6 HttpServletResponse
web服务器接收到客户端的http请求,针对这个请求,分别创建一个代表请求的HttpServletResponse对象,代表相应的一个HttpServletResponse
-
如果要获取客户端请求过来的参数:找HttpServletRequest
-
如果要给客户端响应一些信息:找HttpServletResponse
1. 简单分类
负责向浏览器发送数据的方法
ServletOutputStream getOutputStream() throws IOException; PrintWriter getWriter() throws IOException;
负责向浏览器发送响应头的方法
void setCharacterEncoding(String var1); void setContentLength(int var1); void setContentLengthLong(long var1); void setContentType(String var1); 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);
响应的状态码
重点:200 404 500
1 int SC_CONTINUE = 100; 2 int SC_SWITCHING_PROTOCOLS = 101; 3 int SC_OK = 200; 4 int SC_CREATED = 201; 5 int SC_ACCEPTED = 202; 6 int SC_NON_AUTHORITATIVE_INFORMATION = 203; 7 int SC_NO_CONTENT = 204; 8 int SC_RESET_CONTENT = 205; 9 int SC_PARTIAL_CONTENT = 206; 10 int SC_MULTIPLE_CHOICES = 300; 11 int SC_MOVED_PERMANENTLY = 301; 12 int SC_MOVED_TEMPORARILY = 302; 13 int SC_FOUND = 302; 14 int SC_SEE_OTHER = 303; 15 int SC_NOT_MODIFIED = 304; 16 int SC_USE_PROXY = 305; 17 int SC_TEMPORARY_REDIRECT = 307; 18 int SC_BAD_REQUEST = 400; 19 int SC_UNAUTHORIZED = 401; 20 int SC_PAYMENT_REQUIRED = 402; 21 int SC_FORBIDDEN = 403; 22 int SC_NOT_FOUND = 404; 23 int SC_METHOD_NOT_ALLOWED = 405; 24 int SC_NOT_ACCEPTABLE = 406; 25 int SC_PROXY_AUTHENTICATION_REQUIRED = 407; 26 int SC_REQUEST_TIMEOUT = 408; 27 int SC_CONFLICT = 409; 28 int SC_GONE = 410; 29 int SC_LENGTH_REQUIRED = 411; 30 int SC_PRECONDITION_FAILED = 412; 31 int SC_REQUEST_ENTITY_TOO_LARGE = 413; 32 int SC_REQUEST_URI_TOO_LONG = 414; 33 int SC_UNSUPPORTED_MEDIA_TYPE = 415; 34 int SC_REQUESTED_RANGE_NOT_SATISFIABLE = 416; 35 int SC_EXPECTATION_FAILED = 417; 36 int SC_INTERNAL_SERVER_ERROR = 500; 37 int SC_NOT_IMPLEMENTED = 501; 38 int SC_BAD_GATEWAY = 502; 39 int SC_SERVICE_UNAVAILABLE = 503; 40 int SC_GATEWAY_TIMEOUT = 504; 41 int SC_HTTP_VERSION_NOT_SUPPORTED = 505;
2. 常见应用
-
向浏览器输出消息getWriter等等
-
下载文件
-
要获取下载的路径
-
下载的文件名
-
设置想办法让浏览器能够支持下载需要的东西
-
获取下载文件的输入流
-
创建缓冲区
-
获取OutputStream对象
-
将FileOutputStream流写入到buffer缓冲区
-
使用OutputStream将缓冲区中的数据输出到客户端
1 import javax.servlet.ServletException; 2 import javax.servlet.ServletOutputStream; 3 import javax.servlet.http.HttpServlet; 4 import javax.servlet.http.HttpServletRequest; 5 import javax.servlet.http.HttpServletResponse; 6 import java.io.FileInputStream; 7 import java.io.IOException; 8 import java.net.URLEncoder; 9 10 public class FileServlet extends HttpServlet { 11 @Override 12 protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { 13 //1.获取下载文件的路径 14 String realPath = "C:\\Users\\88534\\Desktop\\Java入门\\JavaWeb-Servlet\\Response\\src\\main\\resources\\Java.jpg"; 15 System.out.println("下载文件的路径;"+realPath); 16 //2.下载的文件名 17 //截取字符串,选取\后边的文字 18 String fileName = realPath.substring(realPath.lastIndexOf("\\")+1); 19 //3.设置办法让浏览器能够支持下载需要的东西 20 // attachment后边是分号不是冒号,UTF -8转码表示可以下载带中文名的文件,否则有可能会乱码 21 resp.setHeader("Content-Disposition","attachment;filename="+ URLEncoder.encode(fileName,"UTF-8")); 22 //4.获取下载文件的输入流 23 FileInputStream in = new FileInputStream(realPath); 24 //5.创建缓冲区 25 int len = 0; 26 byte[] buffer = new byte[1024]; 27 //6.获取OutputStream 28 ServletOutputStream out = resp.getOutputStream(); 29 //7.将FileOutputStream流写入到buffer缓冲区,使用OutputStream将缓冲区中的数据输出到客户端 30 while ((len = in.read(buffer))>0){ 31 out.write(buffer,0,len); 32 } 33 in.close(); 34 out.close(); 35 } 36 37 @Override 38 protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { 39 super.doPost(req, resp); 40 } 41 }
-
<servlet> <servlet-name>fileDownload</servlet-name> <servlet-class>FileServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>fileDownload</servlet-name> <url-pattern>/down</url-pattern> </servlet-mapping>
运行Tomcat,地址输入\down就可以下载文件

3. 验证码功能
验证的来源:
前端获取
后端获取:
1 import javax.imageio.ImageIO; 2 import javax.servlet.ServletException; 3 import javax.servlet.http.HttpServlet; 4 import javax.servlet.http.HttpServletRequest; 5 import javax.servlet.http.HttpServletResponse; 6 import java.awt.*; 7 import java.awt.image.BufferedImage; 8 import java.io.IOException; 9 import java.util.Random; 10 11 public class ImageServlet extends HttpServlet { 12 @Override 13 protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { 14 //让 浏览器3s自动刷新一次 15 resp.setHeader("refresh","3"); 16 17 //在内存中创建一个图片 18 BufferedImage image = new BufferedImage(80, 20, BufferedImage.TYPE_INT_RGB); 19 //得到图片 20 Graphics2D g = (Graphics2D) image.getGraphics();//笔 21 //设置图片的背景颜色 22 g.setColor(Color.white); 23 g.fillRect(0,0,80,20);//画矩形 24 //给图片写数据 25 g.setColor(Color.blue); 26 g.setFont(new Font(null,Font.BOLD,20)); 27 g.drawString(makeNum(),0,20); 28 //告诉浏览器,这个请求用图片的方式打开 29 resp.setContentType("image/jpg"); 30 //此时网页存在缓存,不让浏览器缓存 31 resp.setDateHeader("expires",-1); 32 resp.setHeader("Cache-Control","no-cache"); 33 resp.setHeader("Pragma","no-cache"); 34 //把图片写到浏览器 35 ImageIO.write(image,"jpg",resp.getOutputStream()); 36 } 37 38 //生成随机数 39 private String makeNum(){ 40 Random random = new Random(); 41 String num = random.nextInt(99999999) + ""; 42 StringBuffer sb = new StringBuffer(); 43 for (int i = 0; i < 7 - num.length(); i++) { 44 sb.append("0");//不断刷新,不足7位的话用0补充 45 } 46 String s = sb.toString() + num; 47 return num;//保证都是7位 48 } 49 50 @Override 51 protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { 52 super.doPost(req, resp); 53 } 54 }
<servlet> <servlet-name>ImageServlet</servlet-name> <servlet-class>ImageServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>ImageServlet</servlet-name> <url-pattern>/image</url-pattern> </servlet-mapping>

4.实现重定向
一个 web资源受到客户端A请求后,B会通知A客户端去访问另外一个web资源C,这个过程叫做重定向。
常见场景:
用户登录
import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; public class RedirectServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { resp.sendRedirect("/Response_war/image");//需要回退到上一级目录 /* 原理:上述语句等效于 resp.setHeader("Location","/Response_war/image"); resp.setStatus(302); */ } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { super.doPost(req, resp); } }
<servlet> <servlet-name>RedirectServlet</servlet-name> <servlet-class>RedirectServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>RedirectServlet</servlet-name> <url-pattern>/redirect</url-pattern> </servlet-mapping>
地址栏访问/redirect后切换到/image

面试题:重定向和转发的区别
相同点:
页面都会实现跳转
不同点:
请求转发的时候,url不会发生变化;307
重定向的时候,url地址栏会发生变化;302
5.登录界面
用户的登录需要在JSP文件中加入表单
<html> <body> <h2>Hello World!</h2> <%--这里提交的路径,需要寻找到项目的路径--%> <%--${pageContext.request.contextPath}代表当前的项目--%> <form action="${pageContext.request.contextPath}/login" method="get"> <%-- br换行,get接收,post发送--%> 用户名:<input type="text" name="username"><br> 密码:<input type="password" name="password"><br> <input type="submit"> </form> <%--中文编码防止乱码--%> <%@page contentType="text/html; charset=UTF-8" %> </body> </html>
需要下载maven相应的jsp包



在左侧栏中出现jsp的包即表示下载成功
后台只需要表示要进入这个请求
import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; public class RequestTest extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { System.out.println("进入这个请求了"); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { super.doPost(req, resp); } }
<servlet> <servlet-name>request</servlet-name> <servlet-class>RequestTest</servlet-class> </servlet> <servlet-mapping> <servlet-name>request</servlet-name> <url-pattern>/login</url-pattern> </servlet-mapping>
运行Tomcat进入登录页面,输入用户名和密码提交后可在地址栏找到自己传递的明码账户信息,且后台程序显示已经进入请求程序。


接下来对请求进行处理
新建登录成功的JSP文件Success.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>Title</title> </head> <body> <h1>Success!</h1> </body> </html>
对doGet方法进行添加
@Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { System.out.println("进入这个请求了"); //处理请求 String username = req.getParameter("username"); String password = req.getParameter("password"); System.out.println(username+":"+password); //重定向时一定要注意路径的正确,要切回到原来的Artifact路径下,否则会404 resp.sendRedirect("/Response_war/Success.jsp");//重定向到登录成功界面 }
登录成功后完成跳转!

6.7 HttpServletRequest
HttpServletRequest代表客户端的请求,用户通过Http协议访问服务器,HTTP请求中的所有信息会被封装到HttpServletRequest,通过这个方法获得客户端的所有信息。
req.get一列方法

1. 获取前端传递的参数
req.getParameter
req.getParamterValues
2. 请求转发
req.getRequestDispatcher(跳转路径).forword(req,resp)
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>Title</title> </head> <body> <h1>登录</h1> <div> <%-- 以get接收的方式提交表单,提交我们的login请求--%> <form action="${pageContext.request.contextPath}/login" method="get"> 用户名:<input type="text" name="username"><br> 密码:<input type="password" name="password"><br> 爱好: <input type="checkbox" name="hobbies" value="唱歌">唱歌 <input type="checkbox" name="hobbies" value="跳舞">跳舞 <input type="checkbox" name="hobbies" value="rap">rap <input type="checkbox" name="hobbies" value="篮球">篮球 <input type="submit"> </form> </div> </body> </html>
import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.util.Arrays; public class LoginServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { req.setCharacterEncoding("utf-8"); resp.setCharacterEncoding("utf-8"); String username = req.getParameter("username"); String password = req.getParameter("password"); String[] hobbies = req.getParameterValues("hobbies"); System.out.println("============"); System.out.println(username); System.out.println(password); System.out.println(Arrays.toString(hobbies)); System.out.println("============"); //通过请求转发,不用加根路径/Request_war req.getRequestDispatcher("/Success.jsp").forward(req,resp); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { super.doPost(req, resp); } }
<servlet>
<servlet-name>Login</servlet-name>
<servlet-class>LoginServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>Login</servlet-name>
<url-pattern>/login</url-pattern>
</servlet-mapping>
index.jsp默认界面,点击submit提交后才会进入/login
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>Title</title> </head> <body> <h1>登录成功!</h1> </body> </html>


7. Cookie、Session
7.1 会话
会话:用户打开了浏览器,点击了很多超链接,访问多个web资源,关闭浏览器,这个过程可以称之为会话
有状态会话:一个同学来过教室,下次再来教室,就会知道这个同学曾经来过
一个网站证明自己来过
客户端 服务端
-
服务端给客户端一个信件,客户端下次访问服务端带上信件就可以开始了:cookie
-
服务器等级你来过了,下次你来的时候来匹配你:session
7.2 保存会话的两种技术
cookie
-
客户端技术(响应、请求)
session
-
服务器技术,利用这个技术,可以保存用户的会话信息
-
把信息或数据放在session中
常见:网站登陆之后,下次不用再登陆了,第二次访问直接就上去了
7.3 Cookie
-
从请求中拿到cookie消息
-
服务器响应给用户端cookie
1 package com.zhou.servlet; 2 3 import javax.servlet.ServletException; 4 import javax.servlet.http.Cookie; 5 import javax.servlet.http.HttpServlet; 6 import javax.servlet.http.HttpServletRequest; 7 import javax.servlet.http.HttpServletResponse; 8 import java.io.IOException; 9 import java.io.PrintWriter; 10 import java.util.Date; 11 12 //保存用户上一次访问的时间 13 public class CookieDemo01 extends HttpServlet { 14 @Override 15 protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { 16 //服务器告诉你你来的时间,把这个时间封装成为一个信件,下次带来,就知道你来了 17 18 //解决中文乱码 19 req.setCharacterEncoding("utf-8"); 20 resp.setCharacterEncoding("utf-8"); 21 resp.setContentType("text/html"); 22 23 PrintWriter out = resp.getWriter(); 24 25 //Cookie,服务器端从客户端获取 26 Cookie[] cookies = req.getCookies();//这里返回数组,说明cookie可能存在多个 27 28 //判断Cookie是否存在 29 if (cookies!=null){ 30 //如果存在怎么办 31 out.write("你上一次访问的时间是:"); 32 for (int i = 0; i < cookies.length; i++) { 33 Cookie cookie = cookies[i]; 34 //获取Cookie的名字 35 if (cookie.getName().equals("lastLoginTime")){ 36 //获取cookie的值 37 long lastLogintime = Long.parseLong(cookie.getValue()); 38 Date date = new Date(lastLogintime); 39 out.write(date.toLocaleString()); 40 } 41 } 42 }else { 43 out.write("这是您第一次访问网站"); 44 } 45 46 //服务器给客户端响应一个cookie,新建 47 Cookie cookie = new Cookie("lastLoginTime",System.currentTimeMillis() + "");//转为String 48 cookie.setMaxAge(24*60*60);//有效期一天,单位,秒 49 resp.addCookie(cookie);//响应给客户端一个cookie 50 } 51 52 @Override 53 protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { 54 super.doPost(req, resp); 55 } 56 }
cookie:一般会保存在本地的用户目录下appdata
一个网站cookie是否存在上限?
-
一个cookie只能保存一个信息
-
一个web站点可以给浏览器发送多个cookie,最多存放20个cookie
-
cookie大小有限制4kb
-
300个cookie浏览器上限
删除cookie
-
不设置有效期,关闭浏览器,自动失效
-
设置有效期,时间为0
package com.zhou.servlet; import javax.servlet.ServletException; import javax.servlet.http.Cookie; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; public class CookieDemo02 extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { //创建一个cookie,名字必须要和要删除的名字一致,覆盖原有cookie Cookie cookie = new Cookie("lastLoginTime",System.currentTimeMillis()+""); //将cookie有效期设置为0,删除cookie cookie.setMaxAge(0); resp.addCookie(cookie); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { super.doPost(req, resp); } }
中文数据传递,需要编码解码
package com.zhou.servlet; import javax.servlet.ServletException; import javax.servlet.http.Cookie; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.io.PrintWriter; import java.net.URLDecoder; import java.net.URLEncoder; import java.util.Date; public class CookieDemo03 extends HttpServlet { //中文数据传递 @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { req.setCharacterEncoding("utf-8"); resp.setCharacterEncoding("utf-8"); resp.setContentType("text/html"); PrintWriter out = resp.getWriter(); //Cookie,服务器端从客户端获取 Cookie[] cookies = req.getCookies();//这里返回数组,说明cookie可能存在多个 //判断Cookie是否存在 if (cookies!=null){ //如果存在怎么办 out.write("你上一次访问的时间是:"); for (int i = 0; i < cookies.length; i++) { Cookie cookie = cookies[i]; //获取Cookie的名字 if (cookie.getName().equals("name")){ //获取cookie的值 //System.out.println(cookie.getValue());出现乱码 //解码 out.write(URLDecoder.decode(cookie.getValue(),"UTF-8")); } } }else { out.write("这是您第一次访问网站"); } //编码 Cookie cookie = new Cookie("name", URLEncoder.encode("Java语言","UTF-8")); resp.addCookie(cookie); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { super.doPost(req, resp); } }
<servlet> <servlet-name>CookieDemo03</servlet-name> <servlet-class>com.zhou.servlet.CookieDemo03</servlet-class> </servlet> <servlet-mapping> <servlet-name>CookieDemo03</servlet-name> <url-pattern>/c3</url-pattern> </servlet-mapping>
输入/c3可看到输出:你上一次访问的时间是:Java语言
输出了中文字符
7.4 Session(重点)
-
服务器会给每一个用户(浏览器)创建一个session对象
-
一个Session独占一个浏览器,只要浏览器没有关闭,这个Session就存在
-
用户登陆之后,整个网站都可以访问—>保存用户的信息,保存购物车的信息等等……
1. 创建并访问
1 package com.zhou.servlet; 2 3 import javax.servlet.ServletException; 4 import javax.servlet.http.*; 5 import java.io.IOException; 6 import java.io.PrintWriter; 7 8 public class SessionDemo01 extends HttpServlet { 9 @Override 10 protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { 11 //解决中文乱码,后续学习这个可以由简单方法代替 12 req.setCharacterEncoding("utf-8"); 13 resp.setCharacterEncoding("utf-8"); 14 resp.setContentType("text/html;charset=utf-8"); 15 16 //得到Session 17 HttpSession session = req.getSession(); 18 19 //给Session存东西 20 session.setAttribute("name","Java语言"); 21 22 //获取Session的ID 23 String id = session.getId(); 24 25 //判断Session是不是新创建 26 if (session.isNew()){ 27 resp.getWriter().write("session创建成功,ID:"+id); 28 }else { 29 resp.getWriter().write("session已经在服务器中存在了,ID:"+id); 30 } 31 32 //Session创建的时候做了什么事情 33 // Cookie cookie = new Cookie("JESSIONID",id); 34 // resp.addCookie(cookie); 35 } 36 37 @Override 38 protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { 39 super.doPost(req, resp); 40 } 41 }
<servlet> <servlet-name>SessionDemo01</servlet-name> <servlet-class>com.zhou.servlet.SessionDemo01</servlet-class> </servlet> <servlet-mapping> <servlet-name>SessionDemo01</servlet-name> <url-pattern>/s1</url-pattern> </servlet-mapping>
输出:session已经在服务器中存在了,ID:7228E652C4832920BCAFE9327383E793
2. 得到Session
1 package com.zhou.servlet; 2 3 import javax.servlet.ServletException; 4 import javax.servlet.http.HttpServlet; 5 import javax.servlet.http.HttpServletRequest; 6 import javax.servlet.http.HttpServletResponse; 7 import javax.servlet.http.HttpSession; 8 import java.io.IOException; 9 10 public class SessionDemo02 extends HttpServlet { 11 @Override 12 protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { 13 //解决中文乱码,后续学习这个可以由简单方法代替 14 req.setCharacterEncoding("utf-8"); 15 resp.setCharacterEncoding("utf-8"); 16 resp.setContentType("text/html;charset=utf-8"); 17 18 //得到Session 19 HttpSession session = req.getSession(); 20 21 String name = (String) session.getAttribute("name"); 22 System.out.println(name); 23 } 24 25 @Override 26 protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { 27 super.doPost(req, resp); 28 } 29 }
<servlet> <servlet-name>SessionDemo02</servlet-name> <servlet-class>com.zhou.servlet.SessionDemo02</servlet-class> </servlet> <servlet-mapping> <servlet-name>SessionDemo02</servlet-name> <url-pattern>/s2</url-pattern> </servlet-mapping>
输出:后台控制台打印“Java语言”
3. 删除Session
package com.zhou.servlet; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; import java.io.IOException; public class SessionDemo03 extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { //删除Session HttpSession session = req.getSession(); session.removeAttribute("name"); session.invalidate();//手动注销 } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { super.doPost(req, resp); } }
<servlet> <servlet-name>SessionDemo03</servlet-name> <servlet-class>com.zhou.servlet.SessionDemo03</servlet-class> </servlet> <servlet-mapping> <servlet-name>SessionDemo03</servlet-name> <url-pattern>/s3</url-pattern>
删除session,再通过s2无法访问500粗偶(清空后调用toString空指针异常),s1创建了一个新的session和原来的id不一样
4. 会话自动过期xml设置
<!-- 设置session默认的失效时间--> <session-config> <!-- 1分钟后Session自动失效,以分钟为单位--> <session-timeout>1</session-timeout> </session-config>
5. Session和Cookie的区别
-
Cookie是把用户的数据写给用户的浏览器,浏览器保存
-
Session是把用户的数据写到用户独占Session中,服务器端保存(保存重要的信息,减小服务器资源的浪费)
-
Session对象由服务器创建
-
Cookie存放字符串(数据小),Session可以存放对象(数据大)
适用场景:
-
保存一个登录用户的信息
-
购物车信息
-
在整个网站中经常会使用的数据,保存在Session中

浙公网安备 33010602011771号