首先新建一个javaEE的动态web项目,这需要下载(并破解)一个IDEA Ultimate
一个大坑:
绑了服务器以后URL会有变化,具体看“运行/调试配置/部署”里面的应用程序上下文是啥,并不是想当然的http://ip地址:端口号/工件号/资源名,context root打不对,琢磨一个小时也404。
正片开始!!!什么是Servlet
Servlet就是JavaEE规范之一,规范就是接口。其文档在java_ee_api中。javax.servlet
JavaWeb三大组件分别是Servlet程序、Filter过滤器、Listener监听器
Servlet是运行在服务器上的一个java小程序,它可以接受客户端发送过来的请求,并响应数据给客户端。
如何实现Servlet接口
编写一个类implements Servlet接口、实现service方法处理请求并响应数据,到web.xml中配置servlet程序的访问地址
具体配置方法:xml中servlet标签内嵌servlet-name别名(一般起成类名),servlet-class包名.类名(可以看成是声明这个Servlet类的对象servlet-name);servlet-mapping标签内嵌别名标签和url-pattern标签配置访问地址
斜杠在服务器地址解析的时候,表示"http://ip地址:port端口号/工程路径/",url-pattern标签的值是斜杠加随便起一个名字作资源路径,访问用这个名字所以要起得相关。url-pattern不以斜杠打头会报错
一个程序可以占用多个端口号,一个端口号只对应一个程序
客户:IP地址确定服务器,端口号确定资源
服务器:通过wb.xml找到servlet,servlet接口实现类,进而是service方法。端口号也是监听对象
Servlet生命周期
-
执行Servlet构造器方法
-
执行init()初始化方法
前两步是在第一次访问后创建servlet,Servlet程序是单例模式的,多次访问只有一个实例
-
执行service()方法
每次访问都会调用
-
执行destroy()销毁方法
web工程停止的时候才被调用
get和post
get请求和post请求都会执行service方法
service方法里要区分可以先把参数里的ServletRequest转成HttpServletRequest,再调用getMethod()方法以知道它是“GET”还是“POST”
根据“单一职责”原则,把if/else中的大段分别提成doGet()和doPost()方法
通过继承HttpServlet创建servlet程序
实际开发中不是直接实现Servlet接口,而是扩展出HttpServlet的子类,然后重写doGet()、doPost()
Servlet继承体系
GenericServlet实现Servlet,HttpServlet继承GenericServlet,自定义的Servlet程序继承HttpServlet
查看源码看到GenericServlet中除了空方法,都是跟ServletConfig有关。进一步说,GenericServlet类实现了Servlet接口,做了很多空实现,并持有一个ServletConfig类的引用,并对ServletConfig的使用写了一些方法。有一个抽象的service(ServletRequest req, ServletResponse res)方法留待子类HttpServlet实现。
HttpServlet的任务就是实现service()方法,实现了请求的分发处理。先重载使service导向以HttpServletRequest,HttpServletResponse为参数,以便使用HttpServletRequest的getMethod()方法区分出是get还是post,分别处理。可以看到除了METHOD_GET、METHOD_POST还有以前听说过并不常用的METHOD_HEAD、METHOD_PUT、METHOD_DELETE、METHOD_OPTIONS、METHOD_TRACE。然而HttpServlet的doGet()和doPost()方法只负责抛出异常说不支持GET/POST,除非被子类重写。
自定义的Servlet程序继承HttpServlet、根据自己的业务需要重写doGet()、doPost()
maven中如何查看源码
Ctrl点击继承类名进入.class反编译文件,右上角下载源可得到带作者注释的源码;不要随便点“更改源”,不然下载下来版本不对的不好看,改起来麻烦
ServletConfig类
Servlet程序的配置信息类
Servlet程序和ServletConfig对象都是由Tomcat负责创建,我们负责使用。
Servlet程序默认是第一次访问的时候创建,ServletConfig是每个Servlet程序创建时,就创建一个对应的ServletConfig对象(所以init()方法有一个ServletConfig参数)。
GenericServlet的init()方法会用这个参数,所以
在自定义Servlet中重写init()方法注意要在开头加一句super.init(config);
,否则会出现问题
ServletConfig类的3种作用
-
获取Servlet程序的别名servlet-name的值
-
获取初始化参数init-param
init-param是web.xml里servlet标签的子标签,里面以param-name标签和param-value标签组成键值对。
-
获取ServletContext对象
ServletContext类
什么是ServletContext?
-
是一个接口,它表示Servlet上下文对象
-
一个web工程只有一个ServletContext对象实例
-
ServletContext对象是一个“域对象”
-
在web工程部署启动的时候创建,在web工程停止的时候销毁。
什么是域对象?
域对象是可以像Map一样存取数据的对象,叫域对象。
这里的域指的是存取数据的操作范围覆盖整个工程。
存数据 | 取数据 | 删除数据 | |
---|---|---|---|
Map | put() | get() | remove() |
域对象 | setAttribute() | getAttribute() | removeAttribute() |
ServletContext类的4个常见作用
-
获取web.xml中配置的上下文参数context-param
也是web.xml里配,web-app标签的子标签context-param,param-name标签和param-value标签组成键值对,属于整个web工程,web工程中的每个servlet都能获得。
-
获取当前的工程路径,格式:/工程路径
servletContext.getContextPath()
-
获取工程部署后在服务器硬盘上的绝对路径
servletContext.getRealPath("/")
-
像Map一样存取数据,同一web工程下的不同servlet可以通过servletContext进行通信
可以在doGet()、doPost()方法中使用
servletContext.setInitParameter()报错的原因:不知道,反正暂时不去用这个方法,只用setAttribute()就好了。