Servlet学习笔记
文章目录
1.什么是Servlet
在前端页面中,网络中用户对后台输入的请求,后台必须理解其用户的需要并且将这个请求分配对应的处理类。
(1) Servlet(Server Applet),全称Java Servlet。是⽤Java编写的服务器端程序,其主要功能在于交互式地浏览和修改数据,⽣成动态Web内容。其中,⼴义的Servlet 是指任何实现了这个Servlet接⼝的类,将Servlet理解为后者更为确切。
(2) Servlet运⾏于⽀持Java的应⽤服务器中。从实现上讲,Servlet可以响应任何类型的请求,但绝⼤多数情况下Servlet只⽤来扩展基于HTTP协议的Web服务器。
(3) Servlet⼯作模式: ① 客户端发送请求⾄服务器 ② 服务器启动并调⽤Servlet,Servlet根据客户端请求⽣成响应内容并将其传给服务器 ③ 服务器将响应返回客户端。
2.搭建Servlet
在搭建Tomcat的基础上(Tomcat搭建方法请参照我前面的博客)后,进行如下操作即可。
2.1 将包放入前面设置好的lib目录下
2.2 进入File->Project Structure->dependencis
在lib中,设置为Provided,运行调用时方便使用。
2.3 最后创建项目即可
package web;
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.SyncFailedException;
public class TestServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("get");
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("post");
}
}
在上面的Demo中,我们继承其对象后,重写doget()
和dopost()
方法(Ctrl+o),创建了一个Servlet的继承类。
3.Servlet API
不同的对Servlet使用,一般采用的方法不一。如下图展示的是在进行不同的调用时所采用的方法。
1.在索引页输入以下代码进行试验
<html>
<head>
<title>$Title$</title>
</head>
<body>
<h1>这是我的第一个项目</h1>
<a href="test"></a>
<form action="test" method="post">
<input type="submit" value="post-test">
</form>
</body>
</html>
2.在web.xml
文件中打入如下代码
<servlet>
<servlet-name>a1</servlet-name>
<servlet-class>web.servletdemo1</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>a1</servlet-name>
<url-pattern>/test</url-pattern>
//注意上面要加上/test,没有斜杠服务器会报错滴。这是因为此时在请求地址。
</servlet-mapping>
3.在前面2.3创建的Servlet实例中一样重写如下
public class TestServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("get");
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("post");
}
}
- 首先,第3点进行对方法的重写,以完成服务器和后台之间的交互类。
- 其次,在第1点完成基本框架的写法,将其中的响应发送给xml后台。
- XML文件中对其中的Servlet类名和相应的类进行映射,如果HTML其中某一块有对应的URL响应,XML文件会对Servlet中的类名进行对比参照并进行反射。得到对应类名再调用其相应的方法。
其结果大致如下。
每当点击按钮时,在IDEA下面会出现post的响应。
4.Servlet工作原理
- Servlet接⼝定义了Servlet与servlet容器之间的契约。这个契约是:Servlet容器将Servlet类载⼊内存,并产⽣Servlet实例和调⽤它具体的⽅法。但是要注意的是,在⼀个应⽤程序中,每种Servlet类型只能有⼀个实例。
- ServletRequest中封装了当前的Http请求
- ⽤户请求致使Servlet容器调⽤Servlet的Service()⽅法,并传⼊⼀个ServletRequest对象和⼀个 ServletResponse对象。ServletRequest对象和ServletResponse对象都是由Servlet容器(例如 TomCat)封装好的
5.Servlet的生命周期
生命周期部分主要以如上图片展开。
- 在客户端首次发送第一个请求时,首先由容器解析请求。根据请求中找到对应的Servlet。首先判断该类的对象是否存在,如果存在则调取初始化方法。在Object中调用
Service()
方法,由Service()
判断客户端的请求方式。处理方式完成后,作出相应的结果返回给客户端,单词请求处理完毕。 - 再次请求时,同样判断其对象是否存在,但是不再调用
init()
方法,而是直接调取Service()
方法。 - 当服务器关闭时,调取
destroy()
方法进行销毁。
6.请求和响应
在第5点所表达的生命周期,请求和响应是其中两个很重要的对象。service()
会判断客户端的请求方式,如果是请求方式,则调用doGet()
;如果是响应方式,则调用doGet()
。
6.1 请求Request
6.1.1 String getParameter(String name)
- 根据表单组件名称获取提交数据,返回值是
String
- 此时在服务器中接收到的数据一般来说统一使用字符串格式进行。
**【实例1】**通过调用doGet()
方法获取用户名和密码
--index.jsp
<h1>这是我的第二个项目</h1>
<a href="testRequest?upass=abc&uage=18">点击我!</a>
<form action="testReuest" method="post">
账号名:<input type="text" name="username">
<input type="submit" value="提交">
</form>
--web.xml
<servlet>
<servlet-name>b1</servlet-name>
<servlet-class>web.TestRequestDemo1</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>b1</servlet-name>
<url-pattern>/testRequest</url-pattern>
</servlet-mapping>
--新建类TestRequestDemo1
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String upass=req.getParameter("upass");
String age=req.getParameter("uage");
System.out.println(upass+","+age);
}
返回结果如下:点击<a>点击我!</a>
后,IDEA会收到其中的信息。
而后,在输入框中输入仍意如下图所示,IDEA也会返回值过来。
第一个是输入123后的输出返回,第二个由于输入中文字符会产生乱码(doGet不会出现中文乱码的问题,在Tomcat8后已经解决了该问题)。
此时在重写的doPost()后面第一行再添加如下代码即可支持中文。
req.setCharacterEncoding("utf-8");
6.1.2 String[]getParamenterValues(String name)
- 它在于获取表单组件对应多个值时的请求数据
**【实例】**接下来试着用上面的方法
兴趣爱好:<input type="checkbox" name="hobby" value="basketball">篮球
<input type="checkbox" name="hobby" value="football">足球
<input type="checkbox" name="hobby" value="swimming">游泳
<input type="submit" value="提交">
- 首先在前面的基础上,添加3个复选框的功能。
String[] Hobby=req.getParameterValues("hobby");
for (String interest:Hobby){
System.out.println(interest);
}
System.out.println("That is all!");
- 其次,在重写方法
doPost()
中添加如上代码。
最后的调试运行后,选择篮球和足球后,会发生后面的事情。
basketball
football
That is all!
6.1.3 getRequestDispatcher(String path)
该方法最主要在重写方法中写入,运行编译后可跳转某一个界面。
例如在Web下写入一个test.html,跳转如下。
req.getRequestDispatcher("/test.html").forward(req,resp);
//首先前的调用调动资源自动找到/test.html
//后面的forward(req,resp)可以理解成模板,即就是这么写的
6.1.4 存值&取值
存值:request.setAttribute("key",value);
取值:request.getAttribute("key");
- 取值后需要向下转型!
//示例:
String a1=(String)request.getAttribute("uname")
6.2 响应Response
6.2.1 常用方法
void addCookie(Cookie var1);
void sendRedirect(String var1);
发送一条响应码,将浏览器跳转到指定位置。
【示例】
resp.sendRedirect(s:"/my.html") //跳转
resp.setContentType("text/html") //响应的内容可以是文本,也可以是html页面
resp.addCookie();//设置cookie值存储胡
PrintWriter writer = resp.getWriter();//得到一个给前端输出信息的输出流对象
7.转发和重定向(了解)
在第6点的讲解时,同时对Request
和Response
中进行跳转页面的方法介绍。
其中,使用req.getRequestDispatcher()
方法称为转发;使用resp.sendRedirect(s:"/my.html")
称为重定向。
两者的区别如下:
- 前者括号内部是
path
,后者方法内部是String
。 - 转发属于⼀次请求⼀次响应(既有页面地址,又有页面内容)。重定向属于两次请求(地址栏修改了两次)两次响应。其中,后者具体表现在比如在进行一次地址的跳转请求时,第一次请求响应后会出现”没有内容“,第二次对地址的请求后才会返回获取相对应的内容给客户端。
- 转发时地址栏显示的是请求⻚⾯的地 址,request数据可以保存。重定向时地址栏会改变,request中存储的数据会丢失(因为一次响应无法获取目标地址的响应内容)。
8.会话session
会话的出现在于,每当进行请求的时候,由于是一次请求一次响应,在进行多次请求时就需要调用多次Request
。并且Request
存值只能在单次请求时保存,并且加上一次请求一次响应的特性,所保存的数据无法跨页面。所以在请求时会出现一些麻烦。
会话的出现使得其能包含若干个request
,并且能够在多个页面上共享。
会话:例如用户打开浏览器到关闭浏览器,期间访问服务器的过程称为一次会话。
8.1 常用方法
void setAttribute(String key,Object value)
以key/value的形式保存对象值,将数据存储在服务器端
Object getAttribute(String key)
通过key获取对象值
void invalidate()
设置session对象失效
String getId()
获取session中的id,当第一次登录成功后,session会产生一个唯一的id。浏览器之后的访问时如果当前id值等于前面的id,说明此时访问的是同一个会话。
void setMaxInactiveInterval(int interval)
设定session的⾮活动时间。具体表现在登录一段时间未进行任何操作,就要进行重新登陆。此时就是设定了非活动时间。
【示例】比如在重写的doPost()
中使用其中的方法
HttpSession session=req.getSession(); //首先返回一个session对象
session.setAttribute("k1","aaa"); //使用session对象进行存储对象
session.getAttribute("k1"); //取出来
session.removeAttribute("k1"); //删除掉
String id=session.getId(); //获取会话id值
System.out.println(id); //输出id
在前面的示例的基础上,同样的编译运行调试过程。
运行结果如下所示。
5519672D144FBDC3D581A935670C765F
小艾扶
basketball
football
swimming
That is all!
11-Jun-2021 09:34:29.874 信息 [localhost-startStop-1] org.apache.catalina.startup.HostConfig.deployDirectory Deploying web application directory [C:\Program Files\Java\apache-tomcat-8.5.34\webapps\manager]
11-Jun-2021 09:34:29.925 信息 [localhost-startStop-1] org.apache.catalina.startup.HostConfig.deployDirectory Deployment of web application directory [C:\Program Files\Java\apache-tomcat-8.5.34\webapps\manager] has finished in [50] ms
post
5519672D144FBDC3D581A935670C765F
小艾扶
basketball
football
swimming
That is all!
同样的,可以将之前写的示例代码删掉,只留下上面刚刚重写的方法进行示例展示也可以。
【补充】session失效的方式
invalidate()
removeAttribute("key")
- 直接关闭浏览器。
9.初始化参数获取
初始化参数主要在于维护上面的灵活使用。在针对前面的示例中,我们使用过req.setCharacterEncoding("utf-8");
。虽然在现阶段的使用没有出现太多问题,但是在后续的学习上必然需要进行更严谨的设置。
实现方式1:在xml文件上定义初始化参数
1.web.xml
中定义初始化参数
<servlet>
<servlet-name></servlet-name>
<servlet-class></servlet-class>
<init-param>
<param-name>encoding</param-name>
<param-value>utf-8</param-value>
</init-param>
</servlet>
2.servlet中获取初始化参数方法。
public void init(ServletConfig config) throws ServletException {
encoding= config.getInitParameter("encoding");//在前面的xml文件设置时添加的<param-name></param-name>,将其获取出来
sout~//输出上面的代码即可
}
注意:这种⽅式的初始化参数仅限于当前servlet中使⽤。
实现方式2:全局初始化配置参数
1.在xml文件上同样添加以下代码
<context-param>
<param-name>bianma</param-name>
<param-value>utf-8</param-value>
</context-param>
此时不同的是,该标签是跟Servlet标签同等级的。所以进行插入时记住这一点。
2.获取数据
public void init(ServletConfig config) throws ServletException {
bianhao=config.getServletContext().getInitParameter("bianma"); //获取Context标签下的param-value信息
System.out.println(bianhao);
10.Servlet 3.0
了解Servlet3.0,首先了解注解和注释的含义。
**注解:提供给程序进行读取的信息。**比如@Override
注释:提供给程序员看的信息。
- 从Servlet3.0开始,配置Servlet⽀持注解⽅式,但还是保留了配置web.xml⽅式.
- 所以,使⽤Servlet有两种⽅式: (1)Servlet类上使⽤@WebServlet注解进⾏配置 (2)web.xml⽂件中配置
【实例如下】
@WebServlet(urlPatterns="/stu/test",name="myname",initParams={
@WebInitParam(name="init-stu",value="myinitparams") //设置初始化参数
},loadOnStartup=1)
init()//重写方法一下以便测试
以上是Servlet的大致学习内容,请大家批评指正~