Servlet学习笔记

来源:互联网 发布:没有网络监控怎么安装 编辑:程序博客网 时间:2024/05/20 14:16

Web应用程序的目录结构

/root   Web 应用程序的根目录
/root/WEB-INF   存放Web应用程序的部署描述文件
/root/WEB-INF/classes   存放Servlet和其他有用的Class文件
/root/WEB-INF/lib    存放Web应用程序需要用的jar文件
/root/WEB-INF/web.xml   Web应用程序的部署描述文件

***************************************************************************************************
<form action="abc" method="POST" enctype="multipart/form-data">
action: 表单提交给服务器的哪个资源处理
method: 提交方式  "POST","GET"
 GET---->通过URL提交表单信息
 POST--->通过Http Body提交表单信息
enctype: multipart/form-data 通常可用于上传文件


web.xml 中的配置
--------------------------------------------------
  <servlet>
    <servlet-name>myServlet</servlet-name>    ---->Servlet name
    <servlet-class>com.MyFirstServlet</servlet-class>   --->Servlet class的位置
  </servlet>
  <servlet-mapping>
    <servlet-name>myServlet</servlet-name>
    <url-pattern>/hello</url-pattern>     --->Servlet的映射名,Browser通过此名字来访问Servlet
-------------------------------------------------------

解决Servlet中的中文乱码问题:
1、静态中文信息乱码
response.setContentType("text/html; charset=gbk");
2、中文输入乱码
request.setCharacterEncoding("gbk");
String name =new String(request.getParamete("name").getBytes("iso-8859-1"));

servlet中输出流的默认字符编码是ISO-8859-1的
***************************************************************************************************


HttpServletRequest ---> 对象由Web Container封装用户Http请求数据报而成,
可通过它获得所有跟用户请求数据报相关的信息
request.getParameter()              ------>获取输入域的值,如果有多个的话就获取第一个

request.getParameterValues("phone")    ------>几个输入域同名时,获得提交信息,返回String类型的数组

request.getParameterNames()         ------->获取输入域的名字,返回Enumeration枚举

request.getRemoteAddr()             ------>客户端IP
       
request.getRemotePort()      ------>客户端端口号
      
request.getLocalAddr()              ------>服务器端IP

request.getLocalPort()              ------>服务器端口号

---------------------------------------------------------
Enumeration headNames=request.getHeaderNames();            ---->获取所有消息报头的名字的枚举
while(headNames.hasMoreElements()){
      String name=(String)headNames.nextElement();            ----->获取报头名
      String value=request.getHeader(name);                   ----->根据报头名取其
      out.println("<tr>");
      out.println("<td>"+name+"</td>");
      out.println("<td>"+value+"</td>");
      out.println("<tr>");
  }
--------------------------------------------------------------
***************************************************************************************************
Servlet的生命周期

(1)加载和实例化
Servlet容器负责加载和实例化一Servlet,当Servlet容器启动时或在容器检测到需要这个 Servlet来响应一个请求时,创建Servlet实例

(2)初始化
在Servlet实例化后,容器必须调用Servlet的init()方法初始化这个对象,目的是为了Servlet对象在客户请求前完成一些初始化工作,如建立数据库连接,获取配置信息.

(3)请求处理
容器调用Servlet的service()方法

(4)服务终止
Servlet实例在销毁之前容器调用Servlet的destroy()方法

***************************************************************************************************
Servlet上下文

一个ServletContext对象表示一个Web应用程序的上下文
ServletContext对象是Web服务器中的一个已知路径的根,如http://localhost:8080/demo/index.html,Servlet上下文被定位于http://localhost:8080/demo

ServletContext---->对应整个Web Application运行环境,可以用来读取web.xml
中配置的应用初始信息,写日志,共享数据等,ServletContext被所有Servlet共享

如何获得ServletContext对象
1、config.getServletContext()
2、this.getServletContext()


getAttribute(String)         ----->读取共享属性
setAttribute(String,String)         ----->设置共享属性
getInitParameter(String)     ----->读取初始参数


请求转发

如何获得RequestDispatcher对象
1、request.getRequestDispatcher(String page)   ---->相对路径
2、ServletContext.getRequestDispather(String page)  ---->绝对路径

ServletContext context=getServletContext();
RequestDispatcher rd=context.getRequestDispatcher("/cg.html");
rd.forward(request,response);
rd.include(request,response);

response.sendRedirect("/cg.html");   --->重定向

*在转发之后,后面的语句如果没用的话,最好用一个return 语句,避免后面的语句继续执行。

利用ServletContext写日志
log(String info)

***************************************************************************************************
动态部署

<Host name="localhost" apBase="webapps"
unpaclWARs="true" autoDeplou="true"
cmlValidation="false" xmlNamespaceAware="false">
<Context path="目录名" docBase="路径" reloadable="ture"/>
</Host>


  <servlet>
    <servlet-name>lifeservlet</servlet-name>
    <servlet-class>lifeapp.LifeServlet</servlet-class>
    <load-on-startup>3</load-on-startup>
  </servlet>

