JSP总结

第一部分:

1.java中的finally不受return 影响..

2.javaexception的用处.......方法可以抛出....

3.java的工具类...及迭代...

4.Servlet使用标准的API,可被更多的Web服务器支持..

5.Servlet是单例多线程....

6.Servlet可访问Java平台丰富类库..

7.Servlet容器给Servlet提供额外的功能...如错误处理和安全..

8.server.xml中可以修改Tomcat的默认端口....

<Connector port="80" protocol="HTTP/1.1" connectionTimeout="20000" redirectPort="8443" /> ..

9.CATALINA_HOME环境变量...设置为TomCat安装目录....

   Servlet API类库:classpath=%classpath%;E:/apache-tomcat-6.0/lib/servlet-api.jar

   在Servlet容器中运行时,Web应用程序的类加载器将首先加载classes目录下,其次才是lib目录下的类....如果两个目录下存在同名类,起作用的将是classes目录下的类..

    web.xml文件为Web应用程序的部署描述符......包含如下的配置:SevletContext的初始化信息..Session的配置..MIME类型映射...   

10.startup启动失败,而又看不到出错信息时,可用catalina.bat.....//参数start为在一个单独的窗口中启动Tomcat,run表示在当前窗口中启动,故可以看到出错信息..

11.Tomcat体系结构(组件)....Server(整个容器)..Service...Connector...Engine...Host...Context(一个Web应用程序)....

12.Tomcat的管理程序..manager....用于管理部署Tomcat中的应用程序...

     tomcat-users.xml<tomcat-users><role rolename="manager"/><user username="hanyin" password="1234" roles="manager"/></tomcat-users>,进入manager页面中后,可以管理Web应用程序...

13.Servlet接口的几个方法

init(servletConfig)....初始化Servlet对象,它有一个ServletConfig参数,Servlet容器通过这个参数向Servelt传递配置信息..

service(request,response).....处理请求,通过request得到客户端的相关信息和请求信息,response设置响应信息...

destroy()..getServletConfig()....getServletInfo().....

14.ServletRequest(封闭请求数据)ServletResponse(封闭响应数据)......它们作为参数传递给service(),此方法来处理....  

    Request://getAttribute()...removeAttribute()...stAttribute(xx,xxx)...

       getCharacterEncoding()(得到在请求正文中所用字符编码)...

getContentType()(得到MIME类型)...

       getLocalAddr()...getLocalPort().....getLocalName()....

getParameter()....getParameterNames()....getParameterValues()...

       getReader()...getProtocol()...

getRemote[Addr|Port]()(得到最后一个代理ip)...getServetPort()....

setCharacterEncoding()(覆盖在请求正文中所用字符编码)

 Response://flushBuffer()//(强制把任何在缓存中的内容发送到客户端)...

getCharacterEncoding()(返回在响应正文中所用的字符编码)

getContentType()(返回在响应正文中所用的MIME类型)....

        setCharacterEncoding()...setContentType()....

 ServletCofig://Servlet容器在Servlet初始化期间向ServletConfig传递配置信息....一个Servlet只有一个ServletConfig对象..

getInitParameter("name")....getServletContext()....

15.GenericServlet.......init(){super.init(config);.......}  当调用init(config),系统会自动把参数传递进来....

16..HttpServlet....

两个Service()方法....第一个把参数转换后传递给第二个方法...第二个再根据请求类型调用相应的doXxx()方法.....所以,我们只需要重写相应的doXxx()方法.....

HttpServletRquest:  getCookies().....

getSession()//得到和此请求相关的Session如果没有,则他一个新的Session....

getSession(true/false)........getQueryString()....

getRequestURI()...getRequestURL()...

HttpServletResponse: addCookie()....encodeRedirectURL()....encodeURL()....

    sendError()....sendRedirect()....setStatus().....

17.HttpServlet....

response.setContentType("text/html;  charset=gb2312");

//设置MIME,字符编码.....html;之间不能有空格..

必须在

out=response.get.gtWriter(); //默认为ISO-8859-1.....

之前....

18.GETPOST:

通常当表单使用get方法时,提交的内容被作为URL参数,如登录时:

 输入用户名密码后提交后.........

    http://218.198.237.36/MySite/welcome?username=hanyin&password=1234

Post方法则不然...提交数据作为正文的内容发送到服务器端...

19.Servlet异常:  ServletExceptionUnavailableException...

20.Servlet生命周期:

加载与实例化:程序员不应提供带参构造方法...Servlet容器启动后要知道类Servlet在什么地方,成功加载后,调用默认构造方法创实例..

初始化实例化后,容器调用init()方法.....初始化期间,实例可以用容器为它准备的ServletConfig对象从应用程序配置信息(web.xml中配置)中获取初始化的参数信息..

处理请求:service()方法处理请求...当执行期间,发生错误,则抛出异常...

服务终止:释放资源..

21.Servlet上下文_________ServletContext:

ServletContext:Web服务器中一个已知路径的根,如 webapps/MySite,它可以与Servlet容器通信,如得到文件的MIME类型,转发请求,或者向日志写入消息....它与一个应用程序的所有文件关联..

对共享属性操作:getAttribute()....setAttribute()....removeAttribute()...任何一个Servlet都可以设置某个属性...

getInitParameter()//Web上下文参数可以被所有的Servlet使用......web.xml中的

   <context-param>中设置...

getMimeType()....getRquestDispatcher()....log().....

22.请求转发:RequestDispatche......

该对象可由 ServletContext接口的 getRequetDispatcher()得到....

方法:

forward(request,response)....//请求作初步处理后,调用此方法,但是必须在响应客户端之前调用,forward()之后,原先在响应缓存中的东西被自动清除...

include(request,response)....//在响应中包含其它资源的内容______被调用的Servlet对请求作出响应,并且,该响应会被并入原来的响应之中_______<jsp:include >与此对应...

