sun公司制订的一种用于扩展web服务器功能的组件规范。
1)扩展web服务器功能
a,早期的web服务器(apache,iis)只能够处理静态资源的请求
(即,需要事先将html文件写好,并且保存到web服务器上面)
,这限制了很多应用。
b,为了让web服务器能够处理动态资源的请求(即,需要依据
请求参数进行计算,动态生成html),需要扩展web服务器功能:
方案一使用cgi(common gateway interface)程序来扩展
其功能,cgi程序可以使用很多语言来开发(c,perl等),但是,存在几个问题,比如请求参数的处理比较麻烦,另外,可
移植性也不是很好。
方案二使用servlet
使用servlet,容器会完成请求参数的解析过程,开发
相对简单,另外,不存在移值性问题(比如,servlet可以在
tomcat,weblogic,websphere等容器上运行)。
2)组件规范
组件:
符合特定规范,并且实现了相应的功能的软件模块,
必须部署到相应的容器上面才能运行。
容器:
符合特定的规范,提供组件的运行环境,并且管理
组件的生命周期,提供相应基础服务(比如请求参数
的解析)的程序。
2、如何开发一个servlet?
step1写一个java类,实现Servlet接口或者
继承HttpServlet类。
step2编译
step3打包
appname
WEB-INF
classes(.class文件)
lib(.jar文件,可选)
web.xml(部署描述文件)
step4部署
将step3生成的整个文件夹或者(使用jar命令将整个文件
夹压缩之后生成的.war文件)拷贝到servlet容器特定的
目录下面。
servlet容器(比如tomcat),同时,也具有一个完整的
web服务器的功能。
step5启动服务器,访问
http://ip,port/appname/servlet-uri
http://localhost:8080/firstweb/sayHello
3、tomcat的安装与简单使用
1)安装
step1将tomcat解压缩到 /home/soft01
step2配置环境变量(只有JAVA_HOME是必须要有的)
cd /home/soft01
vi .bash_profile
JAVA_HOME: jdk的安装目录
CATALINA_HOME:tomcat的安装目录,比如
/home/soft01/apache-tomcat
PATH:/home/soft01/apache-tomcat/bin
step3启动tomcat
cd /home/soft01/apache-tomcat/bin
sh startup.sh (linux,unix) windows用: startup.bat
或者
sh catalina.sh run
打开浏览器,输入http://localhost:8080
2)简单使用
关闭tomcat: sh shutdown.sh windows用:shutdown.bat
3)各个文件夹的作用
bin:可执行文件
common:可以被部署到该服务器上面的所有程序
共享的文件
conf:服务器的配置文件
webapps:部署目录
work:服务器运行过程中产生的一些临时文件,比如
jsp对应的servlet源文件及字节码文件
4) servlet是如何运行的?
当在浏览器地址栏输入
http://localhost:8080/firstweb/sayHello
step1浏览器依据ip,port建立与服务器之间的连接。
step2浏览器依据http协议将请求数据打包,
"firstweb/sayHello"称之为请求资源路径,也会放到
请求数据包里面。
step3浏览器发送请求。
step4服务器解包(将请求数据包中的数据解析出来,
放到request对象里,方便servlet去获取请求参数),
另外,服务器还会创建一个response对象(方便servlet
将处理结果发送给浏览器)。
step5服务器依据请求资源路径找到要访问的servlet并
创建其实例,接下来,调用该对象的service方法(在调用
该方法时,会将事先创建好的request,response对象
作为参数传递过来)。servlet可以通过request获得请求
参数,通过response输出请求处理的结果。
step6服务器从response对象中取出处理结果,将这些
数据打包,发送给浏览器。
5)使用myeclipse开发servlet
step1让myeclipse管理tomcat(可以使用
myelipse启动、关闭tomcat,自动部署)。
step2创建一个web工程
6)常见问题(常见错误)
a,404
错误原因:请求地址写错了
解决:按照http://ip,port/appname/servlet-uri
仔细检查。
http://localhost:8080/web01/greeting?name=zs
b,405
错误原因:找不到service方法
解决:检查service方法,注意必须是public void
方法名必须是service,异常必须是ServletException,
IOException。
c,500
错误原因:系统出错(程序出错)
解决: 检查代码。
package first;
import javax.servlet.*;
import javax.servlet.http.*;
import java.io.*;
public class HelloServlet extends HttpServlet{
public void service(HttpServletRequest request,
HttpServletResponse response) throws ServletException,
IOException{
response.setContentType("text/html");
PrintWriter out = response.getWriter();
out.println("<span style='color:red;font-size:50px;'>Helloworld</span>");
out.close();
}
}
package web;
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 GreetingServlet extends HttpServlet{
public void service(HttpServletRequest request,
HttpServletResponse response)
throws ServletException,IOException{
//step1读取请求参数
//请求参数如果写错,会返回null。
String name = request.getParameter("name");
//step2处理请求
String greetingStr =
"<span style='font-size:60px;color:red'>" +
"Hello " + name + "</span>";
//step3输出结果
//生成一个消息头content-type,告诉浏览器
//返回的数据的类型。
response.setContentType("text/html");
//为了向response中输出处理的结果,需要先
//通过response获得一个输出流。
PrintWriter out = response.getWriter();
out.println(greetingStr);
out.close();
}
}
web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.4"
xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
<servlet>
<servlet-name>greetingServlet</servlet-name>
<!-- 注意类名与包名 -->
<servlet-class>web.GreetingServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>greetingServlet</servlet-name>
<url-pattern>/greeting</url-pattern>
</servlet-mapping>
</web-app>
1、http协议(了解)
1)什么是http协议(超文本传输协议)?
http协议定义了浏览器与web服务器之间通讯的过程
及数据的格式。
2)通讯的过程
step1 浏览器建立与服务器之间的连接
step2 浏览器将请求数据打包(请求数据包),发送
给服务器。
step3 服务器将处理结果打包(响应数据包),发送
给浏览器。
step4 服务器立即关闭连接。
如果浏览器要再次发送请求,需要重新建立连接。
这种“一次请求,一次连接"的通讯方式,其优点是
服务器能够为更多的用户服务。
3)数据的格式
请求数据包:
请求行(请求方式,请求资源路径,协议的类型及版本)
若干消息头
消息头是浏览器与服务器之间通讯的一些约定,消息
头一般由w3c定义,比如,浏览器可以发送一个User-Agent
消息头,告诉服务器,浏览器的类型及版本。
实体内容
只有当请求方式是post方式的时候,浏览器才会将请求
参数及参数值放在这儿,如果是get方式,浏览器会
将请求参数及参数值放到请求资源路径的后面。
响应数据包:
状态行(协议的类型及版本,状态码,状态码的描述)
状态码是由w3c定义的一些数字,表示不同的通讯
状态,常见的200:ok,500:系统出错,404,找不到对应的
资源。
若干消息头
比如,服务器可以发送content-type消息头,告诉
浏览器服务器返回的数据类型及编码。
实体内容
服务器返回给浏览器的处理结果。
2、get方式与post方式
1)哪一些是get方式
a,在浏览器地址栏直接输入某个地址
b,表单默认提交的方式
c,点击链接地址
2)哪一些是post方式
a,给表单的method属性设置成"post"。
3)区别
a,get方式会将请求参数添加到请求资源路径之后,
所以,请求参数不能过多,并且,get方式会将请求参数
显示在浏览器地址栏,相对来讲,不安全。
b,post方式会将请求参数添加到实体内容里面,请求
参数没有限制,不会将请求参数显示在浏览器地址栏,
相对来说会安全一些。
4)结论
get方式适合于向服务器请求获得一些资源,而post
方式适合于提交数据。
3、表单的处理
1)如何获得表单中的参数值
String request.getParameter(String paraName);
//如果有多个请求参数名相同
//比如 ?city=bj&city=wh&city=cc
String[] request.getParameterValues(String paraName);
2)如果表单中有中文参数值,如何处理
step1 在html文件当中,添加<meta
http-equiv="content-type"
content="text/html;charset=utf-8">
确保浏览器以指定的编码格式打开这个页面。
另外,表单要采用post方式提交。
step2 在服务器端,添加
request.setCharacterEncoding("utf-8");
告诉服务器,以指定的编码格式去解码。
编码方面的基础知识:
jvm在内存当中,保存的所有的字符都采用unicode编码格式
保存。(unicode编码也称为原码)
在输出时,需要编码:即将unicode编码格式保存的字符转换
成某种本地编码(比如gbk,gb2312,utf-8)格式保存的字符。
在输入时,需要解码:即将某种本地编码格式保存的字符转
换成unicode编码格式保存的字符。
练习:
设计一个页面,用户可以添加员工基本信息(包括
姓名,薪水,年龄) ,服务器端读取员工基本信息并显示。
注意中姓名有可能包含中文。
4、访问数据库
step1 将数据库的驱动程序(.jar文件) 放到
WEB-INF\lib下。
step2 在servlet类的service方法里面,使用
jdbc技术访问数据库。
5、mysql的简单使用
1)登录
mysql -uroot;
2) 查看当前的数据库实例
show databases;
3) 创建一个数据库
//创建一个名叫jd1205db的数据库,其默认
//的字符集是utf8,这样设置的目的是为了保存
//中文
create database jd1205db default character set utf8;
4) 查询当前数据库有哪些表
use jd1205db; //使用jd1205db这个数据库
show tables;
5) 建表
create table t_emp(
id int primary key auto_increment,
name varchar(50),
salary double,
age int
);
auto_increment: 自增长列,即主健的值由数据库自
动生成。
6)插入记录
insert into t_emp(name,salary,age) values('zs',2000,22);
7)查询
select * from t_emp;
8)删除
delete from t_emp where id=2;
9)修改
update t_emp set name='ww' where id=1;
练习:
写一个ListEmpServlet,可以将t_emp表中的所有记录
查询出来,并且以表格的形式显示在页面上。
web02项目
bmi_form.html
<html>
<head>
<!-- 模拟一个消息头content-type,告诉浏览器
当前html文件的编码格式,浏览器一定会使用这种编码
打开该页面 -->
<meta http-equiv="content-type"
content="text/html;charset=utf-8">
</head>
<body style="font-size:30px;">
<form action="bmi" method="post">
<fieldset>
<legend>bmi指数计算</legend>
身高:<input name="height"/><br/>
体重:<input name="weigth"/><br/>
性别:男<input type="radio" name="gender"
value="m" checked="checked"/>
女<input type="radio" name="gender"
value="f"/><br/>
城市:<select style="width:120px;" name="city"
multiple="multiple">
<option value="bj">北京</option>
<option value="wh">武汉</option>
<option value="cs">长沙</option>
</select><br/>
姓名:<input name="name"/><br/>
<input type="submit" value="确定"/>
</fieldset>
</form>
</body>
</html>
web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.4"
xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
<servlet>
<servlet-name>addEmp</servlet-name>
<servlet-class>web.AddEmpServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>addEmp</servlet-name>
<url-pattern>/add</url-pattern>
</servlet-mapping>
</web-app>
package web;
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 BMIServlet extends HttpServlet{
public void service(HttpServletRequest request,
HttpServletResponse response) throws
ServletException,IOException{
//告诉服务器,对表单中的参数值按utf-8进行解码
request.setCharacterEncoding("utf-8");
//step1 读取请求参数
String heightStr = request.getParameter("height");
String weigthStr = request.getParameter("weigth");
String gender = request.getParameter("gender");
String[] citys = request.getParameterValues("city");
for(int i=0;i<citys.length;i++){
System.out.println(citys[i]);
}
String name = request.getParameter("name");
System.out.println("name:" + name);
//step2 计算
// 在获得请求参数值之后,一般需要进行验证
// 要判断参数值是否为null,或者为""。
double weigth = Double.parseDouble(weigthStr);
double height = Double.parseDouble(heightStr);
double bmi =
weigth / height / height;
String status = "";
if(gender.equals("m")){
if(bmi < 20){
status = "过轻";
}else if(bmi >=20 && bmi < 25){
status = "正常";
}else if(bmi >=25 && bmi < 30){
status = "过重";
}else if(bmi >=30 && bmi < 35){
status = "肥胖";
}else{
status = "非常肥胖";
}
}else{
if(bmi < 19){
status = "过轻";
}else if(bmi >=19 && bmi < 24){
status = "正常";
}else if(bmi >=24 && bmi < 29){
status = "过重";
}else if(bmi >=29 && bmi < 34){
status = "肥胖";
}else{
status = "非常肥胖";
}
}
//step3 输出
//在默认情况下,服务器会采用iso-8859-1编码格式
//进行编码。
//setContentType这句话在这儿有两个作用:
//作用1:告诉服务器,在输出时,采用utf-8编码格式
//进行编码。
//作用2:会生成一个content-type消息头,告诉浏览器,
//返回的数据类型及编码。浏览器会采用utf-8编码格式打开
//该页面。
response.setContentType("text/html;charset=utf-8");
PrintWriter out = response.getWriter();
out.println("<h1>你的bmi指数是:"
+ bmi + " 你的身体状况是:" + status + "</h1>");
out.close();
}
}
package test;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.net.URLEncoder;
public class Test {
/**
* @param args
* @throws UnsupportedEncodingException
*/
public static void main(String[] args) throws UnsupportedEncodingException {
// TODO Auto-generated method stub
String str = "张三";
//encode方法:将str按照utf-8进行编码,然后将
//编码之后得到的字节数组转换成对应的字符串。
String str2 = URLEncoder.encode(str,"utf-8");
System.out.println(str2);
//decode方法:解码
String str3 = URLDecoder.decode(str2,"utf-8");
System.out.println(str3);
}
}
web02_2项目
<html>
<head>
<meta http-equiv="content-type"
content="text/html;charset=utf-8">
</head>
<body style="font-size:30px;">
<form action="add" method="post">
<fieldset>
<legend>添加员工信息</legend>
姓名:<input name="name"/><br/>
薪水:<input name="salary"/><br/>
年龄:<input name="age"/><br/>
<input type="submit" value="添加"/>
</fieldset>
</form>
</body>
</html>
web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.4"
xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
<servlet>
<servlet-name>addEmp</servlet-name>
<servlet-class>web.AddEmpServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>addEmp</servlet-name>
<url-pattern>/add</url-pattern>
</servlet-mapping>
</web-app>
package web;
import java.io.IOException;
import java.io.PrintWriter;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class AddEmpServlet extends HttpServlet{
public void service(HttpServletRequest request,
HttpServletResponse response) throws
ServletException,IOException{
request.setCharacterEncoding("utf-8");
response.setContentType("text/html;charset=utf-8");
PrintWriter out = response.getWriter();
String name =request.getParameter("name");
String salary = request.getParameter("salary");
String age = request.getParameter("age");
//使用jdbc将员工信息插入到数据库
Connection conn = null;
try {
Class.forName("com.mysql.jdbc.Driver");
conn = DriverManager.getConnection(
"jdbc:mysql://localhost:3306/jd1205db",
"root","1234");
PreparedStatement prep =
conn.prepareStatement(
"insert into t_emp(name,salary,age) " +
"values(?,?,?)");
prep.setString(1, name);
prep.setDouble(2, Double.parseDouble(salary));
prep.setInt(3, Integer.parseInt(age));
prep.executeUpdate();
out.println("插入成功");
out.close();
} catch (Exception e) {
//记录日志
e.printStackTrace();
//依据异常的类型来分别进行处理:
// 如果异常不能够恢复(系统异常,
//比如,数据库连接不上,数据库关闭,
//网络通讯问题等等),通知用户稍后重试
//如果是能够恢复的异常(应用异常,比如,
//在转帐的时候,用户输入了一个不存在的
//帐号),应该立即恢复。
out.println("系统异常,请稍后<a href='addEmp.html'>重试</a>");
out.close();
}finally{
if(conn != null){
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
}