1,什么是可重用组件:是指能够完成某种特定的功能,并提供了一个或多个访问接口的聚合模块程序,可重复使用是它最大的特点。
在java企业级开发中,最重要的两类组件是javabean和EJB。
javabean本质就是一个java类,但是这个java类的组成必须符合一定的规则,这个规则也就是javabean规范,其中包括缺省的构造方法,setXXX和getXXXde风格来构造属性等。他可以很容易的被组合到程序中去,一般包括业务逻辑代码和数据访问代码等。jsp在使用他的时候可以用普通的java脚本实例化这个类,像其他java对象一样使用,也可以使用jsp提供的动态标签来访问。
EJB 相对于javabean来说是一个大得多的组件,他必须生存在符合javaee规范的应用服务器中,它的定义和调用都要复杂的多,在实际的java开发中很小使用EJB组件。
2,javabean规范:
(1),它是一个公开类(public class);
(2),他有一个公开的无参数 的构造方法。
(3),提供了公开的setXXX和getXXX方法来决定javabean的属性,
3,用jsp完成一种特定的功能时,有三种实现方式:
(1),在html代码中间夹杂java语言写成的jsp脚本,功能逻辑就在java语言中完成。缺点是:代码可读性差,很难维护。
(2),把功能逻辑包装在一个javabean内,然后在jsp脚本中,用new关键字实例化这个javabean,在调用set和get方法来完成特定的功能,这种方式虽然维护比第一种好一些,但是可读性仍然不好。
(3),同样先把功能逻辑包装在一个javabean钟,再利用jsp提供的动作标签来访问javabean的属性,这种方式比第二种耦合度进一步降低了,是一种值得推荐的方式。
4,jsp使用javabean的标签详解:
(1),定义javabean的动作标签<jsp:useBean>
<jsp:useBean>标签用于在特定的范围内实例化或查找一个javabean,基本语法如下:
<jsp:useBean id="唯一标示名字"
scope="page|request|session|application";
type="父类型"
class="实现类">
id:表示在特定范围内的唯一标示的名字;
scope:指定bean的存活范围,有4种:page:默认是page,标示jsp的页面范围,如果是同一个请求的另外一个jsp也页面就不见了。request:当前这一次的请求范围,包含多个jsp页面;session:标示会话范围;application:标示整个web应用,与servlet上下文同义。
class:javabean的实例类名,必须是完整类名。
type:javabean的父类或者一实现接口。
<jsp:useBean>动作标签的基本工作机制如下:
(1),在指定范围内寻找是否已有名字为id属性指定的对象。
(2),如果存在,且指定了type属性,则用该type做一次强制类型转换后再返回该对象的引用,如果没用指定 ,则直接返回该对象的引用。
(3),如果不存在,则用class属性指定的类实例化一个新的对象并返回,并将该对象保存到scope内。
(2),设置javabean属性动作标签<jsp:setProperty>
<jsp:setProperty>:是为javabean的可写属性赋值,它既可以放在<jsp:useBean>中间,也可以单独使用,基本语法如下:
<jsp:setProperty
id="与javabean的属性同名"
property="可写属性名"
value="字面值"
params="请求参数的名字"/>
name:bean的id
property:可写属性名,如setAge(),属性名为age,如果是*,则表示将所有的属性一一与请求参数按名匹配赋值。
value:为属性复字面值,
params:http请求的参数名。
3,获取javabean属性动作标签<jsp:getProperty>
<jsp:getProperty>是获取javabean的可读属性,它既可以放在<jsp:useBean>中间,也可以单独使用,基本语法如下: <jsp:getProperty
name="与javabean的id属性值相同"
property="可读属性名">
4,javaBean封装数据库操作的代码如下:
private static final String url="jdbc:mysql://localhost:3306/test";
private static final String username="root";
private static final String password="123";
private String table;
private Object[] params;
public Connection getCon(){
Connection conn=null;
try {
Class.forName("com.mysql.jdbc.Driver");
conn=DriverManager.getConnection(url, username, password);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return conn;
}
public void close(Connection conn,Statement st,ResultSet rs){
if(rs!=null){
try {
rs.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if(st!=null){
try {
st.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if(conn!=null){
try {
conn.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
public String getTable() {
return table;
}
public void setTable(String table) {
this.table = table;
}
public Object[] getParams() {
return params;
}
public void setParams(Object[] params) {
this.params = params;
}
5,javaBean封装添加数据操作:
public boolean getInsertData(){
//Æ´½ÓsqlÓï¾ä
String sql="insert into "+table+" values(";
for (int i = 0; i <params.length; i++) {
sql+="?";
if(i!=params.length-1){
sql+=",";
}
}
sql+=")";
boolean rst=false;//¶¨Òå²Ù×÷½á¹û
Connection conn=null;//¶¨ÒåÁ¬½Ó¶ÔÏó
PreparedStatement pst=null;//¶¨Òå»á»°¶ÔÏó
try {
conn=this.getCon();//»ñÈ¡Êý¾Ý¿âÁ¬½Ó
conn.setAutoCommit(false);//¹Ø±Õ×Ô¶¯Ìá½»
pst=conn.prepareStatement(sql);//´´½¨»á»°
//Ñ»·ÉèÖòÎÊý
for (int i = 0; i < params.length; i++) {
pst.setObject(i+1,params[i]);
}
int num=pst.executeUpdate();//Ö´ÐÐsqlÓï¾ä
conn.commit();//Ìá½»ÊÂÎñ
//Èç¹ûÖ´Ðнá¹û´óÓÚ0 £¬´ú±íÖ´Ðгɹ¦
if(num>0){
rst=true;
}
} catch (SQLException e) {
// TODO Auto-generated catch block
if(conn!=null){
try {
conn.rollback();//»Ø¹öÊÂÎñ
} catch (SQLException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
}
e.printStackTrace();
}finally{
close(conn,pst,null);//¹Ø±ÕÁ¬½Ó
}
return rst;
}
6,javabean封装删除数据操作:
public boolean getDeleteData(){
String sql="delete from "+table+" where "+params[0]+" =?";
boolean rst=false;
Connection conn=null;
PreparedStatement ps=null;
try {
conn=this.getCon();
conn.setAutoCommit(false);
ps=conn.prepareStatement(sql);
ps.setObject(1,params[1]);
int num=ps.executeUpdate();
conn.commit();
if(num>0){
rst=true;
}
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally{
close(conn,ps,null);
}
return true;
}
7,javabean封装修改数据操作:
public boolean getModifyData(){
String sql="update "+table+" set "+params[0]+" =? where "+params[2]+"=?";
boolean rst=false;
Connection conn=null;
PreparedStatement ps=null;
try {
conn=this.getCon();
conn.setAutoCommit(false);
ps=conn.prepareStatement(sql);
ps.setObject(1,params[1]);
ps.setObject(2,params[3]);
int num=ps.executeUpdate();
conn.commit();
if(num>0){
rst=true;
}
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally{
close(conn,ps,null);
}
return rst;
}
8,javabean封装查询数据操作:
private Connection conn=null;
private PreparedStatement ps=null;
private ResultSet rs=null;
public void setQuery(String sql){
try {
conn=this.getCon();
ps=conn.prepareStatement(sql);
rs=ps.executeQuery();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public List getList(){
List list=new ArrayList();
try {
while(rs.next()){
String str="";
for (int i = 0; i <params.length; i++) {
str +=rs.getObject(params[i].toString());
if(i!=params.length){
str +=",";
}
list.add(str);
}
}
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally{
this.close(conn,ps, rs);
}
return list;
}
9,分页技术:逻辑分页和物理分页
逻辑分页:查询sql语句不变,只不过通过java代码从逻辑上控制结果集光标的位置,从而实现分页;
物理分页:改变sql语句,在数据库查询的时候只需取出需要的结果集,但是各个数据库控制结果集的sql语句不一样,;mysql:limit,orcale:rownum
两种分页技术各有优缺点:逻辑分页效果低,但是程序容易控制,但不能跨数据库。
10,逻辑分页:逻辑分页的关键点在于根据当前的节点去定位结果集的下标位置,把下标定位好以后,就知道它是否有下一页和上一页信息等。
实现逻辑分页的步骤:(1),确定每页的最大记录数。(2),查询总共记录数。(3),根据总记录数和每页最大记录数确定最大页码。(4)查询结果集。(5),根据每页最大记录数和当前页码对结果集的下表进行定位。(6),不超过最大记录数的循环打印结果集。
11,物理分页的实现思想还是需要确定每页的最大记录数、当前页码、最大页码、总记录数的信息,但是它把结果集下标定位交个数据库来完成了,开发者需要做的就是把sql写好。
对于mysql数据库,需要开发者熟悉他的limit语句,limit语句需要追加到查询语句的后面,告诉sql只返回规定行数的记录,基本语法如下:
limit n #返回前 n行数据
limit n,m #返回从n+1行开始,最多m行的数据。
1,开发一个servlet大致需要的步骤:
(1),编写servlet源码并编译。
(2),在web.xml进行相应的配置。
(3),将包含该servlet的web应用程序部署到web容器里,并启动web容器。
(4),通过浏览器访问该servlet。
2,servlet 的四个周期: 加载,初始化(init()),提供服务(service()),销毁(detory())
3,get的请求方式会把请求的参数追加到请求的url后面,首先在url的后面加一个?,然后使用"参数名=参数值",的形式追加参数。
post请求方式则是把请求的参数放在请求的正文里,不能直接通过url看到。,
4,获取客户端参数的两种方式:getParament()(只有一哥 参数)和getParamentValues()(用于多值的参数)
例子:
String username= request.getParament("username")
String[] hobbies=request.getParamentValues("hobby");
5,cookie:记录在客户端浏览器的数据,它的格式是“名-值”对,一般可以通过cookie保存一些用户的数据,如,登录名,密码等。
java web容器会在用户第一次请求的时候在浏览器的cookie里加入 一条名为“jsessionid”的数据,同样web容器也有。以后的每次请求浏览器都会把cookie的值传回到服务器端,所以服务器就会根据‘jsessionid’的值跟踪一个用户了。浏览器关闭,跟踪结束。(回话的时间是有限制的)
6,servlet转发一个http请求分为直接转发和间接转发。
间接转发本质是两次http请求,服务器端在响应第一次请求的时候,让浏览器再向另外一个url发送,从而达到转发的目的。
直接转发是浏览器只发出一次请求,servlet把请求转发给servlet,Html,jsp或其他信息资源,有第二个信息资源响应该请求,在请求对象request中保存的对象对于每个信息资源都是共享的。
web应用程序大多会有一个控制器,由控制器来控制请求应该转发给那个信息资源,然后有信息资源处理请求,处理我完后还可能转发给另外的信息资源返回给用户,这个过程既是经典的MVC模式。
7,过滤器:就是在目标资源和源头资源之间起到过滤作用的一个东西。对于web应用程序来说,过滤器是处于服务器端的,队请求消息和响应消息进行过滤的一中组件。
过滤器是一种重要的设计模式,不仅引用在javaweb开发中,其他开发领域也会应用到过滤器模式,他可以在不侵入原有代码的基础上为他们提供一些功能。
8,java web 应用程序的范围模型。
request:请求 代表了一次http请求,他的生命周期从请求开始知道请求的响应结束。中间可能会穿插多个信息资源,如过滤器, servlet,jsp。
Session 会话,代表了一次会话,也可认为代表了一个用户,一个会话里可以包含多次的请求。如果用户长时间不发出请求,可能导致会话超时而过期,超时时长可以设置。因为它代表一个用户,所以一般使用session保存用户的数据,如购物车。
application :应用 他的生命周期从web 容器启动或部署该应用开始,一web 容器停止,或取消部署而结束。他的作用范围最大,一般用于存放应用标题,或其他外部资源连接器等。
9,监听器体现了一种监听事件模型。
三种事件监听:1,request事件监听实现接口(ServltRequestListener)
2,session事件监听接口(HttpSessionListener)
3,application事件监听接口(ServletContextListener)
10,forward和redirect的区别:
forward是直接转发,通过request调用
redirect是间接转发,通过response调用
forward在服务端的内部发生,对于客户端来说是不可见的,即使请求在服务器端的各个资源间转发过多次,客户端浏览器的地址栏的地址依然是最初的请求地址,redirect则相反,他的请求转发实质是向客户端发送一条请求另一个地址的结果,浏览器会修改地址栏的地址,再重新发一次新的请求,对于客户端来说是可见的。
11,
Servlet体系结构和层次结构
1,Servlet体系结构
------请求 ---> -------> ------->
客户端 HTTP服务器 Servlet容器 Servlet
<----- 响应 ---- <--------- <-------
2,Servlet层次结构
Servlet是实现javax.servlet.Servlet接口的对象,大多数Servlet通过GenericServlet或HttpServlet进行扩展. Servlet API 由两个程序包组成
javax.servlet 包
类:
ServletInputStream类:从客户端读取二进制数据;
ServletOutputStream类;向客户端发送二进制数据;
GenericServlet类:抽象类,定义了一个通用的,独立于底层协议的Servlet。
接口:
Servlet接口:管理Sevlet。定义实现Servlet的必须方法。一个Servlet必须实现Servlet接口或Servlet接口的扩展。
ServletConfig接口:Servlet初始化时,向Servlet传递配置信息。
ServletContext接口;Servlet上下文,使Servlet与其他的Servlet容器进行交互通信。
ServletRequest接口:向Servlet客户端提供请求信息
ServletResponse接口;Servlet向客户端提供响应信息。
javax.servlet.http 包
类:
Cookie类
HttpServlet类:抽象类,继承自GenericServlet。应用于HTTP协议的请求和响应的Servlet。
接口:
HttpSession接口:
HttpAttributeListener接口:会话的属性监听接口;
HttpServletRequest接口;扩展ServletRequest接口,向Servlet客户端提供HTTP请求信息。
HttpServletResponse接口;扩展ServletResponse接口,Servlet向客户端提供HTTP响应信息。
总体可以分为:
Servlet类: 实现具体协议的业务类,其目的是一个业务实现的WEB组件类;
Servlet接口: 该接口独立于协议实现,其目的是为了定义服务器的组件标准;
GenericServlet抽象类: 该类提供了一个独立于协议的实现,其目的是为了满足服务器;
HttpServlet: 该类实现了HTTP协议,其目的是为了让客户程序扩展;