Servlet运行机制

Servlet的单例模式

当多个客户端请求在同一时刻同时访问一个Servlet时该怎么办 ?

为每个请求都创建一个Servlet对象

  1. 不存在多线程并发访问的问题,但是会造成内存的巨大压力
  2. 频繁的创建和销毁对象会占用大量cpu资源

只创建一个Servlet对象,同时被多个线程共享

  1. 多线程并发问题可通过编程方式解决

编程验证Servlet的单例特性

多次请求该地址,count一直累加,说明只创建一个对象

@WebServlet("/count")
public class CountServlet extends HttpServlet {
    private int count;
    @Override
    protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        request.setCharacterEncoding("charset=utf-8");
        PrintWriter out = response.getWriter();
        out.write("<h3>当前计数器:" + (count++) + "</h3>");
        out.flush();
        out.close();
    }
}

Servlet生命周期的三个方法

  • 1、init(),初始化对象,执行一次
  • 2、service(),提供服务,多次使用
  • 3、destroy(),销毁对象,只执行一次
@WebServlet(value = "/count", initParams = {@WebInitParam(name = "name", value = "张三")
        , @WebInitParam(name = "sex", value = "男")})//servlet对象初始化参数,私有参数
public class CountServlet extends HttpServlet {
    private int count;

    /**
     * 多次调用提供请求服务
     */
    @Override
    protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        request.setCharacterEncoding("utf-8");
        PrintWriter out = response.getWriter();
        out.write("<h3>当前计数器:" + (count++) + "</h3>");
        out.flush();
        out.close();
    }

    /**
     * 销毁对象的方法
     * 只执行一次
     */
    @Override
    public void destroy() {
        System.out.println("servlet 对象销毁");
    }

    /**
     * 生命周期的初始化方法
     * 只执行一次
     */
    @Override
    public void init(ServletConfig config) throws ServletException {
        super.init(config);
    }
}

小结

  • servlet生命周期:
  • 单例模式,一个servlet类只创建一个对象,在客户端第一次请求时在服务器创建,用来处理客户端请求。
  • 内存不足或者服务器关闭时销毁
  • request生命周期:
  • 多例模式,每次请求创建一个对象,当请求到达服务器时由服务器创建,当服务器响应结束后返回客户端时销毁。
  • session生命周期
  • 客户端请求服务器调用getSession方法时由服务器创建,有效期超时或者服务器关闭销毁。
  • context生命周期
  • 单例模式:服务器启动时创建,服务器关闭时销毁。
  • Cookie生命周期
  • 服务器响应客户时由服务器创建,响应结束后返回返回客户端浏览器保存对象。
  • 如果设置有效期,有效期结束后由浏览器删除,默认是关闭服务器则删除。

ServletConfig对象

由tomcat创建并传递给init函数
由HttpServlet的init函数负责保存在成员变量中
用于读取程序员配置在web.xml中的配置信息

初始化参数由一个名字和一个值组成 。
在Servlet中通过继承下来的getServletConfig()方法获得ServletConfig对象
通过servletConfig对象的getInitParameter(“”)获得web.xml中的配置信息
(系统自动创建Servlet对象,自动调用getServletConfig()方法来获取对象)
语法:

<servlet>
	 <servlet-name></servlet-name>
    <servlet-class></servlet-class>
	  <init-param>
	     <param-name>fileName</param-name>
         <param-value>data.properties</param-value>
    </init-param>
</servlet>

实例:

类名
类的全限定名(指定到那个类)
键值对(存值)

    <!--配置servlet名称和对应的类-->
    <servlet>
        <servlet-name>TestServlet</servlet-name>
        <servlet-class>servlet.TestServlet</servlet-class>

        <!--键值对的方式进行初始化-->
        <init-param>
            <param-name>age</param-name>
            <param-value>50</param-value>
        </init-param>
		
		<init-param>
            <param-name>weight</param-name>
            <param-value>75</param-value>
        </init-param>
        
    </servlet>

或者用注解的方式
value代表地址,默认可以不写。initParams 内存放键值对。

@WebServlet(value = "/count", initParams = {@WebInitParam(name = "name", value = "张三")
        , @WebInitParam(name = "sex", value = "男")})//servlet对象初始化参数,私有参数

重定向的工作原理

执行流程:

  1. 客户端发送请求到到Servlet A
  2. Servle tA响应客户端,并命令其发送请求到Servlet B
  3. 客户端发送请求到Servlet B
  4. Servlet B响应客户端

请求转发的工作原理

执行流程:

  1. 客户端发送请求到Servlet A
  2. Servlet A将请求转发给Servlet B
  3. Servlet B响应客户端

