<servlet>
字段添加 <load-on-startup>1(代表第1个Servlet)
.. service():->doGet() doPost:调用几次,则执行几次
destroy():关闭tomcat服务时
由两个大类四个软件包组成::
即Servlet API可以适用于任何通信协议。但绝大多数情况下Servlet只用来扩展基于HTTP协议的Web服务器。
我们学习的Servlet,是位于 javax.servlet.http
包中的类和接口,是基础HTTP协议。
ServletConfig:接口
ServletContext getServletContext():获取Servlet上下文对象 application
String getInitParameter(String name):在当前Servlet范围内,获取名为name的参数值(初始化参数)
a.ServletContext中的常见方法(application):
getContextPath():相对路径
getRealPath():绝对路径
setAttribute()、getAttribute()
---->
String getInitParameter(String name);在当前Web容器范围内,获取名为name的参数值(初始化参数)
初始化全局参数
<context-param> <param-name>globalParam</param-name> <param-value>global value...</param-value> </context-param>
初始化Servlet参数
<servlet> <servlet-name>my</servlet-name> <servlet-class>com.hacker.servlet.MyServlet</servlet-class> <load-on-startup>2</load-on-startup> <!--配置当前Servlet初始化参数 --> <init-param> <param-name>servletparamname</param-name> <param-value>servletparamvalue...</param-value> </init-param> </servlet>
@WebServlet(value = "/Servlet3",loadOnStartup = 1,initParams = {@WebInitParam(name="servletparamname30",value = "servletparamvalue30")})
注意:此注解只隶属于某一个具体的Servlet,因此无法为整个Web容器设置初始化参数(如果要通过3.0方式设置,仍需在web.xml中设置)
获取全局参数
ServletContext对象表示Servlet应用程序。每个Web应用程序都只有一个ServletContext对象。在将一个应用程序同时部署到多个容器的分布式环境中,每台Java虚拟机上的Web应用都会有一个ServletContext对象。
通过在ServletConfig中调用getServletContext方法,也可以获得ServletContext对象。
@Override public void init() throws ServletException { System.out.println("init..."); //获取整个Web容器的初始化参数 String str=super.getServletContext().getInitParameter("globalParam"); System.out.println("当前Web容器的初始化的参数为"+str); }
获取当前Servlet参数
当Servlet容器初始化Servlet时,Servlet容器会给Servlet的init( )方式传入一个ServletConfig对象
其中几个方法如下:
@Override public void init() throws ServletException { System.out.println("init..."); //获取当前Servlet的初始化参数 String str=super.getInitParameter("servletparamname"); System.out.println("当前Servlet的初始化参数为"+str); }
当我们在在请求Servlet容器具体的执行流程的细节是什么呢?一起来看一看
首先我们知道请求的过程最终传给了名为service的方法,那service方式到底是怎么执行的,我们先来简单的了解下
首先查看入口类继承的HTTPServlet类
点进去发现继承至GenericServlet,继续跟进
GenericServlet实现了一个Servlet接口
接口中定义了service方法,并且有两个参数ServletRequest和ServletResponse代表请求和响应,那么我们自定义的Servlet肯定不是实现的这个service方法,因为我们重写的service方法形参为HttpServletRequest和HttpServletResponse
现在就来找找到底是重写的那个service方法,首先来看GenericServlet类
在GenericServlet类中发现实现了service的抽象方法,传入参数为ServletRequest,明显也不是,继续跟进HTTPServlet类
在HTTPServlet类中发现两个service方法,很明显第二个service方法参数也是ServletRequest,所以第二个service方法为实现方法,下面来看看具体实现
public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException { HttpServletRequest request; HttpServletResponse response; try { request = (HttpServletRequest)req; response = (HttpServletResponse)res; } catch (ClassCastException var6) { throw new ServletException(lStrings.getString("http.non_http")); } this.service(request, response); }
可以看到该实现方法将Servlet强转为了HttpServlet,
HttpServlet继承自Servlet,将父类变为了子类,把通用的响应,转换为了特需的HTTP响应, 之所以能够这样强制的转换,是因为在调用Servlet的Service方法时,Servlet容器总会传入一个HttpServletRequest对象和HttpServletResponse对象,预备使用HTTP。
因此,转换类型当然不会出错了。
PS:Java中父类想要转换为子类,父类的实例必须指向子类的应用,形如
public static void main(String[] args) { //Car为父类,BigCar为子类 Car car=new BigCar();//这里car父类对象的引用为BigCar子类 父类是子类构造出来的实例 BigCar bc=(BigCar)car;//所以这里可以将父类对象car强转为子类对象BigCar bc.setName("ssss");//这里就可以调用子类的方法 test(new BigCar()); } public static void test(Car car) { BigCar bigCar = (BigCar) car; if (bigCar instanceof Car) { System.out.println("1"); } }
最后调用了当前类中的重载方法service
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { String method = req.getMethod(); long lastModified; if (method.equals("GET")) { lastModified = this.getLastModified(req); if (lastModified == -1L) { this.doGet(req, resp); } else { long ifModifiedSince; try { ifModifiedSince = req.getDateHeader("If-Modified-Since"); } catch (IllegalArgumentException var9) { ifModifiedSince = -1L; } if (ifModifiedSince < lastModified / 1000L * 1000L) { this.maybeSetLastModified(resp, lastModified); this.doGet(req, resp); } else { resp.setStatus(304); } } } else if (method.equals("HEAD")) { lastModified = this.getLastModified(req); this.maybeSetLastModified(resp, lastModified); this.doHead(req, resp); } else if (method.equals("POST")) { this.doPost(req, resp); } else if (method.equals("PUT")) { this.doPut(req, resp); } else if (method.equals("DELETE")) { this.doDelete(req, resp); } else if (method.equals("OPTIONS")) { this.doOptions(req, resp); } else if (method.equals("TRACE")) { this.doTrace(req, resp); } else { String errMsg = lStrings.getString("http.method_not_implemented"); Object[] errArgs = new Object[]{method}; errMsg = MessageFormat.format(errMsg, errArgs); resp.sendError(501, errMsg); } }
在该方法中,将请求类型进行了划分,判定请求类型调用不同的方法,所以我们重写的service方法实际上是接收了所有类型的请求,那么可以针对不同请求重写相应的方法,来简化我们的操作。
一般装饰者就是在主体组件扩展到具体的实现类时,会引入一个中间层,把装饰者的公布部分引入进来,在引入具体的实现时,只需要实现自己特定的部分就行了。公共的就放在上面,中间层中。
学了这么多,现在就来动手实现一个MVC简单登录案例:grinning:,再来复现一遍什么是MVC模式:
M
:Model ,模型 :一个功能。用JavaBean实现。 V
:View,视图: 用于展示、以及与用户交互。使用html js css jsp jquery等前端技术实现 C
:Controller,控制器 :接受请求,将请求跳转到模型进行处理;模型处理完毕后,再将处理的结果 login.jsp