Servlet、页面跳转、乱码问题

Day36

servlet生命周期

service方法前端发送请求,无论发送什么请求都会调用,如果get请求和post方法要分开处理,则不适用。

此时可以用doGet()方法和doPost()方法,如果客户端发送给当前的servlet请求方式是get就调用doGet方法,如果是post就调用doPost方法,参数仍然是req和resp。

请求不加/,servlet里要加,因为/表示跳回到上一级。

研究生命周期的目的:什么生命周期的时候该调用什么方法。

如:servlet在项目结束的时候被销毁,会调用destroy()方法,可以再这个时候调用各种回收的方法。

如何研究:servlet类里面写一个构造方法,打印信息,查看什么时候创建的对象。写一个init()方法,查看什么时候初始化(这个是父类调用)。写一个destroy()方法查看什么时候销毁。

发现:在打开页面的时候没有创建,但是在页面第一次提交(前端第一次发送请求)的时候,会按顺序调用无参构造、init()、doPost()或doGet()方法,后续多次发送请求会不断调用doPost()(或者doGet)方法。

注:(但是如果构造方法为有参构造,会报错:响应状态码为500。

响应状态码可以按第一个数组分为五大类:
1xx、2xx、3xx、4xx、5xx

4xx:客户端错误

5xx:服务端错误

出现错误信息的时候看root cause

发现没有找到构造方法,因为写了有参构造系统不会默认实现无参构造。所以经验:不要写有参构造。)

销毁:服务器正常关闭时。

注:非正常关闭不是指报错。报错项目会崩掉但是服务器不会。如果手动删掉服务器则算作非正常关闭,不会调用destroy()方法。

深入servlet生命周期

Servlet调用底层逻辑完整顺序:

客户端将请求发送到Tomcat服务器,服务器拿到请求去寻找项目,然后找到web.xml配置文件。通过配置文件里的和获取到类全路径。

Tomcat通过web.xml配置文件获取到类全路径后,Tomcat会获取Servlet容器(一个map,key存的全路径,value存的对象),在Servlet容器中查询是否有该Servlet对象。

一、没有的情况:1.调用该Servlet的构造方法(默认的无参构造)。

2.调用父类的父类(GenericServlet)的有参init()方法,传入当前Servlet的配置文件对象参数,(在里面可以配置属性,在Servlet类里可以调用get方法获取属性)但是现在没有对象。所以会在底层创建ServletConfig对象,即当前Servlet配置文件对象( ServletConfig对象是在Servlet的初始化过程中由Servlet容器创建的。 )。

3.解析web.xml里面的servlet里面的init-param的数据。

4.将init-param数据添加到ServletConfig对象里面去。

5.在底层调用GenericServlet类的init方法(ServletConfig config)(回到并完成第二步)。方法内容为将配置文件对象赋值给本对象的配置文件属性,再调用init()无参方法,即子类重写的init()方法。

Tomcat会将创建好的对象添加到Servlet容器中。

二、有的情况:

获取Servlet容器中的Servlet对象。

然后:

Tomcat服务器解析请求数据,并封装到HttpServletRequest对象中。

Tomcat会将响应数据封装到HttpServletResponse对象中。

Tomcat调用HttpServlet类的service(req,reps)方法。

该方法会判断method为post还是get,分别调用doPost()和doGet()去获取数据、传出数据返回前端等(可以重写doPost()和doGet()方法或者重写service()方法,建议前者,因为可以分别处理两种method的情况)。
在这里插入图片描述

面试题:Servlet是单例的吗?

是?–>有待考证。

面试题:Servlet什么时候创建?

1.第一次发送请求时

2.在web.xml里面的servlet里面配置了1,项目启动时就会创建Servlet对象。

注意:1.数字表示优先级别,数字>0,越小优先级越高。(一般从1开始)当有多个Servlet优先级相同的时候,多线程会抢资源。

2.可以再注释里面配置,@webServlet(value=“/register”,initParams={@webInitParam(name=“code”,value=“UTF-8”)},loedOnStartup=1)。

注意要加斜杠,项目无法运行很大概率是配置问题。

在servlet类也可以编写简单注解如@WebServlet(“/Servlet01”)

线程安全

高并发情况:多个客户端同时向servlet发送请求,多线程操作同一资源。

面试题:Servlet是否是单例的?

答案:Servlet一般情况下是单例的,但如果实现了SingleThreadModel接口,(目前这个接口已弃用),客户端(多个)第一次同时发送请求时阻塞会创建Servlet对象。之后只要阻塞就分别用多个Servlet对象服务多个客户端,如果不阻塞就只用一个。