23.<Context path="/xxx" docBase="D:/xxx/xx/xxx" reloadable="true"/>  

   //若在 ROOT,path="".....reloadable="true",Tomcat自动监视Servelt的改动....

(META-INF/context.xml中配置...也可在localhost下的  mysite.xml中配置....也可在server.xml中配置,但是不建议,因为这个文件只读取一次,当有改动时,不起作用....)

24.打包成war文件...在 mysite......jar -cvf mysite  war  *       //查看: jar -tf   mysite.war

注意:在打包之前,要建立正确的Web应用程序的目录层次结构:WEB-INF...classes..lib(jar)....web.xml....META-INF

25.Servlet的配置原则:

(1).尝试对路径与映射进行精确配置..

(2).尝试最长路径前缀...

(3).如有扩展名,试着匹配有这个扩展名的Servlet.

(4).调用默认的Servlet...如没有则404..Over!!!

     部署: /*  ,  *.jsp  ,*.do ,/    

26.数据库:

//加载JDBC驱动是调用Class类的static方法forName()向其传递要加载的JDBC类名,类加载器找到这个类后加载该类.

//在加载之后,需要注册驱动程序类的一个实例....DriverManager类是驱动程序管理器类,负责管理驱动程序,这个类中所有的方法都是

  静态的.....在这个类中提供了registerDriver()来注册实例,但是通常这个方法不需要主动调用,因为这个类包含注册的表态代码..

  当这个类被加载时(Class.forName("类名")),类加载器会执行该类的静态代码,从而注册一个实例....

                 如:   class Driver extends...implements...{

....static{  DriverManager.registerDriver(new Driver() ); }  ....}

                        }

               即: Class是管理类的,  DriverManager是管理驱动的..

 

import java.io.*;                                                //IOException,PrintWriter....

import java.sql.*;

import java.servlet.ServletException;

import javax.servlet.http.*;                                 //HttpServlet,request,response..

Class.forName("com.mysql.jdbc.Driver");           //可设置成抛出ClassNotFoundException异常....加载失败.

Connection conn=DriverManager.getConnection(url,user,password);

Statement  stmt=conn.createStatement();

stmt.executeUpdate("  ");

Resultset rs=stmt.executeQuery("  ");

    数据的批处理操作. addBatch()..

executeQuery()....executeUpdate()....executeBatch()....

    ResultSet的操作...

next()....getInt()...getString()....getDate()....getTime()....getTimestamp()...getFloat()...

 在这些方法中,又提供了两种形式调用:一种以列索引(1开始),另一种是以列名...作为参数.. 

   getString(int columnIndex)....getString(String columnName)....getDate()....getObject()..

   PreparedStatement pstmt=conn.prepareStatement("....?,?,....?,......?...");

pstmt.setInt(1,10);

pstmt.setFloat(2,10.0f);

pstmt.setString(3,"ok,how are you");

pstmt.setDate(4,java.sql.Date.valueOf("2004-5-8"));

pstmt.executpUpdate();

//还可以 通过循环  pstmt.addBatch()...然后一次执行,以减少执行时间...

    SQL数据与java数据类对应...

几个特殊的...java.math.BigDecimal....java.sql.Date[Time,Timestamp,Blob,Clob,Array]

    CallableStatement://用于SQL存储过程..

    

    事务处理:保证所有的事务都作为一个单元来执行...要么完整提交,要么整个事务回滚......

   conn.setAutoCommit(false);  conn.rollback(); conn.commit();

    事务隔离:并行的多个事务之间进行分离...避免污染(脏读[读到一个没有完成修改的数据],

    不可重复读[另一个事务修改了此事务已经读取的数据,这样同一事务两次读取的内容不同],

    幻读[一个事务读取完成以后,再次读取时,另一事务已经插入了一行])..

  conn.setTransactionIsolation();

    可滚动和可更新结果集:

last()...absolute()....isLast()...next()....previous()...

    JDBC数据源和连接池.

DataSource接口由数据库供应商来实现....

利用数据源,不需要在客户程序中加载JDBC驱动,也不需要使用DriverManager....只需要向JNDI服务器查询来得到DataSource对象,

然后利用DataSource对象的getConnection()方法来建立数据库的连接

....

javax.naming.Context ctx=new javax.naming.InitialContext();

javax.sql.DataSource ds=(javax.sql.DataSource)ctx.lookup("java:comp/env/jdbc/bookstore");

java.sql.Connection   conn=ds.getConnection();

...

conn.close();

javax.naming.Context  表示一个命名上下文,在这个接口中,对义了将对象和名字绑定,以及通过名字查询对象的方法.

ctx.lookup()是在ctx上下文中查询数据源..

DataSource的实现:产生连接....连接池实现......分布式事务实现..

<Context  ....><Source name="jdbc/bookstore" auth="Container"  ..............................     /></Context>

27.会话跟踪:会话(区别用户)+状态(记住前面请求信息).

java Servlet APISession来跟踪会话和管理会话内的状态.

通过在第一个请求和响应中包含Session ID,服务器就可以把一个用户与另一个用户区别开..

传递Session的方法:  Cookies 或 URL重写.

Cookies存储在内存或硬盘中.

服务器用响应报头 Set-Cookie 来发送 Cookie信息...:

Set-Cookie: NAME=Jsessionid;  [Comment=value;]  Domain=value; Max-Ag=value; [ Path=value;] [Secur;] Version=1*DIGIT

URL重写:Session ID作为URL字符串中的路径参数..

每有一个会话请求,Servelt容器就创建一个HttpSession对象,有了这个对象之后,就可以利用这个对象来保存客户的状态信息..并且这个Session有一个唯一的Session ID,Servlet容器将其作为Cookie(URL一部分)发送给浏览器,浏览器将在内存中保存这个Cookie...客户再次请求时,浏览器将Cookie随请求一起发送........servlet 容器又由Session ID来找到对应的Session对象..从而得到客户的状态信息.

   整个过程都是透明的,开发人员只需得Session对象,然后调用setAttribute()或 getAttribute()..

Session:  getAttribute()...rmoveAttribute()....getId()...isNew()...getSession()//返回与请求相关的session...invalidate()..

Cookie: getName()....getValue()//value是以:  name1-value1&name2-value2形式的..

      如: cookie=new Cookie("userinfo","user-hanyin&pwd-1234");

      cookie.setMaxAge(-1);  //当浏览器关闭时,Cookie会被删除..在内存中..

      resp.addCookie(cookie);

     得到Cookie:  cookies=req.getCookies(); 

          for(.....){ 

         cookie=cookies[i];  

         cName=cookie.getName();

         if(cName.equals("userinfo"){

         cValue=cookie.getValue();

             String []   userInfo=cValue.split("&");

               .......

}

          }

               共享Cookie只能在一个进程中....

Session只是在超出了一定时间才消失....

会话跟踪的Cookie:  request.doGetSession();                   

    //由于设置了cookie.MaxAge(-1);故只能存储于内存中..

{实现片段:

cookie=new Cookie(Globals.SESSION_COOKIE_NAME,session.getIdInternal());

......

response.addCookieInternal(cookie);

               }

Session持久化,要求sessionsession内的对象实现 Serializable接口....

28:异常处理:

可以将所有的异常交给一个页面处理..

...

catch(exception ec){

req.setAttribute("java.exception",ae);

req.setAttribute("java.exception_uri",req.getRequestURI());

RequestDispatcher rd=req.getRequestDispatcher("Exceptionpage");

rd.forward(req,resp);

}

//Exceptionpage:

String uri=(String)req.getAttribute("java.exception_uri");

Object excep=req.getAttribute("java.exception");

28.线程安全:  线程池,管理线程....(连接池)...

可在server.xml <Connector>元素设置线程池中线程数目....

变量的线程安全....如  conn.......第一次关闭后没有设置为null导致...两次关闭...

属性的线程安全:  如 application(不同用户对同一数据的操作)....session(同一用户不同页面的操作)...

29.JSP技术:  是建立在Servelt规范功能之上的网页技术..

ServletContext......对应于........application

PageContext.........对应于........pageContext

config,session,out.....都可以由pageContext来得到....

指令元素: <%@  page|include|taglib   ....%>       //taglib用于自定义标签..

脚本元素:声明: <%!   int i=1;  %>   

            对应的XML <jsp:declaration>   declarations  </jsp:declaration>

        脚本段: <%   xxxx;  %>   

     表达式:  <%=    i   %>

动作元素为请求处理阶段提供信息......标准动作是一些标签,JSP容器来实现...当在转换成Servlet期间,jsp窗口遇到这个标签时,就用预先定义好的java代码来替代它....//可在work目录下查看对应的 Servlet代码...

jsp 中定义了20个标准的动作:

<jsp:useBean>,<jsp:setProperty>,<jsp:getPropety>

<jsp:param>.......//可用于include ,forward,plugin标签中..

<jsp:include page="..."  flush="true|false"/>   //在当前页面中包含资源,一旦被包含的页面执行完毕,请求处理将在调用页面中继续进行.....被包含的页面不能设置响应的状态代码和报头...

注意其与<%@  include   file="..."  %>的区别:

       1.调用时间不同,2.被调用相对路径,一个是相对于page,一个是file..

JSP隐含对象及对应的类型:

pageContext:    getAttribute("name",scope);   //得到scope范围内的对象..

exception:         异常....当有isErrorPage=true的页面(错误页面)中才可以使用....

30.留言板,创建可滚动结果集:

stmt=conn.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE,

                          ResultSet.CONCUR_READ_ONLY);

得到总行数: rs.last();   int rowCount=rs.getRow();

得到总页数: pageCount=(rowCount+countPerPage-1)/countPerPage;

游标到第一行: rs.absolute((curPage-1)*countPerPage+1);

显示:        i=0;        while(i<countPerPage&&!rs.isAfterLast()){.......}

/下页: <a href="show.jsp?page=<%curPage-1%>">下一页</a>

31.jsp文档:采用xml语法编写 jsp页面....效果与标准jsp语法相同,但是没有必要,可在MIME类型中指定文档类型..

32.JSPJavaBean:

   JavaBean:封闭业务逻辑......本质上是一个java....

Jsp页面中

<useBean id="operatedb" scope="application" class="xxx.xxx.xxx.OperateDB"/>

则  operatedb是一个对象名.....

可在此页面中操作此对象的方法.......

33.网上书店,购物车的实现:

//图书类:

BookBean:  

   BookBean(int id,String title,String author,String publish_date,float price,int amount,String remark)//get/set方法..

//购物车中条目类:    //计算出总价格,设置数目..

CartItemBean: book,quantity:    CartItemBean(book),  get/setBook, get/setQuantity..

//购物车类:增加,删除,清除,计算车中图书总数,设置某本书数目,所有图书的价格,所有书的条目,判断某本书是否已经在车中...

CartBean:   

   HashMap<Integer,CartItemBean>items=null,    int numOfItems=0;

deleteItem(),addItem(),setItemNum(),getTotalPrice(),getItems(), isExist().

//数据库类:

BookDBBean:

BookDBBean(){

      Context ctx=new InitialContext(); 

      ds=(DataSource)ctx.lookup("java:comp/env/jdbc/bookstore");}

       getConnection(),

          closeCollection(conn);  

      closeSttement(stmt);

          closePreparedStatement(pstmt);closeResultSet(rs);

//得到所有图书信息:Collection<BookBean> getBooks();

//得到选择的图书信息:  BookBean getBook(bookId);

//通过关键字搜索图书:  Collection <BookBean> searchBook(keyword)

//判断剩余图书是否大于购买数量: isAmountEnough(bookId,quantity);

//购买购物车中图书:  buyBooks(cart) ; 

        //pstmt且 pstm.addBatch();  最后  pstm.executeBatch();

34.技巧:如何提交某一页面后,在同一页面中处理并且返回同一页面?  

       :一个作为显示作用的表单.....修改某一项后,保存修改...(即时显示)

     String action=request.getParameter("action");

if(action!=null&&action.equals("保存修改")){

....

itemNum=Integer.parseInt(strItemNum);

for(int i=0;i<itemNum;i++){

strNum=request.getParameter("num_"+i);

strBookId=request.getParameter("book_"+i);

int quantity=Integer.parseInt(strNum);

int bookId=Integer.parseInt(strBookId);

//然后对这一项进行操作...bookid,设置数量...

}

//.....

// 在  form中显示:

int i=0;

       whie(it.hasNext()){

cartItem=(CartItemBean)it.next();

BookBean book=cartItem.getBook();

int bookId=book.getId();

String fieldNum="num_"+i;

String fieldBook="book_"+i;

<input type="text" name="<%=fieldNum%>" value=<%=cartItem.getQuantity()%> size=2 />

<input type="hidden" name="<%=fieldBook%>" value="<%=bookId%">  />     

    //注意:这个隐藏对象传递显示的图书的ID

35.文件的上传与下载:  

  可以上传到服务器的硬盘目录或数据库中,也可以在目录或数据库中下载....request.getInputStream().

36.中文乱码问题:

常用字符集: ASCII(128)  ISO-8859-1(包含ascii ,256)  GB2312(字节最高位为1,GBK的子集)  Unicode  UTF-8(1,2,3byte)..

乱码原因: java内部使用Unicode....java在读取数据时,将本地字符集编码的数据转换为Unicode编码,而在输出时,Unicode转换为本地字符集编码......

例如:在中文系统下,读取"",实际读取GBK0xD6D0,java中转换成0x4E2D,此时内存中""对应0x4E2D,当输出到控制台时,javaUnicode编码再转换到GBK,中文系统再根据GBK字符集画出相应的字符...

Java,不同字符集编码的转换,都是通过Unicode编码作为中介来完成的..

:GBK--->ISO-88591             GBK---->Unicode----->ISO-8859-1

:  GBK:  0xD6D0--->Unicede  : 0x4E2D  但是 0x4E2DISO-8859-1中无对应编码...于是得到0x3f...."?"

当从Unicode编码向某个字符集转换时,如果在该字符集中没有对应的编码,则得到 0x3f即 "?",这就是为什么我们有时输入中文,却得到了问号...

从其它字符集向Unicode转换时,如果这个二进制数从在该字符集中没有标识任何的字符(即不在范围内),则得到的结果是0xfffd... :GBK编码 0x8140,GB2312Unicode转换,然后0x8140不在GB2312字符集范围内,故无对应字符...所以转换 

浏览器会根据本地系统默认的字符集来提交数据,Web容器默认采用ISO-8859-1解析POST数据,在浏览器提交后Web容器采用ISO-8859-1将接收的二进制数转换为Unicode编码,Web应用中按照Unicode处理(即调用getParameter(),得到),再输出到response,输出时默认ISO-8859-1,当有指定时调用指定字符集进行转换...:

浏览器:""(GB2312 0xd6d0)------------->Web容器:使用ISO-8859-1转换成(Unicode /u00d6/u00d0)[  new String(buf,"ISO-8859-1");]------->在应用程序中getParameter():得到/u00d6/u00d0---->输出到浏览器:

A.没有指定字符集默认ISO-8859-1,  "/u00d6/u00d0".getBytes("ISO-8859-1"),得到ISO-8859-1编码 0xd6d0,在浏览器中以中文查看正好是GB2312的  0xd6d0

B.指定字符集GB2312:  "/u00d6/u00d0".getBytes("GB2312")  ---->  ? ?[因为这两个编码在GB2312中都无对应编码]

//:注意其它字符集向Unicode转换时, ISO-8859-1Unicode则是byte(1)-->char(2byte),  反过来:  char(2byte)---byte(1)

  GB2312   向 Unicode   ,   2byte<----------->2byte.

37.中文乱码解决方案:

buf=str.getBytes("ISO-8859-1");//把字符串,转换成进制数...(找到对应编码)..    new String(buf,"gb2312");//把二进制数转换成gb2312..两个字节..

1.POST方法:

由于Web容器默认编码为ISO-8859-1,所以在应用中request.getParameter()方法得到的字符串是ISO-8859-1转换而来的....这就是乱码原因之一.........

   为了避免容器以ISO-8859-1返回字符串,对于POST正文,可在获得请求参数之前,调用request.setCharacterEncodeing("gb2312");向浏览器发送之前,指定输出内容的编码方式 是 GB2312.... response.setContentType("text/html;gb2312");

2.GET方法:

String name=request.getParameter("name");   

       //对于""   得到(通过iso)转换成unicode后的 /u00d6/u00d0

name  =new String(name.getBytes("ISO-8859-1"),"gb2312");  

   工具方法:

public String toGB2312(String str)throws java.io.UnsupportedEncodingException

{

return new String(str.getBytes("ISO-8859-1"),"gb2312");

}

3.数据库中读取中文:  只需要把数据库字符集改为:  GBKgb2312....

java程序和数据库之间传递数据都是以Iso-8859-1为默认格式的...

所以,中文传递:   

提交gb2312---->(gb2312----->Unicode)----->iso-8859-1(java数据库驱动)------>数据库(iso-8859-1---->设定字符集)  出现问题..

  //通过过滤器处理乱码问题:

38.文件上传.

form中  ENCTYPE="multipart/form-data"

对于读取文件中内容,要用request.getInputStream()得到输入流....//具体实现请参照RFC1867

利用commons-fileupload...                       lib:    (commons-fileupload-xxx.jar  , commons-io-xxx.jar )

主要的三个类:FileItem,DiskFileItemFactory,ServletFileUpload.

ServletFileUpload负责处理上传的文件数据,并将每部分的数据封装到一个FileItem对象中..

DiskFileItemFactory是创建FileItem对象的工厂类,在这个工厂中可配置内存缓冲区大小和存放临时文件的目录.

ServletFileUpload在接收上传文件数据时,会将文件内容保存到内存缓冲区中,如果文件内容超过到指定缓冲区大小,那么文件会保存在指定的临时文件,等文件数据都接收完毕后,ServletFileUpload再从临时文件中将数据写入到上传文件目录下的文件中..

FileItem接口中定义的主要方法:

byte[]get()//返回文件数据据项的内容..

getContentType(),getFieldName() //返回文件数据项对应的表单中字段名字,getInputStream(),getName(),

getOutputStream(),getSiz(),getString(),getString(charset),isFormField()//判断是否表示了一个简单表单字段..

write(file)//将文件内容写到硬盘上..

//示例:

DiskFileItemFactory itemFactory=new DiskFileItemFactory();

itemFactory.setSizeThreshold(0x80000);   //设置内存缓冲区512K

File tempDir=new File("E://temp");    //临时文件夹.

if(!tempDir.exists()){

tempDir.mkdir();

}

itemFactory.setRepository(tempDir); //设置存储的临时文件目录..

ServletFileUpload sfu=new ServletFileUpload(itemFactory);

sfu.setSizeMax(0xA0000);                              //设置上传文件的最大数据量为10M

List fileItems=sfu.parseRequest(request); //解析得到的FileItem对象的列表..

Iterator it=fileItems.iterator();

@@

while(it.hasNext()){  //依次处理每个上传的文件...  //此时文件已经传递到临时文件夹中了..

FileItem item=(FileItem)it.next();

if(!item.isFormField()){

long size=item.getSize();

if(name==null||name.equals(""))&&size==0)continue;

out.println(item.getName());

out.println(item.getSize());

File uploadFileDir=new File("E://UploadFile");         @1

if(!uploadFileDir.exists())uploadFileDir.mkdir();       @2

int index=name.lastIndexOf(File.separator);              

if(index>0)name=name.subString(index+1,name.length());//取出文件名.

File file=new File(uploadFileDir,name); @3

item.write(file); @4

}

else{

out.println(item.getFieldName());

out.printn(item.getString("gb2312"));

}

}

//:以下是把文件存储到数据库中:

数据库中表为:  id ,filename,filesize,data(MEDIUMBLOB类型)

大部分处理都是一样的,不一样的为:

@@处加上:<配置数据源连接>

pstmt=conn.prepareStatement("insert inot uploadfile(filename,filesize,data) values(?,?,?)");

去掉@1,2,3,4.

@4处改为:

pstmt.setString(1,name);pstmt.setInt(2,(int)size);

InputStream is=item.getInputStream();

pstmt.setBinaryStream(3,is,(int)size); //往数据库中写二进制大对象的方法setBinaryStream(索引,输入流,字节数);

pstmt.executeUpdate();         

is.close();

39.文件下载:

注意,不要用Jsp文件实现下载,因为在下载充分反映地,我们利用的是ServletOutputStream sos=response.getOutputStream(),得到二进制输出流,Jsp页面有一个隐含的输出流对象out,其类型是Writer,这样会造成冲突.....

//在对客户端的输出中,要么使用二进输出,要么和字符输出,二者不可混用..

文件的安全,可以利用程序实现下载,把文件放在Web以外的目录中,也可以放在数据库中..

设置报头:

Content-Type:application/x-msdownload

Content-Disposition:attachment;filename=downloadfile

Content-Length:filesize

浏览器在接收到上述的报头后,就会弹出"文件下载"对话框....

//:

String strId=request.gtParameter("id");

if(null==strId||strId,equals(""))return ;

File file=null;

InputStream is=null;

String fileName=null;

int fileSize=0;

//对于硬盘下载:

if(strId.equals("111")){

file=new File("D://tomcat.exe");

is=new FileInputStream(file);

fileName=file.getName();

fileSize=(int)file.length();

}

else{

int id=Integer.parseInt(strId);

try{

conn=ds.getConnection();

pstmt=conn.prepareStatement("select * from uploadfile where id=?");

pstmt.setInt(1,id);

rs=pstmt.executeQuery();

if(rs.next()){

fileName=rs.getString("filename");

fileSize=rs.getInt("filesize");

is=rs.getBinaryStream("data");                      //读二进制数据...

}

 }

//设置报头:

response.setContentType("application/x-msdownload");

String str="attatchement;filename="+fileName;

response.setHeader("Content-Disposition",str);

response.setContentLength(fileSize);

//得到响应的输出流:

ServletOutputStream sos=response.getOutputStream();

byte[]data=new byte[2048];

int len=0;

while((len=is.read(data))>0){

sos.write(data,0,len);   //向浏览器输出文件数据..

}

is.close();

sos.close();

                

               //......数据库的关闭..

40.下载时,中文文件名的问题.

下载时,如果下载的文件名中有中文字符,则乱码......要解决这个问题,只需要对下载的盲人摸象中按照UTF-8编码..IE就能正确显示了..

public static String toUTF8String(String str){

StringBuffer sb=StringBuffer();

int len=str.length();

for(int i=0;i<len;i++){

char c=str.charAt(i);

if(c>=0&&c<=255)sb.append(c);

else{

byte [] b;

try{

b=Character.toString(c).getByts("UTF-8");

}

catch(UnsupportedEncodingException ex){

System.err.println(ex);

b=null;

}

for(j=0;j<b.length;j++){

int k=b[j];

if(k<0)k&=255;   //保持原来b[j]的内容....去掉int高字节的1..

sb.append("%"+Integer.toHexString(k).toUpperCase());

}

}//else 

   

}//for

return sb.toString();

}

//对于0~255之间Unicode不做任何处理,对于其它的先转换成UTF-8,然后再转换成%HH字符串形式....?????

fileName=toUTF8String(filename);

41.HTTP.

请求:  请求行+  消息报头 请求正文       

    :(GET/form.html HTTP/1.1 (CRLF))+( ......  )+(CRLF空行)+(user=zhangsan&pwd=1234)

响应:  状态行消息报头响应正文        

:(HTTP/1.1 200 OK (CRLF) )+(.....)+(CRLF空行)+(<html>.....</html>)

HTTP消息:开始行+消息报头+空行+消息正文

42.避免表单的重复提交.

43.给图片添加水印和文字..

     图片格式JPEG,水印图片:gifJPEG

InputStream is=rs.getbinaryStream(data);

//通过jpeg图像数据输入流创建jpeg数据流解码器.

JPEGImageDecoder jpegDecoder=JPEGCodec.createJPEGDecoder(is);

//解码当前jpeg数据,返回BufferedImage对象

BufferedImage buffImg=jpegDecoder.decodeAsBufferedImage();

//得到Graphics对象用于输出绘图和文字.

Graphics g=buffImg.getGraphics();

//创建Icon对象,logo.gif作为水印

ImageIcon imgIcon=new ImageIcon("F:/logo.gif");

//得到Image对象

Image img=imgIcon.getImage();

//将水印画到图片上.

g.drawImage(img,80,80,null);

g.setColor(Color.RED);

Font font=new Font("Courier New",Font.BOLD,20);

g.setFont(font);

g.drawString("http://风韵");

//释放图形上下文使用资源.

g.dispose();

response.setContentType("image/jpeg");

ServletOutputStream sos=response.getOutputStream();

//创建编码器,将内存中图像数据输出到JPEG数据输出流

JPEGImageEncoder jpgEncoder=JPEGCodec.createJPEGEncoder(sos);

//编码BufferedImage对象到输出流.

jpgEncoder.encode(buffImg);

is.close();

sos.close();

44.过滤器:对用户进行统一验证,请求和响应数据的替换..

45.Servlet的监听器.

46.JSP表达式语言,标签库..

第二部分

<Context>元素:可在server.xml, conf/context.xml, conf/xxxx/localhost/context.xml.default,  localhost/xxx.xml,  xxx/META-INF/context.xml.

<servlet>的子元素:icon, init-param,jsp-file,servlet-class,.....

这个文件是直接解压得到的,不是安装的..

首先要配置:java_home,jre_home...............jdk 与 jre目录.

startup.bat  实际上是 catalina.bat start 

当启动出错时,catalina.bat run可以查看出错信息.

jdk中要用的类+Tomcat中的类

webapp下的每一个目录都是一个web应用.. 

并且目录组织形式为:  mysite{  web-inf{classses (.class) ,lib(.jar)  ,web.xml },   index.jsp   }

注意:web-inf是无法被客户端访问的..

Servlet容器运行时,Web应用程序首先加载classes目录下的,其次是lib目录下的.

Servlet 的几种形式:

Servlet--------GenericServlet------HttpServlet

//它们存在一种继承机制.................

//HttpServlet ,由于请求URL都是GET方法,,实现doGet()即可...

JSP:

 指令(page,include,taglib),脚本(声明,脚本段,表达式),动作.

 <%@include %> 与 <jsp:include    />

 jsp隐含对象及其类型.....

MySql 配置安装,驱动..

对于一个项目,不但要有...,而且在 localhost下要有 "项目名.xml" 的配置文件...

重装时,不但要删除my.ini文件,也要删除 MySQL Server 5.1/data

web.xml中 servlet 最好在 servlet-mapping 之前.....

//配置很重要:

web.xml 中  sevlet-mappting 中有一个不存在的 Servlet,这个Web程序就不能启动...

Tomcat自动加载修改过的Servlet: reloadable="true"

Enumeration headNames=req.getHeaderNames();

ServletContext  :Servlet上下文 ......Servlet容器在Web应用程序加载时创建ServletContext对象,作为Web应用程序的运行时表示,ServletContext对象可以被Web应用程序中所有的Servlet所访问.

//context.getAttribute("counter");  当第一次访问时,还没有这个属性,故会返回null

//context.setAttribute("counter",count);

//RequestDispatcher........//用于封闭一个由路径所标识的服务器资源.

sendRedirect()forward()的区别.

web配置:

config/server.xml  :

<Context path="/MySite"    docBase="F:/JSP/../MySite"  reloadable="true"  />

JDBC驱动程序4种类型 :  JDBC-ODBC部分API部分Java驱动程序,JDBC网络JAVA驱动程序,本地协议纯Java驱动程序.   

JDBC操作数据库:加载数据库,获取连接,访问数据.

Statement,PrepaedStatement,ResultSet,CallableStatement.

JSP:  注意,<%@ page contentType="text/heml;charset=gb2312" %>,网页有时打不开,而是直接下载...... 是因为设置响应JSP页面的mime类型错误.....

//初始时,ResultSet对象的游标在第一行之前...故要调用一次next().

//注意,sendRedirect()之后,要用return结束当前方法.

PreparedStatement:  ps=con.prepareStatement("insert employee values(?,?,?)");   ps.setInt(1,2);ps.setString(2,"han");ps.seDate(3,java.sql.Date.valueOf("2004-5-8")); ps.executeUpdate();

//存储过程与元数据.

executeQuery();

executeUpdate();

execute();

executeBatch();

rs.getXxx():

getInt().getDate().getTime();getTimestamp().getString().

//using mysql in batch  model.    ????

// select database();

CREATE TABLE shop ( 

-> article INT(4) UNSIGNED ZEROFILL DEFAULT '0000' NOT NULL, 

-> dealer CHAR(20) DEFAULT '' NOT NULL, 

-> price DOUBLE(16,2) DEFAULT '0.00' NOT NULL, 

-> PRIMARY KEY(article, dealer)); 

mysql> INSERT INTO shop VALUES 

-> (1,'A',3.45),(1,'B',3.99),(2,'A',10.99),(3,'B',1.45), 

-> (3,'C',1.69),(3,'D',1.25),(4,'D',19.95); 

SELECT * FROM shop; 

mysql:

mysql -u root -p 1234

show database;

use xxx;

show tables;

describe tables;

//事务处理:保证所有事务作为一个工作单元来执行....要么所有都完成,要么返回到原来状态.

//setAutoCommit(false)取消自动提交事务.所有SQL成功执行后,调用commit()方法来提交事务,出错时,调用rollback()回滚.

//事务隔离:并行事务......隔离级别.

脏读(一个访问并修改,但是没有提交,另一个读取了这个数据,或前一个发生回滚),

不可重复读(一个事务内读取两次数据,并不同),

幻读(第一个事务读取了满足条件所有行后,第二个事务加了一行数据,当它再次读取时,多了一行数据).

设置级别:

 setTransactionIsolation().

//当结果集中只有一条时,也要调用next()才行...

//可滚动,.

supportsResultSetType();

createStatement(xxx,xxx);

//可更新结果集

updateXxx().

updateRow();

//jdbc数据源和连接池.

//数据源:   DataSource......可以看成是连接工厂.

javax.naming.Context ctx=new javax.naming.InitialContext();  

       //表示一个命名上下文,定义了将对象和名字绑定,以及通过名字查询对象的方法.

       //jdbc子上下文保留给JDBC数据源使用.           java:com/env是环境命名上下文.

javax.sql.DataSource ds=(javax.sql.DataSource)ctx.lookup("java:comp/env/jdbc/book");

java.sql.Connection conn=ds.getConnection();

....

conn.close();

conn=null;

localhost/ch04.xml    .......

<Context docBase="F:/JSPLesson/ch04" reloadable="true">

<Resource name="jdbc/book" auth="container"

 type="javax.sql.DataSource"

 maxActive="100" maxIdle="30" amxWait="10000"

    username="root" password="1234"

    driverClassName="com.mysql.jdbc.Driver"

url="jdbc:mysql://localhost:3306/book?autoReconnect=true"/>

</Context>

//因为种种原因我们是用Tomcat提供的数据源实现来访问MySQL,因为种种原因要将MySQLJDBC驱动复制到Tomcatlib,要明确的是,

Tomcat需要JDBC驱动,而不是应用程序需要JDBC驱动.

//webapps目录下的web应用程序会被Tomcat自动加载......故不需要<context>docBase属性指出Web应用程序根目录.

//Web程序直接在Webapps目录下时,如何配置JDBC数据源...   

<context>也可以在META-INFcontext.xml中设置....               

 如webapps/JSP/   ,  webapps/JSP/META-INF/context.xml

会话跟踪:

1.如何会话.....识别单个用户的一系列请求.

2.状态............记住前面请求的信息.

三种机制:SSL,Cookies,URL重写

Session: 保存在服务器端,对于用户和开发人员都是透明的........

//传递Session ID可由URL重写和Cookie实现

//服务器会同时采用这两种机制

//Cookie可用时,如已经访问某web程序,则再次发送的消息报头会存在Session ID...

//当使用URL重写时,url会带参数session id...

//通过传递到服务器的session id,服务器识别出对应session对象,从而可以设置用户状态..

//若使用invalidate(),用户与服务器会失去这个session id联系....服务端删去此session...

HttpSession session=req.getSession();

session.setAttribute("xxx",value);

param=(String)session.getAttribute("xxx");

///对于用户禁用Cookie,可以用 URL重写机制跟踪用户会话..

只须 对向用户客户端发送URL链接的代码作如下修改..

action=resp.encodeURL("a url")

resp.sendRedirect(resp.encodeRedirectURL("a url ");

//encodeRedirectURL()encodeURL()都是在 url 上加上session信息,达到 url重写的目的...

//注意:  服务器会同时采用这两种机制:  在响应中发送Set-Cookie报头,同时会向URL附加Session ID(假设这个URL采用了response.encodeURL()进行编码.

<form method=post action=loginchk;jsessionid=D93E0E3C27B8AC5202C17DA72246EC1D>

session:存在于服务器.....通常,为了跟踪用户会话,需要将Session ID交给客户端,在用户下交请求时,将这个ID请求一起发送回来....

可以采用CookieURL重写方式,Session ID发送给客户端...........

cookie.存在于客户端.

req.getCookies();

resp.addCookie();

servlet异常处理:   

4xx客户端错误..

5xx服务端错误..

//声明式异常处理;;; 

 <error-page>

<error-code>404</error-code>

<location>/filenotfoune.html</location>

</error-page>

//程序式异常,try..catch()...

RequestDispatcher:将请求转发给其它的Servlt处理.........带上参数.............

rd.forward(req,resp);

//数据源,连接池..........是对数据库来说的.

//线程池.............................多线程.

//Servlet容器采用单例多线程方式...减少产生Servlet实例的开销..

//

try{

    .....

    rs.close();

    rs=null;

    stmt.close();

    stmt=null;

    conn.close();             //注意,连接被放回连接池

   //conn=null;                //此语句被删去将引发问题.................确保关闭连接不会发生两次...........

   }

 catch(){

    ......        AA

 }

 fianlly{

    ...........  BB  

    if(null!=conn){ try{ conn.close()}catch(){}finally{conn=null} } 

    conn=null;

 }

/注意,T1执行到AA,T2开始执行,并利用  conn所指的对象进行连接,在查询进行一半时,

T1开始执行,并两次执行了conn.close()....断开了数据库的连接...........

属性的线程安全:

ServletContext  :  在任何时候都可以被所有Servlet访问...当某一Servlet设置(如删除)一个属性时,其它的ServletServlet正在显示这个属性..则出现异常..

HttpSession      :  同一session............若几个窗口同时访问,一个删,一个显示..   synchronized(session){...................}

ServletRequest :  只在一个线程中使用..

第三部分

//Context配置注意,一定不能放在  web-inf/web.xml可以放在 meta-inf/context.xml,不然会发生错误,(另外,web.xml不能为空文件....)

<%@ page language="java"%>

<%@ page import="java.io.*"%>

<%@ page contentType="text/html;charset=gb2312"%>

<%! int count=1000 ;%>

<%= count %>

<% out.println(" hello world!");

      out.println("你好!");

%>

<%@ ,  <%! ,<% .......

<%-- jsp comments --%>

<!--  html comments -->

<textarea></textarea>  //后面必不可少/>是不行的..

//一个标准JavaBean组件具有以下几个特征:

1.它是一个公开的(public)

2.默认构造函数.

3.提供setXXX()getXXX();

4.实现序列化.

//JavaBean的属性和实例变量不具有一一对应关系.......

如 getInfo(){return new String("okok");}  得到的info没有与之对应的实例变量....

<jsp:useBean>用于实例化或定位一个已经存在的JavaBean实例,并把实例的引用给一个变量...

参数: id 标识JavaBean名字,并被初始化为JavaBean实例的引用..

scope:  JavaBean的范围..........

class:完整类名,.........................................(,若换为type则是找到一个已经建立的useBean...,找不到时会抛出异常..)

beanName: Bean的名字,提供给  instantiate()方法...

其动作如下:jsp容器首先在scope范围内找指定idjavabean,如果找到了,,,

A.没找到但是有class则建一个新的..并赋值给id...

B.没找到但是有beanName则用beanName作为参数调用instantiate()新建对象,并给id..

<jsp:getProperty  name="name" property="propertyname"> name对应于 usebean的 id...

<jsp:setProperty  name="name" property="propertyName"|property="propertyName" param="parameterName"|property="propertyName" value="parameterValue">

//: getProperty中 须有setXXX()....同理getXxx();

//如果property属性的值是"*",标签就会在请求对象中查找所有请求参数,看看是否有参数名字和Bean属性名字相同,如果找到匹配的,主会按照正确的类型转换,将参数的值设置为属性的值..

如果参数值为空,则属性值就不会被修改...

//在设置property属性时,如果,请求参数的名字和Bean属性名字不同,则可用param来指定参数的名字...

//value: 用于请求时属性表达式...

//  jsp  useBean示例 :::::::::::::::;

<% @ page contentType="text/html;charset=gb2312" %>

<% request.setCharacterEncoding("gb2312"); %>

<jsp:useBean id="user" scope="session" class"beans.UserBean"/>

<jsp:setProperty name="user" property="*"/>   

<jsp:setProperty name="user" property="email" param="mail"/>

<!--注意,property="*",可以把所有request中参数与属性名相同的值赋给匹配参数...-->

你的学历:<jsp:getProperty name="user" property="education"/>

........:<jsp:getProperty name="user" property="..."/>

import java.io.Serializable;

import java.util.ArrayList;

import java.util.Collection;

import java.Iterator;

import java.sql.*;

import javax.sql.Datasource;

import javax.naming.Context;

import javax.naming.InitialContext;

import javax.naming.NamingException;

//购物车实现:

1.书本信息 bookBean......bookinfo表对应

2.购物车中一个条目.....包括bookbean对象,数量,合计..

3.购物车:

/*在购物车中增加一个条目,若已经存在,则什么也不*/

