C, PHP, VB, .NET

Дневникът на Филип Петров


* Сървлети с Jetty

Публикувано на 03 март 2015 в раздел Уеб JSP.

Сървлетите са основната технология за динамични уеб страници в Java. Всъщност простите примери за JSP страници, които показахме досега, в крайната си фаза се компилират до сървлети. Нека направим нашия първи сървлет: В тази статия освен работа със сървлети ще покажем и работа със сесийни променливи и предаване на параметри чрез HTTP POST.

import java.io.*; 
import javax.servlet.*; 
import javax.servlet.http.*; 

public class FirstServlet extends HttpServlet { 
  public void doGet(HttpServletRequest reqest, 
  HttpServletResponse response) throws ServletException, IOException{
    response.setContentType("text/html; charset=UTF-8");
    PrintWriter out = response.getWriter();
    out.print("<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.1//EN\"");
    out.print("\"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd\">");
    out.println("<html xmlns=\"http://www.w3.org/1999/xhtml\" xml:lang=\"bg\">");
    out.println("<head><title>Моята първа сървлет страница</title></head><body>");
    out.println("<p>Hello world!!!</p>"); 
    out.println("</body></html>"); 
  } 
}

Нашият първи сървлет е с име "FirstServlet". Виждате, че той наследява клас HttpServlet и предефинира метод "doGet". Този метод получава два параметъра - един HttpServletRequest (от него можем да четем параметри подадени от потребителя чрез заявка от тип HTTP GET) и един HttpServletResponse (изходен поток, с който можем да подаваме отговор към потребителя). Както виждате в нашия първи сървлет ние взимаме обект от тип PrintWriter за изходния поток и отпечатваме елементарна уеб страничка с него. Съществува и втори метод - doPost - който можем да предефинираме. С него можем да обработваме заявки подадени чрез HTTP POST. Работата с този метод е напълно аналогична.

За да изпълним този сървлет, първо трябва да го компилираме. Ще видите, че javax.servlet пакета не е наличен в стандартния JDK. Този пакет идва с уеб сървъра Jetty и трябва да го добавите в classpath на вашия проект. Намира се в <където сте инсталирали Jetty>\lib\servlet-api-3.1.jar. Ето пример как сме го добавили в средата DrJava:

DrJava classpath
DrJava classpath

След като компилирате ще получите съответния клас файл FirstServlet.class. Създайте директория C:\Jetty\mybase\webapps\ROOT\WEB-INF\classes (досега нашата база беше mybase - ще я използваме нея) и копирайте class файла там. Финално трябва да създадем файл C:\Jetty\mybase\webapps\ROOT\WEB-INF\web.xml със следното съдържание:

<?xml version="1.0" encoding="UTF-8"?>
<web-app>
  <servlet>
    <servlet-name>FirstServlet</servlet-name>
    <servlet-class>FirstServlet</servlet-class>
  </servlet>
  <servlet-mapping>
    <servlet-name>FirstServlet</servlet-name>
    <url-pattern>/servlets/FirstServlet</url-pattern>
  </servlet-mapping>
</web-app>

В тага <servlet> посочваме името на сървлета и съответстващия клас, който стои зад това име (в случая сме ги указали едни и същи). Важно е файлът, който сме качили в WEB-INF\classes директорията на приложението да отговаря на името посочето в <servlet-class> тага. В таг <servlet-mapping> се описва по какъв начин ще бъде достъпен дадения сървлет чрез URL.

Сега стартирайте Jetty и отидете на http://localhost:8080/servlets/FirstServlet и ще видите нашето първо сървлет приложение в действие:

firstservlet

Първоначално изглежда очевидно, че писането на сървлет страници е по-сложно, отколкото писането на JSP. В действителност това е така ако ние ще използваме сървлетите за презентационната част на проекта - много по-адекватно би било да използваме JSP ако ще отпечатваме големи обеми от HTML код. Ще забележите впоследствие, че за някои неща JSP не са чак толкова удобни - например когато трябва да се свържем с база от данни, да направим някаква обработка на данните и т.н. Тогава миксирането на java кода с html всъщност "ще пречи". Това е и случая, в който преместването на код в чист сървлет ще бъде по-удобно. Нека дадем един пример - елементарна login форма.

Файл C:\Jetty\mybase\webapps\ROOT\login.jsp:

<%
	String user =  (String)session.getAttribute("Session-username");
	if(user!=null){
		response.sendRedirect("securearea.jsp");
		return;
	}
%>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
    "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<%@ page contentType="text/html;charset=UTF-8" language="java"
 pageEncoding="UTF8" %>
