Web开发(一)--Servlet
来源:互联网 发布:暴雪防沉迷算法 编辑:程序博客网 时间:2024/05/18 13:08
Java Servlet是和平台无关的服务器端组件,功能是实现对客户端请求的响应。
Servlet组件运行在Servlet容器中,我们通常说的Servlet容器一般就指Tomcat服务器。
Servlet容器负责Servlet和客户的通信,以及调用Servlet的方法,Servlet和客户采用“请求/响应”的模式。
客户<---(请求/响应)--->Servlet容器<----(ServletRequest/ServletResponse)---->Servlet组件
Servlet可完成如下功能:
1.创建并返回基于客户请求的动态HTML页面
2.创建可嵌入到现有HTML页面中的部分HTML页面(Html片断)
3.与其他服务器资源进行通信,如数据库,基于Java的应用程序
Servlet其实就是一组Java程序,最顶层是接口Interface Servlet,Servlet组件实现该接口定义的方法,javax.servlet.Servlet接口
1、Servlet的创建与配置
在Eclipse中创建一个Dynamic Web Project,并且配置Tomcat服务器,选择next,最后可勾选web.xml的自动生成。
在src下创建package,并且创建HelloWorld类,实现Servlet接口,并且实现Servlet接口定义的方法,无参构造函数
public class HelloWorld implements Servlet{@Overridepublic void destroy() {System.out.println("destroy");}@Overridepublic ServletConfig getServletConfig() {System.out.println("getServletConfig");return null;}@Overridepublic String getServletInfo() {System.out.println("getServletInfo");return null;}@Overridepublic void init(ServletConfig arg0) throws ServletException {System.out.println("init");}@Overridepublic void service(ServletRequest arg0, ServletResponse arg1) throws ServletException, IOException {System.out.println("service");}public HelloWorld() {System.out.println("HelloWorld constructor ...");}}配置web.xml文件,在WebContent/WEB-INF下,配置HelloWorld类的Servlet和映射
<?xml version="1.0" encoding="UTF-8"?><web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0"> <display-name>ServletTest2</display-name> <servlet> <servlet-name>HelloWorld</servlet-name> <servlet-class>com.cqupt.java.servlet.HelloWorld</servlet-class> </servlet> <servlet-mapping> <servlet-name>HelloWorld</servlet-name> <url-pattern>/hello</url-pattern> </servlet-mapping></web-app>
配置两个元素:servlet和servlet-mapping
url-pattern元素中的/hello,其中"/"代表web应用的根目录,也就是http://localhost:8080/项目名/
右键项目,运行在服务器上,在Eclipse或系统的浏览器上,输入网址http://localhost:8080/项目名/配置的url-pattern
在这里是http://localhost:8080/ServletTest/hello,Eclipes显示的结果为:
HelloWorld constructor ...
init
service
无限制刷新网页时,每次只显示service
关闭服务器,显示destroy
这说明了Servlet的生命周期。
web.xml文件中servlet的配置和映射,如果只配置servlet,不配置映射servlet-mapping,并且设置为Tomcat启动时加载,会显示:
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0"> <display-name>ServletTest2</display-name> <servlet> <servlet-name>HelloWorld</servlet-name> <servlet-class>com.cqupt.java.servlet.HelloWorld</servlet-class> <load-on-startup>1</load-on-startup> </servlet></web-app>
HelloWorld constructor ...
init
但不会显示service
注意:Servlet程序必须存储在"web应用程序目录\WEB-INF\classes\"目录中
2、Servlet的生命周期
使用Servlet时,我们不需要手动new类的实例,也不用手动调用方法,这一切都是Servlet容器帮我们完成的操作。
Servlet容器:运行Servlet、Jsp、Filter等的软件环境,可以来创建Servlet,并调用Servlet的相关生命周期方法。
由上节的HelloWorld可以看出,Servlet的生命周期:
1.构造方法:只被调用一次,只有在第一次请求Servlet时,才创建对应的Servlet实例,调用构造器。说明Servlet是单实例的!(单实例,就会存在线程安全问题,不推荐使用全局变量)
2.init方法:只被调用一次,在创建好实例后,立即被调用,用于初始化当前Servlet,init方法的形参有特殊的作用(ServletConfig类型的形参)。
3.service方法:被多次调用,每次请求都会调用service方法,实际用于响应请求的方法。
4.destroy方法:只被调用一次,在当前servlet所在的web应用被卸载前调用,用于当前Servlet所占用的资源。
这些方法都是Servlet容器负责调用。
3、load-on-startup
在servlet元素配置中,加入load-on-startup的配置标签,是为了,不需要请求,在Tomcat服务器启动时就加载该Servlet。
数值为负数,在请求时加载;数值为0和整数,在服务器启动时加载,并init初始化,并且,数值越小,越早被加载创建
<servlet> <servlet-name>HelloWorld</servlet-name> <servlet-class>com.cqupt.java.servlet.HelloWorld</servlet-class> <load-on-startup>0</load-on-startup> </servlet> <servlet> <servlet-name>Second</servlet-name> <servlet-class>com.cqupt.java.servlet.SecondServlet</servlet-class> <load-on-startup>3</load-on-startup> </servlet> <servlet> <servlet-name>Third</servlet-name> <servlet-class>com.cqupt.java.servlet.ThirdServlet</servlet-class> <load-on-startup>5</load-on-startup> </servlet>先创建加载HelloWorld,然后是Second,最后是Third
4、关于servlet-mapping
有关servlet-mapping的配置需注意两点
1.一个Servlet可以配置多个servlet-mapping,这样可以通过不同的url地址访问Servlet实例
2.url-pattern配置中使用通配符*只有两种合法的形式:
一种是 *.扩展名 的方法,例如 *.html,那么在访问web应用主目录 或者 aa.html 、.html时都可以请求到该Servlet
<servlet> <servlet-name>Third</servlet-name> <servlet-class>com.cqupt.java.servlet.ThirdServlet</servlet-class> <load-on-startup>5</load-on-startup> </servlet> <servlet-mapping> <servlet-name>Third</servlet-name> <url-pattern>*.html</url-pattern> </servlet-mapping>访问 :
web主目录:http://localhost:8080/ServletTest/
http://localhost:8080/ServletTest/.html
http://localhost:8080/ServletTest/aa.html都可以得到Servlet 的响应。
第二种是以正斜杠/开头,并以 /* 结尾
<servlet> <servlet-name>Third</servlet-name> <servlet-class>com.cqupt.java.servlet.ThirdServlet</servlet-class> <load-on-startup>5</load-on-startup> </servlet> <servlet-mapping> <servlet-name>Third</servlet-name> <url-pattern>/*</url-pattern> </servlet-mapping>其他例如 /*.action 都不合法。
5、初始化参数及ServletConfig类
Servlet配置时,可以给需要的Servlet配置初始化参数,配置方法:在servlet标签下使用init-param标签
<servlet> <servlet-name>HelloWorld</servlet-name> <servlet-class>com.cqupt.java.servlet.HelloWorld</servlet-class> <!-- init-param 标签必须放在load-on-startup标签之前 ,否则有错--> <init-param> <!-- 参数名 --> <param-name>user</param-name> <!-- 参数值 --> <param-value>root</param-value> </init-param> <init-param> <param-name>password</param-name> <param-value>1234</param-value> </init-param> <load-on-startup>0</load-on-startup> </servlet> <servlet-mapping> <servlet-name>HelloWorld</servlet-name> <url-pattern>/hello</url-pattern> </servlet-mapping>注意:init-param 标签必须放在load-on-startup标签之前 ,否则有错
那么如何在Servlet类中获取呢,关键在ServletConfig类,Servlet的init方法的形参就是ServletConfig类型
可以通过Servlet的init方法获取配置的初始化参数:
1.使用ServletConfig的getInitParameter(参数名)获取
@Overridepublic void init(ServletConfig config) throws ServletException {System.out.println("init get init-param");String user = config.getInitParameter("user");System.out.println("user:"+user);String password = config.getInitParameter("password");System.out.println("password:"+password);}
2.使用ServletConfig类的getInitParameterNames()获取所有参数名的Enumeration集合对象,再根据参数名获取参数值
@Overridepublic void init(ServletConfig config) throws ServletException {System.out.println("init get init-param");Enumeration<String> names = config.getInitParameterNames();while(names.hasMoreElements()){String name = names.nextElement();System.out.println(name+":"+config.getInitParameter(name));}}也可以使用getServletName()获取Servlet的名字
System.out.println(config.getServletName());
还可以使用getServletContext获取ServletContext对象,经常使用。
ServletContext servletContext = config.getServletContext();
6、ServletContext
ServletContex同ServletConfig类一样,是Servlet中经常使用且很重要的类。
ServletContext对象代表当前Web应用:可以认为ServletContext是当前web应用的大管家,可以从中获取关于Web应用的各种信息。
1.设置当前Web应用的初始化参数,直接在web-app标签下配置context-param标签即可
<!-- 配置当前web应用的初始化参数 --> <context-param> <param-name>driver</param-name> <param-value>com.mysql.jdbc.Driver</param-value> </context-param> <context-param> <param-name>jdbcUrl</param-name> <param-value>jdbc:mysql:///test</param-value> </context-param>
通过ServletContext配置的初始化参数可以被所有的Servlet获取,而Servlet配置的初始化参数只能被其自身获取。
通过getInitParameter(参数名)和getInitParameterNames()获取
@Overridepublic void init(ServletConfig config) throws ServletException {System.out.println("init ...");ServletContext servletContext = config.getServletContext();String driver = servletContext.getInitParameter("driver");System.out.println(driver);Enumeration<String> names = servletContext.getInitParameterNames();while(names.hasMoreElements()){String name = names.nextElement();String value = servletContext.getInitParameter(name);System.out.println(value);}}
2.获取当前Web应用的某一个文件在服务器上的绝对路径,而不是部署前的路径。
使用getRealPath(String path),path是根目录下的路径文件,以/开始
//note.txt在WebContent/下,获取的不是部署前的路径String realPath = servletContext.getRealPath("/note.txt");System.out.println(realPath);//D:\java\.metadata\.plugins\org.eclipse.wst.server.core\tmp1\wtpwebapps\ServletTest\note.txt
3.获取当前web应用的名称
String webName = servletContext.getContextPath();System.out.println(webName);//输出:/ServletTest输出Web应用的名称,不是项目的名称,默认的Web名称是项目的名称,但是后期在配置服务器发布web应用时,经常会改变,通过这个方法可以动态获取到Web应用的名称。
4.获取文件输入流,getResourceAsStream(String path),其中path是当前Web应用的根目录开始的:"/"
try{ClassLoader classLoader = getClass().getClassLoader();InputStream prop = classLoader.getResourceAsStream("jdbc.properties");System.out.println(prop);}catch(Exception e) {e.printStackTrace();}try{//使用Servlet获取文件输入流,文件路径必须是从web应用开始//而在项目src下的所有文件都部署在web应用的/WEB-INF/classes/目录下//InputStream in = servletContext.getResourceAsStream("jdbc.properties");//null获取不到InputStream in = servletContext.getResourceAsStream("/WEB-INF/classes/jdbc.properties");System.out.println(in);}catch(Exception e) {e.printStackTrace();}
5.和Attribute相关的方法,后续。
7、HTTP协议
HTTP协议是超文本传输协议,是TCP/IP协议族的应用层协议,负责浏览器与服务器之间数据交换的过程,以及数据本身的格式。
HTTP协议是无状态的,每次网页的请求,都必须建立连接----发送请求-----返回数据-----断开连接,之所以服务器可以跟踪客户的网页访问,是Session起的作用(后续)
每次连接只处理一个请求和响应。
请求消息的结构:一个请求行,若干消息头,以及实体内容,消息头和实体内容之间要用空行隔开
响应消息的结构:一个状态行,若干消息头,以及实体内容,同样,消息头和实体内容之间要用空行隔开
请求方式有两种:GET请求和POST请求
GET请求,将参数附加在URL后,以键值对的方式,传送的数据是有限制的,一般在1kb以下
http://localhost:8080/ServletTest/loginServlet?user=bbb&password=123&submit=submit
POST请求,把参数插入在请求体里,传送的数据量比GET请求传送的多。
GET请求
1.在浏览器中输入URl地址或者单击网上的一个超链接时,浏览器发出的HTTP请求方法就是GET
2.如果网页的form表单指定了请求方法为GET,浏览器提交这个表单时,生成的HTTP请求消息的请求方式也是GET
3.使用GET请求为WEB服务器传参数格式:url?参数名1=参数1&参数名2&参数2
http://localhost:8080/ServletTest/loginServlet?user=bbb&password=123
4.使用GET请求传递的数据在1k以下,传递参数一般够用。
POST请求
1.网页表单form指定的请求方式为post,生成的HTTP请求使用POST方法
2.POST请求将form表单提交的数据作为HTTP消息的请求实体发送给WEB服务器,传递的数据比GET方法要大得多。
提交文件时,必须使用POST请求
8、service方法
service方法是响应请求的实际方法,每次客户端对Servlet的请求都调用该Servlet的service方法。
public void service(ServletRequest request, ServletResponse response) throws ServletException, IOException {}
service方法可以获取到请求的信息,也可以对请求作出响应,主要通过其参数ServletRequest和ServletResponse对象
ServletRequest和ServletResponse是Servlet容器实现的,目的是容器将接收到的HTTP请求封装到ServletRequest中传递给Servlet组件,解析ServletResponse中的响应转为HTTP响应。
客户<---(请求/响应)--->Servlet容器<----(ServletRequest/ServletResponse)---->Servlet组件
ServletRequest封装了请求信息,从中可以获取到任何的请求信息;
ServletResponse封装了响应信息,如果想给用户什么响应,可调用该类型对象的方法;
这两个接口的实现类,都是服务器给与实现的,并在服务器调用service方法时传入
ServletRequest
<form action="loginServlet" method="get">user:<input type="text" name="user"/>password:<input type="text" name="password"/><br/><br/>interesting:<input type="checkbox" name="interesting" value="reading"/>reading<input type="checkbox" name="interesting" value="game"/>game<input type="checkbox" name="interesting"/ value="movie">movie<input type="checkbox" name="interesting"/ value="tv">tv<input type="checkbox" name="interesting"/ value="running">running<input type="checkbox" name="interesting" value="sleep"/>sleeping<input type="submit" name="submit" value="submit"/></form>/loginServlet地址的映射
<servlet> <servlet-name>loginServlet</servlet-name> <servlet-class>com.cqupt.java.servlet.LoginServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>loginServlet</servlet-name> <url-pattern>/loginServlet</url-pattern> </servlet-mapping>LoginServlet类
@Overridepublic void service(ServletRequest request, ServletResponse response) throws ServletException, IOException {System.out.println("请求来了");//根据参数名获取参数值String user = request.getParameter("user");System.out.println("user:"+user);//根据一个参数名获取多个值的参数值String[] params = request.getParameterValues("interesting");for(String param : params){System.out.println("intersting:"+param);}//intersting:reading//intersting:game//intersting:sleepMap<String,String[]> maps= request.getParameterMap();for(Map.Entry<String,String[]> map:maps.entrySet()){System.out.println(map.getKey()+":"+Arrays.asList(map.getValue()));}//user:[wwa]//password:[12321]//interesting:[reading, game, sleep]//submit:[submit]}2.获取请求的URI,统一资源标示符,在这里是站点下的请求页面的资源地址
@Overridepublic void service(ServletRequest request, ServletResponse response) throws ServletException, IOException {//HttpServletRequest是ServletRequest的子接口,实现类可以为HttpServletRequest,获取更多方法HttpServletRequest httpServletRequest = (HttpServletRequest)request;//1.获取请求的uriString uri = httpServletRequest.getRequestURI();System.out.println(uri);//输出:/ServletTest/loginServlet//2.获取请求的提交方法:POST or GETString method = httpServletRequest.getMethod();System.out.println(method);//GET//3.若是一个GET请求,获取请求参数对应的那个字符串,即请求?后的字符串,若是POST方式,则获取值为nullString query = httpServletRequest.getQueryString();System.out.println(query);//user=wwa&password=12321&interesting=reading&interesting=game&interesting=sleep&submit=submit//4.获取servlet的映射路径,就是配置在servlet-mapping的url-patternString servletPath = httpServletRequest.getServletPath();System.out.println(servletPath);// /loginServlet}
ServletResponse
1.getWriter方法,返回PrintWriter对象,利用该对象的print方法,可以向浏览器页面打印信息。@Overridepublic void service(ServletRequest request, ServletResponse response) throws ServletException, IOException {//2.设置响应的内容类型response.setContentType("application/msword");//1.getWriter获取PrintWriter对象,该对象的print方法,可以把参数直接打印在浏览器页面上。PrintWriter pw=response.getWriter();pw.println("This is Servlet!");}
9、GenericServlet
前边讲到Servlet接口和ServletConfig接口,在Servlet的init方法中,参数是ServletConfig的对象。那么每次在获取Servlet的配置信息时,必须调用init方法,得到ServletConfig对象。这样,比较麻烦,所以,为了更直观的使用Servlet接口,就产生了GenericServlet抽象类,该类其实是对Servlet以及ServletConfig的封装,方便获取信息。public abstract class GenericServlet implements Servlet, ServletConfig, java.io.Serializable { private static final long serialVersionUID = 1L; private transient ServletConfig config; public GenericServlet() { } @Override public void destroy() { } @Override public String getInitParameter(String name) { return getServletConfig().getInitParameter(name); } @Override public Enumeration<String> getInitParameterNames() { return getServletConfig().getInitParameterNames(); } @Override public ServletConfig getServletConfig() { return config; } @Override public ServletContext getServletContext() { return getServletConfig().getServletContext(); } @Override public String getServletInfo() { return ""; } @Override public void init(ServletConfig config) throws ServletException { this.config = config; this.init(); } public void init() throws ServletException { // NOOP by default } public void log(String msg) { getServletContext().log(getServletName() + ": " + msg); } public void log(String message, Throwable t) { getServletContext().log(getServletName() + ": " + message, t); } @Override public abstract void service(ServletRequest req, ServletResponse res) throws ServletException, IOException; @Override public String getServletName() { return config.getServletName(); }}其中,service方法为抽象方法,所有根据特定协议实现的Servlet类,都必须实现覆盖并实现自己的service方法。
10、HttpServlet
HtttpServlet类是针对HTTP协议实现的Servlet类,继承自GenericServlet。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); }}
实现了GenericServlet的service方法,直接将ServletRequest和ServletResponse强转为HttpServletRequest和HttpServletResponse,
- Web开发(一)--Servlet
- Web开发(Servlet)(一)
- 用Servlet开发企业级三层Web应用(一)
- Servlet & Jsp Web——Servlet开发(一)
- Servlet开发入门(一)
- Servlet开发(一)如何在Myeclipse 中使用tomcat(配置tomcat,发布web项目)
- Web开发基础之Servlet学习总结(一)
- Java web 开发笔记 第五章 Servlet编程一
- web(二)、Servlet(一)
- 复习java web 之 servlet(一)
- Java Web学习笔记(一)Servlet
- web开发(一)
- web开发(一)
- web开发(一)
- Java Web开发基础(1)-Servlet
- Java Web开发基础(1)-Servlet
- Servlet(1)web开发入门
- Web开发基础--Servlet
- python 异常处理
- 一次完整的HTTP请求所经历的7个步骤
- spring 配置内存溢出监听器、文件上传、ie下载json问题
- 一起看代码来玩玩QT之13 IO(two TCPServer TcpClient TcpScoket)
- 利用Javascript实现隔行变色
- Web开发(一)--Servlet
- poj 2127 Greatest Common Increasing Subsequence(最长公共上升子序列dp)
- 6.Sense编辑器(Sense Editor)
- JavaSE学习笔记_5:Java多态
- Servlet的一些笔记
- 产品经理必备软件——Axure使用详解(1)
- day05—html之JSP&Servlet进阶
- 类似购物车的计算
- Spring+Mybatis整合(1)- SSM(四)