分享web开发知识

注册/登录|最近发布|今日推荐

主页 IT知识网页技术软件开发前端开发代码编程运营维护技术分享教程案例
当前位置:首页 > 代码编程

JSP的小心得

发布时间:2023-09-06 01:33责任编辑:赖小花关键词:暂无标签

问题:Web容器(例如Tomcat)是怎么来执行jsp文件的?

???首先它会将放在webapps目录下的jsp文件(这里以hello.jsp为例)翻译成hello_jsp.java文件并编译为hello_jsp.class(注意:生成的文件名都是小写字母),存放在Tomcat安装目录\work\Catalina\localhost\webDemo\org\apache\jsp路径下,打开.java源文件,你会看到hello_jsp类继承了httpJspBase类。而HttpJspBase类又是HttpServlet的子类,所以hello_jsp类也就间接实现了Servlet接口,也就是说Web容器把jsp文件转换成了一个servlet类了


???然后Web容器根据配置文件(web.xml)和客户端(浏览器)的请求URL来确定使用哪一个servlet类.接下来调用这个servlet类的service()方法。在hello_jsp.java中看不到这个service()方法,并不代表它没有这个方法,只代表它没有重写这个方法。(除了重写之外,从父类继承的方法在其子类中,都是隐藏的,所以你看不到。)那么如果想看看在这个类中从其父类继承得到的方法长什么样?很简单!找到有这个方法的父类,查看方法的源码即可。那么如果需要调用这个类的service()方法怎么办?放心,No problem呀,它会去寻找所有父类里有这个方法的父类,然后再执行这个父类的方法体(在这里我们把这个机制或者行为笑称为“儿子继承的东西没找到,咱不怕,去找老子”),在这里说明一下:在子类中调用继承的方法,这个方法就是子类的方法,即SubClass.method(),只不过执行的方法体内容和其父类中的方法体内容一模一样而已。那么接着咱们就来说说这个父类HttpJspBase,在它的源码中,你会看到两个方法,第一个方法_japService(),被其子类hello_jsp类重写了。另外一个方法,源码如下

public void service(HttpServletRequest quest,HttpServletResponse response) throws ServletException,IOException{  _jspService(request,response);}

这个父类中的servce()方法,子类hello_jsp继承得到的service方法也就是它。看到没有,多么简单的一个方法呀!上面提过了Web容器在确定使用哪一个sevlet类后,接着要干嘛?当然就是调用这个servlet的service()方法了,开始执行它的方法体,方法体中也没啥复杂的事情,就是调用本类中的_japService()方法,也就是hello_jsp类中的重写父类的_jspService()。

咱们接着看这个重写的_jspService()的方法体,里面有若干个out.write();这个方法的实参不就是jsp文件的HTML内容吗?哦,所以才有我们在浏览器上看到的输出内容。

所以在父类里定义的service()方法的作用我觉得很大:它把我们原始的继承Serlet接口并重写其service()方法的习惯转变为了继承HttpJspBase类并重写其_jspService()方法。这是一种技术上的改进和分支吧,也就造就了JSP技术的发展吧。与之类似的是HttpServlet类,它也间接实现了Servlet接口,重写了service()方法,特别是它继承了元老级的GenericServlet(这个类可是直接实现Servlet接口的第一代类呀,可谓是亲生的嫡长子呀!它提供了很多方法,可以说是一个重大改革,也为HttpServlet铺好了路,关于它以后有空再讲)。那么我们来看看Httpservlet类实现的service()方法吧

 public void service(ServletRequest req, ServletResponse res) ???????throws ServletException, IOException { ???????HttpServletRequest ?request; ???????HttpServletResponse response; ???????try { ???????????request = (HttpServletRequest) req; ???????????response = (HttpServletResponse) res; ???????} catch (ClassCastException e) { ???????????throw new ServletException("non-HTTP request or response"); ???????} ???????service(request, response); ???}

HttpServletRequest和HttpServletResponse分别是ServletRequest和ServletResponse的子类,这样经过强转型,再最后调用自己的service方法,成功完成了接口方法到基类方法的转移了呀!还没有完,接下来才是HttpServlet的高明之处:看看他自己定义的那个service()的源码吧

 ???protected void service(HttpServletRequest req, HttpServletResponse resp) ???????throws ServletException, IOException { ???????String method = req.getMethod(); ???????if (method.equals(METHOD_GET)) { ???????????long lastModified = getLastModified(req); ???????????if (lastModified == -1) { ???????????????// servlet doesn‘t support if-modified-since, no reason ???????????????// to go through further expensive logic ???????????????doGet(req, resp); ???????????} else { ???????????????long ifModifiedSince; ???????????????try { ???????????????????ifModifiedSince = req.getDateHeader(HEADER_IFMODSINCE); ???????????????} catch (IllegalArgumentException iae) { ???????????????????// Invalid date header - proceed as if none was set ???????????????????ifModifiedSince = -1; ???????????????} ???????????????if (ifModifiedSince < (lastModified / 1000 * 1000)) { ???????????????????// If the servlet mod time is later, call doGet() ???????????????????// Round down to the nearest second for a proper compare ???????????????????// A ifModifiedSince of -1 will always be less ???????????????????maybeSetLastModified(resp, lastModified); ???????????????????doGet(req, resp); ???????????????} else { ???????????????????resp.setStatus(HttpServletResponse.SC_NOT_MODIFIED); ???????????????} ???????????} ???????} else if (method.equals(METHOD_HEAD)) { ???????????long lastModified = getLastModified(req); ???????????maybeSetLastModified(resp, lastModified); ???????????doHead(req, resp); ???????} else if (method.equals(METHOD_POST)) { ???????????doPost(req, resp); ???????} else if (method.equals(METHOD_PUT)) { ???????????doPut(req, resp); ???????} else if (method.equals(METHOD_DELETE)) { ???????????doDelete(req, resp); ???????} else if (method.equals(METHOD_OPTIONS)) { ???????????doOptions(req,resp); ???????} else if (method.equals(METHOD_TRACE)) { ???????????doTrace(req,resp); ???????} else { ???????????// ???????????// Note that this means NO servlet supports whatever ???????????// method was requested, anywhere on this server. ???????????// ???????????String errMsg = lStrings.getString("http.method_not_implemented"); ???????????Object[] errArgs = new Object[1]; ???????????errArgs[0] = method; ???????????errMsg = MessageFormat.format(errMsg, errArgs); ???????????resp.sendError(HttpServletResponse.SC_NOT_IMPLEMENTED, errMsg); ???????} ???}

比较长,言而言之,就是这些个逻辑实现,将Web容器最先调用servlet类的service()方法转移到了调用servlet类的doGet(),doPOST()等方法上,因为看不到这些底层的实现代码,所以就让我们产生了HttpServlet的入口是doGet()方法的假象。当然这也带来了简化流程的好处:继承了HttpServlet类的子类只要重写doGet (),doPOST()等方法即可。

总结:jsp实质上还是servlet,是一种加强版的servlet技术吧

JSP的小心得

原文地址:https://www.cnblogs.com/zui-ai-java/p/8158144.html

知识推荐

我的编程学习网——分享web前端后端开发技术知识。 垃圾信息处理邮箱 tousu563@163.com 网站地图
icp备案号 闽ICP备2023006418号-8 不良信息举报平台 互联网安全管理备案 Copyright 2023 www.wodecom.cn All Rights Reserved