# Servlet applet
> Servlet就是一个接口,定义了Java类被浏览器访问到(tomcat识别)的规则;我们需要自定义类,实现Servlet接口复写方法。
1. 创建JavaEE项目
2. 建一个包,定义一个类,实现Servlet中的接口
- `void destroy()`: 服务被关闭之前执行一次,用于释放资源
- `ServletConfig getServletConfig()`: 获取Servlet的配置对象
- `void init(ServletConfig config)`: 服务启动或者第一次访问时被创建,初始化
- `void service(ServletRequest req, ServletResponse res)`:处理请求
- `String getServletInfo()`: 获取Servlet的版本,作者等信息。
```
// 在service中添加一句
System.out.println("某个浏览器在访问我!");
```
3. 根据约束配置`web.xml`:【得写在根标签里面】
```
<servlet>
<servlet-name>Server</servlet-name>
<servlet-class>cn.lc.server.Server</servlet-class> -- 全类名
</servlet>
<servlet-mapping>
<servlet-name>Server</servlet-name>
<url-pattern>/server</url-pattern> -- 虚拟路径
</servlet-mapping>
```
## 二、Servlet执行流程
@@@@@@@@@@@@@@@@@@@@@@@@@@@ Servlet执行原理.bmp
1. 当服务器接受到客户端浏览器的请求后,会解析请求URL路径,获取访问的Servlet的资源路径
2. 查找web.xml文件,是否有对应的`<url-pattern>`标签体内容。
3. 如果有,则在找到对应的`<servlet-class>`全类名
4. tomcat会将字节码文件加载进内存,并且创建其对象【反射机制】
5. 调用其方法--`service`
## 三、Servlet的生命周期方法【vue中的钩子函数也是这样干的】
1. **`init`**:被创建:执行 **`init`** 方法,只执行一次。【初始化方法嘛!】
- Servlet创建时机:
- 默认情况下,第一次被访问时Servlet被创建
- 可以手动配置执行Servlet的创建时机【在`<servlet>`标签下配置】
1. 第一次被访问时创建:`<load-on-startup>-1</load-on-startup>`的值为负数
2. 在服务器启动时创建:`<load-on-startup>0</load-on-startup>`的值为非负数
- Servlet的init方法,只能执行一次,Servlet在内存中只存在一个对象,**Servlet是单例模式的**!
- 多个用户同时访问时,可能存在线程安全问题。
- **为了防止线程安全问题,尽量不要在Servlet中定义成员变量,如果非要定义,也不要去修改值!**
2. **`service`**:提过服务的方法,**`service`**,每次接受到相关请求,这个方法都会被调用来处理请求
3. **`destroy`**:被销毁执行此方法,只执行一次
1. Servlet被销毁时执行。服务器关闭是,Servlet被销毁
2. 只有服务器正常关闭时,才会执行destroy方法
3. destroy方法在Servlet被销毁之前执行,一般用于释放资源。
## 四、Servlet3.0介绍
> **支持注解配置。可以不需要`web.xml`了**。
### 使用步骤
1. 创建JavaEE项目,选择Servlet3.0及以上,不用勾选创建`web.xml`
2. 定义一个类,实现Servlet接口
3. 复写方法
4. 在类的上面添加`@WebServlet`注解,进行配置【 **原理是通过注解获取使用了该注解的全类名** 】
- `@WebServlet("资源路径[对应的路由]")`
> **【通过注解名获取使用了该注解的所有类的全类名的思路】**:递归遍历src路径下的所有包,找到所有的.class文件,获取其文件上的注解,判断是否有对应的注解,如果有则将全类名存入一个列表,最后将这个列表返回即可!
> 估计Tomcat也是使用类似的机制玩儿的。
```
@WebServlet("/index")
public class Index implements Servlet {
...
```
@WebServlet注解【接口】,源码如下
```
@Target({ElementType.TYPE}) //目标可以作用在类上面
@Retention(RetentionPolicy.RUNTIME)// 注解保留在运行时
@Documented // 可以生成文档
public @interface WebServlet {
String name() default ""; //相当于<Servlet-name>,不用管,只是一个对应的关系
String[] value() default {}; // 代表urlPatterns()属性配置【注解默认赋值就是给它!】
String[] urlPatterns() default {}; // 相当于<url-pattern>
int loadOnStartup() default -1; // 相当于<load-on-startup>
WebInitParam[] initParams() default {};
boolean asyncSupported() default false;
String smallIcon() default "";
String largeIcon() default "";
String description() default "";
String displayName() default "";
}
```
## 五.Servlet的体系结构
**`Servlet`** -*父接口*--
- **`GenericServlet`** --*子抽象类*--:将Servlet接口中其他的方法做了默认空实现,只将service()方法作为抽象将来定义Servlet类时,可以继承GenericServlet,实现service()方法即可
- **`HttpServlet`【推荐使用】** --*孙抽象类*--:对http协议的一种封装,封装了用户的请求判断方式【get,post方法】简化操作
- 定义类继承HttpServlet;
- 复写doGet/doPost方法即可
- HttpServlet抽象类部分源码
```
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String method = req.getMethod();
long lastModified;
if (method.equals("GET")) {
...
this.doGet(req, resp);
...
} else if (method.equals("POST")) {
this.doPost(req, resp);
}...
}
```
### 六. Servlet相关配置
#### urlpartten:Servlet访问路径
1. 一个Servlet可以定义多个访问路径【不建议这样写】:`@WebServlet({"/d4","/dd4","/ddd4"})`
2. 路径定义规则
- ` /xxx`:路径匹配
- `/xxx/xxx`:多层路径,目录结构
- `*`:匹配所有,优先级很低【不用】
- `*.do`:扩展名匹配,【注意:**'*'号前面别加'/'**】
|
|