/*删除一个图书条目*/

/*清除购物车中所有图书*/

/*得到购物车中图书总条目*/

/*设置某本书的购买数量*/

/*得到购物车中所有价格*/

/*得到购物车中所有的图书条目*/

/*判断图书是否已经加入购物车中*/

4.BookDBBean....封装数据库的操作,包括实现查阅,购买图书功能..

/*关闭连接对象*/

protected void closeConnection(Connection conn){

if(conn!=null){

try{

conn.close();

conn=null;

}

catch(SQLException ex){

ex.printStackTrace();

}

}

}

/*得到数据库中所有的图书信息*/

public Collection<BookBean>getBooks()throws SQLExcption{

Connection conn=null;

Statement  stmt=null;

Result     rs=null;

ArrayList<BookBean> bookList=new ArrayList<BookBean>();

try{

conn=getConnection();

stmt=conn.createStatement();

rs=stmt.executeQuery("select * from bookinfo ");

while(rs.next()){

BookBean book=new BookBean(rs.getInt(1),rs.getString(2),rs.getString(3),rs.getString(4),rs.getString(5),rs.getFloat(6),rs.getInt(7),rs.getString(8));

bookList.add(book);

}

return bookList;

}

finally{

closeResultSet(rs);

closeStatement(stmt);

closeConnection(conn);

}

}