<%@ page trimDirectiveWhitespaces ="true" %>
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="bg">
<head>
<title>Вход</title> 
</head>
<body>
<p>Login form</p>
<form action="/servlets/CheckLogin" method="POST">
	username: <input type="text" name="username" /><br />
	password: <input type="password" name="password" /><br />
	<input type="submit" name="submit" value="Login" />
</form>
</body>
</html>

В началото проверяваме дали потребителя вече не е влезнал в системата. Ако е влизал, ще има запис в сесийната променлива "Session-username" и съответно ще го пренасочим директно към securearea.jsp. Ако няма сесия, отпечатваме формата за вход, където човека трябва да въведе своите потребителско име и парола.

Файл C:\Jetty\mybase\webapps\ROOT\securearea.jsp:

<%
	String user =  (String)session.getAttribute("Session-username");
	if(user==null){
		response.sendRedirect("login.jsp");
		return;
	}
%>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
    "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<%@ page contentType="text/html;charset=UTF-8" language="java"
 pageEncoding="UTF8" %>
<%@ page trimDirectiveWhitespaces ="true" %>
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="bg">
<head>
<title>Вход</title> 
</head>
<body>
<p>Hello <%= user %></p>
</body>
</html>

Тук действаме по обратен принцип - ако потребителя НЯМА въведена променлива в сесията, ние ще го върнем към login.jsp. В противен случай той ще е влязъл успешно в системата и ние ще отпечатаме "секретната страница".

Сървлет компилиран и копиран в C:\Jetty\mybase\webapps\ROOT\WEB-INF\classes\CheckLogin.class:

import java.io.*; 
import javax.servlet.*; 
import javax.servlet.http.*; 

public class CheckLogin extends HttpServlet { 
  public static String USER_KEY = "Session-username";
  public static String POST_USER = "username";
  public static String POST_PASSWORD = "password";

  public void doPost(HttpServletRequest request, HttpServletResponse response) 
    throws ServletException, java.io.IOException {
    
    // Проверяваме дали не сме вече автентикирани
    HttpSession session = request.getSession(true);
    String user = (String) session.getAttribute("Session-username");
    if (user == null){
      // Ако не сме, ще проверяваме какво има в POST
      String username = request.getParameter(POST_USER);
      String password = request.getParameter(POST_PASSWORD);

      // При невалидно име/парола отпечатваме съобщение за грешка
      if (!validUser(username, password)) {
        response.setContentType("text/html; charset=UTF-8");
        PrintWriter out = response.getWriter();
        out.print("<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.1//EN\"");
        out.print("\"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd\">");
        out.println("<html xmlns=\"http://www.w3.org/1999/xhtml\" xml:lang=\"bg\">");
        out.println("<head><title>LOGIN FAIL</title></head><body>");
        out.println("<p>Въвели сте нелавидно име и/или парола</p>"); 
        out.println("<p>Върнете се обратно и опитайте пак!</p>");
        out.println("</body></html>"); 
        out.flush();
        return;
      }
      
      // При валидно име и парола записваме името в сесията
      session.setAttribute(USER_KEY, username);
    }
    
    // Пренасочваме потребителя там, откъдето е дошъл
    response.sendRedirect("../securearea.jsp");
  }

  protected boolean validUser(String username, String password) {
    // В тази функция може да се вържете с база данни и т.н...
    boolean valid = false;
    if (username.equals("Petar") && password.equals("123456")) return true;
    else return false;
  }
}

В този сървлет ние първоначално проверяваме дали има въведена сесийната променлива. Ако я има, пренасочваме потребителя директно към securearea.jsp. Ако я няма, четем променливите предадени чрез HTTP POST и проверяваме дали те са валидни име и парола. Ако са валидни, записваме сесийната променлива и пренасочваме човека към securearea.jsp. Ако не са валидни, отпечатваме HTML страница със съобщение за грешка (по-удачно ще е да прехвърлим потребителя към JSP страница със съобщение за грешка - направете го!).

Настройки в C:\Jetty\mybase\webapps\ROOT\WEB-INF\web.xml:

<?xml version="1.0" encoding="UTF-8"?>
<web-app>
  <servlet>
    <servlet-name>CheckLogin</servlet-name>
    <servlet-class>CheckLogin</servlet-class>
  </servlet>
  <servlet-mapping>
    <servlet-name>CheckLogin</servlet-name>
    <url-pattern>/servlets/CheckLogin</url-pattern>
  </servlet-mapping>
</web-app>

 



Добави коментар

Адресът на електронната поща няма да се публикува


*