欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

servlet基础

程序员文章站 2022-05-11 23:45:15
...

一. 背景知识
1. 常用的Web服务器
    ~ IIS
    ~ Apache
    ~ Tomcat
2. 通常的动态网页技术
    ~ CGI (Common GateWay Interface)
    ~ API常用的有(NSAPI, ISAPI)
    ~ ASP (Active Server Page)
    ~ PHP (Personal Home Page) ----------->LAMP(Linux+apache+mysql+php)
    ~ JSP/Servlet (Java Server Page)

二. Tomcat的安装与配置
1. 解压到相应目录。如C:\tomcat
2. tomcat6的目录结构
    ~bin: 包含tomcat可执行的二进制文件。常用的有startup.bat, shutdown.bat
    ~conf: 包含tomcat的配置文件。如context.xml, server.xml, web.xml
    ~lib: 包含tomcat所需的Jar文件。
    ~logs: 日志文件
    ~temp: 临时文件
    ~webapps: web应用主目录
    ~work: 保存缓存文件
3. tomcat的配置
    ~配置JAVA_HOME系统环境变量,变量值指向安装的JDK路径。如C:\jdk1.6.0_17
    ~更改端口:打开conf\server.xml, 可把默认8080端口改成80(也可保持默认8080端口不变),在此不变。
 <Connector port="80" protocol="HTTP/1.1" connectionTimeout="20000" redirectPort="8443" URIEncoding="UTF-8" />
    ~自动加载: 打开conf\context.xml, 在Context属性里添加属性reloadable="true"
 <Context reloadable="true">

三. HTTP协议基础
1. HTTP(Hypertext Transfer Protocol, 超文本传输协议)
2. HTTP是以明文方式发送数据的
3. 用于从WWW服务器传输超文本到本地浏览器的传输协议
4. 现在广泛使用的版本HTTP/1.1

四. Servlet简介
1. Servlet是服务器小应用程序
2. 用来完成B/S架构下,客户端请求的响应处理
3. 平*立,性能优良,能以线程方式运行
4. Servlet API为Servlet提供了统一的编程接口
5. Servlet一般在容器中运行
6. 常见的Servlet容器
    ~Tomcat
    ~Jetty/Resin

五. Web Application的概念
1. Web Application Name
1.1 WEB-INF
 ~web.xml: 该web app的配置文件
 ~lib目录: 该web app用到的库文件
 ~classes目录: 存放编译好的servlet
1.2 META-INF
 ~存放该web app的上下文信息,符合J2EE标准
2. Web Application可以直接放在webapp下面
3. 也可以通过配置文件指定到其它目录<host>里面
 <Context path="/虚拟路径名" docBase="目录位置" debug="0" reloadable="true"/>

六. Servlet应用程序实例
1. 建立所需的目录结构
    ~在tomcat安装目录的子目录webapps下新建文件夹hello
    ~在hello文件夹下新建WEB-INF文件夹和index.html文件
    ~在WEB-INF文件夹下新建classes和lib文件夹,以及web.xml文件
