diff --git a/.classpath b/.classpath index d390ad06a53c82d6342b6aace9c7583646a551a1..59b8c5d7bbcf11b04d5d21c59ff6fb4d8a6eda16 100644 --- a/.classpath +++ b/.classpath @@ -2,6 +2,8 @@ + + diff --git a/src/main/java/com/hy/java/uct/cdtocode/CDToCodeTracer.java b/src/main/java/com/hy/java/uct/cdtocode/CDToCodeTracer.java index cbc29a9a02c3b77d60798cc26bc768fae1564345..a6eb3f74f2a4dc479d54789dc9bcc22ad65f17dd 100644 --- a/src/main/java/com/hy/java/uct/cdtocode/CDToCodeTracer.java +++ b/src/main/java/com/hy/java/uct/cdtocode/CDToCodeTracer.java @@ -1,11 +1,12 @@ package com.hy.java.uct.cdtocode; -import java.io.File; -import java.io.FileNotFoundException; +import java.util.Map; -import com.github.javaparser.StaticJavaParser; -import com.github.javaparser.ast.CompilationUnit; -import com.hy.java.utility.common.FileEditor; +import com.hy.java.uct.cdtocode.mapper.InitialMapper; +import com.hy.java.uct.cdtocode.reader.CDReader; +import com.hy.java.uct.cdtocode.reader.CodeReader; +import com.hy.java.uct.cdtocode.reader.DocReader; +import com.hy.java.uct.umlrecog.util.UMLClass; public class CDToCodeTracer { /** @@ -14,12 +15,12 @@ public class CDToCodeTracer { private static final String cd_dir = System.getProperty("user.dir") + "\\src\\main\\resources\\cdtocode\\cd\\"; /** - * 将要设计文档放在doc_dir目录下 + * 将设计文档放在doc_dir目录下 */ private static final String doc_dir = System.getProperty("user.dir") + "\\src\\main\\resources\\cdtocode\\doc\\"; /** - * 将要追踪的代码放在cd_dir目录下 + * 将要追踪的代码放在code_dir目录下 */ private static final String code_dir = System.getProperty("user.dir") + "\\src\\main\\resources\\cdtocode\\code\\"; @@ -30,15 +31,27 @@ public class CDToCodeTracer { /* * 1、读取模型信息 */ - FileEditor model_file = new FileEditor(cd_dir); + // 读取完UML图识别结果后,将实体信息保存在classes_in_CD里 + Map classes_in_CD = CDReader.read(cd_dir + "cd-eclipse_jetty.txt"); + // 检查读取结果,可注释掉 + // CDReader.check(classes_in_CD); /* * 2、读取文档信息 */ + String doc = DocReader.read(doc_dir + "basic-architecture.adoc"); /* - * 3、读取code目录下所有java文件名 + * 3、读取code path指定的目录下所有java文件 */ + Map java_files = CodeReader.read(code_dir + "code path"); + // 检查读取结果,可注释掉 + // CodeReader.check(java_files); /* * 4、遍历模型中的实体元素(类或对象),针对每个元素,在code中寻找能匹配的java文件 + * + * 基于启发式模糊匹配的UML类图与代码追踪方法:首先针对类图中的类和代码中的类,基于类的名称进行字符串完全匹配,从而建立确定的初始追踪;基于同义词、 + * 词缀词典等语料库,定义基于类名称匹配和关联关系的启发式匹配规则,研究基于模糊匹配技术的追踪关系建立方法,基于初始追踪和启发式规则, + * 对类名不一致的模型和代码元素进行启发式追踪,扩展初始追踪关系。 */ + InitialMapper.map(classes_in_CD, java_files, doc); } } diff --git a/src/main/java/com/hy/java/uct/cdtocode/mapper/InitialMapper.java b/src/main/java/com/hy/java/uct/cdtocode/mapper/InitialMapper.java new file mode 100644 index 0000000000000000000000000000000000000000..088c7de8a020342347d8f415d045baf467e3d1ee --- /dev/null +++ b/src/main/java/com/hy/java/uct/cdtocode/mapper/InitialMapper.java @@ -0,0 +1,87 @@ +package com.hy.java.uct.cdtocode.mapper; + +import java.util.Map; +import java.util.Set; + +import com.hy.java.uct.umlrecog.util.UMLClass; + +public class InitialMapper { + + /** + * 针对类图中的类和代码中的类,基于同义词、词缀词典等语料于库,定义基类名称匹配和关联关系的启发式匹配规则,研究基于模糊匹配技术的追踪关系建立方法,解决类名不一致的模型和代码元素的追踪问题: + *

+ *

    + *
  • 1、针对类图中的每个类,基于类的名称、与代码中的类文件进行字符串模糊匹配,从源码文件中选出可能映射的文件,存在UML_class.possible_java_files中 + * + *
  • 2、然后针对UML_class的每条out_rela,记录其target_class,看possible_java_files中的每个文件是否也有out_rela,且文件的out_rela目标文件也在target_class的possible_java_files中。如果有,则UML_class映射到该文件,且target_class映射到文件的out_rela目标文件。 + * + *
  • 3、in_rela同上。 + *
+ * + * @param classes_in_CD 键值对:<类名(图里的类名),类对象(UMLClass对象)> + * @param java_files 键值对:<类全称(包+类名),java文件地址(可用javaparser解析文件内容)> + * @param doc + */ + public static void map(Map classes_in_CD, Map java_files, String doc) { + Set key_set = classes_in_CD.keySet(); + // 1、针对类图中的每个类,基于类的名称、与代码中的类文件进行字符串模糊匹配,从源码文件中选出可能映射的文件,存在UML_class.possible_java_files中 + for (String key : key_set) { + UMLClass UML_class = classes_in_CD.get(key); + // 对每个UML_class,根据其title,找java_files中类全称的类名与其相似的java文件 + Set java_file_set = java_files.keySet(); + for (String java_file_full_name : java_file_set) { + if (titleSimilarWithFile(UML_class.getTitle(), java_file_full_name.substring(java_file_full_name.lastIndexOf(".") + 1))) { + UML_class.possible_java_files.add(java_file_full_name); + } + } + } + // 2、然后针对UML_class的每条out_rela,记录其target_class,看possible_java_files中的每个文件是否也有out_rela,且文件的out_rela目标文件也在target_class的possible_java_files中。如果有,则UML_class映射到该文件,且target_class映射到文件的out_rela目标文件。 + for (String key : key_set) { + UMLClass UML_class = classes_in_CD.get(key); + if (UML_class.possible_java_files.size() < 1) { + System.out.println(UML_class.getTitle() + "\t" + "没有映射"); + } else { + for (String possible_java_file : UML_class.possible_java_files) { + // 针对UML_class的每条out_rela... + // 针对UML_class的每条out_rela... + // 针对UML_class的每条out_rela... + // 针对UML_class的每条out_rela... + // 针对UML_class的每条out_rela... + // 针对UML_class的每条out_rela... + // 针对UML_class的每条out_rela... + // 针对UML_class的每条out_rela... + System.out.println(UML_class.getTitle() + "\t" + possible_java_file); + } + } + } + // 3、in_rela同上。 + } + + /** + * 对每个UML_class,根据其title,找java_files中类全称的类名与其相似的java文件 + */ + private static boolean titleSimilarWithFile(String UML_class_title, String java_file_name) { + // 如果两个String相等,则返回true + if (UML_class_title.equals(java_file_name)) { + return true; + } + // 如果两个String相似,则返回true + else { + // 处理一下两个String,然后看它们是否相似 + + // 处理处理处理处理处理处理 + // 处理处理处理处理处理处理 + // 处理处理处理处理处理处理 + // 处理处理处理处理处理处理 + // 处理处理处理处理处理处理 + // 处理处理处理处理处理处理 + // 处理处理处理处理处理处理 + // 判断处理后的两个String是否相似 + if (java_file_name.contains(UML_class_title)) { + return true; + } + } + // 如果两个String既不相等也不相似,则返回false + return false; + } +} diff --git a/src/main/java/com/hy/java/uct/cdtocode/reader/CDReader.java b/src/main/java/com/hy/java/uct/cdtocode/reader/CDReader.java new file mode 100644 index 0000000000000000000000000000000000000000..1b0450d8affc26ff9a6b8652ab22592bfa6a8303 --- /dev/null +++ b/src/main/java/com/hy/java/uct/cdtocode/reader/CDReader.java @@ -0,0 +1,93 @@ +package com.hy.java.uct.cdtocode.reader; + +import java.util.HashMap; +import java.util.Map; +import java.util.Set; + +import com.hy.java.uct.umlrecog.util.Relation; +import com.hy.java.uct.umlrecog.util.UMLClass; +import com.hy.java.utility.common.FileEditor; + +public class CDReader { + /** + * 读取UML图识别结果,将实体信息保存在result里并返回 + */ + public static Map read(String cd_recog_res_path) { + Map result = new HashMap<>(); + // UML图识别结果 + FileEditor model_file = new FileEditor(cd_recog_res_path); + // 保存类名、属性、方法。类之间以“#”隔开 + String[] class_strs = model_file.readFileToString().split("#"); + for (String class_str : class_strs) { + UMLClass UML_class = new UMLClass(); + // 类名、属性、方法用“@”隔开 + String[] class_info_strs = class_str.split("@"); + // 类名 + UML_class.setTitle(class_info_strs[0].substring(class_info_strs[0].lastIndexOf(")") + 1, class_info_strs[0].length() - 1)); + // 属性 + if (class_info_strs[1].length() > 0) { + UML_class.setAttrisStr(class_info_strs[1].substring(0, class_info_strs[1].length() - 1)); + } else { + UML_class.setAttrisStr(class_info_strs[1]); + } + // 方法 + if (class_info_strs[2].length() > 0) { + UML_class.setMethodsStr(class_info_strs[2].substring(0, class_info_strs[2].length() - 1)); + } else { + UML_class.setMethodsStr(class_info_strs[2]); + } + result.put(UML_class.getTitle(), UML_class); + } + // 根据类名保存关系(出、入两类) + for (String class_str : class_strs) { + String[] class_info_strs = class_str.split("@"); + UMLClass UML_class = result.get(class_info_strs[0].substring(class_info_strs[0].lastIndexOf(")") + 1, class_info_strs[0].length() - 1)); + // 出 + if (class_info_strs.length >= 4) { + if (!class_info_strs[3].isBlank()) { + // 关系用“¥”隔开 + String[] out_relas = class_info_strs[3].split("¥"); + for (String out_rela_str : out_relas) { + Relation relation = new Relation(); + String[] rela_info = out_rela_str.split("%"); + relation.source = result.get(rela_info[0].substring(0, rela_info[0].length() - 1)); + relation.target = result.get(rela_info[1].substring(0, rela_info[1].length() - 1)); + relation.type = rela_info[2]; + UML_class.out_relas.add(relation); + } + } + } + // 入 + if (class_info_strs.length == 5) { + // 关系用“¥”隔开 + String[] in_relas = class_info_strs[4].split("¥"); + for (String in_rela_str : in_relas) { + Relation relation = new Relation(); + String[] rela_info = in_rela_str.split("%"); + relation.source = result.get(rela_info[0].substring(0, rela_info[0].length() - 1)); + relation.target = result.get(rela_info[1].substring(0, rela_info[1].length() - 1)); + relation.type = rela_info[2]; + UML_class.in_relas.add(relation); + } + } + } + return result; + } + + public static void check(Map classes_in_CD) { + Set keys = classes_in_CD.keySet(); + for (String key : keys) { + UMLClass uc = classes_in_CD.get(key); + System.out.println("类名:" + uc.getTitle()); + System.out.println("属性:" + uc.getAttrisStr()); + System.out.println("方法:" + uc.getMethodsStr()); + for (Relation r : uc.out_relas) { + System.out.println("出关:" + r.source.getTitle() + "→" + r.target.getTitle() + "是" + r.type); + } + for (Relation r : uc.in_relas) { + System.out.println("入关:" + r.source.getTitle() + "→" + r.target.getTitle() + "是" + r.type); + } + System.out.println("======================="); + } + } +} diff --git a/src/main/java/com/hy/java/uct/cdtocode/reader/CodeReader.java b/src/main/java/com/hy/java/uct/cdtocode/reader/CodeReader.java new file mode 100644 index 0000000000000000000000000000000000000000..7ad057e94e7106d308002ef55e02e1ff5d082d49 --- /dev/null +++ b/src/main/java/com/hy/java/uct/cdtocode/reader/CodeReader.java @@ -0,0 +1,71 @@ +package com.hy.java.uct.cdtocode.reader; + +import java.io.File; +import java.io.FileNotFoundException; +import java.util.HashMap; +import java.util.Map; +import java.util.Optional; +import java.util.Set; + +import com.github.javaparser.StaticJavaParser; +import com.github.javaparser.ast.CompilationUnit; +import com.github.javaparser.ast.PackageDeclaration; +import com.hy.java.utility.common.FileEditor; +import com.hy.java.utility.common.Traverser; +import com.hy.java.utility.common.Traverser.FileNode; + +public class CodeReader { + + public static Map read(String code_path_file_path) { + // 该Map保存所有遍历到的java文件,形式为 + Map result = new HashMap<>(); + // 读取配置文件 + FileEditor code_path_file = new FileEditor(code_path_file_path); + // 配置文件指定的代码根目录所对应的FileNode。遍历其children下的java文件即可 + FileNode code_files_root = Traverser.traverseDir(code_path_file.readFileToString()); + // 遍历 + System.out.println("正在遍历" + code_files_root.path + "下的源码文件,请稍候..."); + filterJavaFileFromFN(code_files_root, result); + System.out.println("已遍历完java文件"); + return result; + } + + /** + * 递归遍历code_files_root下的所有java文件,以存在Map中 + */ + private static void filterJavaFileFromFN(FileNode code_files_root, Map java_files) { + if (code_files_root.children == null) { + if (code_files_root.path.endsWith(".java")) { + // 过滤\src\test\下的文件 + if (!code_files_root.path.contains("\\src\\test\\")) { + // 这里put的key是类全称(包+类名) + try { + CompilationUnit cu = StaticJavaParser.parse(new File(code_files_root.path)); + Optional package_declaration = cu.getPackageDeclaration(); + if (!package_declaration.isEmpty()) { + java_files.put(package_declaration.get().getNameAsString() + "." + + code_files_root.path.substring(code_files_root.path.lastIndexOf("\\") + 1, code_files_root.path.lastIndexOf(".")), code_files_root.path); + } + } catch (FileNotFoundException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + } + } else { + for (FileNode code_file_or_dir : code_files_root.children) { + filterJavaFileFromFN(code_file_or_dir, java_files); + } + } + } + + /** + * 检查一下是不是遍历了所有java文件 + */ + public static void check(Map java_files) { + Set class_names = java_files.keySet(); + for (String class_name : class_names) { + System.out.println(class_name + "\t" + java_files.get(class_name)); + } + } +} diff --git a/src/main/java/com/hy/java/uct/cdtocode/reader/DocReader.java b/src/main/java/com/hy/java/uct/cdtocode/reader/DocReader.java new file mode 100644 index 0000000000000000000000000000000000000000..5e1f7ee10def2ef23f41acb5b21c208e19f33461 --- /dev/null +++ b/src/main/java/com/hy/java/uct/cdtocode/reader/DocReader.java @@ -0,0 +1,13 @@ +package com.hy.java.uct.cdtocode.reader; + +import com.hy.java.utility.common.FileEditor; + +public class DocReader { + /** + * 读取文档信息 + */ + public static String read(String doc_file_path) { + FileEditor doc_file = new FileEditor(doc_file_path); + return doc_file.readFileToString(); + } +} diff --git a/src/main/java/com/hy/java/uct/umlrecog/util/Relation.java b/src/main/java/com/hy/java/uct/umlrecog/util/Relation.java index c4a983fe1a4e30711d2992a685d5ff36506776e9..a0b379e37949db7b6d7d2bd01400a133b552da1e 100644 --- a/src/main/java/com/hy/java/uct/umlrecog/util/Relation.java +++ b/src/main/java/com/hy/java/uct/umlrecog/util/Relation.java @@ -14,4 +14,7 @@ public class Relation { public Relation(PolygonalLine poly_line) { this.poly_line = poly_line; } + + public Relation() { + } } diff --git a/src/main/java/com/hy/java/uct/umlrecog/util/UMLClass.java b/src/main/java/com/hy/java/uct/umlrecog/util/UMLClass.java index 19833da35f72512620b82d68098fc5b50af8a2a5..abea3328a200fdc07e60c89bd3983b12e65c6302 100644 --- a/src/main/java/com/hy/java/uct/umlrecog/util/UMLClass.java +++ b/src/main/java/com/hy/java/uct/umlrecog/util/UMLClass.java @@ -19,11 +19,22 @@ public class UMLClass { private String title; private String attris_str; private String methods_str; - // 从该class出发的关系 + /** + * 从该class出发的关系 + */ public List out_relas = new ArrayList<>(); - // 指向该class的关系 + /** + * 指向该class的关系 + */ public List in_relas = new ArrayList<>(); + /** + * java_files中类全称的类名与其相同的java文件 + * + * 从这些文件中去找真正的映射(由于抽象层次不同,所以可能不止一个java文件是真正的映射)。寻找时要参考关系网 + */ + public List possible_java_files = new ArrayList<>(); + public String getTitle() { return title; } diff --git a/src/main/resources/cd/temp result.png b/src/main/resources/cd/temp result.png index 0dc87447b2f8ca34540b52902217acfeb1732ef8..d943a61799c37b3054433cc772380bb90c3a130e 100644 Binary files a/src/main/resources/cd/temp result.png and b/src/main/resources/cd/temp result.png differ diff --git a/src/main/resources/cdtocode/cd/cd-eclipse_jetty.png b/src/main/resources/cdtocode/cd/cd-eclipse_jetty.png new file mode 100644 index 0000000000000000000000000000000000000000..777eed91c15ffbd9e3931055f27fabb1cb83aee8 Binary files /dev/null and b/src/main/resources/cdtocode/cd/cd-eclipse_jetty.png differ diff --git a/src/main/resources/cdtocode/cd/cd-eclipse_jetty.txt b/src/main/resources/cdtocode/cd/cd-eclipse_jetty.txt new file mode 100644 index 0000000000000000000000000000000000000000..2395f46f95c58a70be6e56d9b142acee12af382d --- /dev/null +++ b/src/main/resources/cdtocode/cd/cd-eclipse_jetty.txt @@ -0,0 +1,60 @@ +(611,446)AbstractHandler +@@@AbstractHandler +%AbstractLifeCycle +%继承¥AbstractHandler +%Handler +%继承¥@#(165,446)AbstractConnector +@@@AbstractConnector +%AbstractLifeCycle +%继承¥AbstractConnector +%Connector +%继承¥@#(366,303)AbstractLifeCycle +@@+doStart() ++doStop() +@AbstractLifeCycle +%LifeCycle +%继承¥@AbstractConnector +%AbstractLifeCycle +%继承¥AbstractHandler +%AbstractLifeCycle +%继承¥#(167,204)Connector +@+host: String ++port: int +@@Connector +%Buffers +%实现¥Connector +%LifeCycle +%实现¥@AbstractConnector +%Connector +%继承¥#(616,205)Handler +@@+handle(target,request,...) +@Handler +%LifeCycle +%实现¥@AbstractHandler +%Handler +%继承¥#(470,204)ThreadPool +@@+dispatch(Runnable) +@ThreadPool +%LifeCycle +%实现¥@#(110,19)Buffers +@@+getBuffer(size): Buffer ++returnBuffer(Buffer) +@Buffers +%Buffer +%依赖¥@Connector +%Buffers +%实现#(16,19)Buffer +@@@@Buffers +%Buffer +%依赖#(394,17)LifeCycle +@@+start() ++stop() +@@AbstractLifeCycle +%LifeCycle +%继承¥Connector +%LifeCycle +%实现¥ThreadPool +%LifeCycle +%实现¥Handler +%LifeCycle +%实现¥# \ No newline at end of file diff --git a/src/main/resources/cdtocode/code/code path b/src/main/resources/cdtocode/code/code path new file mode 100644 index 0000000000000000000000000000000000000000..39b9e7642207e8030f4c58804e8b12e7cecf1e07 --- /dev/null +++ b/src/main/resources/cdtocode/code/code path @@ -0,0 +1 @@ +D:\eclipse-committers\jetty.project-jetty-9.4.41.v20210516 \ No newline at end of file diff --git a/src/main/resources/cdtocode/doc/basic-architecture.adoc b/src/main/resources/cdtocode/doc/basic-architecture.adoc new file mode 100644 index 0000000000000000000000000000000000000000..7eef28c3bf5750c8876d27c3330d93ae6e9587ad --- /dev/null +++ b/src/main/resources/cdtocode/doc/basic-architecture.adoc @@ -0,0 +1,178 @@ +// +// ======================================================================== +// Copyright (c) 1995-2021 Mort Bay Consulting Pty Ltd and others. +// ======================================================================== +// All rights reserved. This program and the accompanying materials +// are made available under the terms of the Eclipse Public License v1.0 +// and Apache License v2.0 which accompanies this distribution. +// +// The Eclipse Public License is available at +// http://www.eclipse.org/legal/epl-v10.html +// +// The Apache License v2.0 is available at +// http://www.opensource.org/licenses/apache2.0.php +// +// You may elect to redistribute this code under either of these licenses. +// ======================================================================== +// + +[[basic-architecture]] +=== Jetty Architecture + +==== View from 20,000 feet + +The Jetty link:{JDURL}/org/eclipse/jetty/server/Server.html[Server] is the plumbing between +a collection of `Connector`s that accept connections and a collection of `Handler`s that +service requests from the connections and produce responses, with threads from a thread pool doing the work. + +image:reference/architecture/images/jetty-high-level-architecture.png[image,width=576] + +While the Jetty request/responses are derived from the Servlet API, the full features of the Servlet API +are only available if you configure the appropriate handlers. +For example, the session API on the request is inactive unless the request has been passed to a `SessionHandler`. +The concept of a Servlet itself is implemented by a `ServletHandler`. +If Servlets are not required, there is very little overhead in the use of the servlet request/response APIs. +Thus you can build a Jetty server using only connectors and handlers, without using Servlets. + +The job of configuring Jetty is building a tree of connectors and handlers and providing their individual configurations. +As Jetty components are simply Plain Old Java Objects (POJOs), you can accomplish this assembly +and configuration of components by a variety of techniques: + +* In code, see the examples in the Jetty Source XRef. +* Using Jetty XML, a dependency injection style in XML format. +* With your dependency injection framework of choice, Spring or XBean. +* Using Jetty WebApp and Context Deployers. + +==== Patterns + +The implementation of Jetty follows some fairly standard patterns. +Most abstract concepts such as `Connector`s and `Handler`s are captured by interfaces. +Generic handling for those interfaces is then provided in an abstract implementation +such as `AbstractConnector` and `AbstractHandler`. + +image:reference/architecture/images/basic-architecture-patterns.png[image,width=576] + +The JSR77 inspired life cycle of most Jetty components is represented by the `LifeCycle` +interface and the `AbstractLifeCycle` implementation used as the base of many Jetty components. + +==== Connectors + +A `Connector` is the component that accepts TCP connections. +For each accepted TCP connection, the `Connector` asks a `ConnectionFactory` to create +a `Connection` object that handles the network traffic on that TCP connection, parsing +and generating bytes for a specific protocol. + +A `ServerConnector` can therefore be configured with one or more `ConnectionFactory`. + +The simplest case is a single `ConnectionFactory` such as `HttpConnectionFactory`, that +creates `HttpConnection` objects that parse and generate bytes for the HTTP/1.1 protocol. + +A more complex case can be a `ServerConnector` configured with three factories: +`ProxyConnectionFactory`, `SslConnectionFactory` and `HttpConnectionFactory`. +Such connector will be able to handle PROXY protocol bytes coming from a load balancer +such as HAProxy (with the `ProxyConnectionFactory`), then handle TLS bytes (with +`SslConnectionFactory`) and therefore decrypting/encrypting the bytes from/to a remote +client, and finally handling HTTP/1.1 bytes (with `HttpConnectionFactory`). +Each `ConnectionFactory` is asked to create a `Connection` object for each TCP connection; +the `Connection` objects will be chained together to handle the bytes, each for its +own protocol. +Therefore the `ProxyConnection` will handle the PROXY protocol bytes, `SslConnection` +will handle the encryption/decryption of the bytes, and `HttpConnection` will handle +the HTTP/1.1 bytes producing a request and response object that will be processed by +applications. + +Advanced usages of Jetty will allow users to write their own `ConnectionFactory` to +handle custom protocols that are not implemented directly by the Jetty project, +therefore using Jetty as a generic network server. + +==== Handlers + +A `Handler` is the component that deals with HTTP requests and responses. +The core API of a handler is the handle method: + +image:reference/architecture/images/basic-architecture-handlers.png[image,width=576] + +[source, java] +---- +public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException +---- + +Parameters: + +* `target` – the target of the request, either a URI or a name. +* `baseRequest` – the original unwrapped request object. +* `request` – the request object, either as the `baseRequest` object or a wrapper of `baseRequest`. +You can use the HttpConnection.getCurrentConnection() method to access the Request object if required. +* response – the response object, either unwrapped as `Response` or a wrapper of that response. +You can use the HttpConnection.getCurrentConnection() method to access the `Response` object if required. + +An implementation of this method can handle the request, pass the request onto another handler (or servlet) +or it might modify and/or wrap the request and then pass it on. +This gives three styles of Handler: + +* Coordinating handlers – handlers that route requests to other handlers (`HandlerCollection`, `ContextHandlerCollection`) +* Filtering handlers – handlers that augment a request and pass it on to other handlers (`HandlerWrapper`, `ContextHandler`, `SessionHandler`) +* Generating handlers – handlers that produce content (`ResourceHandler` and `ServletHandler`) + +===== Nested Handlers and Handlers Called Sequentially + +You can combine handlers to handle different aspects of a request by nesting them, +calling them in sequence, or by combining the two models. + +image:reference/architecture/images/basic-architecture-nested-handlers.png[image,width=576] + +Handlers called in sequence perform actions that do not depend on the next invocation, nor on the handler order. +They handle a request and generate the response without interacting with other handlers. +The main class for this model is `HandlerCollection`. + +Nested handlers are called according to a before/invokeNext/after pattern. +The main class for nested handlers is `HandlerWrapper`. +Nested handlers are much more common than those called in sequence. + +See also xref:writing-custom-handlers[]. + +===== Servlet Handler + +The `ServletHandler` is a `Handler` that generates content by passing the request to any +configured Servlet Filters and then to a Servlet mapped by a URI pattern. + +image:reference/architecture/images/basic-architecture-servlet-handler.png[image,width=576] + +A `ServletHandler` is normally deployed within the scope of a `ServletContext`, which is a +`ContextHandler` that provides convenience methods for mapping URIs to servlets. + +Filters and Servlets can also use a `RequestDispatcher` to reroute a request to another context +or another Servlet in the current context. + +[[what-is-a-context]] +==== Contexts + +Contexts are handlers that group other handlers below a particular URI context path or a virtual host. +Typically a context can have: + +* A context path that defines which requests are handled by the context (e.g. `/myapp`) +* A resource base for static content (a document root) +* A class loader to obtain classes specific to the context (typically from `/WEB-INF/classes` and `/WEB-INF/lib`) +* Virtual host names + +Contexts implementations include: + +* `ContextHandler` +* `ServletContextHandler` +* `WebAppContext` + +A web application context combines handlers for security, session and servlets in a single unit +that you can configure with a `web.xml` descriptor. + +==== Web Application + +A `WebAppContext` is a derivation of `ServletContextHandler` that supports the standardized layout +of a web application and configuration of session, security, listeners, filter, servlets, and JSP +via a `web.xml` descriptor normally found in the `/WEB-INF` directory of a web application. + +image:reference/architecture/images/basic-architecture-web-application.png[image,width=576] + +Essentially `WebAppContext` is a convenience class that assists the construction and configuration +of other handlers to achieve a standard web application configuration. +Configuration is actually done by pluggable implementations of the Configuration class and the +prime among these is `WebXmlConfiguration.`