{"id":2280,"date":"2013-09-09T19:52:09","date_gmt":"2013-09-09T17:52:09","guid":{"rendered":"http:\/\/www.tutego.de\/blog\/javainsel\/?p=2280"},"modified":"2013-09-09T19:52:09","modified_gmt":"2013-09-09T17:52:09","slug":"httpservletrequest-und-httpservletresponse-und-die-header","status":"publish","type":"post","link":"https:\/\/www.tutego.de\/blog\/javainsel\/2013\/09\/httpservletrequest-und-httpservletresponse-und-die-header\/","title":{"rendered":"HttpServletRequest und HttpServletResponse und die Header"},"content":{"rendered":"<p>Sendet der HTTP-Client eine Anfrage an den Server, so sendet er gleichzeitig einige Informationen \u00fcber sich mit. Sie nennen sich <em>Header<\/em> und bezeichnen Schl\u00fcssel-Werte-Paare, die durch einen Doppelpunkt getrennt sind. Ein Webbrowser kann zum Beispiel Folgendes formulieren:<\/p>\n<pre>GET \/seminare\/index.html HTTP\/1.0\nAccept-Language: de<\/pre>\n<p>Der Browser sendet hier den Header Accept-Language mit dem Wert <strong>de<\/strong>. So kann der Server unter Auswertung dieser Parameter optimal reagieren, zum Beispiel bei der Pr\u00e4ferenz der Sprache eine lokalisierte Webseite liefern. Um an die Header zu gelangen, m\u00fcssen wir das HttpServletRequest-Objekt lesen und die Header erfragen.<\/p>\n<h4>Header auslesen<\/h4>\n<p>Zum Lesen der Header in einem Servlet bieten sich zwei L\u00f6sungen an: Wenn wir einen speziellen Header erfragen wollen, dann holen wir mit getHeader() auf dem HttpServletRequest den passenden Wert zum Schl\u00fcssel. Sind wir an allen Schl\u00fcsseln interessiert, dann besorgt uns getHeaderNames() eine Enumeration. Die k\u00f6nnen wir dann durchlaufen und die Werte wiederum mit getHeader() auslesen. Falls ein Schl\u00fcssel nicht existiert, liefert die Methode null. \u00c4hnlich wie bei getParameter() k\u00f6nnen hier auch mehrere Eintr\u00e4ge existieren, die mit getHeaders() abgerufen werden k\u00f6nnen.<\/p>\n<pre>&lt;%\njava.util.Enumeration headerNames = request.getHeaderNames();\nwhile ( headerNames.hasMoreElements() )\n{\nString headerNameKey = (String) headerNames.nextElement();\nString headerNameValue = request.getHeader( headerNameKey );\n%&gt;\n&lt;%= headerNameKey %&gt;: &lt;%= headerNameValue %&gt;\n&lt;p&gt;\n&lt;%\n}\n%&gt;<\/pre>\n<p>Das Servlet erzeugt f\u00fcr eine Anfrage etwa folgende Ausgabe:<\/p>\n<pre>accept: image\/gif, image\/x-xbitmap, image\/jpeg, image\/pjpeg, application\/vnd.ms-excel, application\/vnd.ms-powerpoint, application\/msword, *\/*\naccept-language: de\naccept-encoding: gzip, deflate\nuser-agent: Mozilla\/4.0 (compatible; MSIE 9.0; Windows NT 5.0)\nhost: localhost:8080\nconnection: Keep-Alive\ncookie: JSESSIONID=EB9D8DFAB0D0AA1B38D292507983B6B1<\/pre>\n<p>Der Anfragetyp (GET, POST und so weiter) wird hier ebenso wenig angezeigt wie der Remote-Host. Dieser findet sich nicht im Header und muss mit anderen Funktionen erfragt werden.<\/p>\n<h4>Hilfsfunktion im Umgang mit Headern<\/h4>\n<p>Wieder gibt es f\u00fcr oft benutzte Header Abk\u00fcrzungen.<\/p>\n<ul>\n<li>getMethod() liefert eine Zeichenkette wie GET oder POST. <\/li>\n<li>Die Methode getRequestURI() liefert die URI der Anfrageseite. <\/li>\n<li>getProtocol() liefert das Protokoll von der Statuszeile, also heutzutage entweder HTTP\/1.0 oder HTTP\/1.1. <\/li>\n<li>getCookies() liefert den Inhalt des Cookie-Headers (dazu sp\u00e4ter mehr). <\/li>\n<li>getAuthType() und getRemoteUser() zerteilen die Information im Authorization-Feld in Komponenten. <\/li>\n<li>getDateHeader() und getIntHeader() sind wieder Hilfsmethoden.<\/li>\n<\/ul>\n<h4>\u00dcbersicht der Browser-Header<\/h4>\n<p>Hier eine \u00dcbersicht \u00fcber die \u00fcblichen Header, von denen wir manche schon aus dem Beispiel und auch vom Server kennen:<\/p>\n<ul>\n<li>Accept. Der vom Browser bevorzugte MIME-Typ. <\/li>\n<li>Accept-Charset. Der vom Browser bevorzugte Zeichensatz. <\/li>\n<li>Accept-Encoding. Die Kodierung, die der Browser verarbeiten kann, wie etwa gzip oder compress. Unser Servlet-Programm sollte vor dem Komprimieren testen, ob der Browser \u00fcberhaupt komprimierte Dateien verarbeiten kann. <\/li>\n<li>Accept-Language. Die Sprache, die der Browser bevorzugt anzeigt. Mehr als ein Eintrag, wenn der Browser mehr als eine Sprache spricht. <\/li>\n<li>Authorization. Information \u00fcber Autorisierung, die normalerweise eine Antwort auf die WWW-Authenticate-Anfrage des Servers ist. <\/li>\n<li>Connection. Informiert, ob persistente Verbindungen genutzt werden. Persistente \u00dcbertragungen \u00fcbermitteln in einer TCP\/IP-Verbindung mehrere Dateien, etwa eine HTML-Datei und mehrere Grafiken. Wenn der Wert von Connection \u00bbKeep-Alive\u00ab hei\u00dft, dann lassen sich mit einer Netzwerkverbindung mehrere Seitenteile \u00fcbermitteln. Wenn die Request-Zeile die http-Version 1.1 anzeigt, sind Keep-Alive-Verbindungen Standard. Unsere Aufgabe bei diesen Verbindungen ist es, den Header ContentLength in die Antwort zu setzen. Server-abh\u00e4ngig wird hier teilweise schon automatisch in einen Puffer geschrieben und die Gr\u00f6\u00dfe gesetzt. Dies muss aber nicht so sein, daher bietet es sich an, die Informationen in einen ByteArrayOutputStream zu schreiben, um sp\u00e4ter die L\u00e4nge und den Inhalt abzufragen. <\/li>\n<li>Content-Length. Die L\u00e4nge des Bytestroms. Hier z\u00e4hlt der Browser die Bytes und informiert den Server, wie viele Daten noch kommen. <\/li>\n<li>Cookie. Cookie-Information, die der Browser automatisch mitschickt. <\/li>\n<li>From. Ein optionaler Header, der oft von Webrobotern gesetzt wird. Bei Browsern nicht \u00fcblich. <\/li>\n<li>Host. Rechnername und Host, wie in der Original-URL angegeben. <\/li>\n<li>If-Modified-Since. Liefert ein neues Server-Dokument, wenn die im Header angegebene Zeit auf ein neueres Dokument verweist. Ist das Browser-Dokument aktueller, gibt der Server den Antwortcode 304 mit der Nachricht \u00bbNot Modified\u00ab zur\u00fcck. <\/li>\n<li>Pragma. Gibt Informationen \u00fcber das automatische Neuladen der Seiten. Der Wert no-cache zeigt an, dass der Server immer eine neue Seite liefern soll, auch wenn der Proxy eine Kopie h\u00e4lt. <\/li>\n<li>Referer. Die URL mit dem Verweis, der auf die aktuelle Seite gezeigt hat. <\/li>\n<li>User-Agent. Der Browsertyp. Praktisch, wenn unser Servlet JavaScript-Code einbettet, der vom Browser abh\u00e4ngig ist. <\/li>\n<li>UA-Pixels, UA-Color, UA-OS, UA-CPU. Von Microsoft eingef\u00fchrte propriet\u00e4re Header f\u00fcr den Internet Explorer, die Bildschirmgr\u00f6\u00dfe, Farbtiefe, Betriebssystem und CPU-Typ anzeigen.<\/li>\n<\/ul>\n<h4>Header, die der Server setzt<\/h4>\n<p>Bisher kennen wir von der Klasse HttpServletResponse die Methode setHeader() f\u00fcr beliebige Header.<\/p>\n<p><b>Beispiel:<\/b> Setze den Header pragma, damit vom Browser keine Daten im Cache gehalten werden:<\/p>\n<pre>response.setHeader( &quot;pragma&quot;, &quot;no-cache&quot; );<\/pre>\n<p>Mit dieser Aufforderung soll der Browser die Seite jedes Mal neu laden. Das ist bei dynamischen Seiten besonders wichtig, da sie bei jedem Aufruf neu generiert werden und sich Werte \u00e4ndern k\u00f6nnen, wie es zum Beispiel bei Warenkorbsystemen der Fall ist. Da wir uns als Applikationsentwickler nicht immer mit dem Namen der Header herum\u00e4rgern wollen, bietet die Bibliothek einige Spezialfunktionen an.<\/p>\n<p><b>Beispiel:<\/b> F\u00fcr den Header Content-Type gibt es die spezielle Methode setContentType():<\/p>\n<pre>response.setHeader( &quot;Content-Type&quot;, &quot;text\/html&quot;);\nresponse.setContentType( &quot;text\/html&quot; );<\/pre>\n<p>Daneben gibt es setContentLength(), die den Header Content-Length setzt. Diese L\u00e4nge muss nicht gesetzt werden und wird automatisch berechnet. Falsche L\u00e4ngen k\u00f6nnten zu Ausnahmesituationen f\u00fchren. Der Gebrauch ist jedoch n\u00fctzlich, wenn vorher die gesamte Webseite in einem StringBuffer sb gesammelt und in einem Rutsch \u00fcbertragen wird. Dann k\u00f6nnen wir setContentLength(sb.length()) aufrufen.<\/p>\n<p>Um einen Datums-Header zu setzen, existiert setDateHeader(String, long). Das Argument ist eine beliebige Zeichenkette, die mit einem Datumswert verbunden wird. Das long gibt die Millisekunden seit dem 1.1.1970 an. Die erzeugte Ausgabe schreibt einen UTC-String. Eine weitere Hilfsfunktion ist setIntHeader(), die Zahlenwerte mit Schl\u00fcsseln in den Header schreibt. Hier \u00fcbernimmt die Methode die Konvertierung von String in eine Ganzzahl.<\/p>\n<p>Neben diesen setXXX()-Methoden, die m\u00f6glicherweise gesetzte Header \u00fcberschreiben, l\u00e4sst sich mit containsHeader(String) abfragen, ob Wertepaare schon gesetzt sind. Neben den setXXX()-Methoden gibt es auch entsprechende addXXX()-Methoden, die die Werte nicht \u00fcberschreiben, sondern hinzuf\u00fcgen. F\u00fcr Cookies existiert eine zus\u00e4tzliche Methode namens addCookie(), die einen Cookie im Header setzt.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Sendet der HTTP-Client eine Anfrage an den Server, so sendet er gleichzeitig einige Informationen \u00fcber sich mit. Sie nennen sich Header und bezeichnen Schl\u00fcssel-Werte-Paare, die durch einen Doppelpunkt getrennt sind. Ein Webbrowser kann zum Beispiel Folgendes formulieren: GET \/seminare\/index.html HTTP\/1.0 Accept-Language: de Der Browser sendet hier den Header Accept-Language mit dem Wert de. So kann [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_jetpack_memberships_contains_paid_content":false,"footnotes":"","_links_to":"","_links_to_target":""},"categories":[9,15],"tags":[],"class_list":["post-2280","post","type-post","status-publish","format-standard","hentry","category-java-ee","category-web-frameworks"],"jetpack_featured_media_url":"","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/www.tutego.de\/blog\/javainsel\/wp-json\/wp\/v2\/posts\/2280","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.tutego.de\/blog\/javainsel\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.tutego.de\/blog\/javainsel\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.tutego.de\/blog\/javainsel\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.tutego.de\/blog\/javainsel\/wp-json\/wp\/v2\/comments?post=2280"}],"version-history":[{"count":1,"href":"https:\/\/www.tutego.de\/blog\/javainsel\/wp-json\/wp\/v2\/posts\/2280\/revisions"}],"predecessor-version":[{"id":2281,"href":"https:\/\/www.tutego.de\/blog\/javainsel\/wp-json\/wp\/v2\/posts\/2280\/revisions\/2281"}],"wp:attachment":[{"href":"https:\/\/www.tutego.de\/blog\/javainsel\/wp-json\/wp\/v2\/media?parent=2280"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.tutego.de\/blog\/javainsel\/wp-json\/wp\/v2\/categories?post=2280"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.tutego.de\/blog\/javainsel\/wp-json\/wp\/v2\/tags?post=2280"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}