9.3 webxml解析及反射应用

SAX方式解析webxml内容

数据

<?xml version="1.0" encoding="UTF-8"?>
<web-app>
	<servlet>
		<servlet-name>login</servlet-name>
		<servlet-class>com.dxt.LoginServlet</servlet-class>
	</servlet>
	<servlet-mapping>
		<servlet-name>login</servlet-name>
		<url-pattern>/login</url-pattern>
		<url-pattern>/g</url-pattern>
	</servlet-mapping>
	<servlet>
		<servlet-name>reg</servlet-name>
		<servlet-class>com.dxt.RegisterServlet</servlet-class>
	</servlet>
	<servlet-mapping>
		<servlet-name>reg</servlet-name>
		<url-pattern>/reg</url-pattern>
	</servlet-mapping>
</web-app>

代码
      因为在xml数据中有 servlet 和 servlet-mapping 两个外部标签,所以我们要建立两个类来帮助解析xml数据,这两个类分别是Entity.class 和 Mapping.class。
Entity.class

/**
 * 针对servlet建立的类
 * @author dxt
 *
 */
public class Entity {
	private String name;
	private String clz;
	
	public Entity(){}
	public Entity(String name, String clz){
		super();
		this.name = name;
		this.clz = clz;
	}
	
	public void setName(String name){
		this.name = name;
	}
	public String getName(){
		return this.name;
	}
	public void setClz(String clz){
		this.clz = clz;
	}
	public String getClz(){
		return this.clz;
	}
	
}

Mapping.class

import java.util.HashSet;
import java.util.Set;
/**
 * 针对<servlet-mapping>
 * @author dxt
 *
 */
public class Mapping {
	private String name;
	private Set<String> patterns;
	
	public Mapping(){
		patterns = new HashSet<String>();
	}
	
	public void setName(String name){
		this.name = name;
	}
	public String getName(){
		return this.name;
	}
	
	public Set<String> getPatterns(){
		return this.patterns;
	}
	public void addPattern(String pattern){
		this.patterns.add(pattern);
	}
	
}

SAX解析代码:

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;

import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;

public class XmlTest03 {
	public static void main(String[] args) throws ParserConfigurationException, SAXException, IOException{
		//1. 获取解析工厂
		SAXParserFactory factory = SAXParserFactory.newInstance();
		//2. 从解析工厂获取解析器
		SAXParser parse = factory.newSAXParser();
		
		//3. 编写处理器
		
		//4. 加载文档注册处理器
		WebHandler handler = new WebHandler();
		//5. 进行解析
		parse.parse(Thread.currentThread().getContextClassLoader()
				.getResourceAsStream("dxt/webxml/servlet.xml"), handler);
	
		//处理数据
		List<Entity> entitys = handler.getEntitys();
		List<Mapping> mappings = handler.getMappings();
		for(Entity e : entitys){
			System.out.println(e.getName() + "---" + e.getClz());
		}
		for(Mapping m : mappings){
			System.out.println(m.getName() + "----" + m.getPatterns());
		}
	}
}

class WebHandler extends DefaultHandler{
	private List<Entity> entitys;
	private List<Mapping> mappings;
	private Entity entity;
	private Mapping mapping;
	private String tag; //存储操作标签
	private boolean isMapping = false;
	
	
	public void startDocument(){
		System.out.println("------文档解析开始------");
		entitys = new ArrayList<Entity>();
		mappings = new ArrayList<Mapping>();
		
	}
	
	public void startElement(String uri, String localName, String qName, Attributes attributes){
		if(null != qName){	//处理换行与空格
			tag = qName;
			//处理对应的标签
			if(tag.equals("servlet")){
				entity = new Entity();
				isMapping = false;
			}else if(tag.equals("servlet-mapping")){
				mapping = new Mapping();
				isMapping = true;
			}
		}
	}
	
