1. Введение проблемы
когда мы только встретилисьservlet
Когда мы разработали это так:
- Чтобы написать функцию входа пользователя, мы создаем новую
LoginServlet
. - Для того, чтобы написать функцию регистрации пользователя, мы создаем новую
SignUpServlet
. - Чтобы написать функцию обновления пользователя, мы создаем новую
UserUpdateServlet
. - Чтобы написать функцию удаления пользователя, мы создаем новую
UserDeleteServlet
. - для……
Ха-ха, это простоUser
, но очевидно, что двузначные классы сущностей на обычных предметах — это нормально.
Должны ли мы создавать N сервлетов, как указано выше, для работы каждого класса сущностей? Разве это не десяткиServlet
соответствовать развитию функций. . .
Далее эта статья решит эти сомнения для вас OwO
2. Как сервлет отвечает на наши запросы?
Прежде чем обсуждать, как решить вышеуказанные проблемы, давайте посмотрим, как сервлет отвечает на наши запросы.
Рисунок ниже является стандартнымServlet
, мы инициируемget
илиpost
Запрос доступаservlet
Но задумывались ли вы когда-нибудь, почему нашget
/post
запрос, вы можете позвонить в соответствующийdoGet
/doPost
метод?
Итак, давайте узнаем!
Сначала давайте посмотрим на то, что мы только что создалиLoginServlet
структурная схема
На рисунке вы можете увидеть отношения наследования сервлета,servlet
Интерфейс находится на верхнем уровне, иGenericServlet
Достигнутоservlet
интерфейс.
давайте посмотрим на вершинуservlet
Что в интерфейсе, давайте сосредоточимся на этомservice
метод будет делать
// servlet接口
public interface Servlet {
// servlet被创建时进行的初始化方法
void init(ServletConfig var1) throws ServletException;
ServletConfig getServletConfig();
// Called by the servlet container to allow the servlet to respond to a request.
// 翻译下就是:由Servlet容器调用,以允许Servlet响应请求。
void service(ServletRequest var1, ServletResponse var2) throws ServletException, IOException;
String getServletInfo();
void destroy();
}
Поэтому мы узналиservlet
в интерфейсеservice
Методы используются для ответа на запросы.
Однако интерфейс просто определяет набор спецификаций, нам нужно посмотреть, что представляет собой конкретная реализация.
Итак, давайте спустимся и посмотрим, что реализованоservlet
интерфейсGenericServlet
.
Тем не менее, мы нажимаем вGenericServlet
Когда исходный код обнаруживается, что класс является абстрактным классом, вservlet
На основе обогащения некоторыми методами.
В то же время внутриservice
метод является абстрактным методом, мы предполагаем, что он может быть его подклассомHttpServlet
Достигнутоservice
метод
public abstract class GenericServlet implements Servlet, ServletConfig, Serializable {
// 里面比较长,这里就列一个service方法.
public abstract void service(ServletRequest var1, ServletResponse var2) throws ServletException, IOException;
}
Итак, давайте спустимся и посмотрим на наследствоGenericServlet
изHttpServlet
.
мы обнаруживаемservice
Метод реализован здесь!
Ха-ха, есть какое-то разделение?答案
Вкус становится ближе.
Тогда давайте посмотрим.
Мы видим, что существует множествоif
судить.
существуетif (method.equals("GET"))
Следующее называетсяdoGet
Метод, Пост тот же.
// HttpServlet
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 获取请求的类型,比如Post、Get等等
String method = req.getMethod();
long lastModified;
// 如果为 GET
if (method.equals("GET")) {
lastModified = this.getLastModified(req);
if (lastModified == -1L) {
// 调用doGet
this.doGet(req, resp);
} else {
long ifModifiedSince;
try {
ifModifiedSince = req.getDateHeader("If-Modified-Since");
} catch (IllegalArgumentException var9) {
ifModifiedSince = -1L;
}
if (ifModifiedSince < lastModified / 1000L * 1000L) {
this.maybeSetLastModified(resp, lastModified);
this.doGet(req, resp);
} else {
resp.setStatus(304);
}
}
} else if (method.equals("HEAD")) {
lastModified = this.getLastModified(req);
this.maybeSetLastModified(resp, lastModified);
this.doHead(req, resp);
// 如果为 Post
} else if (method.equals("POST")) {
// 调用 doPost
this.doPost(req, resp);
} else if (method.equals("PUT")) {
this.doPut(req, resp);
} else if (method.equals("DELETE")) {
this.doDelete(req, resp);
} else if (method.equals("OPTIONS")) {
this.doOptions(req, resp);
} else if (method.equals("TRACE")) {
this.doTrace(req, resp);
} else {
String errMsg = lStrings.getString("http.method_not_implemented");
Object[] errArgs = new Object[]{method};
errMsg = MessageFormat.format(errMsg, errArgs);
resp.sendError(501, errMsg);
}
}
В этот момент мы, вероятно, понимаем,Servlet
Как ответить на нашу просьбу.
Резюме: если нашservlet
без перезаписиservice
метод, тоservlet
позвонюhttpServlet
осуществленныйservice
метод ответа на запрос. В зависимости от типа запроса вызываются разные методы.
3. Написание базового сервлета
Далее, это ядро нашей статьиBaseServlet
Вскоре! ! !
Идеи:
- Напиши
BaseServlet
наследоватьHttpServlet
, и перезапишитеservice
метод. - Используя механизм отражения, завершите
单Servlet
многоцелевого. - давай будем нормальными
业务Servlet
наследоватьBaseServlet
- Обычное использование (описано ниже)
Далее поговорим с кодом, мы будем简单理解
Немного.
3.0 Сначала ознакомьтесь с тем, как использовать
Вот краткое введение в использование
- Во-первых, поставить
@WebSerlvet
написано как/xxxx/`的形式,这个`/
означает соответствие всем - напишите свой метод
- URL-адрес отправки внешнего интерфейса записывается как
(省略)/UserServlet/xx
Хорошо, этоxx
Относится к имени метода, которое вы написали сами.
Ха-ха, не правда ли, это очень легко и быстро использовать!
И, самое главное, мы изначальноServlet
Можно написать только один метод, и становится возможным написать多个
метод, реализующий нашу功能模块化
цель!
Но не волнуйтесь, давайте перейдем к самому главномуBaseServlet
пишу
3.1 Написание BaseServlet
Одним словом: BaseServlet в основном использует反射的机制
Вышеупомянутая функция завершена.
Мы хотим продумать идею конкретной операции, и лучше всего добавить код.
-
Прежде всего, нам нужно знать запрос, отправленный внешним интерфейсом, и какой метод мы хотим вызвать, например, вход или регистрацию?
Ответ: по
@WebServlet
в примечаниях/xx/*
, мы можем указать, что если нам нужно вызвать метод входа в систему, мы можем записать его как/xx/login
, этот логин (то есть имя метода) является ключевым словом, которое мы используем, чтобы определить, какой метод вызывать. -
Получить имя вызываемого метода, что, если мы вызовем этот метод?
Ответ: через
反射
чтобы получить метод и вызвать его.
Полный код и анализ:
public class BaseServlet extends HttpServlet {
// 覆写service方法
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 1. 这里获取URL或者URI都可以,URI: /lemonfish/UserServlet/login URL: http://localhost/lemonfish/UserServlet/login
String requestURI = req.getRequestURI();
// 2. 获取最后`/`的索引
int beginIndex = requestURI.lastIndexOf("/");
// 3. 使用substring,获取方法名称
String methodName = requestURI.substring(beginIndex + 1);
try {
/***
* 记住谁调用了“service”方法,this就是谁,
* 因为我们自己编写的UserServlet继承了BaseServlet
* 因此,这个service方法也是属于UserServlet的
* 而前端访问的是UserServlet
* 因此 this 是 UserServlet的一个对象
*
* 4. 这里 根据 方法名称 和 方法参数的class类型 ,利用反射获取UserServlet的该方法。
*
* 如果大家这两行代码看不太懂,可以先去复习下 反射 的知识。
***/
Method method = this.getClass().getDeclaredMethod(methodName, HttpServletRequest.class, HttpServletResponse.class);
// 5. 使用this调用该方法。
method.invoke(this, req, resp);
} catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
e.printStackTrace();
}
}
}
4. Пример демонстрации BaseServlet
4.1 Напишите базовый сервлет
как указано выше
4.2 Напишите UserServlet и наследуйте BaseServlet
В этом UserServlet есть два метода, один из нихlogin
Логин, одинsignUp
регистр
4.3 Запустите Tomcat и получите доступ к UserServlet
Запускаем tomcat и вводим в адресную строкуhttp://localhost/lemonfish/UserServlet/login
(Это регулируется в соответствии с вашим собственным портом и путем, мой порт здесь 80, иapplicationContext
даlemonfish
), нажмите клавишу Enter.
Посмотрим, что выдает консоль.
Дангданг! ! !
Вот успешный выводLog In
, указывая на то, что мы на полпути.
Но не волнуйтесь, давайте попробуем еще разsignUp
метод
Ха-ха, теперь мы можем быть уверены!
Мы успешно прошлиBaseServlet
завершил визитServlet
В то же время можно использовать несколько методов.
Таким образом, когда мы разрабатываем, мы можем написать соответствующий код в соответствии с потребностями нашего бизнеса.xxxServlet
Вот и все.
4.4 Обработка небольшой ямы пересылки
При написании пути пересылки не забудьте добавить/
О, это будет добавлено непосредственно к корневому пути
если написать какhello.jsp
, затем добавляется к текущему пути (то естьUserServlet
под),
такservice
метод пойдетUserServlet
Найдите имя нижеhello.jsp
метод, он сообщит об ошибке!
request.getRequestDispatcher("/hello.jsp").forward(request, response);
5. Адрес исходного кода DEMO
Для всеобщего удобства я решил загрузить исходный код этой демонстрации прямо наGithub
Всем удобно читать и учиться. Если вы считаете, что это хорошо, пожалуйста, вознаградите меня.Star
(●'◡'●)
Хотя облако кода использовалось много раньше, в основном его следует использовать в последнее время.Github
.
6. Пишите в конце
пакет одинBaseServlet
Это значительно повысило эффективность нашей разработки, особенно до того, как мы коснулись фреймворка.
Я надеюсь, что каждый сможет что-то получить после прочтения~~(●'◡'●)
Если вы сочтете это полезным, вы можете нажать 👍b( ̄▽ ̄)d, это лучше всего, ххх