欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

Java注解-注解处理器、servlet3.0|乐字节

程序员文章站 2022-04-30 22:26:56
大家好,我是乐字节的小乐,上次给大家带来了Java注解-元数据、注解分类、内置注解和自定义注解|乐字节,这次接着往下讲注解处理器和servlet3.0 一、注解处理器 使用注解的过程中,很重要的一部分就是创建于使用注解处理器。Java SE5扩展了反射机制的API,以帮助程序员快速的构造自定义注解处 ......

大家好,我是乐字节的小乐,上次给大家带来了java注解-元数据、注解分类、内置注解和自定义注解|乐字节,这次接着往下讲注解处理器和servlet3.0

Java注解-注解处理器、servlet3.0|乐字节

 

一、注解处理器

使用注解的过程中,很重要的一部分就是创建于使用注解处理器。java se5扩展了反射机制的api,以帮助程序员快速的构造自定义注解处理器。

1、注解处理器类库java.lang.reflect.annotatedelement

java使用annotation接口来代表程序元素前面的注解,该接口是所有annotation类型的父接口。除此之外,java在java.lang.reflect 包下新增了annotatedelement接口,该接口代表程序中可以接受注解的程序元素,该接口主要有如下几个实现类:

class:类定义
constructor:构造器定义
field:累的成员变量定义
method:类的方法定义
package:类的包定义

java.lang.reflect 包下主要包含一些实现反射功能的工具类,实际上,java.lang.reflect 包所有提供的反射api扩充了读取运行时annotation信息的能力。当一个annotation类型被定义为运行时的annotation后,该注解才能是运行时可见,当class文件被装载时被保存在class文件中的annotation才会被虚拟机读取。


annotatedelement 接口是所有程序元素(class、method和constructor)的父接口,所以程序通过反射获取了某个类的annotatedelement对象之后,程序就可以调用该对象的如下四个个方法来访问annotation信息:

①<t extends annotation> t getannotation(class<t> annotationclass): 返回该程序元素上存在的、指定类型的注解,如果该类型注解不存在,则返回null。

②annotation[] getannotations():返回该程序元素上存在的所有注解。


③boolean is annotationpresent(class<?extends annotation> annotationclass):判断该程序元素上是否包含指定类型的注解,存在则返回true,否则返回false.


④annotation[] getdeclaredannotations():返回直接存在于此元素上的所有注释。与此接口中的其他方法不同,该方法将忽略继承的注释。(如果没有注释直接存在于此元素上,则返回长度为零的一个数组。)该方法的调用者可以随意修改返回的数组;这不会对其他调用者返回的数组产生任何影响。

2、解析实例

public class parsecoder {
	public static void main(string[] args) {
		string codername="名称:";
		string codertype="类型:";
		string coderprovider="厂家信息如下 ";
		field [] fields=coder.class.getdeclaredfields();
		for(field field:fields){
			if(field.isannotationpresent(programmer.class)){
				programmer pro=(programmer)field.getannotation(programmer.class);
				codername=codername+pro.value();
				system.out.println(codername);
			}else if(field.isannotationpresent(programmertype.class)){
				programmertype type=(programmertype)field.getannotation(programmertype.class);
				codertype=codertype+type.type().tostring();
				system.out.println(codertype);
			}else if(field.isannotationpresent(programmerproductor.class)){
				programmerproductor fruitprovider=(programmerproductor)field.getannotation(programmerproductor.class);
				coderprovider+="编号:"+fruitprovider.id()+" 名称:"+fruitprovider.name()+" 地址:"+fruitprovider.address();
				system.out.println(coderprovider);
			}
		}
	}
}

二、 servlet3.0

@webservlet

使用注解达到零配置,开发servlet项目,使用@webservlet将一个继承于javax.servlet.http.httpservlet的类定义为servlet组件。在servlet3.0中,可以使用@webservlet注解将一个继承于javax.servlet.http.httpservlet的类标注为可以处理用户请求的servlet。

