image.png
根据路径找到servlet-name,再根据servlet-name找到servlet-class,然后利用反射

解析web.xml

web.xml文件

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <web-app>
  3. <servlet>
  4. <servlet-name>login</servlet-name>
  5. <servlet-class>com.sxt.server.basic.servlet.LoginServlet</servlet-class>
  6. </servlet>
  7. <servlet>
  8. <servlet-name>reg</servlet-name>
  9. <servlet-class>com.sxt.server.basic.servlet.RegisterServlet</servlet-class>
  10. </servlet>
  11. <servlet-mapping>
  12. <servlet-name>login</servlet-name>
  13. <url-pattern>/login</url-pattern>
  14. <url-pattern>/g</url-pattern>
  15. </servlet-mapping>
  16. <servlet-mapping>
  17. <servlet-name>reg</servlet-name>
  18. <url-pattern>/reg</url-pattern>
  19. </servlet-mapping>
  20. </web-app>

解释

public class XmlSax {

    public static void main(String[] args) throws ParserConfigurationException, SAXException, IOException {
        // TODO Auto-generated method stub
        SAXParserFactory factory = SAXParserFactory.newInstance();
        SAXParser parse = factory.newSAXParser();

        WebHandler handler = new WebHandler();
        parse.parse(Thread.currentThread().getContextClassLoader().getResourceAsStream("com/leon/servlet/web.xml"), handler);

        List<Entity> entitys = handler.getEntitys();
        List<Mapping> mappings = handler.getMappings();
        System.out.println(entitys.size());
        System.out.println(mappings.size());
        for(Entity e : entitys) {
            System.out.println(e.getName() + "-->" + e.getClz());
        }

        for(Mapping m : mappings) {
            System.out.println(m.getName());
            for(String s : m.getPatterns()) {
                System.out.println(s);
            }
            System.out.println("-------------------------");
        }

    }

}

class WebHandler extends DefaultHandler{

    private List<Entity> entitys;
    private List<Mapping> mappings;
    private Entity entity;
    private Mapping mapping;
    //存储当前标签名
    private String tag;
    //判断当前标签是否为servlet-mapping
    private boolean isMapping;

    @Override
    public void startDocument() throws SAXException {
        entitys = new ArrayList<Entity>();
        mappings = new ArrayList<Mapping>();
    }

    @Override
    public void endDocument() throws SAXException {    }

    @Override
    public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
        if(null != qName) {
            tag = qName;
            if(qName.equals("servlet")) {
                entity = new Entity();
                isMapping = false;
            }
            else if(qName.equals("servlet-mapping")) {
                mapping = new Mapping();
                isMapping = true;
            }
        }    
    }

    @Override
    public void endElement(String uri, String localName, String qName) throws SAXException {
        if(qName != null) {
            if(qName.equals("servlet")) {
                entitys.add(entity);
            }
            else if(qName.equals("servlet-mapping")) {
                mappings.add(mapping);
            }
        }
        //避免结束标签与另外的开始标签之间的空内容覆盖标签内容
        tag = null;
    }

    @Override
    //读取标签之间的内容,不管标签是否一一对应
    public void characters(char[] ch, int start, int length) throws SAXException {
        String msg = new String(ch, start, length).trim();
        if(tag != null) {
            if(isMapping) {//操作servlet-mapping
                if(tag.equals("servlet-name")) {
                    mapping.setName(msg);
                }
                if(tag.equals("url-pattern")) {
                    mapping.add(msg);
                }
            }else {//操作servlet
                if(tag.equals("servlet-name")) {
                    entity.setName(msg);
                }
                if(tag.equals("servlet-class")) {
                    entity.setClz(msg);
                }
            }    
        }
    }

    public List<Entity> getEntitys() {
        return entitys;
    }


    public List<Mapping> getMappings() {
        return mappings;
    }
}

结果
image.png


反射web.xml

在上面XmlSax类中的main方法补充下列代码

WebContext webContext = new WebContext(entitys, mappings);
String name = webContext.getClz("/reg");

Class clz = Class.forName(name);
Servlet servlet = (Servlet)clz.getConstructor().newInstance();
System.out.println(servlet);

servlet.service();

通过路径获取类名

public class WebContext {
    private List<Entity> entitys = null;
    private List<Mapping> mappings = null;

    //key:name   value:clz
    private Map<String, String> entityMap = new HashMap<>();
    //key:pattern value:name
    private Map<String, String> mappingMap = new HashMap<>();

    public WebContext(List<Entity> entitys, List<Mapping> mappings) {
        this.entitys = entitys;
        this.mappings = mappings;

        for(Entity entity : entitys) {
            entityMap.put(entity.getName(), entity.getClz());
        }

        for(Mapping mapping : mappings) {
            for(String pattern : mapping.getPatterns()) {
                mappingMap.put(pattern, mapping.getName());
            }
        }
    }

    public String getClz(String pattern) {
        String name = mappingMap.get(pattern);
        return entityMap.get(name);
    }

}

自定义Servlet接口

public interface Servlet {
    void service();
}

实现Servlet的类

LoginServlet

public class LoginServlet implements Servlet {

    @Override
    public void service() {
        // TODO Auto-generated method stub
        System.out.println("LoginServlet");
    }
}

RegisterServlet

public class RegisterServlet implements Servlet {

    @Override
    public void service() {
        System.out.println("RegisterServlet");
    }
}