load-on-startup: 表示Servlet在部署时通过ClassLoader直接载入并初始化,
数值越低,载入的优先级越高


init()--->对Servlet将要使用的资源作初始化,如读入配置文件信息等
init(ServletConfig config)

  <servlet>
    <servlet-name>lifeservlet</servlet-name>
    <servlet-class>lifeapp.LifeServlet</servlet-class>
    <init-param>
      <param-name>email</param-name>
      <param-value>hr@tarena.com.cn</param-value>
    </init-param>
    <load-on-startup>5</load-on-startup>
  </servlet>

String email=config.getInitParameter("email");

ServletConfig---->对应某个具体的Servlet,主要用来读取web.xml中配置的
Servlet初始信息,不能被其它Servlet共享

如何获得ServletConfig对象
1、init(ServletConfig config)
2、this.getServletConfig()


***************************************************************************************************
Servlet的数据库访问

4种方法:
1:JDBC-ODBC桥
效率底,需要客户机上有JDBC-ODBC驱动、ODBC驱动程序和相应数据库的本地API

2:部分本地API,部分JAVA驱动程序
需要在客户机上安装本地JDBC驱动程序和特定厂商的本地API

3:JDBC网络纯JAVA驱动程序
利用中间件的应用服务器来访问数据库

4:本地协议纯JAVA驱动程序
效率最高,访问不同的数据库需要不同的JDBC驱动


访问数据库的步骤:
1.加载并注册数据库驱动
2.加载与注册JDBC驱动
3.建立到数据库的连接
4.访问数据库

---------------------------------------------------------------
Class.forName("Driver");
Connection conn=DriverManager.getConnection("url");
Statement stmt=conn.createStatement();
ResultSet rs=stmt.executeQuery("sql语句");
---------------------------------------------------------

常用的Driver
com.microsoft.jdbc.sqlserver.SQLServerDriver
oracle.jdbc.driver.OracleDriver
com.mysql.jdbc.Driver


常见URL

jdbc:microsoft:sqlserver://localhost:1433:databasename=pubs
jdbc:oracle:thin:@localhost:1521:ORCL 
jdbc:mysql://localhost:3306/databasename

 

Statement
createStatement()       ----->建立一个Statement对象,用于发送SQL语句
executeQuery()           ----->执行指定的SQL语句,返回一个ResultSet对象
executeUpdate()           ----->执行INSERT、UPDATE、DELETE语句,也用于执行SQL DDL语句
addBatch(sql);         ----->将插入数据的SQL语句组成一个命令列表 
executeBatch();         ------>批量执行SQL语句


ResultSet
通过Statement对象的executeQuery()方法创建一个ResultSet对象,它以逻辑表格的形式封装了执行数据库的结果集,初始,游标在第一行之前

next()     -----> 移动游标到下一行,返回一个boolean值
getString()      ----->获取String 类型的数据,还有获取其他类型数据的方法getXXX()
                       有两中方式,getString(int Index) / getString(String 列名)


PreparedStatement
用来执行只是参数不同的SQL语句,参数用(?)表示
setXXX(index,value)             ----->设置参数,第一个参数是索引,第二个是值


pstmt=conn.prepareStatement("INSERT account VALUES(?,?)");
pstmt.setString(1,"甲");
pstmt.setFloat(2,500.00f);
pstmt.executeUpdate();


事务回滚
conn.setAutoCommit(false)             ------>设置自动提交为false,默认为true
conn.commit()                         ------>提交
conn.rollback()                       ------>回滚


可滚动的结果集

createStatement(int resultSetType,int resultSetConcurrency)

resultSetType有3个取值:
TYPE_FORWARD_ONLY            ------>只能向前移动
TYPE_SCROLL_INSENSITIVE      ------>结果集可滚动,但对数据库变化不敏感
TYPE_SCROLL_SENSITIVE        ------>结果集可滚动,并对数据库变化敏感

resultSetConcurrency有2个取值
CONCUR_READ_ONLY             ------>结果集不用于更新数据库
CONCUR_UPDATABLE             ------>结果集用于更新数据库

更新数据
updateXXX();           ----->更新当前行
updateRow();           ----->传递到数据库

插入一行
moveToInsertRow();           ----->移动到要插入行
updateXXX();                 ----->更新数据
inserRow();                  ----->将新行传递到数据库

删除一行
deleteRow();

 

JDBC数据源和连接池

利用DataSource建立数据库连接,不需要在客户程序中加载JDBC驱动,也不用DriverManager类,只要通过向一个JNDI服务器查询得到DataSource对象,
调用DataSource对象的getConnection()来建立数据库连接

DataSource接口的3种实现

基本实现                   ------->产生一个标准的连接对象
连接池实现                 ------->产生一个自动参与要连接池的连接对象,需要和一个中间连接池管理器一起工作
分布式事务实现             ------->产生一个用于分布式事务的连接对象,几乎总是参与要连接池

