一、Servlet的实现
Servlet时服务端小程序的意思。使用Java语言编写的服务器端程序
1.创建Web项目
URL为默认打开地址
默认项目路径
2.Servlet的实现
实现Servlet规范
之间建立一个类即可,但是需要实现Servlet规范,即继承HttpServlet类
重写service方法
满足Servlet规范只是让我们的类能够满足接受请求的要求,接收到请求后需要对请求进行分析,以及进行业务逻辑处理,计算出结果,则需要添加代码,在规范中有一个叫做service()的方法,专门用来做请求处理的操作。
设置注解
在完成代码后
@WebServlet("/ser01")
通过注解设置Servlet类的访问路径
注:
1.service方法由服务器自动调用
2.访问Servlet时,路径格式如下:
http://localhost:端口/项目路径/资源路径?参数名=参数值
项目路径: 站点名,项目对外访问路径,在Tomcat中设置(Devlopment属性中设置Application context)
资源路径:servlet对外访问路径,通过@WebServlet注解设置
2.3Servlet 的工作流程
- 通过请求头获知浏览器访问的是哪个主机
- 再通过请求行获取访问的是一个web应用
- 再通过请求行中的请求路径获知访问的是哪个资源
- 通过获取的资源路径再配置中匹配到真实的路径
- 服务器会创建servlet对象,
- 调用service方法来处理请求和响应的操作
- 调用service完毕后会返回路由器 由路由器将response缓冲区的数据取出,以http响应的格式发送到浏览器
2.4Servlet的生命周期
Servlet没有main方法,不能独立运行,他的运行完全由Servlet引擎来控制和调度,所谓声明周期,指的是servlet容器什么时候创建servlet实例,什么时候调用其方法进行请求的处理,何时销毁
-
实例和初始化时机:
当请求到达容易时,容器查找该servlet对象是否存在,如果不存在,则会创建实例并进行初始化。 -
就绪/调用/服务阶段
有请求到达容器,容器调用servlet对象的service()方法,处理请求的方法在整个生命周期中可以被多次调用;HttpServlet的service方法,会根据请求方式来调用doGet()和doPost()方法,但是这两个方法默认情况下都会抛异常 -
销毁时间
当容器关闭时候(应用程序停止时)会将程序中的Servlet实例进行销毁。
public class servlet03 extends HttpServlet {
@Override
public void init() throws ServletException {
System.out.println("init...");
}
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("service");
}
@Override
public void destroy() {
System.out.println("destroy...");
}
}
三、HttpServletRequest对象
HttpServletRequest对象:主要作用是用来接收客户端发送过来的请求信息,例如:请求的参数信息,例如:请求的参数,发送的头信息等都属于客户端发来的信息,service()方法中形参接收的是HttpServletRequest接口的实例化对象,表示该对象主要应用在HTTP协议上,该对象是由Tomcat封装好传递过来。
HttpServletRequest是ServletRequest的子接口,
3.1接收请求
3.1.1常用方法
String url = request.getRequestURI().toString();
System.out.println("获取客户端请求的完整URL:" + url);
String uri = request.getRequestURI();
System.out.println("获取客户端请求的部分URL:"+ uri);
//获取请求行中的参数信息
String queryString = request.getQueryString();
System.out.println("获取请求行中的参数部分"+queryString);
String method = request.getMethod();
System.out.println("获取请求方式" + method);
String protocol = request.getProtocol();
System.out.println("获取HTTP版本号:"+protocol);
String webapp = request.getContextPath();
System.out.println("获取webapp名字:" + webapp);
3.1.2获取请求参数
getParameter(name) 获取指定名称的参数
getParameterValue(String name) 获取指定名称参数的所有值
String uname = request.getParameter("uname");
String upwd = request.getParameter("upwd");
System.out.println("姓名:"+ uname + ",密码" +upwd);
String[] hobbys = request.getParameterValues("hobby");
System.out.println(hobbys.length);
3.2请求乱码问题
由于request属于接收客户端的参数,所以必然有默认的语言编码,所以解析时一定会出现乱码
方式一:
request.setCharacterEncoding("utf-8");
这种方式支队POST有效(必须在接收所有数据之前设定)
方式二:
new String(request.getParameter(name).getBytes("ISO-8859-1"),"UTF_8");
通用
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
req.setCharacterEncoding("UTF-8");
System.out.println(req.getParameter("name"));
}
3.3请求转发❤️
请求转发,是一种服务器的行为,当客户端请求到达后,服务器进行转发,此时会将请求对象进行保存,地址栏中的URL地址不会改变,得到响应后服务器再将响应发送给客户端,从始至终只有一个请求发出
实现方式,达到多个资源协同响应的效果
req.getRequestDispatcher("").forward(req,resp);
实例
//请求转发
@WebServlet("/ser03")
public class servlet03 extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("servlet 03...");
//接收请求的用户名和密码
String name = req.getParameter("name");
String pwd = req.getParameter("pwd");
System.out.println("姓名"+name + ",密码:" + pwd);
//请求转发调转到首页
req.getRequestDispatcher("index.jsp").forward(req,resp);
}
}
特点:地址栏不发生改变
请求转发只有一次请求
3.4 request作用域
通过该对象可以在一个请求中传递数据,作用范围:在一次请求中有效,即服务器跳转有效。
只在一次请求中有效
//设置域对象内容
request.setAttribute("userName",uname);
request.getAttribute(String name);
request.removeAttribute(String name);
四、HttpServletResponse对象
web收到服务器客户端的http请求,会针对每一次请求,分别创建一个用于代表请求的request对象和代表响应的response对象
request和response对象代表请求和响应:获取客户端数据,需要通过request对象;向客户端输出数据,需要通过response对象。
HttpServletResponse的主要功能用于服务器对客户端的请求,将web服务器处理后的结果返回给客户端。service()方法中形参接收的是HttpServletResponse接口的实例化对象,这个对象中封装了向客户端发送数据、发送响应头、发送响应状态的方法。
4.1响应数据
接收到客户端请求后,可以通过HttpServletResponse对象直接进行响应,响应时需要获取输入流。
有两种形式:
getWrite() 获取字符流
getOutputStream() 获取字节流(能响应一切数据)
4.2相应乱码问题
在响应中,如果我们响应的内容中含有中文,则有可能出现乱码。这是因为服务器响应的数据也会经过网络传输,服务器端有一种编码方式,在客户端也存在一种编码方式,当两端使用的编码方式不同时出现乱码。
解决:
respoense.setCharacterEncoding("UTF-8“)
同时
指定客户端的解码方式:
resp.setHeader(“content-type”,“text/html:charset=UTF-8”);
4.3重定向❤️
重定向是一种服务器指导,客户端的行为。客户端发出第一个请求,被服务器接收处理后,服务器会进行响应,在响应的同时,服务器会给客户端一个新的地址(response.sendRedirect(url)😉,当客户端接收到响应后,会立刻、马上、自动根据服务器给的新地址发起第二个请求,服务器接收请求并做出响应,重定向完成。
特点:
- 1.地址栏会发生改变
- 2.客户端跳转
- 3.有两次请求
- 4.request对象不共享
//重定向到index.jsp
response.sendResirect("index.jsp");
4.4请求转发与重定向的区别
请求转发(req.getRequestDispatcher().forward()) | 重定向(resp.sendRedirect()) |
---|---|
一次请求,数据在request域中共享 | 两次请求,数据不共享 |
服务器端行为 | 客户端行为 |
地址栏不发生变化 | 地址栏发生变化 |
绝对地址定位到站点后 | 绝对地址可以写到http:// |
resp.sendRedirect("https://www.baidu.com");//可以实现跳转到百度,但是请求转发不可以,请求转发只可以跳转本项目路径
五、Cookie对象
Cookie是浏览器提供的一种技术,通过浏览器的程序,能将一些只需保存在客户端或者客户端进行处理的数据,放在本地的计算机上,不需要通过网络传输,因而提高网页处理的效率,并且能够减少服务器的负载,但是由于Cookie是服务器端保存在客户端的信息,所以其安全性也是很差的。例如常见的记住密码则可以通过Cookie来实现。
有一个专门操作Cookie的类
随着服务器端的响应发送给客户端,保存在浏览器。当下次在访问服务器时把Cookie再带回服务器。
Cookie的格式:键值对用”=“链接,多个键值对通过;隔开
5.1Cookie的创建和发送
通过new Cookie(“key”,“value”);来创建一个对象,要想将Cookie随响应发送到客户端,需要先添加到response对象中,response.addCookie(cookie);此时cookie对象则随着响应时间发送到了客户端。在浏览器上可以看见。
Cookie cookie = new Cookie("uname","admin");
resp.addCookie(cookie);
5.2Cookie的获取
在服务器端只提供了一个getCookies()方法用来湖片区客户端回传的所有cookie组成的一个数组,如取单个Cookie则需要遍历,getName()获取Cookie的名称,getValue()获取cookie的值
@WebServlet("/cook02")
public class Cookie02 extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// Cookie cookie = new Cookie("uname","admin");
// resp.addCookie(cookie);
Cookie[] cookies = req.getCookies();
//判断是否存在
if(cookies != null && cookies.length > 0){
for(Cookie cookie : cookies){
System.out.println("名称" + cookie.getName() + "值:" + cookie.getValue());
//获取指定cookie对象
if("uname".equals(cookie.getName())){
System.out.println("指定值为:" + cookie.getValue());
}
}
}
}
}
@WebServlet("/cook02")
public class Cookie02 extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// Cookie cookie = new Cookie("uname","admin");
// resp.addCookie(cookie);
Cookie[] cookies = req.getCookies();
//判断是否存在
if(cookies != null && cookies.length > 0){
for(Cookie cookie : cookies){
System.out.println("名称" + cookie.getName() + "值:" + cookie.getValue());
//获取指定cookie对象
if("uname".equals(cookie.getName())){
System.out.println("指定值为:" + cookie.getValue());
}
}
}
}
}
5.3Cookie设置到期时间
除了Cookie的名称和内容外,我们还需要关心到期时间,到期时间用来指定该cookie何时失效。默认为当前浏览器关闭即失效。我们可以手动设定cookie的有效时间,通过setMaxAge(int time);方法设定cookie的最大有效时间,以秒为单位。
到期时间的取值:
-
负整数
表示不存储该cookie
cookie的默认属性就是i-,表示只在浏览器中存活,一旦关闭浏览器,那么cookie就会消失。 -
正整数
表示存储的秒数,当圣米格大于0时,浏览器就会把Cookie保存到硬盘上,就算关闭浏览器,就算重启电脑,也会存活。 -
0
表示删除该cookie
5.4Cookie的注意点
Cookie保存在当前的浏览器中。
在一般的站点中常常有记住用户名这样一个操作,该操作只是将信息保存在本机上,换电脑以后这些信息就无效了。而且Cookie不能跨浏览器。
同名Cookie问题
如果服务器端发送重复的Cookie那么就会覆盖原来的
浏览器存放Cookie的数量
String name = URLDecoder.decode(cookie.getName());
String value = URLDecoder.decode(cookie.getValue());
5.5Cookie的路径
Cookie的setPath设置cookie的路径,这个路径直接决定服务器的请求是否会从浏览器中加载某些cookie
六、HttpSession对象
对于服务器而言。每一个连接到它的客户端都是一个session,servlet容器使用此接口创建HTTP客户端和HTTP服务器之间的会话。会话将保留指定的时间段,跨多个连接来自用户的页面请求。
Session无用论客户端还是服务端都可以感知到,若重新打开一个新的浏览器,则无法获得之前设置的因为每一个session只保留在当前的浏览器当中,并在相关的页面获得。
Session的作用就是为了标识一次会话,或者说确认一个用户;并且在一次会话(一个用户的多次请求)期间共享数据。我们可以通过request.getSession()方法,来获取当前会话的session对象。
//若存在则获取,否则创建
HttpSession session = request.getSession();
public class Session01 extends HttpServlet {
@Override
protected void service(HttpServletRequest request, HttpServletResponse resp) throws ServletException, IOException {
//获取会话标识符
HttpSession session = request.getSession();
System.out.println("会话标识符" + session.getId());
//是否是新的session对象
System.out.println("是否是新的" + session.isNew());
//会话开始时间
System.out.println("会话开始时间:" + session.getCreationTime());
//最后一次访问时间
System.out.println("最后一次访问时间:" + session.getLastAccessedTime());
}
6.1 标识符
Session既然是为了标识一次会话,那么此次会u啊就应该有一个唯一的标志,这个标志就是sessionId.
每当一次请求到达服务器,如果开启了会话(访问了session),服务器第一步会查看是否从客户端回传一个名为JSESSIONID的cookie,如果没有则认为这是一次新的对话,会创建一个新的session对象,并且用唯一的sessionId为此次对话做一个标志。
这里的cookie是一种比较特殊的cookie,当用户请求服务器时,如果访问了sesson,则服务器创建一个名SESSIONID,值为获取到的session并添加到response对此昂中,响应给客户端,有效时间为关闭浏览器。
Session的底层依赖为Cookie
6.2session域对象
👊Session用来表示一次会话,在一次会话中数据是可以共享的,这是session作为域对象存在,可以通过setAttribute(name,value)方法向域对象中添加数据,通过getAttribute(name)从域对象中获取数据,通过removeAttribute(name)从域对象中移出数据。
public class Session02 extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//获取会话标识符
HttpSession session = req.getSession();
//设置域对象
session.setAttribute("uname","admin");
session.setAttribute("upwd","123456");
//移出session域对象
session.removeAttribute("upwd");
//request域对象
req.setAttribute("name","zhangsan");
//请求转发
//req.getRequestDispatcher("index.jsp").forward(req,resp);
//重定向
resp.sendRedirect("index.jsp");
}
数据存储在session域中,当session对象不存在了,或者是两个不同的session对象时,数据也就不能共享了。
6.3session对象的销毁
1.默认到期时间
💞当客户端第一次请求servlet并且操作session时,session对象生成,Tomcat中session默认的存活时间为30min,即你不操作界面的时间,一旦有操作,session会重新计时。
2.自己设定到期时间
除了以上的修改方式,我们还可以在程序中自己设定session的生命周期,通过
3.立即失效
session.invalidate();
4.关闭浏览器
5.关闭服务器
session.setMaxInactiveInterval(15);
public class Session03 extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//获取会话标识符
HttpSession session = req.getSession();
//设置域对象
session.setAttribute("uname","admin");
//session 对象的最大不活动时间
System.out.println("session 对象的最大不活动时间:" + session.getMaxInactiveInterval());
//修改最大不活动时间
session.setMaxInactiveInterval(15); // 15秒失效
//立即销毁
// session.invalidate();
//关闭浏览器失效(session底层是cookie,cookie关闭浏览器就失效)
}