实现SingleThreadModel接口可以一定程度上实现线程安全。

或者采用加锁的方法。

经验:怎样解决Servlet线程安全问题?

1.加锁

2.少用成员属性

页面跳转

跳转的几种方式:
1.页面跳页面:(1)超链接(2)按钮(3)表单

<h1>页面跳转页面</h1><br/>
    <a href="page01.html">超链接跳转</a><br/>
    <button onclick="function01()">按钮跳转</button><br/>
    <form action="page01.html" method="post"><!--html文件、图像文件、CSS文件和JS文件都是静态资源,不用去配置文件里面进行配置-->
      <input type="submit" value="表单跳转页面"/><br/>
    </form>
    <hr/>

2.页面跳Servlet:(1)超链接(这种跳法是get请求,可以携带数据。)

(2)按钮,可以携带数据

(3)表单,可以指定请求

<h1>页面跳转Servlet</h1><br/>
    <a href="Servlet01?username=aaa&password=123123&name=小明">超链接跳转Servlet</a><br/>
    <button onclick="function02()">按钮跳转Servlet</button><br/>
    <form action="Servlet01" method="post"><!--指定请求-->
        账号:<input type="text" name="username"/><br/>
        密码:<input type="password" name="password"/><br/>
        姓名:<input type="text" name="name"/><br/>
      <input type="submit" value="表单跳转Servlet"/><br/>
    </form>
    <hr/>

3.Servlet跳Servlet

(1)转发:利用请求对象跳转request.getRequestDispatcher(“目标Servlet”).forward(request,response)

(2)重定向:利用响应对象重定向

response.sendRedirect(“目标Servlet”)

<h1>Servlet跳转Servlet</h1><br/>
    <a href="Servlet02">转发 -Servlet02跳转Servlet03</a><br/>
    <a href="Servlet04">重定向-Servlet04跳转Servlet05</a><br/>
    <hr/>

4.Servlet跳页面

(1)转发:利用请求对象跳转request.getRequestDispatcher(“目标html”).forward(request,response)

(2)重定向:利用响应对象重定向

response.sendRedirect(“目标html”)

<h1>Servlet跳转页面</h1><br/>
    <a href="Servlet06">转发-Servlet06跳转page02</a><br/>
    <a href="Servlet07">重定向-Servlet07跳转page02</a><br/>

转发和重定向的区别

区别一:访问普通页面,转发是一次请求(属于服务器内部跳转);重定向是两次请求(客户端会再次发送请求)。

request.getRequestDispatcher("page01.html").forward(request,response);

转发:客户端直接找到Servlet01,Servlet01调用doPost()方法,里面执行转发方法,利用request和response参数对page01页面进行请求和响应,只发送一次请求,地址栏仍然是Servlet01,而不是page01。

response.sendRedirect("page01.html");

重定向:客户端发送请求到Servlet01,Servlet01调用doPost()方法,进行重定向,让客户端重新发送请求到page01页面,发送了两次请求,地址栏更改为page01。

区别二:访问外部页面,转发无法访问到外部页面,因为转发是服务器内部跳转,服务器不能访问外部的服务器。而重定向可以。

request.getRequestDispatcher("http://www.baidu.com").forward(request,response);

重定向可以访问到外部页面

response.sendRedirect("http://www.baidu.com");

转发无法访问到外部页面

区别三:访问受保护的页面(WEB-INF内的html)。客户端不能直接访问受保护的资源。

request.getRequestDispatcher("WEB-INF/page01.html").forward(request,response);

转发可以访问受保护的页面。

response.sendRedirect("WEB-INF/page01.html");

重定向无法访问受保护的页面。

乱码问题

(8.0版本)在doPost里面设置请求和响应的编码格式(request和response调用相关set方法)

注意:重定向里面涉及到中文会有问题,客户端无法识别到中文页面。但是跳转可以,因为跳转是服务器内部跳转,格式一致。

解决:response.sendRedirect(UrlEncoder.encode(“中文.html”,“UTF-8”));

重定向跳转中文页面必须加上编码格式。

@WebServlet("/Servlet02")
public class Servlet02 extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        this.doPost(request, response);
    }

    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

        //注意:重定向跳转中文页面必须加上编码格式
        response.sendRedirect(URLEncoder.encode("中文页面.html","UTF-8"));
    }
}
  • 30
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值