///

conn=getConnection();

pstmt=conn.prepareStatement("select * from bookinfo where id=?");

pstmt.setInt(1,bookId);

rs=pstmt.executeQuery();

//集合类:

三种:::: 

Set(不重复)______________List(可重复)________________Map(不重复,键值对应)....

Set:  size()...contains(element)...remove(element)..add(element).....clear().....___iterator()___

List: 

 get(int index)...set(index,element)....add(index,element)...

 remove(index)...addAll(index,collection)..indexOf(object)..

 lastIndexOf(object)...___listIterator()___..subList(int from,int to)..

Map:    

    put(key,value)...get(key)...remove(key)...containsKey(key)...

    containsValue(value)...size()...hashCode()...isEmpty()...clear()..putAll(Map t)..

    //集合视图:keySet()...values()....entySet()...

迭代器:

Iterator:  hasNext()...next()....remove()...

//jsp文档: : :  xml式语法格式....

分页显示技术:

每页显示的  条数 m

当前页数     作为url参数设置 curpage

查询结果集总条数  n   

每次都是查询一次结果集,然后滚动到某页的第一行,开始显示至多 xx....

关于上下页则要求求出总页数 

 pagecount=(n+m-1)/m;     

//相当于(n%m+m-1)/m+n/m......当余数大于0,单独作为一页...

示例:

1.查询结果...得到 rs..............滚动到rs.last() ....rs.getRow()当前行得到总条数

2.计算出总页数,并 由  rs.absolute((curpage-1)*countPerPage+1)滚动到要显示的游标出...

3.动态显示上下页,根据 curPage与 1,pageCount的关系.....

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值