请求转发与重定向的区别

请求转发是在服务器内部实现的,重定向要返回客户端,由浏览器发起第二次请求。
请求转发时,浏览器的地址不会变,重定向时地址栏的地址会发生变化。
请求转发时两个servlet处于一个请求当中,使用的是一个request对象,重定向时两个servlet处于两个不同的请求当中,不共享一个request对象
请求转发只能在相同应用中使用,重定向可以定向到其他应用中

中文乱码产生的原因

当用户提交表单时,浏览器会按照浏览器默认的字符集对表单中的字符进行编码

  • 中文操作系统 :gb2312(GBK)
  • 英文操作系统 :iso-8859-1

Java语言使用的是unicode字符集(utf-8) , 当浏览器的编码和utf-8产生冲突时,中文就编程了乱码
解决办法 :使用函数request.setCharacterEncoding( “浏览器字符集”) ;

  • 该函数会告知tomcat,浏览器采用的字符集,然后tomcat会按照规则将该字符集转化为java需要的utf-8字符集
  • 该函数必须在request.getParameter(“”)之前调用

应答乱码的解决办法

果在应答时不指明应答内容的字节编码,浏览器会按照默认编码进行解析。如果浏览器的默认编码与utf-8不一致时,就会出现中文乱码
解决办法 :在产生应答结果之前,指明应答内容的编码方式

  • 即使用函数response.setCharacterEncoding(“utf-8”);
  • 如果应答字符集和java默认字符集不一致,tomcat会在应答输出之前将数据转化为指定字符集

GET和POST

GET和POST是HTTP协议中浏览器发送请求的两种方式 :

GET :

  • 在地址栏中直接输入URL发送请求
  • 通过点击超级链接发送请求
  • 提交method=“get”的表单
  • 表单的默认提交方式也是get .

POST

  • 提交method=“post”的表单

GET与POST的区别

Get方式发送请求时,客户端参数在地址栏中能够显示,POST不显示
GET方式能够发送的最大数据长度有限制,具体数值取决于浏览器对URL最大值的限制,POST没有最大值得限制

  • GET和POST解决中文乱码的方式不一致 :
  • POST : request.setCharacterEncoding( “” );
  • GET :修改tomcat下conf/server.xml 70行 加URIEncoding= “utf-8”

GET与POST的处理方法

在同一个servlet中,可以对两种方式提交的请求进行分开处理
不要覆盖service(…)方法
覆盖doGet 与 doPost 两个方法 。
doGet与doPost的方法声明与service一致

  • 当用户用get方式调用Servlet时,执行doGet方法
  • 当用户使用post方式调用servlet时,执行doPost方法

对于servlet而言,如果对POST和GET的处理没有区别的话就可以直接覆盖service方法,如果有必要分别处理的话则覆盖doGet和doPOST

Web应用的目录结构

TOMCAT安装目录/
 |-    conf :配置文件
 |-    bin : 可执行文件
 |-    lib  : 被所有应用共享的jar文件
 |-    webapps :所有web应用
       |-    appA
       |-    appB
             |-    WEB-INF
             |     |-     web.xml
             |     |-     classes :本应用的所有类文件
             |     |-     lib :    本应用所有jar文件
             |-    静态 资源 ( html,css,js , css  … )

Filter

Filter称作过滤器
如果一个Servlet配置了过滤器,那么请求在到达Servlet之前先要经过过滤器的处理
作用:适合进行登陆验证,字符集转化等工作。

  • 过滤器,对所有请求过滤,只有满足过滤条件的请求才能达到servlet服务
  • 单例模式,一个filter类只创建一个对象,默认是服务器启动时创建,关闭销毁。
  • 生命周期:
  • 0、对象创建,创建一次
  • 1、初始化,执行一次
  • 2、对象过滤服务,每次过滤都执行,根据条件是否过滤
  • 3、对象销毁,执行一次,服务器关闭执行

编写Filter

implements Filter
doFilter(ServletRequest,ServletResponse,FilterChain)过滤过程
ServletRequest,ServletResponse要进行类型强转
FilterChain: 用于连接Filter与Servlet,可以通过chain.doFilter(…)将请求转给浏览器真正要访问的Servlet
init() : Filter初始化时调用
destroy() :Filter销毁时创建
实例

/**
 * 过滤器,对所有请求过滤,只有满足过滤条件的请求才能达到servlet服务
 * 单例模式,一个filter类只创建一个对象,默认是服务器启动时创建,关闭销毁。
 * 生命周期:
 * 0、对象创建,创建一次
 * 1、初始化,执行一次
 * 2、对象过滤服务,每次过滤都执行,根据条件是否过滤
 * 3、对象销毁,执行一次,服务器关闭执行
 */
