1、Servlet 是什么?
Servlet(Server Applet)是Java Servlet的简称,称为⼩服务程序或服务连接器,
⽤Java编写的服务器端程序,具有独⽴于平台和协议的特性,
是运⾏在 Web 服务器或应⽤服务器上的程序。
2、Servlet 的作⽤
它是作为来⾃ Web 浏览器或其他 HTTP 客户端的请求和 HTTP 服务器上的数据库或应⽤程序之间的中间层。
主要功能在于收集来⾃⽹⻚表单的⽤户输⼊,交互式地浏览和⽣成数据,还可以⽣成动态Web内容。
3、个人的理解
前端提交数据 --》 server --》具体的代码逻辑
新建一个jsp文件,执行代码后,访问这个jsp文件
这里直接复制index.jsp
运行程序,会在“Using CATALINA_BASE”文件下生成两个对应的文件(java/class)
具体路径为,
%Using CATALINA_BASE%\work\Catalina\localhost\ROOT\org\apache\jsp
假设这个test.jsp是后门的话,攻击者访问下这个test.jsp文件,就会生成(java/class)
最开始以为需要以下三步才会清理干净,
删除test.jsp后,同时删除上边两个生成的对应文件,最后重启容器
经过测试发现,只需要删除test.jsp之后,重启tomcat容器即可
生成的(java/class)会被自动清理
Servlet3.0⾥引⼊了注解;注解@WebServlet⽤来定义Web应⽤程序中的⼀个Servlet。
@WebServlet⽤来注册Servlet;name是Servlet的名字;value是通过请求的url地址
以下代码的意思是,通过访问/hello-servlet访问HelloServlet
这个value的值可以任意,比如,下边通过
"/hello", "/aaa.php"来访问这个文件,
除了上边的注解方式,还可以通过配置web.xml来设置路由
具体的配置在src/main/webapp/WEB-INF/web.xml
<servlet>
<servlet-name>helloServlet</servlet-name>
<servlet-class>com.example.demo.HelloServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>helloServlet</servlet-name>
<url-pattern>/hi</url-pattern>
</servlet-mapping>
server-name是设计一个联系的纽带
server-class是具体指向哪个class文件
url-pattern是直接对应的路由
当注解有web.xml的文件冲突时,以web.xml为准;注解会直接失效
即当注解也加了路由,web.xml也加了路由的情况,路由路径还不一样
这里一个问题是以下这个文件既没有找到注解,也没有web.xml配置,但是可以直接访问
src/main/webapp/index.jsp
直接的记录是,webapp目录下的文件可以直接访问,但是不明白为什么,
其根本原因是,tomcat默认自带的server解析的,
apache-tomcat-9.0.68\conf\web.xml
这个文件内有一些server与servlet-mapping的映射
三个步骤即:初始化------>处理请求------>销毁
创建Servlet对象后
---------->初始化(调⽤ init () ⽅法)
--------->处理/响应客户端的请求(调⽤ service() ⽅法)
--------->销毁(调⽤ destroy() ⽅法,
最后由 JVM 的垃圾回收器进⾏垃圾回 收)
init方法,
只会在第⼀次创建 Servlet 时被调⽤,在后续每次⽤户请求时不再调⽤
init可以初始化一些变量,比如mysql的链接信息等
service() ⽅法
每次服务器接收到⼀个 Servlet 请求时,都会调用该方法
destroy() ⽅法
在⻓时间没有被调⽤或者是服务器关闭时,会调⽤destroy()⽅法来销毁Servlet对象
destroy() ⽅法只会被调⽤⼀次,在 Servlet ⽣命周期结束时被调⽤。
destroy() ⽅法可以让Servlet 关闭数据库连接、停⽌后台线程、
把 Cookie 列表或点击计数器写⼊到磁盘,并执⾏其他类似的清理活动。
在调⽤ destroy() ⽅法之后,servlet 对象被标记为垃圾回收。
新建一个java文件,名称任意,
将新建的类继承Servlet类接口,
将鼠标放到放到“class”或者“test”上,将下边的方法都实现,
现在将上边描述的三个方法都增加一下输出,
启动项目,
此时没有访问test,所以下边没有任何输出,
访问test路由,
init方法和service方法被执行,
多次访问/刷新test路由,init方法不在执行,server则访访问一次,执行一次
当我们手动终止项目的时候,
destroy方法被执行,
@WebServlet(value = "/test",initParams={@WebInitParam(name="username",value="xbb"),@WebInitParam(name="age",value="20")})
String username = servletConfig.getInitParameter("username");
int age = Integer.parseInt(servletConfig.getInitParameter("age"));
System.out.println("username: "+username+"age: "+age);
上边是通过注解来初始化,下边通过web.xml
<servlet>
<servlet-name>test</servlet-name>
<servlet-class>com.example.demo.test</servlet-class>
<init-param>
<param-name>username</param-name>
<param-value>xbb</param-value>
</init-param>
<init-param>
<param-name>age</param-name>
<param-value>18</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>test</servlet-name>
<url-pattern>/test11</url-pattern>
</servlet-mapping>
值得一提的是,假设通过注解的方法也同时存在时,
这两个路由会同时生效,
在上边测试,没有初始化参数的时候,当web.xml与注解同时出现的话,注解会失效,
但是当都存在初始化参数的时候,两个都生效
但是假设当注解和web.xml声明的路由相同时,会直接报错,
先看下最初的,在init内定义了一个变量,
doget进行输出,
index.jsp
<%@ page contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" %>
<!DOCTYPE html>
<html>
<head>
<title>JSP - Hello World</title>
</head>
<body>
<h1><%= "Hello World!" %>
</h1>
<br/>
<a href="aaa.php?username=xbb&age=20">get传输参数</a><br>
<%--<form action="/aaa.php" method="post">--%>
<%-- 账号:<input name="username" type="text"><br>--%>
<%-- 年龄:<input name="age" type="text"><br>--%>
<%-- 兴趣:--%>
<%-- <input type="checkbox" name="hobby" value="song">唱--%>
<%-- <input type="checkbox" name="hobby" value="jump">跳--%>
<%-- <input type="checkbox" name="hobby" value="rap">rap--%>
<%-- <input type="submit" value="提交">--%>
<%--</form>--%>
</body>
</html>
HelloServlet
package com.example.demo;
import java.io.*;
import javax.servlet.http.*;
import javax.servlet.annotation.*;
@WebServlet(name = "helloServlet", value ={"/hello", "/aaa.php"})// "/hello-servlet",)
public class HelloServlet extends HttpServlet {
private String message;
public void init() {
message = "Hello World!";
}
//重点
public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException {
response.setCharacterEncoding("utf-8"); //如果有中乱码可以设置接收编码utf-8
String username = request.getParameter("username");
int age = Integer.parseInt(request.getParameter("age"));
System.out.println(String.format("前端传输过来的参数 username = %s age = %s",username,age));
response.setContentType("text/html");
// Hello
PrintWriter out = response.getWriter();
out.println("");
out.println("传输完成
");
out.println("");
}
public void destroy() {
}
}
index.jsp
<%@ page contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" %>
<!DOCTYPE html>
<html>
<head>
<title>JSP - Hello World</title>
</head>
<body>
<h1><%= "Hello World!" %>
</h1>
<br/>
<%--<a href="aaa.php?username=xbb&age=20">get传输参数</a><br>--%>
<form action="/aaa.php" method="post">
账号:<input name="username" type="text"><br>
年龄:<input name="age" type="text"><br>
兴趣:
<input type="checkbox" name="hobby" value="song">唱
<input type="checkbox" name="hobby" value="jump">跳
<input type="checkbox" name="hobby" value="rap">rap
<input type="submit" value="提交">
</form>
</body>
</html>
HelloServlet
package com.example.demo;
import java.io.*;
import javax.servlet.http.*;
import javax.servlet.annotation.*;
@WebServlet(name = "helloServlet", value ={"/hello", "/aaa.php"})// "/hello-servlet",)
public class HelloServlet extends HttpServlet {
private String message;
public void init() {
message = "Hello World!";
}
public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException {
response.setCharacterEncoding("utf-8"); //如果有中乱码可以设置接收编码utf-8
String username = request.getParameter("username");
int age = Integer.parseInt(request.getParameter("age"));
System.out.println(String.format("前端传输过来的参数 username = %s age = %s",username,age));
response.setContentType("text/html");
// Hello
PrintWriter out = response.getWriter();
out.println("");
out.println("传输完成
");
out.println("");
}
//关注点
public void doPost(HttpServletRequest request, HttpServletResponse response) throws IOException {
response.setCharacterEncoding("utf-8"); //如果有中乱码可以设置接收编码utf-8
String username = request.getParameter("username");
int age = Integer.parseInt(request.getParameter("age"));
System.out.println(String.format("前端传输过来的参数 username = %s age = %s",username,age));
//接受参数集合
String[] hobbys = request.getParameterValues("hobby");
for (String s : hobbys) {
System.out.println(s);
}
response.setContentType("text/html");
// Hello
PrintWriter out = response.getWriter();
out.println("");
out.println("post请求完成
");
out.println("");
}
public void destroy() {
}
}