Servlet
今天文章较长,因为包含了几个案例,请耐心看。
JavaServlet是运行在Web服务器或应用服务器上的程序,它是作为来自Web浏览器或其他HTTP客户端的请求和HTTP服务器上的数据库或应用程序之间的中间层。
使用Servlet,您可以收集来自网页表单的用户输入,呈现来自数据库或者其他源的记录,还可以动态创建网页。
JavaServlet通常情况下与使用CGI(CommonGatewayInterface,公共网关接口)实现的程序可以达到异曲同工的效果。但是相比于CGI,Servlet有以下几点优势:
性能明显更好。Servlet在Web服务器的地址在空间内执行。这样它就没有必要再创建一个单独的进程来处理每个客户端请求。Servlet是独立于平台的,因为它们是用Java编写的。服务器上的Java安全管理器执行了一系列限制,以保护服务器计算机上的资源。因此,Servlet是可信的。Java类库的全部功能对Servlet来说都是可用的。它可以通过sockets和RMI机制与applets、数据库或其他软件进行交互。
Servlet生命周期
Servlet生命周期可被定义为从创建直到毁灭的整个过程。以下是Servlet遵循的过程:
Servlet初始化后调用init()方法。Servlet调用service()方法来处理客户端的请求。Servlet销毁前调用destroy()方法。最后,Servlet是由JVM的垃圾回收器进行垃圾回收的。
现在让我们详细讨论生命周期的方法。
Servlet调用过程
Servlet的调
源于视频
Servlet过滤器与监听器
Servlet过滤器可以动态地拦截请求和响应,以变换或使用包含在请求或响应中的信息。
可以将一个或多个Servlet过滤器附加到一个Servlet或一组Servlet。Servlet过滤器也可以附加到JavaServerPages(JSP)文件和HTML页面。调用Servlet前调用所有附加的Servlet过滤器。
Servlet过滤器是可用于Servlet编程的Java类,可以实现以下目的:
在客户端的请求访问后端资源之前,拦截这些请求。在服务器的响应发送回客户端之前,处理这些响应。
例如:统一字符编码,字符的压缩,加密,实施安全控制等;
与过滤器有关的有三个包:FilterFilterChain和FilterConfig;
Filter:所有过滤器都必须实现这个接口;生命周期:web应用加载后立即创建这个web应用的所有过滤器,创建后是驻留在内存中init();过滤器初始化,容器会创建实例后调用这个方法FilterConfig:代表web.xml中对filter的配置信息获取servletContext对象获取初始信息FilterChain:doFilter();用于调用过滤器链中的下一个过滤器,如果是最后一个则将请求提交给处理程序或响应到客户端上;filterChain代表一个连对象,一个资源可以用多个过滤器进行拦截,拦截顺序和filtermapping的顺序决定链的最后一各节点就是访问的资源;FilterConfig:用于过滤器初始化阶段提供过滤器的名字,初始化参数,servlet上下文的信息;StringgetFilterName();返回web.xml文件定义的名称ServletContextgetServletContext()方法,返回调用者所处的Servlet的上下文StringgetInitParameter(Stringname):返回配置过滤器名是name的初始值;‘EnumerationgetgetInitParameterNames()以Enumeration形式返回过滤器所有初始化参数的名称出现servlet3.0后在eclipes中就不需要配置web.xml了如何进行创建出filter中的参数,写在web.xml中是不能实现的:范式:创建filter过滤器,然后在其中的参数列表中选择是否创建参数,然后在改下对应的url-parttern参数让他对应你的jsp文件就可以解决这个问题;
WebFilter(urlPatterns={"/jsp/index.jsp"},initParams={WebInitParam(name="count",value="")})用filterConfig来获取属性的值是多少filterConfig.getInitParameter(Stringname);WebFilter(asyncSupported=true,description="filterdemo",urlPatterns={"/*"})在myeclipse中就必须在web.xml逐一配置出来有:filterfilter-nameFilter1/filter-namefilter-classcn.itcast.filter.Filter1/filter-class/filter!--配置过滤器去拦截哪个资源--filter-mappingfilter-nameFilter1/filter-nameurl-pattern/hello.jsp/url-patterndispatcherREQUEST/dispatcher--用来配置以哪种方式对资源的访问(quest/forward/include/error)可以配置多个dispatcher如果不配置默认为quest请求/filter-mappingWebFilter(asyncSupported=true,description="filterdemo",urlPatterns={"/demo1Filr"})publicclassDemo1FilterimplementsFilter{/***Defaultconstructor.*/publicDemo1Filter(){//TODOAuto-generatedconstructorstub}/***
seeFilter#destroy()*/publicvoiddestroy(){//TODOAuto-generatedmethodstubSystem.out.println("filter销毁了");}/***seeFilter#doFilter(ServletRequest,ServletResponse,FilterChain)*/publicvoiddoFilter(ServletRequestquest,ServletResponsesponse,FilterChainchain)throwsIOException,ServletException{//TODOAuto-generatedmethodstub//placeyourcodeheSystem.out.println("demo1前");//passthequestalongthefilterchain//意思是执行下一个节点可以为过滤器可以为资源chain.doFilter(quest,sponse);System.out.println("demo1后");}/***seeFilter#init(FilterConfig)*/publicvoidinit(FilterConfigfConfig)throwsServletException{//TODOAuto-generatedmethodstubSystem.out.println("filter创建了");}}Servlert经典实例
文件上传
/***ServletimplementationclassUploaddisckServlet*/
WebServlet("/UploaddisckServlet")MultipartConfigpublicclassUploaddisckServletextendsHttpServlet{privatestaticfinallongserialVersionUID=1L;/***seeHttpServlet#HttpServlet()*/publicUploaddisckServlet(){super();//TODOAuto-generatedconstructorstub}/***seeHttpServlet#doGet(HttpServletRequestquest,HttpServletResponsesponse)*/protectedvoiddoGet(HttpServletRequestquest,HttpServletResponsesponse)throwsServletException,IOException{//TODOAuto-generatedmethodstub//1.上传文件Stringupload=this.getServletContext().getRealPath("WEB-INF/upload");Stringtemp=this.getServletContext().getRealPath("WEB_INF/temp");//创建工厂设置缓冲大小和穿就缓冲区路径DiskFileItemFactoryfactory=newDiskFileItemFactory();factory.setSizeThshold(*);factory.setRepository(newFile(temp));//2.生产文件上传核心类ServletFileUploadfileUpload=newServletFileUpload(factory);//设置编码fileUpload.setHeaderEncoding("UTF-8");//设置文件大小的上传限制fileUpload.setFileSizeMax(**10);fileUpload.setSizeMax(**);//检查当前是项目是否为上传文件//if(fileUpload.isMultipartContent(quest)){//thrownewRuntimeException("请用正确的表单上传");//}//解析quest//3.利用文件上传核心类来解析questtry{ListFileItemlist=fileUpload.parseRequest(quest);MapString,Stringmap=newHashMap();//循环遍历for(FileItemitem:list){if(item.isFormField()){//普通的字段获得的是一个表单Stringname=item.getFieldName();Stringvalue=item.getString("utf-8");map.put(name,value);System.out.println(name+":"+value);}else{//当前一个文件上传项Stringfilename=item.getName();//文件名//设置一个独一无二的文件名Stringuuidfilename=UUID.randomUUID().toString()+"_"+filename;map.put("alname",filename);map.put("uuidname",uuidfilename);map.put("ip",quest.getRemoteAddr());Stringsavepath="/WEB-INF/upload";//转换为hash值inthash=uuidfilename.hashCode();//转化为hash字符串Stringhashstr=Integer.toHexString(hash);char[]hss=hashstr.toCharArray();for(charc:hss){upload+="/"+c;savepath+="/"+c;}newFile(upload).mkdirs();map.put("savepath",savepath);InputStaminputStam=item.getInputStam();OutputStamoutputStam=newFileOutputStam(newFile(upload,uuidfilename));IOUtils.In2Out(inputStam,outputStam);IOUtils.close(inputStam,outputStam);//删除临时文件item.delete();}}//像数据库中插入Resourcesource=newResource();BeanUtils.populate(source,map);Stringsql="insertintonetdiskvalues(null,?,?,?,?,null,?)";QueryRunnerrunner=newQueryRunner(DaoUtils.getSource());runner.update(sql,source.getUuidname(),source.getRealname(),source.getSavepath(),source.getIp(),source.getDescription());//3.重定向回主页sponse.sendRedict(quest.getContextPath()+"/disk/index.jsp");}catch(FileUploadExceptionIllegalAccessException
InvocationTargetException
SQLExceptione){//TODOAuto-generatedcatchblocke.printStackTrace();}}/***
seeHttpServlet#doPost(HttpServletRequestquest,HttpServletResponsesponse)*/protectedvoiddoPost(HttpServletRequestquest,HttpServletResponsesponse)throwsServletException,IOException{//TODOAuto-generatedmethodstubdoGet(quest,sponse);}}版本二:
/***ServletimplementationclassUploadServlet*/
WebServlet(description="文件上传",urlPatterns={"/UploadServlet"})publicclassUploadServletextendsHttpServlet{privatestaticfinallongserialVersionUID=1L;/***seeHttpServlet#HttpSep=rvlet()*/publicUploadServlet(){super();//TODOAuto-generatedconstructorstub}/***seeHttpServlet#doGet(HttpServletRequestquest,HttpServletResponsesponse)*/protectedvoiddoGet(HttpServletRequestquest,HttpServletResponsesponse)throwsServletException,IOException{//TODOAuto-generatedmethodstub//通过工厂类来实现DiskFileItemFactoryfactory=newDiskFileItemFactory();//设置缓冲区大小factory.setSizeThshold(*);//设置临时文件夹factory.setRepository(newFile(this.getServletContext().getRealPath("WEB-INF/temp")));//2.生产文件上传核心类ServletFileUploadfileUpload=newServletFileUpload(factory);try{//判断是否为真正的表单上传文件//if(fileUpload.isMultipartContent(quest)){//thrownewRuntimeException("请用正确的表单上传");//}//设置文件大小的上传限制fileUpload.setFileSizeMax(**10);fileUpload.setSizeMax(**);//设置编码fileUpload.setHeaderEncoding("UTF-8");//设置上传监听进度条:fileUpload.setProgssListener(newProgssListener(){//LongbeginTime=System.curntTimeMillis();//已经读了,总共多少,读到第几个了Overridepublicvoidupdate(longpBytesRead,longpContentLength,intpItems){//TODOAuto-generatedmethodstub//转换为kb//doublebr=pBytesRead*1.0/;//doublecl=pContentLength*1.0/;//为了保留字节用以下方法BigDecimalbr=newBigDecimal(pBytesRead).divide(newBigDecimal(),2,BigDecimal.ROUND_HALF_UP);BigDecimalcl=newBigDecimal(pContentLength).divide(newBigDecimal(),2,BigDecimal.ROUND_HALF_UP);System.out.print("当前读取的是第"+pItems+"个上传项,总大小"+cl+"KB,已经读取"+br+"KB");//剩余字节数BigDecimalll=cl.subtract(br);System.out.print("剩余"+ll+"KB");//上传百分比BigDecimalper=br.multiply(newBigDecimal()).divide(cl,2,BigDecimal.ROUND_HALF_UP);System.out.print("已经完成"+per+"%");//上传用时LongnowTime=System.curntTimeMillis();LonguseTime=(nowTime-beginTime)/0;System.out.print("已经用时"+useTime+"秒");//上传速度BigDecimalspeed=newBigDecimal(0);if(useTime!=0){//四舍五入模式向“最近邻居”转弯,除非两个邻居都是等距的,在这种情况下是圆括弧的。speed=br.divide(newBigDecimal(useTime),2,BigDecimal.ROUND_HALF_UP);}System.out.print("上传速度为"+speed+"KB/S");//大致剩余时间BigDecimalltime=newBigDecimal(0);if(!speed.equals(newBigDecimal(0))){//返回一个BigDecimal,其值为(this/divisor),其比例为指定。ltime=ll.divide(speed,0,BigDecimal.ROUND_HALF_UP);}System.out.print("大致剩余时间为"+ltime+"秒");System.out.println();}});//3.利用文件上传核心类来解析questListFileItemlist=fileUpload.parseRequest(quest);//循环遍历for(FileItemitem:list){if(item.isFormField()){//普通的字段获得的是一个表单??Stringname=item.getFieldName();Stringvalue=item.getString("utf-8");System.out.println(name+":"+value);}else{//当前一个文件上传项Stringfilename=item.getName();//文件名//设置一个独一无二的文件名Stringuuidfilename=UUID.randomUUID().toString()+"_"+filename;//转换为hash值inthash=uuidfilename.hashCode();//转化为hash字符串Stringhashstr=Integer.toHexString(hash);char[]hss=hashstr.toCharArray();Stringpath=this.getServletContext().getRealPath("upload");for(charc:hss){path+="/"+c;}newFile(path).mkdirs();InputStaminputStam=item.getInputStam();OutputStamoutputStam=newFileOutputStam(newFile(path,uuidfilename));IOUtils.In2Out(inputStam,outputStam);IOUtils.close(inputStam,outputStam);//删除临时文件item.delete();}}}catch(FileUploadExceptione){//TODOAuto-generatedcatchblocke.printStackTrace();thrownewRuntimeException();}}/***seeHttpServlet#doPost(HttpServletRequestquest,HttpServletResponsesponse)*/protectedvoiddoPost(HttpServletRequestquest,HttpServletResponsesponse)throwsServletException,IOException{//TODOAuto-generatedmethodstubdoGet(quest,sponse);}}IOUtils
publicclassIOUtils{privateIOUtils(){}publicstaticvoidIn2Out(InputStamin,OutputStamout)throwsIOException{byte[]bs=newbyte[];inti=0;while((i=in.ad(bs))!=-1){out.write(bs,0,i);}}publicstaticvoidclose(InputStamin,OutputStamout){if(in!=null){try{in.close();}catch(IOExceptione){e.printStackTrace();}finally{in=null;}}if(out!=null){try{out.close();}catch(IOExceptione){e.printStackTrace();}finally{out=null;}}}}
自动登录拦截器
package
JavaMail需要Properties来创建一个session对象。它将寻找字符串"mail.smtp.host",属性值就是发送邮件的主机.用法: Propertiesprops=newProperties();//Propertiesprops=System.getProperties(); props.put("mail.smtp.host","smtp..
这个Session类代表JavaMail中的一个邮件session.每一个基于JavaMail的应用程序至少有一个session但是可以有任意多的session。在这个例子中,Session对象需要知道用来处理邮件的SMTP服务器。用法:
SessionsendMailSession=Session.getInstance(props,null);//不须认证(3)javax.mail.Transport类
邮件是既可以被发送也可以被受到。JavaMail使用了两个不同的类来完成这两个功能:Transport和Sto.Transport是用来发送信息的,而Sto用来收邮件。在这发送邮件我们只需要用到Transport对象。用法:Transporttransport=sendMailSession.getTransport("smtp");
用JavaMailSession对象的getTransport方法来初始化Transport。传过去的字符串申明了对象所要使用的协议,如"smtp"。这将为我们省了很多时间。因为JavaMail以经内置了很多协议的实现方法。 注意:JavaMail并不是绝对支持每一个协议,目前支持IMAP、SMTP和POP3.(4)javax.mail.MimeMessage类
Message对象将存储我们实际发送的电子邮件信息,Message对象被作为一个MimeMessage对象来创建并且需要知道应当选择哪一个JavaMailsession。
用法:MessagenewMessage=newMimeMessage(sendMailSession);(5)javax.mail.InternetAddss类一旦您创建了Session和Message,并将内容填入消息后,就可以用Addss确定信件地址了。和Message一样,Addss也是个抽象类。您用的是Javax.mail.internet.InternetAddss类.用法:InternetAddssfrom=newInternetAddss("xxf