Servlets

server applet 运行在服务器端的小程序

WebServlet

使用

public class MyServlet implements Servlet{   ...    @Override    public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {        servletResponse.getWriter().println("hello world");    }    ...}
<servlet>    <servlet-name>MyServlet</servlet-name>    <servlet-class>wang.ismy.web.MyServlet</servlet-class></servlet><servlet-mapping>    <servlet-name>MyServlet</servlet-name>    <url-pattern>/*</url-pattern></servlet-mapping>

原理

生命周期方法

被创建:执行init方法,只执行一次

* Servlet什么时候被创建?            * 默认情况下,第一次被访问时,Servlet被创建            * 可以配置执行Servlet的创建时机。                * 在<servlet>标签下配置                    1\. 第一次被访问时,创建                        * <load-on-startup>的值为负数                    2\. 在服务器启动时,创建                        * <load-on-startup>的值为0或正整数        * Servlet的init方法,只执行一次,说明一个Servlet在内存中只存在一个对象,Servlet是单例的            * 多个用户同时访问时,可能存在线程安全问题。            * 解决:尽量不要在Servlet中定义成员变量。即使定义了成员变量,也不要对修改值

提供服务:执行service方法,执行多次

* 每次访问Servlet时,Service方法都会被调用一次。

被销毁:执行destroy方法,只执行一次

* Servlet被销毁时执行。服务器关闭时,Servlet被销毁        * 只有服务器正常关闭时,才会执行destroy方法。        * destroy方法在Servlet被销毁之前执行,一般用于释放资源
sequenceDiagram    客户端 ->> Servlet容器: 发送请求    Servlet容器 ->> Servlet容器: 解析请求    Servlet容器 ->> Servlet: 创建实例    Servlet容器 ->> Servlet: 调用init()    Servlet容器 ->> Servlet: 调用service()    Servlet ->> Servlet容器: 输出响应    Servlet容器 ->> 客户端: 返回响应    Servlet容器 ->> Servlet: 调用destory()

Servlet3.0

@WebServlet("/*")

体系结构

批注 2019-08-09 093125

配置

路径定义规则:

Request

体系结构

request对象继承体系结构:            ServletRequest        --    接口            |    继承        HttpServletRequest    -- 接口            |    实现        org.apache.catalina.connector.RequestFacade 类(tomcat)

方法

请求转发

req.getRequestDispatcher("/404")                .forward(req,resp);

共享数据

request域:代表一次请求的范围,一般用于请求转发的多个资源中共享数据

Response

方法

* 重定向的特点:redirect                1\. 地址栏发生变化                2\. 重定向可以访问其他站点(服务器)的资源                3\. 重定向是两次请求。不能使用request对象来共享数据            * 转发的特点:forward                1\. 转发地址栏路径不变                2\. 转发只能访问当前服务器下的资源                3\. 转发是一次请求,可以使用request对象来共享数据

乱码问题

PrintWriter pw = response.getWriter();获取的流的默认编码是ISO-8859-1

//设置编码,是在获取流之前设置response.setContentType("text/html;charset=utf-8");

ServletContext

获取:

获取MIME类型

System.out.println(getServletContext().getMimeType("a.jpg"));

域对象:共享数据

获取文件真实路径

Servlet 过滤器(Filter)

一般用于完成通用的操作。如:登录验证、统一编码处理、敏感字符过滤

@WebFilterpublic class LoggingFilter implements Filter {    @Override    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {        //...    }}

也可以不适用注解使用如下xml配置

<filter>    <filter-name>demo1</filter-name>    <filter-class>wang.ismy.javaee.LoggingFilter</filter-class></filter><filter-mapping>    <filter-name>demo1</filter-name>    <!-- 拦截路径 -->    <url-pattern>/*</url-pattern></filter-mapping>

执行流程

生命周期方法

拦截方式配置:资源被访问的方式

@WebFilter(value = "/*",dispatcherTypes = DispatcherType.ERROR)

过滤器链

事件监听器(Listener)

异步支持

@WebServlet(urlPatterns = "/hello",asyncSupported = true)public class MyServlet extends HttpServlet {    @Override    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {        AsyncContext async = req.startAsync();        async.addListener(new AsyncListener() {            @Override            public void onComplete(AsyncEvent asyncEvent) throws IOException {                asyncEvent.getSuppliedResponse().getWriter().write("jntm");            }            //...        });        new Thread(()->{            try {                Thread.sleep(1000);            } catch (InterruptedException e) {                e.printStackTrace();            }            async.complete();        }).start();    }}

非阻塞IO

AsyncContext async = req.startAsync();ServletInputStream inputStream = req.getInputStream();inputStream.setReadListener(new ReadListener() {    @Override    public void onDataAvailable() throws IOException {        byte[] bytes = new byte[1024];        while (inputStream.isReady() && inputStream.read(bytes)!=-1){            System.out.println(new String(bytes));        }        async.complete();    }    @Override    public void onAllDataRead() throws IOException {        async.complete();    }    @Override    public void onError(Throwable throwable) {        throwable.printStackTrace();        async.complete();    }});

WebFragment

可以对XML配置进行分区

安全

错误映射

<error-page>    <error-code>404</error-code>    <location>/404.html</location></error-page><error-page>    <exception-type>java.lang.RuntimeException</exception-type>    <location>/500.html</location></error-page>

文件上传

工作原理

Servlet

体系结构:

屏幕截图 2020-10-06 105912

ServletContexnt:贯穿请求的上下文

ServletConfig:传递参数集合

StandardWrapper.loadServlet() 方法创建Servlet实例

InstanceManager instanceManager = ((StandardContext)getParent()).getInstanceManager();try {    servlet = (Servlet) instanceManager.newInstance(servletClass;...

StandardWrapper.initServlet() 调用Servlet.init()

servlet.init(facade);