本文详尽的介绍了servlet的相关知识,包含servlet基础与tomcat相关知识、servlet声明周期原理及其应用、servlet多请求携带数据、以及单个servlet如何处理多请求的相关知识!
文章目录
一、servlet基础-tomcat
1、Servlet是什么?
- Servlet是什么
- Servlet(Server Applet)是Java Servlet的简称,称为小服务程序或服务连接器,泛指用 Java编写的服务器端程序。在编程过程中也指一切 实现了Servlet接口的类(约定以Servlet结尾命名)
servlet
接口定义的是一套处理网络请求的规范
,所有实现servlet的类,都需要实现它的那五个方法,其中最主要的是两个声明周期方法init()和destory(),还有一个处理请求的service()。
- Servlet请求处理
- servlet是一个规范,那实现了servlet的类,就能处理请求了吗?
不能
- 请求是怎么来到servlet的呢?
- 答案是web服务器,比如我们最常用的Tomcat。servlet都是部署在一个容器中的,不然你的servlet根本不起作用。
Tomcat才是与客户端直接打交道的家伙
- 它监听了端口,请求过来后,根据URL等信息(
<url-pattern>
),确定要将请求交给哪个servlet去处理,然后调用那个servlet的service方法,service方法返回一个response对象,Tomcat再把这个respond返回给客户端。
- 它监听了端口,请求过来后,根据URL等信息(
- servlet是一个规范,那实现了servlet的类,就能处理请求了吗?
2、安装配置tomcat
2.1 tomcat目录结构
bin
: 该⽬录存放的是可执⾏的⼆进制⽂件(startup.bat⽤于启动Tomcat、shutdown.bat⽤于停⽌Tomcat)conf
:存放的是Tomcat的配置⽂件(server.xml可以配置Tomcat的端⼝,web.xml)lib
此⽬录存放了Tomcat服务器运⾏web项⽬所需的基础类库(jar包)logs
: 存放Tomcat服务器的运⾏⽇志、记录了服务器启动、运⾏异常及关闭等操作的记录webapps
:存放Tomcat管理的web项⽬的⽬录
,此⽬录中默认部署了Tomcat管理器等⼏个web项⽬work
: 运行时生成的文件,最终运行的文件都在这里。- (当客户端用户访问一个JSP文件时,Tomcat会 通过JSP生成Java文件,然后再编译Java文件生成class文件,生成的java和class文件都会存放到这个目录下。)
2.2 重装Tomcat
-
tomcat 基于jdk运行的
- java_home
- classpath
- path
-
需要清理操作系统的环境变量 catalina字样 (
重新安装时需要清除
) -
关于服务:ip地址+端口号 端口唯一必须遵守规则
-
tomcat默认端口:8080 代表 tomcat-HOME/webapps/ROOT(没有指定具体项目名时,默认访问ROOT项目)
2.3 部署一个web项目
- 手工部署一个静态网站
- 在tomcat/webapps目录下新建应用目录(应用名);
- 在该目录下建/images、/js、/css
- 将写好的html文件放置于该目录下
- 打包war包-项目部署
可以将web程序打包为war包,将其放置到tomcat/webapps
- 启动tomcat后,即可以进行访问(tomcat会默认将其解压缩为文件夹)
3、Servlet规范的引入
- jdk版本支持
- javaEE7支持servlet3.1规范
- javaEE8支持servlet4.0规范
- 以前的版本 2.0、2.1\2.2.\2.3\2.4\2.5\3.0\3.1
- 应用程序中配置文件web.xml 因为规范版本不同,也有不同的设置
- servlet编写规则也因为选择的servlet规范版本变化
- 不同版本的tomcat支持的servlet规范不同
4、如何编写一个servlet类
4.1 作用
- 相比于套接字网络编程,其
更方便的处理http请求
4.2 规范
-
首先,一个Servlet类必须继承HttpServlet(接口或抽象类)
-
其次,重写其service方法(doGet\doPost)
-
再次,将servlet在web.xml注册
-
<!-- 注册自定义servlet--> <servlet> <servlet-name>my</servlet-name> <!-- 全限定路径名--> <servlet-class>com.xcu.web.MyFirstServlet</servlet-class> </servlet> <servlet-mapping> <!-- servlet在web容器中的对象名 (必须与上面完全一致)--> <servlet-name>my</servlet-name> <!-- 本servlet对外暴露的请求path--> <url-pattern>/login</url-pattern> </servlet-mapping>
注意:servlet与servlet-mapping 不能交叉
-
最后,编写html页面表单 发请求
5.难点
- servlet中的处理方法
- 方法名固定:doGet、doPost、service
- 方法的入参固定: 第一个参数类型:HttpServletRequest对象;第二参数类型:HttpServletResponse对象
- 方法的抛出异常:ServletException 和IOException
- 方法的返回值是:void
二、Servlet生命周期原理及其应用
1、servlet处理请求的流程
- 启动工程,系统会使用该工程的web.xml初始化此项目(包括外部访问url,创建一个servlet对象的名称的引用(句柄))
- 当浏览器访问本服务器上的应用时,应用会自动调用默认的欢迎页面呈现客户
- 用户点击欢迎页面提交表单按钮(以添加新用户信息为例)
- 浏览器会调用该表单的onsubmit方法(进行校验) ,并向由( url地址 +form.action组成)的新url(ip:端口/应用名/请求path)发出请求
- tomcat服务器接收请求,并解析它,
- 在web.xml的servlet-mapping中查找和请求path路径匹配的 url-pattern节点
- 再继续找url-pattern的兄弟 servlet-name的值(对象名)
- 如果servlet-name所指的对象不存在,则再去servlet节点中查找同名项的兄弟节点servlet-class
- 拿到servlet-class的文本值
使用反射创建此对象,并将其以servlet-name 对象名
- 系统再调用其service方法处理请求,并响应之;
- 如果第二次对此服务path进行请求,则因为以servlet-name为名称的对象已存在(
唯一实例
),则直接调用其service方法处理请求;
2、servlet对象产生过程
servlet对象由web容器(tomcat、weblogic、websthere、jboss)负责产生
- 使用load-on-startup节点可以设置servlet创建的时机,含有load-on-startup节点则在服务器启动时创建servlet对象;如果不含有,则会在首次请求时创建对象
- 再由容器调用init方法初始化servlet对象
- 容器调用service方法提供服务(
如果没有(重写)service,则实际是执行父类的service方法(子类继承过来的service方法),在其中会根据请求的method调用doGet或doPost方法服务(实际上调用的是子类的)
) - 下次,请求来时,直接对外提供服务,不会创建servlet对象
(唯一实例)
- 最后,当容器关闭时,容器会先调用servlet的destroy方法再关闭
3、servlet处理请求多个场景
-
请求数字
- 所有的表单提交的数据均是字符。因此,必须要进行类型转换(常见的有Integer.parseInt\Doble.parseDouble\Long.parseLong\Float.parseFloat)
- 需要判空,应为“”或null无法转数字(可以使用三元运算符)
-
请求日期
<input type="datetime-local" name="birthday" />
- 服务端获取日期字符串,需要使用SimpleDateFormat类的函数转换
-
请求中文
- req.setCharacterEncoding(“UTF-8”); //上行编码
- resp.setContentType(“text/html;charset=UTF-8”);//下行转码
- 请求的
method=POST
-
在不同请求模式下中文转码
- get请求乱码必须使用String构造手动转码
4、响应方式
- 请求转向
- 携带数据,整个过程只有一次浏览器请求
- 由req进行处理
req.getRequestDispatcher("页面或servlet").forward(req,resp);
- 重定向
- 不携带数据,整个过程有两次浏览器请求
- 由resp进行处理
resp.sendRedirect("页面或servlet");
- servlet经过重定向告诉浏览器一个新地址,浏览器重新请求新地址(地址栏发生变化)
- 注意事项:
- 在添加、修改、删除之后只能是
重定向
,不能使用请求转发
,否侧刷新
时会重复执行上一步操作(可能会抛出异常) - 原因(以插入servlet转向查询servle为例):
- 使用
重定向
在整个业务流程中会触发两次
浏览器请求,刷新时只会出触发后一次查询的
浏览器请求 - 而
请求转发
在整个业务流程中只会触发一次
浏览器请求,刷新时会触发整个业务流程(包括插入和查询)
- 使用
- 在添加、修改、删除之后只能是
5、EL表达式与JSTL表达式特性
1. EL表达式特性
- EL表达式取数据自动探空
- EL表达式只简化了输出,没有提供任何逻辑代码功能(if、for、while都不含有)
2. JSTL表达式特性
- 自动类型转换
- 自动探空
- 提供任何逻辑代码功能(if、for、while都含有,常配合EL表达式配合使用)
6、浏览器请求注意事项
- 浏览器会将页面所有标签,按照层级将其构成一个对象树,每一个标签节点时一个对象,其每个对象还有属性和方法,js可以对其进行操作
- 表单提交的任何数据都是string类型(eg: text文本框提交的数据是string类型)
- get请求会将地址后携带的值清除,并携带自己本身的表单值
三、Servlet进阶应用
1、jsp-servlet 处理逻辑
2、get-post携带数据请求
- 代码示例:
<form action="teacher?method=addTeacher" method="post">
姓名:<input type="text" name="tname" /><br/>
性别:<input type="radio" name="gender" value="男" />男
<input type="radio" name="gender" value="女"/>女<br/>
入职日期:<input type="text" name="workDate"/><br/>
教授年级:<input type="text" name="workGrade"/><br/>
<input type="submit" value="添加"/>
</form>
- 请求:
- 表单属性
action="teacher?method=addTeacher"
的请求url携带参数,可以看作是get
方式请求,而其属性method="post"
提交方式为post
请求,所以此种请求方式可以看作是get-post携带数据请求
- 表单属性
- 数据获取:
- 以
get-post携带数据请求
的方式,在被请求的servlet
中无论是url后携带的参数(get请求携带参数
),还是通过post请求携带参数
(请求体中携带的参数),均可以使用getParamter("xxx")
获取参数
- 以
3、一个servlet处理多个请求
-
核心思想
- 在请求的url后携带参数
method=xxx
,并在所请求的servlet中编写相同参数值名称的方法,处理相应的请求 - 在后端的
servlet的service方法中获取method参数值
,并通过反射
获取到方法对象
- 通过反射调用执行相应的方法
- 在请求的url后携带参数
-
示例
- 请求
<form action="teacher?method=addTeacher" method="post">
姓名:<input type="text" name="tname" /><br/>
性别:<input type="radio" name="gender" value="男" />男
<input type="radio" name="gender" value="女"/>女<br/>
入职日期:<input type="text" name="workDate"/><br/>
教授年级:<input type="text" name="workGrade"/><br/>
<input type="submit" value="添加"/>
</form>
- 反射获取方法对象
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 1.设置编码格式
req.setCharacterEncoding("UTF-8");
resp.setContentType("text/html;charset=UTF-8");
// 利用反射执行对应的请求方法
String methodName = req.getParameter("method");
try {
Method method = this.getClass().getDeclaredMethod(methodName, HttpServletRequest.class, HttpServletResponse.class);
// 执行方法
method.invoke(this, req, resp);
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
- 处理请求对应的方法
// 增加
private void addTeacher(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 2.
String tname = req.getParameter("tname");
String gender = req.getParameter("gender");
String workDate = req.getParameter("workDate");
String workGrade = req.getParameter("workGrade");
Teacher teacher=new Teacher(0,tname,gender,workDate,workGrade);
// 3.
TeacherService teacherService=new TeacherServiceImpl();
boolean b = teacherService.addTeacher(teacher);
// 4.
if (b){
resp.sendRedirect("teacher?method=findAll");
}else {
resp.sendRedirect("error.jsp");
}
}