	public void characters(char[] ch, int start, int length){
		String contents = new String(ch, start, length).trim();
		if(null != tag){
			if(isMapping){	//处理 mapping
				if(tag.equals("servlet-name")){
					mapping.setName(contents);
				}else if(tag.equals("url-pattern")){
					mapping.addPattern(contents);
				}
			}else{	//处理entity
				if(tag.equals("servlet-name")){
					entity.setName(contents);
				}else if(tag.equals("servlet-class")){
					entity.setClz(contents);
				}
			}
		}
	}
	
	public void endElement(String uri, String localName, String qName){
		if(null != qName){
			if(qName.equals("servlet")){
				entitys.add(entity);
			}else if(qName.equals("servlet-mapping")){
				mappings.add(mapping);
			}
		}
		tag = null;
	}
	
	public void endDocument(){
		System.out.println("------文档解析结束------");
	}
	
	
	public List<Entity> getEntitys(){
		return this.entitys;
	}
	public List<Mapping> getMappings(){
		return this.mappings;
	}
}

结果
p1

依据webxml数据进行反射事件处理

数据
<?xml version="1.0" encoding="UTF-8"?>
<web-app>
	<servlet>
		<servlet-name>login</servlet-name>
		<servlet-class>dxt.webxml.LoginServlet</servlet-class>
	</servlet>
	<servlet-mapping>
		<servlet-name>login</servlet-name>
		<url-pattern>/login</url-pattern>
		<url-pattern>/g</url-pattern>
	</servlet-mapping>
	<servlet>
		<servlet-name>reg</servlet-name>
		<servlet-class>dxt.webxml.RegisterServlet</servlet-class>
	</servlet>
	<servlet-mapping>
		<servlet-name>reg</servlet-name>
		<url-pattern>/reg</url-pattern>
	</servlet-mapping>
</web-app>

      在数据中每一个 url-pattern 都是唯一的,可由url-pattern 找到对应的 servlet-name,再由 servlet-name 找到对应的 servlet-class。每一个 url-pattern 都唯一对应一个 servlet-class,每个 servlet-class 可对应多个 url-pattern。servlet-class标签中的内容就是项目中对应类的地址,可由此地址找到对应类。

目的

      依据xml文件,通过我们输入的 url-pattern 找到项目中的对应类,然后使用此类创建对象。

过程
  1. 解析xml文件。只解析,并不需要打印结果。需要使用Entity.class 和 Mapping.class两个类,这两个类在前面已给出。
  2. 通过给定的 url-pattern 找到对应的 servlet-class。在WebContext.java中实现。
  3. 在项目中创建 servlet-class 对应的类。
  4. 在xmlTest03中使用WebContext提供的类名,通过反射找到对应的类,并创建对象。
代码

XmlTest03.java:

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;

import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;

public class XmlTest03 {
	public static void main(String[] args) throws Exception{
		//1. 获取解析工厂
		SAXParserFactory factory = SAXParserFactory.newInstance();
		//2. 从解析工厂获取解析器
		SAXParser parse = factory.newSAXParser();
		
		//3. 编写处理器
		
		//4. 加载文档注册处理器
		WebHandler handler = new WebHandler();
		//5. 进行解析
		parse.parse(Thread.currentThread().getContextClassLoader()
				.getResourceAsStream("dxt/webxml/servlet.xml"), handler);
	
		//反射事件
		//1. 创建上下文对象
		WebContext wc = new WebContext(handler.getEntitys(), handler.getMappings());
		//2. 依据WebContext 获取我们想要得到的 对应的类名
		//2.1 假设我们输入的是“/reg”
		String name = wc.getClz("/reg");
		//3. 有了类名 ---> 使用反射   获取对应类的信息, 类名就是xml数据中的<servlet-class>
		Class clz = Class.forName(name);
		//4. 使用反射进行实例化
		Servlet s = (Servlet)clz.getConstructor(null).newInstance(null);
		s.service();	//调用对应的方法
	}
}

