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>