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;
}
}
结果
依据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 找到项目中的对应类,然后使用此类创建对象。
过程
- 解析xml文件。只解析,并不需要打印结果。需要使用Entity.class 和 Mapping.class两个类,这两个类在前面已给出。
- 通过给定的 url-pattern 找到对应的 servlet-class。在WebContext.java中实现。
- 在项目中创建 servlet-class 对应的类。
- 在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");
}
}