class WebHandler extends DefaultHandler{
	private List<Entity> entitys;
	private List<Mapping> mappings;
	private Entity entity;
	private Mapping mapping;
	private String tag; //存储操作标签
	private boolean isMapping = false;
	
	
	public void startDocument(){
		System.out.println("------文档解析开始------");
		entitys = new ArrayList<Entity>();
		mappings = new ArrayList<Mapping>();
		
	}
	
	public void startElement(String uri, String localName, String qName, Attributes attributes){
		if(null != qName){	//处理换行与空格
			tag = qName;
			//处理对应的标签
			if(tag.equals("servlet")){
				entity = new Entity();
				isMapping = false;
			}else if(tag.equals("servlet-mapping")){
				mapping = new Mapping();
				isMapping = true;
			}
		}
	}
	
	public void characters(char[] ch, int start, int length){
		String contents = new String(ch, start, length).trim();
		if(null != tag){
			if(isMapping){	//处理 mapping
				if(tag.equals("servlet-name")){
					mapping.setName(contents);
				}else if(tag.equals("url-pattern")){
					mapping.addPattern(contents);
				}
			}else{	//处理entity
				if(tag.equals("servlet-name")){
					entity.setName(contents);
				}else if(tag.equals("servlet-class")){
					entity.setClz(contents);
				}
			}
		}
	}
	
	public void endElement(String uri, String localName, String qName){
		if(null != qName){
			if(qName.equals("servlet")){
				entitys.add(entity);
			}else if(qName.equals("servlet-mapping")){
				mappings.add(mapping);
			}
		}
		tag = null;
	}
	
	public void endDocument(){
		System.out.println("------文档解析结束------");
	}
	
	
	public List<Entity> getEntitys(){
		return this.entitys;
	}
	public List<Mapping> getMappings(){
		return this.mappings;
	}
}

WebContext.java:

import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 目的: 根据url-pattern 找 servlet-class
 * 对于webxml数据
 * 可以依据<servlet-mapping> 中的pattern 找到 name
 * 在根据 name 在<servlet> 中找到class
 * @author dxt
 *
 */
public class WebContext {
	private List<Entity> entitys;
	private List<Mapping> mappings;
	//创建两个map数据,帮助解决问题
	//key:servlet-name  value:servlet-class
	private Map<String, String> entityMap = new HashMap<String, String>();
	//key:url-pattern  value:servlet-name
	private Map<String, String> mappingMap = new HashMap<String, String>();
	
	public WebContext(List<Entity> entitys, List<Mapping> mappings){
		this.entitys = entitys;
		this.mappings = mappings;
		
		//将entity的List转成了map
		for(Entity entity : entitys){
			entityMap.put(entity.getName(), entity.getClz());
		}
		//将mapping的List转为map
		for(Mapping mapping : mappings){
			for(String pattern : mapping.getPatterns()){
				mappingMap.put(pattern, mapping.getName());
			}
		}
	}
	/**
	 * 依据url-pattern 找对应的 servlet-class
	 * 一个url-pattern唯一对应一个class
	 * 一个class可对应多个url-pattern
	 * 返回servlet-class
	 * @param pattern
	 * @return
	 */
	public String getClz(String pattern){
		String name = mappingMap.get(pattern);	//找到对应name
		
		return entityMap.get(name);	//找到对应class
	}
}

Servlet.java:

/**
 * Servlet接口
 * 用于测试
 * @author dxt
 *
 */
public interface Servlet {
	void service();
}

LoginServlet.java

/**
 * 实现Servlet接口
 * @author dxt
 *
 */
public class LoginServlet implements Servlet {

	public void service() {
		System.out.println("LoginServlet");
	}
}

RegisterServlet.java:

/**
 * 实现Servlet接口
 * @author dxt
 *
 */
public class RegisterServlet implements Servlet {

	public void service() {
		System.out.println("RegisterServlet");
	}
}
结果

p2

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值