03.Servlet applet

Servlet applet

一、Servlet的概念以及入门

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("某个浏览器在访问我!");
  1. 根据约束配置web.xml:【得写在根标签里面】

    Server
    cn.lc.server.Server -- 全类名



    Server
    /server -- 虚拟路径

二、Servlet执行流程

Servlet执行原理.png
  1. 当服务器接受到客户端浏览器的请求后,会解析请求URL路径,获取访问的Servlet的资源路径
  2. 查找web.xml文件,是否有对应的标签体内容。
  3. 如果有,则在找到对应的全类名
  4. tomcat会将字节码文件加载进内存,并且创建其对象【反射机制】
  5. 调用其方法--service

三、Servlet的生命周期方法【vue中的钩子函数也是这样干的】

  1. init:Servlet被创建【单例模式】:执行 init 方法,只执行一次。【初始化方法嘛!】

    • Servlet创建时机:
      • 默认情况下,第一次被访问时Servlet被创建
      • 可以手动配置执行Servlet的创建时机【在标签下配置】
        1. 第一次被访问时创建:-1的值为负数
        2. 在服务器启动时创建:0的值为非负数
    • 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("资源路径[对应的路由]")

【通过注解名获取使用了该注解的所有类的全类名的思路】:专门写一个类加载器,递归遍历项目路径下的所有包,找到所有的.class文件,获取其文件上的注解,判断是否有对应的注解@WebServlet,如果有则将全类名存入一个列表,最后将这个列表返回即可!
估计Tomcat也是使用类似的机制玩儿的。

@WebServlet("/index")
public class Index implements Servlet {
...

服务器启动时创建

@WebServlet(value="/httpindex",loadOnStartup=1)
public class Index implements Servlet {
    @Override
    public void init() throws ServletException {
        System.out.println("我随着服务器的启动而启动!");
    }
    ...

@WebServlet注解【接口】,源码如下

@Target({ElementType.TYPE})  //目标可以作用在类上面
@Retention(RetentionPolicy.RUNTIME)// 注解保留在运行时
@Documented // 可以生成文档
public @interface WebServlet {
    String name() default "";  //相当于,不用管,只是一个对应的关系
    String[] value() default {};  // 代表urlPatterns()属性配置【注解默认赋值就是给它!】
    String[] urlPatterns() default {}; // 相当于
    int loadOnStartup() default -1; // 相当于
    WebInitParam[] initParams() default {};
    boolean asyncSupported() default false;
    String smallIcon() default "";
    String largeIcon() default "";
    String description() default "";
    String displayName() default "";
}

五.Servlet的体系结构

Servlet -父接口--

  • GenericServlet --子抽象类【与协议无关的Servlet,设计上前瞻性的考虑】--:将Servlet接口中其他的方法做了默认空实现,只将service()方法作为抽象将来定义Servlet类时,可以继承GenericServlet,实现service()方法即可

    • HttpServlet【推荐使用,HTTP协议的Servlet】 --孙抽象类--:对http协议的一种封装,service方法封装了用户的请求判断方式【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:扩展名匹配,【注意:这里的 ''号前面别加'/'*】
  3. 完全路径匹配,以/开头:

    • /xxx/xxx/xxx
  4. 目录匹配,以/开头,以*结尾:

    • /aaa/*
  5. 扩展名匹配:不能以/开头,以*开头

    • *.action

七、总结

  • 生命周期:默认第一次访问的时候创建Servlet对象,执行init方法,每次请求过来之后执行Service方法,在service方法内部根据请求方式的不同调用不同的doXXX方法,Get请求调用doGet方法,Post请求调用doPost方法,当服务器关闭或者项目被移除了就销毁Servlet对象,执行destroy方法,初始化和销毁方法都只执行一次;Servet是单例,也就是说在Servlet整个生命周期中,Servet对象有且仅有一个
  • http协议默认端口:80;超文本传输协议,基于请求和响应模型,请求先有,后有响应,一次请求只会有一次响应
  • 程序优化思想:在HttpServlet实现子类的注解上添加loadOnStartup=1;将初始化操作放在服务器启动的时候操作【spring框架的配置文件就是这样干的】
  • 项目的虚拟路径最好和项目名相同或者不写
  • get请求的请求参数在请求行的请求路径后面;get请求方式没有请求体
  • 请求头:
    • key:value结构的,一般一个key对应一个value,也有一个key对应多个value的情况
    • user-agent:浏览器的版本信息
    • referer:当前这次请求从哪里发过来------防止盗取链接,做统计工作
  • GET和POST的区别(面试点)
    1. get方式提交的数据显示在地址栏中,准确的说是在请求行中的请求路径后面,没有请求体,而post方式提交的数据不会显示在地址栏中,提交的数据在请求体中,地址栏中也可以传递参数
    2. get方式url的长度有限制,而post没有限制
    3. post方式提交数据相对安全
  • 获得请求方式:
String method = request.getMethod()
获取虚拟路径(项目名):
String contextPath = request.getContextPath();
获得URI/URL:
String uri = request.getRequestURI();
StringBuffer sb = request.getRequestURL();
获得远程ip地址:
String ip = reqeust.getRemoteAddr();
  • 获取请求提交的参数
获得单个值:
String value = reqeust.getParameter(String name);
获得一组值(复选框):
String[] values = request.getParameterValues(String name);
获得所有的值封装到map集合中:
Map map = request.getParameterMap();

  • 提交参数乱码问题的解决
get:tomcat8及以上已自主解决
post:
request.setCharacterEncoding("UTF-8"):
注意:这句话一定要写在获取参数之前
  • 作为域对象存取数据
    作用的范围: 一次请求响应的范围
    什么时候创建:服务器收到客户端请求时创建request对象
    什么时候销毁:服务器对当前这次请求做出响应后销毁
request.setAttribute(String key,Object value);
Object value = request.getAttribute(String key);
request.removeAttribute(String key)
  • 转发特点写法
    1. 浏览器地址栏不变
    2. 只能在当前项目内部跳转
    3. 转发是一次请求一次响应
    4. 转发的路径编写:不需要带虚拟路径
request.getRequestDispatcher("转发路径").forward(request,response);

你可能感兴趣的:(03.Servlet applet)