CGI és servlet
Dinamikus web Kliens oldalon Szerver oldalon DHTML, stílusok nélkül DHTML, stílusokkal Szerver oldalon statikus oldal bizonyos részének speciális készítése teljes egészében programmal generált oldal Javascript applet CSS SSI CGI servlet
SSI
SSI - Server Side Include html-szövegbe külön generált rész beszúrása a beszúrás helye egy kommentársor a kommentár speciális formájú több SSI fajta létezik a szerverben az SSI-opciót külön engedélyezni kell!
SSI fajták AddType text/x-server-parsed-html .html <!--#include virtual =“filename”--> <!--#exec cmd =”full filename”--> <!--#fsize file =”filename”--> <!--#flastmod file =”filename”--> <!--#echo var =”SSI-variable”--> <!--#cgi file =”/cgi-bin/filename params”--> AddType text/x-server-parsed-html .html
SSI példa <center> Ma <b> <font color=red> <!--#include virtual="/dir/aMaiNev.lst"--></font></b> nap van, holnap <b> <!--#include virtual="/dir/aHolnapiNev.lst"--></b> nap lesz! </center> Ma Elza nap van, holnap Melinda nap lesz!
Kliens-szerver http-kommunikáció
Oldal lehívásának folyamata Általában Request <---> Response Request Request-Line (Header)* [CRLF Entity Body] Response Status-Line Esetleg üres
Request-Line Metódus URI Verzió CRLF GET http://www.w3.org/pub/proj.html HTTP/1.0 GET /pub/proj.html HTTP/1.0
Metódusok GET: POST: HEAD: oldalt kérek a szervertől referenciára kattintáskor POST: beadok egy (kitöltött forma) oldalt a szervernek adatbevitel HEAD: egy oldal paramétereinek lekérdezése cache-be kell-e frissítés
Request-Header rész GET http://www.w3.org/pub/proj.html HTTP/1.0 Date: Tue, 15 Nov 1994 08:12:31 GMT If-Modified-Since: Sat, 29 Oct 1994 19:43:31 GMT From: webmaster@w3.org User-Agent: CERN-LineMode/2.15 libwww/2.17b3
Request-Header rész/2. POST /cgi-bin/login HTTP/1.0 Host: www.w3.org User-Agent: CERN-LineMode/2.15 libwww/2.17b3 Content-type: multipart/form-data; boundary=---6299321591390446233 Content-Length: 206 --6299321591390446233 Content-Disposition: form-data; name="userid" dustin --6299321591390446233 Content-Disposition: form-data; name="passwd" foobar --6299321591390446233--
Status-Line Verzió Státuskód Okozat CRLF HTTP/1.0 200 OK HTTP/1.0 304 Not Modified
Response-Header rész HTTP/1.0 200 OK Date: Tue, 15 Nov 1994 08:12:31 GMT Content-Encoding: x-gzip Content-Length: 3495 Content-Type: text/html Expires: Thu, 01 Dec 1994 16:00:00 GMT Last-Modified: Tue, 15 Nov 1994 12:45:26 GMT Server: CERN/3.0 libwww/2.17 A3B8789X23CD...
Response-Header rész/2 HTTP/1.0 302 Found Date: Tue, 15 Nov 1994 08:12:31 GMT Expires: Thu, 01 Dec 1994 16:00:00 GMT Last-Modified: Tue, 15 Nov 1994 12:45:26 GMT Location: http://www.w3.org/WWW/abc.html Server: CERN/3.0 libwww/2.17 Content-type: text/html <HEAD><TITLE>Document moved</TITLE></HEAD> <BODY><H1>Document moved</H1> This document has moved <A HREF="http://ei.cs.vt.edu/~wwwbtb/">here</A>.<P> </BODY>
CGI
CGI - Common Gateway Interface alapvetően formátumozott bevitelhez elemzési feladat html-request paraméterek (From, Host, stb.) MIME-mal kódolt beviteli elemek lefutás eredménye általában egy képernyő ritkábban egy string (lásd SSI)
CGI - Common Gateway Interface Bevitel kódolása kliensben: érték, kulcspár lista látható az URL-sorban ?userid=dustin&passwd=foobar&login=Login+most szerverben: POST metódus: paraméterek a standard inputon GET metódus: paraméterek környezeti változóban (QUERY_STRING) szabványos környezeti változókban is adatok
CGI - szervezés Cgi könyvtár definiálása Hívás folyamata konfigurációs file-ba leírni ez a definició kerül majd behelyettesítésre Hívás folyamata a file az op. rendszerben végrehajtható legyen tetszőleges nyelvi program új task indul lefutáskor a task eltűnik ezért állapotprogramozás közvetlenül nem lehetséges
CGI használata Speciális URL: http://…/cgi-bin/script gyökérbeli “cgi-bin” vizsgálata http:// …/cgi-bin/bbp/dijszam.pl cgi-script futni kezd paraméterek szabványos formában ?param1=v1¶m2=v2 paraméterek átadódnak a scriptnek új oldal a standard output-on
Webes űrlapkezelés CGI program beadás indul ... <FORM ACTION=“/cgi-bin/calc.pl” METHOD=“POST” NAME=“calculation” ONSUBMIT=“chksubmit ()”> .... <INPUT TYPE=“TEXT” SIZE=“25” VALUE=““ NAME=“ins_value” ONCHANGE=“chktxt1 ()”> <INPUT TYPE=“SUBMIT” NAME=“start” VALUE=“Start calculation”> </FORM> CGI program beadás indul
Webes űrlapkezelés ... <FORM ACTION=“/cgi-bin/calc.pl” METHOD=“POST” NAME=“calculation” ONSUBMIT=“chksubmit ()”> .... <INPUT TYPE=“TEXT” SIZE=“25” VALUE=““ NAME=“ins_value” ONCHANGE=“chktxt1 ()”> <INPUT TYPE=“SUBMIT” NAME=“start” VALUE=“Start calculation”> </FORM> http:/cgi-bin/calc.pl?ins_value=300&…&start=Start+calculation
Perl nyelvű cgi-script Practical Report and Extraction Language = Perl “a web nyelve” stringek kezelésére nagyszerű skalár, tömb, asszociatív tömb Perl nyelvű cgi importálni a http-kezelőt kezelés feldolgozni az input folyamot elkészíteni az output web-oldalt
Cgi-script Perl-ben Modulhasználat előkészítése #!/usr/bin/perl require("cgi-lib.pl"); &ReadParse(*input); $autonev=$input{'autonev'}; … print &PrintHeader; ... print "\"$autonev\””; print<<eddig; <center> <table align=center border="0" bgcolor=“fff0c8” width="90%" cellspacing="0”> eddig ... Modulhasználat előkészítése Beolvasás egy asszoc. tömbbe Asszociatív tömbből a változó Kiírás előkészítése Kiírás egyszerűen Kiirás összetetten
Objektumorientált Perl #!/usr/bin/perl use CGI; $cgiobj = new CGI; ... $cim = $cgiobj->remote_addr(); … print $cgiobj->header; print qq~ <html><head> … </html>~; Modulhasználat előkészítése Objektum példányosítás Változóbeolvasás metódushasználattal Objektumváltozóval kiírás előkészítése Kiírás összetetten
Cgi-script shell-nyelven #!/bin/sh echo HTTP/1.0 200 OK echo Content-type: text/plain echo Server: $SERVER_SOFTWARE echo echo SERVER_NAME = $SERVER_NAME echo PATH_INFO = $PATH_INFO echo REMOTE_HOST = $REMOTE_HOST echo REMOTE_ADDR = $REMOTE_ADDR ... Fontos! Itt van vége a header-nek!
Servlet
Servlet Alapvetően a CGI-script helyett Java nyelvű végrehajtható program más filozófiával, mint a cgi-script egyszer iniciálódik a program (init) van egy leállítása (destroy) minden külön felhasználó egy önálló belépés egy-egy szálat indít
Servlet programozása A web-szerverben a servlet-gépezet egy bedugható, konfigurálható modul egy adott könyvtárba vagy a CLASSPATH-ban kell elhelyezni a .class file-okat szükséges kapcsolódó csomagok javax.servlet javax.servlet.http
Servlet használata Speciális URL: http://…/servlet/javaservlet gyökérbeli “servlet” vizsgálata http:// …/servlet/hu.hdi.ekliens.bbp.JspController paraméterek a javaservlet neve után hasonlóan, mint a cgi-bin esetén http://…/servlet/javaservlet?param1=v1 paraméterszövegben a szóköz +-ként kódolva
Servlet életciklusa 1. init() metódus 2. service() metódus az első hívás előtt fut le egyszer - kezdeti beállításokhoz 2. service() metódus ez a servlet szíve - mindent elkap: olvassa a http-request-et készít egy http-response-ot 3. destroy() metódus leállításhoz
Mi van az init()-ben? Lehetséges feladatok globális (singleton) változók iniciálása servlet-konfig kezelése: getServletConfig() kulcs-érték típusú paraméterek kezelése induláskor pl. adatbázis-URL, induló paraméterek servlet-ctx kezelése: getServletContext() bármikor hívható, nemcsak az init-ben pl. MIME-típus, path, servlet-logikai név, aktuális napló adatbázis kapcsolatok megnyitása (JDBC)
Egyszerű servlet public void service ( ServletRequest req, ServletResponse res ) throws ServletException, IOException { res.setContentType( "text/html" ); PrintWriter out = res.getWriter(); out.println( "<html>" ); out.println( "<head> ); out.println( "<title>A Sample Servlet</title>" ); out.println( "</head>" ); out.println( "<body>" ); out.println( "<h1>A Sample Servlet</h1>" ); out.println( "</body>" ); out.println( "</html>" ); out.close(); }
Servlet-ek osztályozása Általános “servlet” adás-vétel kommunikációs alapokon ehhez nem szükséges http (pl. email-servlet) ezt támogatja a javax.servlet csomag Http alapú servlet ehhez a javax.servlet.http csomag kell http-GET-hez doGet(), POST-hoz doPost(), stb. request-paraméterek olvasása: getParameter(“name”) ezt használjuk !
doGet, doPost service() továbbhív a doXXX()-re doXXX( HttpServletRequest req, HttpServletResponse res) két paramétere van: req: ami bejön a HTTP-n keresztül res: ami visszamegy a HTTP-n keresztül HttpServletRequest String s = req.getParameter(„xxx”) vagy String s = req.getParameterValues(„xxx”)[0] HttpServletResponse res.setContentType („text/html”); PrintWriter out = res.getWriter(); rádiógomb
Egyszerű http-servlet public void doPost ( HttpServletRequest req, HttpServletResponse res ) throws ServletException, IOException { res.setContentType( "text/html" ); String firstname = req.getParameter(“firstname”); ... PrintWriter out = new PrintWrite(res.getOutputStream()); out.println( "<html><head>" ); out.println( "<title>A Sample Servlet</title>" ); out.println( "</head>" ); out.println( "<body>" ); out.println( "<h1>Üdvözöllek “ + firstname + “!</h1>" ); out.println( "</body></html>" ); out.close(); } átalakítások (üzleti logika)
MVC 1 5 2 Control output oldal input oldal vezérlő program View View 3 4 bean Model
MVC servlet-tel A feldolgozás és a megjelenítés szétválasztása servlet nem készít közvetlenül megjelenítést viszont készít egy objektumot megjelenít a JSP (Java Server Pages) ami a html kiterjesztése JSP oldal a servlet készítette objektumot olvassa és felhasználja az objektum neve: BEAN
JSP Java Server Pages - Sun találmánya html - Java betétekkel ASP - Active Server Pages, MS-találmány html - VisualBasic betétekkel ez is Java program lesz, mint a servlet kiindulás: HttpJspBase jspInit, jspDestroy, jspService service() itt is használható !!
Speciális JSP-elemek <%! int x = 0; %> <% int y = 4; %> for (int i=1; i<=4; i++) { %> <H<%= i %>>Hello</H<%= i %>> <% x++; y--; } // for-ciklus vége deklaráció scriplet kifejezés
Egyszerű bean Current Employee ID = 123 NAME = Kiss András <%@ page import=”hu.hdi.PhoneNumber" %> <jsp:useBean id="employee" class=”hu.hdi.EmployeeBean"/> <html><body> <b>Current Employee</b> <ul> <li>ID = <jsp:getProperty name="employee" property="id"/> </li> <li>NAME = <jsp:getProperty name="employee" property="lastName”/> <jsp:getProperty name="employee" property="firstName"/> </li> <li>MOBIL = <%= employee.getMobilPhone().toFormattedString() %> </li> </ul> </body></html> Current Employee ID = 123 NAME = Kiss András MOBIL = 30-987-6543
Bonyolultabb JSP <%@ page import=”hu.hdi.PhoneNumber" %> <jsp:useBean id="employee" class=”hu.hdi.EmployeeBean"/> <html><body> <b>Current Employee</b> <ul> <li> <a href="/servlet/FetchEmployeeServlet?cmd=get&id= <jsp:getProperty name="employee" property="id"/>"> <jsp:getProperty name="employee" property="lastName”/> <jsp:getProperty name="employee" property="firstName"/></a></li> <%= employee.getMobilPhone().toFormattedString() %></li> </ul> </body></html>
JSP kifejtve Current Employee Kiss András 30-987-6543 <html><body> <b>Current Employee</b> <ul> <li> <a href="/servlet/FetchEmployeeServlet?cmd=get&id= 123”>Kiss András</a></li> 30-987-6543</li> </ul> </body></html> Current Employee Kiss András 30-987-6543
Deklarált változók előre deklarált változók <html> <title>Környezeti paraméterek</title> <body> <p></p> <p>SERVER_NAME =<%= request.getServerName() %></p> <p>PATH_INFO =<%= request.getPathInfo() %></p> <p>REMOTE_HOST =<%= request.getRemoteHost() %></p> <p>REMOTE_ADDR =<% out.println(request.getRemoteAddr());%> </p> </body> </html> előre deklarált változók
Különleges JSP funkciók <%@ include=”header.jsp” %> <jsp:useBean id=”most" class=”java.util.Date"/> <h1>Helló világ!</h1> <br> <p>A pontos idő: <%= most %> </p> <jsp:include page=”footer.jsp” flush=”true” />
Speciális JSP-elemek <%! int x = 0; %> <% int y = 4; %> for (int i=1; i<=4; i++) { %> <H<%= i %>>Hello</H<%= i %>> <% x++; y--; } // for-ciklus vége deklaráció scriplet kifejezés
public class index extends HttpJspBase { // begin [file=”.../index.jsp”; from=(8,3);to=(8,15)] int x = 0; // end public void _jspService (...) { // begin [file=”.../index.jsp”; from=(9,2);to=(9,15)] int y = 4; // begin [file=”.../index.jsp”; from=(9,17);to=(11,0)] out.write(”\r\n\r\n”); // begin [file=”...index.jsp”; from=(11,2);to=(13,0)] for (int i = 1; i<=4; i++) { // begin [file=„”.../index.jsp”; from=(13,2);to=(14,6)] out.write(”\r\n \t<H”); // begin [file=”.../index.jsp”; from=(14,4);to=(14,23)] out.print(i); ... <%! int x = 0; %> <% int y = 4; %> ugyanaz <H <%= i %>
Bean adatszerkezete névkonvenció !!! public class Employee { private String lastName; private String firstName; private String Id; private String taxNumber; private PhoneNum mobil; public String getLastName() { return this.lastName; } public void setLastName (String lastName) { this.lastName = lastName; . . . névkonvenció !!!
Bean előkészítés public void doPost( HttpServletRequest req, HttpServletResponse res) throws javax.servlet.ServletException; { hu.hdi.EmployeeBean adatok=new EmployeeBean(); ... adatok.setId(azonosito); adatok.setFirstName(vezeteknev); req.setAttribute(”employee", adatok); ... req.getRequestDispatcher(newpage).forward(req, res); }
Működés sorrendje 0. Programozás 1. Felhasználó elindítja a servletet bean-osztály kialakítva servlet osztály kialakítva JSP oldal kész 1. Felhasználó elindítja a servletet megnyom egy „submit” típusú gombot 2. Servlet feltölti a bean-t (bean előkészítés) req.setAttribute(”employee”, adatok); 3. Servlet visszaadja a vezérlést req.getRequestDispatcher(”next.jsp”).forward(req, res); 4. JSP kigenerálódik html oldal megjelenik
Bean-ek hatósugarai scope=“request” scope=“session” <jsp:useBean id="employee” ... scope=”request"/> egy request-response cserére alkalmazása: hibajelzés visszaírása az oldalra scope=“session” <jsp:useBean id="employee” ... scope=”session"/> több oldal közötti adatátadás alkalmazása: állapotprogramozás
Hibakiírások <jsp:useBean id=”allapot" class=”...” scope="session" /> <jsp:useBean id="adatok" class=”...” scope="request" /> <form method=“POST” action=“/servlet/Controller” > ... <input type="text" name="utlevel" class="feld” size="16" value=” <jsp:getProperty name=”adatok” property=”utlevel” /> ”> <br><span class="hiba"> <%= adatok.messages.getHiba("utlevel") %></span> ... </form> xxx --- Hibás útlevélszám!
Session objektum Állapotprogramozás lehetséges létrehozás HttpSession session = req.getSession(); írás bele, olvasás belőle session.setAttribute (“test.counter”, count); Integer count = (Integer)session.getAttribute(“test.counter”); megszüntetés session.invalidate();
„upload” alkalmazás html/jsp oldalai itt szerver alkalmazások itt lefordított class-ok itt
alkalmazás “deployment” descriptora „upload” alkalmazást nézzük
lib-ben a jar-ok vannak
classes-ban a a java osztályok a megfelelő alkönyvtárakban
package-név megfelel a könyvtár struktúrának
Irányzatok Hány servlet-et használjon egy alkalmazás? Egyet, de legyen egy rejtett változó, ami az oldalt mutatja Lehet-e servlet nélküli alkalmazást készíteni? Igen, de kell scriptlet, setProperty, stb.
Új irányzatok JSP kiterjesztés Servlet-programozás felhasználó definiálta JSP-elemek: TAGLIB, JSTL új template nyelvek: Velocity, PHP, stb. Servlet-programozás nem kell többé servlet-et írni: Maverick Struts Turbine, stb.
Taglib 1. <%@ taglib uri="/WEB-INF/prim.tld" prefix=”tle" %> <HTML> <HEAD> <TITLE>Some N-digit Primes</TITLE> </HEAD> <BODY> <UL> <LI>20-digit: <tle:prime length=”20” /> <LI>40-digit: <tle:prime length=”40” /> <LI>80-digit: <tle:prime length=”80” /> <LI>Default (50-digit: <tle:prime /> </UL> </BODY> </HTML>
Taglib 2. <%@ taglib uri=”/foolib/foo.tld” prefix=”foo” %> ... <foo:ifEq name=”empl" property=”firstName” value=”Kis”> <foo:save name=”empl" property=”firstName” /> </foo:ifEq>
JSP, bean és XML <%@ page contentType="application/pdf"%> <jsp:useBean id="empl" class=”hu.hdi.EmployeeBean"/> <%@ taglib uri="/WEB-INF/wea.tld" prefix="wea" %> <wea:fopapply> <?xml version="1.0" encoding="UTF-8"?> <fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format"> <fo:layout-master-set> <fo:simple-page-master master-name="single"> <fo:region-body/> </fo:simple-page-master> </fo:layout-master-set> ... <fo:block>Üdvözöllek <jsp:getProperty name="empl" property="lastName”/> <jsp:getProperty name="empl" property=”firstName”/>! </fo:block> ... </fo:root> </wea:fopapply>
Maverick-leíró <?xml version="1.0"?> <maverick version="1.0"> <command name="DijkeszSubmit"> <view> <redirect path="index.html" /> </view> </command> <command name="LepeselonySubmit"> <controller type="hdi.services.mave.LepeselonyBe"/> <view name="error"> <velocity model="model" path="vm/Lepeselony.vm"> <param name="title" value="Lepeselony"/> </velocity> <view name="success"> <velocity model="model" path="vm/LepeselonyDij.vm"> </maverick>
Velocity-file ... <form name="form1" action= "/intranet/LepeselonySubmit.m" method="post"> <td width="193" class="copytext-simple"> <input type="text" name="ev" size="6" value= "$!model.ev" class="feld"> <input type="text" name="honap" size="6" value= "$!model.honap" class="feld"> <input type="text" name="nap" size="6" value= "$!model.nap" class="feld"> <br> <span class="hiba">$!model.getHiba("szulido")</span> </td>
Servlet <-> applet összehasonlítás Applet: a kliens gépén fut közvetlenül vele beszél a felhasználó (helyben) bonyolult GUI programozás nagy méretű .jar file-okat kell letölteni Servlet: a server gépen fut egyszerű fejlesztés, mert nincs GUI MVC szépen megvalósítható nem igényel különleges konfigurációt a kliensen lassú lehet