Изучив механизм отражения несколько раз в прошлом, на этот раз я использую знания об отражении, чтобы написать небольшую демонстрацию, похожую на механизм обработки фреймворка Struts.
Сервлеты и Стёрты
Прежде чем знакомиться с рефлексией, кратко познакомьтесь с инфраструктурой Sturts и сервлетом. До появления некоторых веб-фреймворков, когда мы хотели писать веб-приложения на Java, использовались сервлеты. Простая демонстрация Servlet показана ниже.
public class HelloWorld extends HttpServlet {
private String message;
public void init() throws ServletException {
message = "Hello World";
}
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/html");
PrintWriter out = response.getWriter();
out.println("<h1>" + message + "</h1>");
}
public void destroy() {
}
}
Сервлет предоставит doGet и doPost и в то же время получит параметры, переданные пользователем, выполнит бизнес-обработку, а затем вернется к представлению. Итак, как сервлет соответствует URL-адресу?Ответ заключается в отношении сопоставления между связывающим сервлетом и URL-адресом в web.xml.
<servlet>
<servlet-name>HelloWorld</servlet-name>
<servlet-class>HelloWorld</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>HelloWorld</servlet-name>
<url-pattern>/HelloWorld</url-pattern>
</servlet-mapping>
Сопоставление, обработка бизнес-логики и возврат представления выполняются в сервлетах, и связь относительно высока.С увеличением URL-адресов будет все больше и больше сервлетов, и многие отношения сопоставления необходимо настроить в файле web.xml, который не способствует уходу. В то же время входные параметры и возвращаемые параметры сервлета сильно зависят от запущенного в данный момент контейнера, который также небезопасен для потоков.Когда входных параметров слишком много, метод getParm нужно вызывать несколько раз, и код очень избыточен. После появления среды Struts унифицированный ActionServlet обрабатывает определенные запросы URL-адресов и сопоставления параметров, а также переходит к различным представлениям в соответствии с различными возвращаемыми результатами Разработчики должны заботиться только о своей собственной бизнес-логике для реализации разработки веб-приложений. Конкретный файл конфигурации Struts примерно такой, как показано в следующем XML.
<?xml version="1.0" encoding="UTF-8"?>
<struts>
<action name="login" class="com.coderising.kailuncen.LoginAction">
<result name="success">/jsp/homepage.jsp</result>
<result name="fail">/jsp/showLogin.jsp</result>
</action>
<action name="logout" class="com.coderising.kailuncen.LogoutAction">
<result name="success">/jsp/welcome.jsp</result>
<result name="error">/jsp/error.jsp</result>
</action>
</struts>
Нам нужно только отдельно реализовать представление и бизнес-логику, а затем связать их через struts, чтобы завершить работу по разработке, которую легче понять и поддерживать. Заинтересованные читатели могут самостоятельно подробно изучить идеи сервлетов и распорок.
небольшая демонстрация
Небольшая демонстрация, которую я хочу написать, состоит в том, чтобы читать xml, использовать отражение для загрузки различных действий, обрабатывать бизнес-логику и, наконец, выводить возвращаемое представление.Вся логическая идея относительно проста, и это чисто практика обучения отражению. Во-первых, определить класс конфигурации и сохранить отношение сопоставления, соответствующее действию, в XML-файле.
private class ActionConfig {
private String name;
private String className;
private Map<String, String> viewResult = new HashMap<>();
Когда начальное чтение xml завершено, получается следующая структура, имя действия соответствует конкретной конфигурации действия
Map<String, ActionConfig> actionConfigMap = new HashMap<>();
Моделирование работы Struts ActionServlet
public View runAction(String actionName, Map<String, String> params) {
String className = cfg.getClassName(actionName);
if (className == null) {
return null;
}
try {
Class<?> clz = Class.forName(className);
Object action = clz.newInstance();
ReflectionUtil.invokeSetMethods(action, params);
String resultName = (String) clz.getDeclaredMethod("execute").invoke(action);
Map<String, Object> result = ReflectionUtil.invokeGetMethods(action);
String resultView = cfg.getViewResult(actionName, resultName);
return new View(resultView, result);
Полное имя класса конкретного класса выполнения получается из класса конфигурации через actionName, Фактически, структура Struts непосредственно анализирует URL-адрес, а затем соответствует соответствующему имени действия конфигурации xml и связывает URL-адрес и конкретное выполнение класс вместе. После этого используйте Class.forName для создания типа класса, а затем создайте соответствующий экземпляр. Что делает ReflectionUtil, так это сначала получает имя соответствующего поля в действии, затем из переменной находит соответствующее значение в соответствии с именем поля, а затем использует метод set для назначения поля действия, которое является соответствующим информация в LoginAction.
public class LoginAction {
private String name;
private String password;
private String message;
Этот шаг избавляет от утомительной операции многократной отмены назначения get при использовании сервлета и использует механизм отражения для прямого присвоения значений переменным-членам.Разработчику нужно только сделать имена параметров, переданные внешним интерфейсом, и имена в фоновых классах. Это может быть подтверждено заранее. Затем через отражение вызывается метод execute, и используется метод Method.invoke. Снова используйте отражение, чтобы получить последнее значение поля, сформируйте карту для возврата, и в то же время, в соответствии с возвращаемым значением метода, перейдите к actionConfigMap, чтобы получить соответствующее представление. Наконец, окончательное отображаемое представление составляется в соответствии с картой возвращаемых значений поля и именем представления.
конец
Вышеприведенное на самом деле является небольшой демонстрацией основного рабочего процесса struts, имитируемого на основе знаний об отражении.Вся веб-инфраструктура обрабатывает множество других вещей, таких как сопоставление параметров, безопасность, обработка Json и т. д. Если вам интересно, вы можете узнать более.