@webservlet注解的相关属性

Java注解-注解处理器、servlet3.0|乐字节

 

servlet的访问url是servlet的必选属性,可以选择使用urlpatterns或者value定义。如一个servlet可以描述成:

@webservlet(name="servletdemo",value="/servletdemo")。

也定义多个url访问:如

@webservlet(name="servletdemo",urlpatterns={"/servletdemo","/servletdemo2"})

或者:

@webservlet(name="annotationservlet",value={"/servletdemo","/servletdemo2"})

initparams可以用来指定当前servlet的初始化参数,它是一个数组, 里面每一个@webinitparam表示一个参数。

@webservlet(value="/servlet/init-param", initparams={@webinitparam(name="param1", value="value1")})

测试实例如下

/**
 * 使用@webservlet将一个继承于javax.servlet.http.httpservlet的类定义为servlet组件。
如@webservlet有很多的属性:
1、asyncsupported:    声明servlet是否支持异步操作模式。
2、description:      servlet的描述。
3、displayname:       servlet的显示名称。
4、initparams:        servlet的init参数。
5、name:           servlet的名称。
6、urlpatterns:servlet的访问url。
7、value:           servlet的访问url。
servlet的访问url是servlet的必选属性,可以选择使用urlpatterns或者value定义。
如@webservlet(name="testservlet",value="/testservlet"),也定义多个url访问:
如@webservlet(name="testservlet",urlpatterns={"/testservlet","/test"})
或@webservlet(name="testservlet",value={"/testservlet","/test"})
 */
@webservlet(name="/testservlet",urlpatterns={"/test"})
public class testservlet extends httpservlet {
	private static final long serialversionuid = 1l;
	protected void doget(httpservletrequest request, httpservletresponse response) throws servletexception, ioexception {
		response.getwriter().print("hello servlet3");
	}
	protected void dopost(httpservletrequest request, httpservletresponse response) throws servletexception, ioexception {
		doget(request, response);
	}
}

 

初始化参数

@webservlet(value="/init", 
initparams={@webinitparam(name="param1", value="sxt")})
public class testinit extends httpservlet {
	private static final long serialversionuid = 1l;
	protected void doget(httpservletrequest request, httpservletresponse response) throws servletexception, ioexception {
	  enumeration<string> paramnames = this.getservletconfig().getinitparameternames();  
      string paramname;  
      while (paramnames.hasmoreelements()) {  
         paramname = paramnames.nextelement();  
         response.getwriter().append(paramname + " = " + this.getservletconfig().getinitparameter(paramname));  
      }  
      response.getwriter().close();  
	}
	protected void dopost(httpservletrequest request, httpservletresponse response) throws servletexception, ioexception {
		doget(request, response);
	}
}

 

@webfilter

/**
 * 使用注解标注过滤器:@webfilter将一个实现了javax.servlet.filter
 * 接口的类定义为过滤器,属性filtername声明过滤器的名称,可选
 * 属性urlpatterns指定要过滤 的url模式,也可使用属性value来声明.
 * (指定要过滤的url模式是必选属性),
 * 可以指定多种过滤模式@webfilter(filtername="testfilter",
 * urlpatterns={"/user","/index.jsp"})
 * @author administrator
 */
@webfilter(filtername="testfilter",urlpatterns="/*")
public class testfilter implements filter  {
	@override
	public void destroy() {
		system.out.println("过滤器销毁");
	}
	@override
	public void dofilter(servletrequest request, servletresponse response, filterchain chain)
			throws ioexception, servletexception {
		system.out.println("执行过滤操作");
		chain.dofilter(request, response);
	}
	@override
	public void init(filterconfig arg0) throws servletexception {
		 system.out.println("过滤器初始化");
	}
}

@multipartconfig

使用注解@multipartconfig将一个servlet标识为支持文件上传。servlet3.0将multipart/form-data的post请求封装成part,通过part对上传的文件进行操作。

