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

2022-10-18,,,,

大家好,我是乐字节的小乐,上次给大家带来了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注解的相关属性

 

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干货资料和视频。

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

下载本文的Word格式文档,以方便收藏与打印。