@WebFilter(value = "/*")// /* 代表所有地址
public class EncodingFilter implements Filter {
    /**
     * 构造对象
     */
    public EncodingFilter() {
        System.out.println("filter对象创建");
    }

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        System.out.println("filter对象初始化");
    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        System.out.println("filter对象过滤");
        HttpServletRequest request = (HttpServletRequest) servletRequest;
        HttpServletResponse response = (HttpServletResponse) servletResponse;
        //统一设置字符编码
        request.setCharacterEncoding("utf-8");
        response.setContentType("text/html;charset=utf-8");
        //放行请求
        filterChain.doFilter(request,response);
    }

    @Override
    public void destroy() {
        System.out.println("filter对象销毁");
    }
}

配置filter

配置xml文件

<filter>
	<filter-name></filter-name>
  <filter-class></filter-class>
</filter>
<filter-mapping>
	<filter-name></filter-name>
  <url-pattern>/admin/*</url-pattern>
  <!--重要】此处配置的并不是Filter自身的URL,而是Filter负责过虑的URL。也就是说,凡是对/admin下所有资源的访问,都要经过这个Filter的过滤
-->
</filter-mapping>

使用注解
@WebFilter(value = “/*”)//过滤所有的请求

Filter的执行顺序

  • 如果存在多个过滤器,执行顺序:
  • 1、如果在web.xml配置,根据顺序从上往下过滤
  • 2、如果是注解方式,根据类名字母的ascii的顺序执行
  • 3、配置文件的过滤器优先执行
  • 销毁过程也是这个顺序

补充函数

        StringBuffer url = request.getRequestURL();//返回全路径
        System.out.println("url:" + url);
        String uri = request.getRequestURI();//返回除去host(域名或者ip)部分的路径
        System.out.println("uri:" + uri);
        String contextPath = request.getContextPath();//返回工程名部分,如果工程映射为/,此处返回则为空
        System.out.println("contextPath:" + contextPath);
        String scheme = request.getScheme();//返回当前链接使用的协议
        System.out.println("scheme:" + scheme);
        String serverName = request.getServerName();//可以返回当前页面所在的服务器的名字;
        System.out.println("serverName:" + serverName);
        int serverPort = request.getServerPort();//以返回当前页面所在的服务器使用的端口
        System.out.println("serverPort:" + serverPort);
        String queryString = request.getQueryString();//获取传递的参数
        System.out.println("queryString:" + queryString);

例如在浏览器上的请求地址:
http://localhost:8080/server_0316/login.html?name=zhangsan&age=20
url:http://localhost:8080/server_0316/login.html
uri:/server_0316/login.html
contextPath:/server_0316
scheme:http
serverName:localhost
serverPort:8080
queryString:name=zhangsan&age=20

Listener

Listener 称作监听器,当web应用中某一特定事件发生时会调用相应的Listener :
常用Listener :
ServletContextListener :监听ServletContext的创建和销毁
HttpSessionListener : 监听HttpSession对象的创建和销毁
也需要配置之后才能使用:
web.xml配置

<listener>
<listener-class>类全限定名</listener-class>
</listener>

注解
@WebListener

ServletContextListener

用于监听SerlvetContext的创建于销毁
implements ServletContextListener
contextInitialized(ServletContextEvent )
当servletContext创建时调用
可以通过ServletContextEvent获得ServletContext对象
event.getServletContext();
contextDestroyed(ServletContextEvent)
当servletContext销毁时调用

实例

/**
 * 监听上下文对象创建和销毁
 */
@WebListener
public class MyServletContextListener implements ServletContextListener {

    @Override
    public void contextInitialized(ServletContextEvent sce) {
        System.out.println("服务器启动创建上下文");
    }
    @Override
    public void contextDestroyed(ServletContextEvent sce) {
        System.out.println("服务器销毁关闭上下文");
    }
}

HttpSessionListener

用于监听Session对象的创建于销毁
implements HttpSessionListener
sessionCreated(SessioEvent) 用于监听session的创建
sessionDestroyed(SessionEvent) 监听Sessiond的销毁
可以通过SessionEvent来获得刚刚创建或销毁的session对象
event.getSession();

实例
web.xml配置

    <!--配置会话的,创建、销毁监听-->
    <listener>
        <listener-class>listener.MyHttpSessionListener</listener-class>
    </listener>
public class MyHttpSessionListener implements HttpSessionListener {
    @Override
    public void sessionCreated(HttpSessionEvent se) {
        System.out.println("会话创建");
    }

    @Override
    public void sessionDestroyed(HttpSessionEvent se) {
        System.out.println("会话销毁");
    }
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值