注意:servlet3没有提供直接获取文件名的方法,需要从请求头中解析出来

1)、页面制作

<%@ page language="java" contenttype="text/html; charset=utf-8"
    pageencoding="utf-8"%>
<!doctype html public "-//w3c//dtd html 4.01 transitional//en" "http://www.w3.org/tr/html4/loose.dtd">
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8">
<title>文件上传</title>
</head>
<body>
	<fieldset>
		<legend>上传文件</legend>
		<!-- 文件上传时必须要设置表单的enctype="multipart/form-data" -->
		<form action="${pagecontext.request.contextpath}/upload" method="post" enctype="multipart/form-data">
			上传文件:<input type="file" name="file1"><br/>
			上传文件:<input type="file" name="file2"><br/>
			<input type="submit" value="上传">
		</form>
	</fieldset>
</body>
</html>

2)、编写servlet

/**
 * servlet3.0将multipart/form-data的post请求封装成part,
 * 通过part对上传的文件进行操作,servlet3没有提供直接获取文件名的方法,
 * 需要从请求头中解析出来,获取请求头,请求头的格式:
 * 火狐和google浏览器下:form-data; name="file"; filename="snmp4j--api.zip"
* @author administrator
 */
@webservlet(name = "testupload", urlpatterns = "/upload")
@multipartconfig
public class testupload extends httpservlet {
	public void doget(httpservletrequest request, httpservletresponse response) throws servletexception, ioexception {
		request.setcharacterencoding("utf-8");
		response.setcharacterencoding("utf-8");
		response.setcontenttype("text/html;charset=utf-8");
		// 存储路径
string savepath = request.getservletcontext().getrealpath("/web-inf/upload");
		// 获取上传的文件集合
		collection<part> parts = request.getparts();
		//上传单个文件
		if (parts.size()==1) {
			//通过文件名获取文件
			part part = request.getpart("file");
			//从请求头中获取文件
			string header = part.getheader("content-disposition");
			//获取文件名
			string filename = getfilename(header);
			//把文件写到指定路径
			part.write(savepath+file.separator+filename);
		}else{
			 for (part part : parts) {//循环处理上传的文件
//请求头的格式:form-data; name="file"; filename="snmp4j--api.zip"
				 string header = part.getheader("content-disposition");
				 //获取文件名
string filename = getfilename(header);
                if(!filename.equals("")){
					//把文件写到指定路径
					part.write(savepath+file.separator+filename);
				}				 
			 }
		}
		printwriter out = response.getwriter();
		out.println("上传成功");
		out.flush();
		out.close();
	}
	@override
	protected void dopost(httpservletrequest req, httpservletresponse resp) throws servletexception, ioexception {
		this.doget(req,resp);
	}
	/**
	 * 获取文件名
* 火狐和google浏览器下:form-data; name="file"; filename="snmp4j--api.zip"
	 * @param header
	 * @return
	 */
	private  string getfilename(string header) {
		string[] headarr = header.split(";")[2].split("=");
		//获取文件名,兼容各种浏览器的写法		
		return headarr[1].substring(headarr[1].lastindexof("\\")+1).replaceall("\"", "");
		
	}
}

@weblistener

servlet3.0提供@weblistener注解将一个实现了特定监听器接口的类定义为监听器。将实现了servletcontextlistener接口的myservletcontextlistener标注为监听器。

@weblistener
public class testlistener implements servletcontextlistener {
	@override
	public void contextdestroyed(servletcontextevent event) {
		 system.out.println("servletcontext销毁");
	}
	@override
	public void contextinitialized(servletcontextevent event) {
		 system.out.println("servletcontex初始化");
		 system.out.println(event.getservletcontext().getserverinfo());
	}
}

有关注解就介绍到这里了,感谢各位老板的光顾和学习。

请继续关注乐字节,后续不断更新java干货资料和视频。