2. 编写HelloWorldServlet.java,并把编译好的class文件放到classes目录下
import java.io.IOException;
import java.io.PrintWriter;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class HelloWorldServlet extends HttpServlet {

 @Override
 protected void doGet(HttpServletRequest request,HttpServletResponse response) throws ServletException, IOException {
  response.setContentType("text/html;charset=gbk");
  PrintWriter out = response.getWriter();
  out.println("<html><head></head><body><center><font color='red'>
    HelloWorldServlet</font></center></body></html>");
  out.flush();
  out.close();
 }

 private static final long serialVersionUID = 1L;
 protected void doGet(HttpServletRequest request,HttpServletResponse response) throws ServletException, IOException {
  doGet(request,response);
 }
}
3. 配置web.xml
<?xml version="1.0" encoding="ISO-8859-1"?>
<web-app xmlns="http://java.sun.com/xml/ns/javaee"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" version="2.5">
                                                                     
    <servlet>
        <servlet-name>hello</servlet-name>
        <servlet-class>HelloWorldServlet</servlet-class>
    </servlet>

    <servlet-mapping>
        <servlet-name>hello</servlet-name>
        <url-pattern>/hello.do</url-pattern>
    </servlet-mapping>
  
</web-app>
4. 编写index.html
<html>
 <head>
  <title>this is a test page</title>
 </head>
 <body>
  <form method="post" name="form1" action="/hello/hello.do" >
   用户名:
   <input type="text" name="username" size=20>
   <br>
   密码:
   &nbsp;
   <input type="password" name="password" size=20>
   <br>
   &nbsp;&nbsp;&nbsp;&nbsp;
   <input type="submit" name="submit" value="提交">
   &nbsp;&nbsp;&nbsp;
   <input type="reset" name="reset" value="重置">
  </form>
 </body>
</html>
5. 在浏览器输入http://localhost:8080/hello/index.html点击提交按钮或者直接输入http://localhost:8080/hello/hello.do
 页面输出HelloWorldServlet
6. 注意
    ~浏览器地址栏输入的访问路径区分大小写,hello.do不能写成Hello.do
    ~访问的路径由 <url-pattern>指定
    ~ <url-pattern>中的/hello.do表示的是hello这个web应用下的hello.do
    ~表单中action="/hello.do"表示访问域名下的hello.do,所以应写出action="/hello/hello.do"或者action="hello.do"(相对index.html的路径)

七. Servlet的生命周期
1. 生命全过程
    ~加载 ClassLoader
    ~实例化 new
    ~初始化 init(ServletConfig)
    ~处理请求 service doGet doPost
    ~退出服务 destory()
2. 只有一个对象
3. API中的过程:
    ~init()  //只执行一次,第一次初始化的时候
    ~public void init(ServletConfig config) throws ServletException
    ~service()
    ~public void service(ServletRequest request,ServletResponse response) throws ServletException, java.io.IOException
    ~destory() //webapp 退出的时候
    ~public void destory()

八. 为什么有两个init()方法
1. void init(ServletConfig config): Called by the servlet container to indicate to a servlet that the servlet is being placed into service.
2. void init(): A convenience method which can be overriden so that there's no need to call super.init(config).
3. ServletConfig 用法示例
3.1 把以下内容copy到web.xml文件中的<servlet></servlet>标签内.
    <servlet>
        <servlet-name>hello</servlet-name>
        <servlet-class>HelloServlet</servlet-class>
        <init-param>
            <param-name>name</param-name>
   <param-value>翁子轩</param-value>
        </init-param>
        <init-param>
   <param-name>age</param-name>
        <param-value>23</param-value>
        </init-param>
    </servlet>
3.2 在HelloServlet.java文件的doGet方法体内添加如下代码:
 response.setContentType("text/html;charset=gbk");
 PrintWriter out = response.getWriter();
 String s = this.getServletConfig().getInitParameter("name");
 String s1 = new String(s.getBytes("ISO-8859-1"),"GBK");
 out.println("<html><head>HelloServlet</head><body>"+s1+"</body></html>");
 out.flush();
 out.close();
3.3 在浏览器中输入http://localhost:8080/hello/hello.do, 页面输出结果为“HelloServlet翁子轩”
3.4 要对配置文件中的参数进行遍历,把上面的代码改写如下:
 response.setContentType("text/html;charset=gbk");
 PrintWriter out = response.getWriter();
 Enumeration e = this.getServletConfig().getInitParameterNames();
 for(;e.hasMoreElements();) {
  String name = e.nextElement().toString();
  String value = this.getServletConfig().getInitParameter(name);
  value = new String(value.getBytes("ISO-8859-1"),"GBK");
  out.println(value);
 }
 out.flush();
 out.close();
 //页面输出结果为"23 翁子轩"

九. 从页面中获取参数
1. 解决参数提交的乱码问题
1.1 解决post方式提交内容的乱码,且一定要写在存取第一个参数之前
 request.setCharacterEncoding("GBK");
1.2 解决get方式提交内容的乱码。修改server.xml,把URIEncoding设定为"GBK",然后重启tomcat.
<Connector port="8080" protocol="HTTP/1.1" connectionTimeout="20000" redirectPort="8443" URIEncoding="GBK" />
1.3 从页面中获取参数
 request.getParameter("username");

十. Cookie
1. 服务器可以向客户端写内容
2. 只能是文本内容
3. 客户端可以阻止服务器写入
4. 只能拿自己webapp写入的东西
5. Cookie分为两种
    ~属于窗口/子窗口(放在内存中的)
    ~属于文本(有生命周期的)
6. 一个servlet/jsp设置的cookies能够被同一个路径下面或者路径下面的servlet/jsp读到(路径=URL)(路径!=真实文件路径)
7. 向客户端写入Cookie
 for(int i=0; i<3; i++) {
  Cookie cookie = new Cookie("Session-Cookie-"+i, "Cookie-Value-S"+i);
  response.addCookie(cookie);  //未设置生命周期的Cookie只存在于内存中

  cookie = new Cookie("Persistent-Conkie-"+i, "Cookie-Value-P"+i);
  cookie.setMaxAge(3600);  //设置Cookie的生命周期
  response.addCookie(cookie);
 }
8. 读取客户端的Cookie
 Cookie[] cookies = request.getCookies();
 if(cookies !=null) {
  Cookie cookie;
  for(int i=0; i<cookies.length; i++) {
   cookie = cookies[i];
   out.println(cookie.getName());
   out.println(cookie.getValue());
  }
 }

十一. Session
1. 服务器的一块内存(存key-value)
2. 和客户端窗口对应(子窗口)(独一无二)
3. 客户端和服务器有对应的SessionID
4. 客户端向服务器端发送SessionID的时候有两种方式:
    ~cookei(内存cookie)
    ~rewriten URL
 response.encodeURL(request.getRequestURL().toString())
5. 浏览器禁掉cookie, 就不能使用session(使用cookie实现的session)
6. 如果想安全的使用session(不论客户端是否禁止cookie). 只能使用URL重写(大大增加编程负担), 所以很多网站要求客户端打开cookie.
7. ServletContext: ServletContext application = this.getServletContext();

十二. Servlet连接Mysql数据库
1. 启动mysql,并在其中建立相应的数据库和表
2. 把jdbc的驱动复制到lib目录下(mysql-connector-java-3.1.13-bin.jar)
3.
 Connection conn = null;
 Statement stmt = null;
 ResultSet rs = null;
  
 response.setContentType("text/html");
 response.setCharacterEncoding("gb2312");
 PrintWriter out = response.getWriter();
  
 out.println("<table border=1>");
 out.println("<tr><td>Content:</td></tr>");
 try {
  Class.forName("com.mysql.jdbc.Driver");
  conn = DriverManager.getConnection("jdbc:mysql://localhost/bbs?user=root&password=12345678");
  stmt = conn.createStatement();
  rs = stmt.executeQuery("select * from article");
  while(rs.next()){
   out.println("<tr>");
   out.println("<td>" + rs.getString("cont") + "</td>");
   out.println("</tr>");
  }
  out.println("</table>");
 } catch (ClassNotFoundException e) {
  e.printStackTrace();
 } catch (SQLException e) {
  e.printStackTrace();
 } finally {
  try {
   if(rs != null) {
    rs.close();
    rs = null;
   }
   if(stmt != null) {
    stmt.close();
    stmt= null;
   }
   if(conn != null) {
    conn.close();
    conn = null;
   }
  } catch (SQLException e) {
   e.printStackTrace();
  }
 }
4. 注意:仔细检查连接串;确认有没有这个表;如果出错,先去后台看报错信息;确认mysql以及启动;把jdbc的驱动复制到lib目录下

十三. Servlet中使用javabean
1. 广义的javabean = 普通java类
    狭义的javabean = 符合Sun JavaBean标准的类
2. 在Servlet中使用Bean和在通常程序中使用Bean类似
    ~属性名称第一个字母必须小写,一般private
    ~一般具有getters and setters
    ~要具有一个参数为空的构造方法
    ~但Bean不应具有GUI表现
    ~一般是用来实现某一业务逻辑或取得特定结果

十四. JSP简介
1. JSP----Java Server Pages
2. 拥有servlet的特性与优点(本身就是一个servlet)
3. 直接在HTML中内嵌JSP代码
4. JSP程序由JSP Engine先将它转换Servlet代码,接着将它编译成类文件载入执行
5. 只有当客户端第一次请求JSP时,才需要将其转换、编译
6. 优点:
 ~性能优良----优于CGI, PHP, ASP
 ~平台无关性----操作系统无关,Web服务器无关
 ~可扩展性----tag的扩展机制,简化页面开发

十五. JSP编程----基本语法
1. JSP传统语法
1.1 Declaration
 ~基本语法:<%! %>
 ~说明:在此声明的变量、方法都会被保留成唯一的一份,直到JSP程序停止执行
 ~例如:
  <%!
   int i;
   public void setName() {... ...}
  %>
1.2 Scriptlet
 ~基本语法:<%程序代码区%>
 ~可以放入任何的Java程序代码
 ~例如:
  <%
   for(int i=0; i<10; i++) {... ...}
  %>
1.3 Expression
1.4 Comment
1.5 Directives
 ~Directive(编译指令)相当于在编译期间的命令
 ~格式:<%@Directive 属性="属性值"%>
 ~常见的Directive:
  page:
   $ 指明与JSP Container的沟通方式
   $ 基本格式:
    <%@page language="script language"
     extends="className"
     import="importList"
     buffer="none|kb size" ----none:不缓冲,默认8k
     session="true|false"  ----是否可以使用session,默认true
     autoFlush="true|false" ----缓冲器是否自动清除,默认true
     isThreadSafe="true|false" ----默认false(永远不要设成true)
     info="info Text"  ----任何字符
     errorPage="errorPageUrl"
     isErrorPage="true|false"
     contentType="contentTypeInfo"
     pageEncoding="gb2312"
    %>
  include
   $ 将指定的JSP程序或者HTML文件包含进来
   $ 格式:<%@include file="fileURL" %>
   $ JSP Engine会JSP程序的转换时期先把file属性设定的文件包含进来,然后开始执行转换及编译的工作。
      (原封不动的把文件的代码copy到该位置,然后进行转换和编译,只生成一个java和class)
   $ 限制:不能向fileURL中传递参数, 如不能abc.jsp?user=aaa
  taglib
1.6 Action动作指令
 ~Action(动作指令)在运行期间的命令
 ~常见的:
  jsp:useBean
   $ jsp:setProperty
   $ jsp:getProperty
  jsp:include
   $ <%@include和jsp:include的区别
   -------------------------------------------------------------------------------------------------------------------
   <%@include file="date.jsp"%> <jsp:include page="date.jsp" flush="true"
   -------------------------------------------------------------------------------------------------------------------
   include编译指令是在JSP程序的转换 而include指令在转换时期是不会被编译的,
   时期就将file属性所指定的程序内容 只有在客户端请求时期如果被执行到才会被
   嵌入,然后再编译执行  动态的编译载入
   -------------------------------------------------------------------------------------------------------------------
   只生成一个class文件   多个
   -------------------------------------------------------------------------------------------------------------------
   include不能带参数   <jsp:include>可以
   -------------------------------------------------------------------------------------------------------------------
   同一个request对象   不同的request对象,可以取得包含它的页面
       的参数,并添加了自己的参数
   -------------------------------------------------------------------------------------------------------------------
  jsp:forward
   $ jsp:param
   $ forward和sendredirect的区别
   -------------------------------------------------------------------------------------------------------------------
   Sendrediret   Forward
   -------------------------------------------------------------------------------------------------------------------
   是不同的request   虽然是不同的对象,但是可以取到上一个
       页面的内容
   -------------------------------------------------------------------------------------------------------------------
   send后的语句会继续执行,除非return farward后的语句不会继续发送给客户端
   -------------------------------------------------------------------------------------------------------------------
   速度慢    速度快
   -------------------------------------------------------------------------------------------------------------------
   需要到客户端的往返,可以转到任何页面 服务器内部转换
   -------------------------------------------------------------------------------------------------------------------
   地址栏有变化   地址栏没有变化
   -------------------------------------------------------------------------------------------------------------------
   可以传参数,直接写在url后面  可以传参数
   -------------------------------------------------------------------------------------------------------------------
   /代表的是http://127.0.0.1/  /代表的是http://127.0.0.1/hello,并且只能
       以/开头
   -------------------------------------------------------------------------------------------------------------------
  jsp:plugin
   $ 嵌入applet
1.7 内置对象
2. JSTL
3. JSF

十六. JSP中使用javabean
1. jsp:useBean各项参数含义
    ~id: 对象实例名称
    ~scope: Bean作用的范围,默认为page, 对整个jsp页面有效
    ~class: Bean类名称(全名)
    ~type: Bean实例类型,可以是本类,或其父类,或实现的接口,默认为本类
2. Scope各项参数的意义
    ~page: 仅涵盖使用JavaBean的页面
    ~request: 有效范围仅限于使用JavaBean的请求
    ~session: 有效范围在用户整个连接过程中(整个会话阶段均有效)
    ~application: 有效范围涵盖整个应用程序。也就是对整个网站均有效

十七. 乱码问题
1. 场合:页面本身有中文的时候
    解决办法:
 servlet: response.setContentType("text/html;charset=gbk");
 Jsp: <%@page contentType="text/html;charset=gb2312"%>
    注意:一定要写在PrintWriter out = response.getWriter(); 之前
2. 场合:解决get方式的乱码问题
    解决办法:修改server.xml------->URIEncoding="GBK"
3. 场合:解决post方式提交内容的乱码
    解决办法:request.setCharacterEncoding("GBK");
    注意:一定要写在存取第一个参数之前,不要调用response.setCharcterEncoding("GBK");
4. 场合:<jsp:param name="user" value="<%=s%>"/>, url地址包含中文参数
    解决办法:<%request.setCharacterEncoding("GBK");%>