servlet和CGI
我们知道Web服务器(如apache)只擅长提供静态页面,因此在动态应用场景,Web服务器会把请求转发给另一个能够动态处理的辅助应用(helper app),这个辅助应用就是CGI,而CGI可以用C、Python、PHP、Perl等等来实现。请求和应答如下图:
而Java的CGI实现就是Servlet,如下图:
由于servlet没有main()方法,因此它受控于web Container app(容器),而Tomcat就是一个这样的容器。Tomcat容器的作用提供通信支持、声明周期管理、多线程支持、声明方式实现安全、JSP支持等,看参考Tomcat初识。它的流程是这样的:
我们使用Eclipse+Maven来构建Java的servlet应用,以前曾经写过一篇超入门级的:maven + eclipse + tomcat 实战JSP,文章里使用的maven构建再导入到eclipse中,当然你也可以从eclipse来使用maven插件来构建项目,我的测试项目如下:
如果提示错误
The superclass "javax.servlet.http.HttpServlet" was not found on the Java Build Path
请参考这里解决:http://www.oseye.net/question/179
默认的部署文件web.xml
- <!DOCTYPE web-app PUBLIC
- "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
- "http://java.sun.com/dtd/web-app_2_3.dtd" >
- <web-app>
- <display-name>Archetype Created Web Application</display-name>
- </web-app>
建立完毕后我们可以通过Run As -> Run on Server就可以浏览index.jsp了(我用的Eclipse是Eclipse Java EE IDE for Web Developers.),显示“Hello World!”。
添加Servlet:项目"mytest"右键->New->Other->Web->Servlet,ClassName填上“HelloOther”,Next会让设置URL路径,初始值等,再Next可以看到你需要的方法如doGet、doPost等,Finish后你会看到web.xml:
如上述原理,当Clinet请求”/HelloOther“时,Web Container会在部署描述文件web.xml中寻找servlet-name为的HelloOther的servlet配置,再找到处理这个请求的servlet类“net.oseye.web.HelloOther”。
- <!DOCTYPE web-app PUBLIC
- "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
- "http://java.sun.com/dtd/web-app_2_3.dtd" >
- <web-app>
- <display-name>Archetype Created Web Application</display-name>
- <servlet>
- <servlet-name>HelloOther</servlet-name>
- <display-name>HelloOther</display-name>
- <description></description>
- <servlet-class>net.oseye.web.HelloOther</servlet-class>
- </servlet>
- <servlet-mapping>
- <servlet-name>HelloOther</servlet-name>
- <url-pattern>/HelloOther</url-pattern>
- </servlet-mapping>
- </web-app>
在net.oseye.web.HelloOthe类的doGet方法体中编码:
你访问”/HelloOther“就能看到结果了。
- response.getWriter().println("Hello Other!");
可以使用mvn命令创建WAR包:
也可以使用Eclipse的Export菜单来导出WAR包。
- mvn package
PS:这里我们只使用Tomcat,没看到使用Web Server呀?这是因为Tomcat本身就具有基本的HTTP服务器的功能,只是没有Apache等专业的Web Server健壮和完整。
简单的MVC
前面的示例我们在servlet中使用了
但如果是整个HTML页面将会非常麻烦,因此我们考虑使用MVC架构,servlet充当Controller角色,JSP充当View,Java Class充当Model,结构图如下:
- response.getWriter().println("Hello Other!");
通过Controller(servlet)从Model(DB)中获取数据,然后把数据包装成Servlet的请求属性,然后把请求(request和reponse)转发至Jsp(View),JSP生成一个HTML页面,并使用应答对象(response)返回至容器,示例图如下:
接着上面的示例代码,在net.oseye.web.HelloOthe类的doGet方法体中编码:
HelloOther.jsp的代码如下:
- request.setAttribute("word", "Hello Other!");
- RequestDispatcher view=request.getRequestDispatcher("HelloOther.jsp");
- view.forward(request, response);
这就实现了MVC结构,项目结构图如下:
- <%@ page language="java" contentType="text/html; charset=ISO-8859-1"
- pageEncoding="ISO-8859-1"%>
- <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
- <html>
- <head>
- <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
- <title>Insert title here</title>
- </head>
- <body>
- <%=request.getAttribute("word")%>
- </body>
- </html>
后记
可以在net.oseye.web.HelloOther的doGet中编码获取:
- <!DOCTYPE web-app PUBLIC
- "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
- "http://java.sun.com/dtd/web-app_2_3.dtd" >
- <web-app>
- <display-name>Archetype Created Web Application</display-name>
- <context-param>
- <param-name>email</param-name>
- <param-value>kevin@oseye.net</param-value>
- </context-param>
- <servlet>
- <servlet-name>HelloOther</servlet-name>
- <display-name>HelloOther</display-name>
- <description></description>
- <servlet-class>net.oseye.web.HelloOther</servlet-class>
- <init-param>
- <param-name>tel</param-name>
- <param-value>13910567832</param-value>
- </init-param>
- </servlet>
- <servlet-mapping>
- <servlet-name>HelloOther</servlet-name>
- <url-pattern>/HelloOther</url-pattern>
- </servlet-mapping>
- </web-app>
- String tel=getServletConfig().getInitParameter("tel");
- String email=getServletContext().getInitParameter("email");
- response.getWriter().println("tel:"+tel+",email:"+email);
- PrintWriter pr=response.getWriter();
- ServletOutputStream os=response.getOutputStream();
- request.getParameter(arg0) //获取get/post参数值
- request.getHeader(arg0) //获取头信息
- request.getCookies() //获取cookies
- request.getSession() //获取session
- request.getRequestDispatcher(arg0) //分派请求
- response.sendRedirect(String arg0) //重定向
- response.setHeader(String arg0, String arg1) //设置头信息,如果重复就替换
- response.addHeader(String arg0, String arg1) //添加头信息
- response.setContentType(arg0) //设置ContentType,避免手动拼写错误