--------------------------------------------------------------------------------
在/Tomcat 5.5/conf/Catalina/localhost添加 (项目名)Demo2.xml,
<?xml version="1.0" encoding="UTF-8"?>
<Context>
<Resource name="jdbc/(项目名)Demo2" auth="Container"
              type="javax.sql.DataSource" maxActive="100" maxIdle="30" maxWait="1000" username="root" password="root"
               driverClassName="com.mysql.jdbc.Driver" url="jdbc:mysql://localhost:3306/hwc?autoReconnect=true"/>
</Context>
--------------------------------------------------------------------------------------

测试类
Context ctx=new InitialContext();
DataSource ds=(DataSource)ctx.lookup("java:comp/env/jdbc/Demo2");
conn=ds.getConnection
-------------------------------------------------------------------------------------------

 

配置Tomcat5.5连接池与数据源
1、进入Tomcat管理页面(http://localhost:8080/admin)
2、找到对应的Web App
 "Tomcat Server---->Service---->Host---->Context(/userWeb)"
 or
 "Resources---->datasource"

3、选择"resource---->datasource"
 DataSource Action---->"Create New DataSource"

4、配置数据源属性
 JNDI Name:    jdbc/myds
 Data Source URL:   jdbc:mysql://localhost/tarena
 JDBC Driver Class: com.mysql.jdbc.Driver
 User Name:    ur_username
 Password:     ur_password

5、"save---->commit changes"

OK!

查看$TomcatHome/conf/server.xml,$TomcatHome/webapps/ur_web/META-INF/context.xml


通过JNDI访问数据源

import javax.naming.*;
Context ic=new InitialContext();
DataSource ds=(DataSource)ic.lookup("java:comp/env/jdbc/myds");

Connection con=ds.getConnection();代替DriverManager.getConnection();


资源引用
web.xml需要作如下配置:
  <resource-ref>
    <res-ref-name>jdbc/myds</res-ref-name>
    <res-type>javax.sql.DataSource</res-type>
    <res-auth>Container</res-auth>
    <res-sharing-scope>Shareable</res-sharing-scope>
  </resource-ref>


***************************************************************************************************
Cookie:客户端保存状态的机制,通过cookie文件来记录信息
Cookie编程:
从request中获得cookie:Cookie[] request.getCookies()
创建一个Cookie:        new Cookie(String name,String value)
获得cookie中的信息:    Cookie.getValue() getName()
设置cookie的有效时间: Cookie.setMaxAge(int seconds)
把cookie写回客户端:    response.addCookie(Cookie cookie)


URL重写
<a href="+response.encodeURL("co2")+">access again</a>

在写回客户端之前要先设置有效时间,如果不设置的话,在Cookie文件夹是没有生产Cookie文件的


session状态维护
Session:服务器端保存状态的机制,通过HttpSession对象来记录信息
Session编程:
获得Session: request.getSession()   getSession(boolean b)
Session存信息:  HttpSession.setAttribute(String name,Object o)
Session取信息:  Object HttpSession.getAttribute()
设置Session有效时间:  
HttpSession.setMaxInactiveInterval(int interval)
手工销毁Session:   HttpSession.invalidate()
判断Session是否新建:    boolean HttpSession.isNew()
获得SessionID:          HttpSession.getId()


客户端维护SessionID:
1、通过Cookie来维护SessionID
Web Server生成Session对象后,每次作response时,会自动把SessionID发回到客户端,
客户端把SessionID记入会话Cookie,下次请求时自动带上
Cookie: JSESSIONID=011EC87CC17C8709058657BF895C6D32

2、重写URL来维护SessionID
把sessionID加到请求的URL中
out.println("<a href="+response.encodeURL("gift2")+">access again</a>");
url--->http://127.0.0.1:8082/stateWeb/gift2;jsessionid=04E2B1AD30782C5DE029FC5C83486CCC
jsessionid=04E2B1AD30782C5DE029FC5C83486CCC


销毁Session:
1、session.invalidate()
2、session.setMaxInactiveInterval(int interval)   1800
 也可通过web.xml来设最长不激活时间:
  <session-config>
    <session-timeout>30</session-timeout>
  </session-config> 
 default value: 60min
3、Web Server crash

***************************************************************************************************
Servlet异常处理

1.声明式异常处理
2.程序式异常处理

用<error-page>处理异常
用try chatch处理异常
用RequestDispatcher处理异常


WEB.xml
  <error-page>
    <error-code>404</error-code>                     ------->异常的类型
    <location>/FileNotFound.html</location>          ------->处理异常的页面
  </error-page>


<error-code>404</error-code>
<error-code>java.io.FileNotFoundException</error-code>
可以是异常的编号,也可以是异常类

国际化问题

WEB.xml
  <locale-encoding-mapping-list>
  <locale-encoding-mapping>
  <locale>zh</locale>
  <encoding>gbk</encoding>
  </locale-encoding-mapping>
  </locale-encoding-mapping-list>