Servlets in Java

Java Servlet — URL redirection

Java Servlet can be used to apply different variants of URL directs as given by HTTP specifications. In this tutorial we will understand the usage of different related status codes and also how server and client browser participate in URL redirection.

Prerequisite

Temporary URL Redirects

Status codes 302 (Found), 303 (See other) and 307 (Temporary redirect) can be used for temporary redirects. In the following example we will use Servlet API to set these status codes and the ‘Location’ header as required by the W3C Specifications.

302 redirect with GET

Redirect Servlet

@WebServlet(urlPatterns = "/test") public class RedirectServlet extends HttpServlet < @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException < System.out.println("----- Get Request for /test ---------"); resp.setStatus(HttpServletResponse.SC_FOUND);//302 resp.setHeader("Location", "http://localhost:8080/example/test2"); // resp.sendRedirect("http://localhost:8080/example/test2"); >. >

Servlet provides a supported method HttpServletResponse#setRedirect() which internally does the same thing done by resp.setStatus(302) and resp.setHeader(location) .

Servlet handling the redirected request

@WebServlet(urlPatterns = "/test2") public class HandlerServlet extends HttpServlet < @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException < System.out.println("----- Request for /test2 ---------"); resp.setContentType("text/html"); PrintWriter writer = resp.getWriter(); writer.write("

Test 2 page

"); > . >

Running embedded Jetty

Output

Entering uri /test will redirect to /test2

Читайте также:  Fileinputstream and bufferedinputstream in java

Let’s look at the requests/responses in chrome developer tool under the Network tab:

In above example we used GET method with the original request. Let’s see the behavior if we use POST method

302 redirect with POST

We are going to use a simple HTML form for POST submission:

src/main/webapp/myForm.html

Above post request will be handled by our HandlerServlet at ‘/example/test’. Let’s add doPost() method:

@WebServlet(urlPatterns = "/test") public class RedirectServlet extends HttpServlet < . @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException < System.out.println("-----Post request for /test ---------"); System.out.println("Post param name: " + req.getParameter("name")); //resp.setStatus(302); // resp.setHeader("Location", "http://localhost:8080/example/test2"); resp.sendRedirect("http://localhost:8080/example/test2"); >>

This time we are using resp.sendRedirect(location) which also sends 302 like above example.

In our HandlerServlet, we have included doPost() as well (in case if browser sends POST request in the second round):

@WebServlet(urlPatterns = "/test2") public class HandlerServlet extends HttpServlet < @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException < System.out.println("----- Request for /test2 ---------"); resp.setContentType("text/html"); PrintWriter writer = resp.getWriter(); writer.write("

Test 2 page

"); > @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException < doGet(req, resp); >. >

Output

Chrome browser changed POST to GET in the second round. The is the same behavior per 303 specification. Also, there’s no direct way to pass post data to the redirected location as GET method doesn’t support that. In RedirectServlet#doPost, we can append the post params as query string like this:

resp.sendRedirect("http://localhost:8080/example/test?name="+req.getParameter("name"));

Or we can internally use HttpSession to save post data information in RedirectServlet#doPost and can retrieve them back in HandlerServlet#doGet. Most likely, we would like to handle form submission data in RedirectServlet#doPost (e.g. persisting in database) before redirecting. The redirected page could show a very general information like ‘Succeeded’ or ‘Failed’. This technique is used to avoid double form submission as well.

Regarding browser’s changing POST to GET during 302 redirect, it is not an ideal outcome per W3C specifications but fixing that would break a lot of existing server code, that’s why browsers are still sticking to the old behavior. Also Servlet future specification will probably send 303 status with resp.sendRedirect(..) instead of 302.

303 will behave exactly like our above example, so we are not going to show an example on that here. Let’s try 307 now.

307 Redirect with POST

The difference between 307 and 302/303 is: 307 doesn’t change HTTP method in the second round, let’s see that with an example

HTML Form

src/main/webapp/myForm2.html

Creating servlets

Let’s create new Servlets for redirecting and handing redirected request:

@WebServlet(urlPatterns = "/test3") public class RedirectServlet2 extends HttpServlet < @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException < System.out.println("----- Request for /test3 ---------"); System.out.println(req.getParameter("name")); resp.setStatus(307); resp.setHeader("Location", "http://localhost:8080/example/test4"); >>
@WebServlet(urlPatterns = "/test4") public class HandlerServlet2 extends HttpServlet < @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException < System.out.println("----- Request for /test4 ---------"); resp.setContentType("text/html"); PrintWriter writer = resp.getWriter(); writer.write("

Test 4 page

"); writer.write("

Result of post

"); writer.write(req.getParameter("name")); > . >

Output

Note that browser did not change POST to GET this time, also the post data is accessible to the final redirected servlet, without we have to populate it in the session or attaching as query parameters. Per specifications, the browser is required to re-post data in the second request.

Permanent URL redirect

301 (Moved permanently) or 308 (Permanent redirect) can be used to redirect a URL permanently. The difference between the two is with 301 client may change the HTTP method but with 308 it cannot be changed. We are going to demonstrate only 308. In the following example first we will see 308 with GET and then with POST.

308 Redirect with GET

@WebServlet(urlPatterns = "/test5") public class RedirectServlet3 extends HttpServlet < @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException < System.out.println("----- Request for /test5 ---------"); resp.setStatus(308); resp.setHeader("Location", "http://localhost:8080/example/test6"); >. >
@WebServlet(urlPatterns = "/test6") public class HandlerServlet3 extends HttpServlet < @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException < System.out.println("----- Request for /test6 ---------"); resp.setContentType("text/html"); PrintWriter writer = resp.getWriter(); writer.write("

Test 6 page

"); > . >

Output

On entering /test5 in the address bar will redirect to /test6:

For subsequent request of /test5, the browser will retrieve the redirected URL (/test6) from the cache and will straight request the final URL instead of two round trips:

This behavior will persist until we clear the browser cache.

308 Redirect with POST

In majority of browsers, including chrome, 301 redirect request is changed from POST to GET (POST data is lost in GET step). 308 was introduced to only allow same HTTP methods in the both requests. Let’s see an example on 308 redirect with Post:

src/main/webapp/myForm3.html

@WebServlet(urlPatterns = "/test5") public class RedirectServlet3 extends HttpServlet < . @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException < System.out.println("----- Post request for /test5 ---------"); System.out.println(req.getParameter("name")); resp.setStatus(308); resp.setHeader("Location", "http://localhost:8080/example/test6"); >>
@WebServlet(urlPatterns = "/test6") public class HandlerServlet3 extends HttpServlet < . @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException < System.out.println("----- Post request for /test6 ---------"); resp.setContentType("text/html"); PrintWriter writer = resp.getWriter(); writer.write("

Test 6 page

"); writer.write("

Result of post

"); writer.write(req.getParameter("name")+""); > >

Output

For the subsequent /myForm3.html submission:

It seems chrome (Version 56.0.2924.87) is not caching the redirected url (/test6) for POST. Every time it is going through the same redirection flow. This behavior is same in Firefox (51.0.1) as well.

A 308 response is cacheable by default; i.e., unless otherwise indicated by the method definition or explicit cache controls.

According to POST definition , it is not cacheable by default:

Responses to this method are not cacheable, unless the response includes appropriate Cache-Control or Expires header fields. However, the 303 (See Other) response can be used to direct the user agent to retrieve a cacheable resource.

Example Project

Dependencies and Technologies Used:

  • javax.servlet-api 3.1.0 Java Servlet API
  • jetty-maven-plugin 9.4.1.v20170120: Jetty maven plugins.
  • JDK 1.8
  • Maven 3.3.9

Источник

Редирект на страницу java

Одной из распространеных задач веб-программирования является переадресация. Рассмотрим, как мы можем в сервлетах выполнять переадресацию на другой ресурс.

Перенаправление запроса

Метод forward() класса RequestDispatcher позволяет перенаправить запрос из сервлета на другой сервлет, html-страницу или страницу jsp. Причем в данном случае речь идет о перенаправлении запроса, а не о переадресации.

Например, пусть в проекте определена страница index.html :

      

Index.html

Данная страница просто выводит заголовок.

И, допустим, мы хотим из сервлета перенаправить запрос на эту страницу:

import java.io.IOException; import javax.servlet.RequestDispatcher; import javax.servlet.ServletContext; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; @WebServlet("/hello") public class HelloServlet extends HttpServlet < protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException < String path = "/index.html"; ServletContext servletContext = getServletContext(); RequestDispatcher requestDispatcher = servletContext.getRequestDispatcher(path); requestDispatcher.forward(request, response); >>

Для того, чтобы выполнить перенаправление запроса, вначале с помощью метода getServletContext() получаем объект ServletContext , который представляет контекст запроса. Затем с помощью его метода getRequestDispatcher() получаем объект RequestDispatcher. Путь к ресурсу, на который надо выполнить перенаправление, передается в качестве параметра в getRequestDispatcher.

Затем у объекта RequestDispatcher вызывается метод forward() , в который передаются объекты HttpServletRequest и HttpServletResponse.

И если мы обратимся к сервлету, то фактически мы получим содержимое страницы index.html, который будет перенаправлен запрос.

Перенаправление запроса в сервлетах Java

Подобным образом мы можем выполнять перенаправление на страницы jsp и другие сервлеты. Например, добавим в проект новый сервлет NotFoundServlet:

Переадресация с сервлета на сервлет Java EE

Определим для NotFoundServlet следующий код:

import java.io.IOException; import java.io.PrintWriter; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; @WebServlet("/notfound") public class NotFoundServlet extends HttpServlet < protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException < response.setContentType("text/html"); PrintWriter writer = response.getWriter(); String try < writer.println("

Not Found: " + id + "

"); > finally < writer.close(); >> >

В данном случае NotFoundServlet сопоставляется с адресом «/notfound».

Изменим код HelloServlet, чтобы он перенаправлял на NotFoundServlet:

import java.io.IOException; import java.io.PrintWriter; import javax.servlet.RequestDispatcher; import javax.servlet.ServletContext; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; @WebServlet("/hello") public class HelloServlet extends HttpServlet < protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException < String path = "/notfound"; ServletContext servletContext = getServletContext(); RequestDispatcher requestDispatcher = servletContext.getRequestDispatcher(path); requestDispatcher.forward(request, response); >>

В данном случае если id равен null, то идет перенаправление на NotFoundServlet. Следует отметить, что в метод requestDispatcher.forward передаются объекты HttpServletRequest и HttpServletResponse. То есть NotFoundServlet получит те же самые данные запроса, что и HelloServlet.

Переадресация

Для переадресации применяется метод sendRedirect() объекта HttpServletResponse. В качестве параметра данный метод принимает адрес переадресации. Адрес может быть локальным, внутренним, а может быть и внешним.

Например, если сервлету HelloServlet не передано значение для параметра id, выполним переадресацию на сервлет NotFoundServlet:

import java.io.IOException; import java.io.PrintWriter; import javax.servlet.RequestDispatcher; import javax.servlet.ServletContext; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; @WebServlet("/hello") public class HelloServlet extends HttpServlet < protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException < String if(id == null) < String path = request.getContextPath() + "/notfound"; response.sendRedirect(path); >else < response.setContentType("text/html"); PrintWriter writer = response.getWriter(); try < writer.println("

Hello Id " + id + "

"); > finally < writer.close(); >> > >

В данном случае переадресация идет на локальный ресурс. Но важно понимать, что в метод sendRedirect передается адрес относительно корня текущего домена. То есть в данном случае у нас домен и порт http://localhost:8001/ , а приложение называется helloapp, то для обращения к сервлету NotFoundServlet необходимо передать адрес «helloapp/notfound». Путь к текущему приложению можно получить с помощью метода getContextPath() .

Также можно выполнять и переадресацию на внешний ресурс, указывая полный адрес:

response.sendRedirect("https://metanit.com/");

Источник

How to send redirect from Java Servlet

In Java web development, to redirect the users to another page, you can call the following method on the HttpServletResponse object response:

response.sendRedirect(String location)

Technically, the server sends a HTTP status code 302 (Moved Temporarily) to the client. Then the client performs URL redirection to the specified location. The location in the sendRedirect() method can be a relative path or a completely different URL in absolute path.

For example, in a Java servlet’s doGet() / doPost() method:

response.sendRedirect("login.jsp");

This statement redirects the client to the login.jsp page relative to the application’s context path.

But this redirects to a page relative to the server’s context root:

response.sendRedirect("/login.jsp");
response.sendRedirect("https://www.yoursite.com");

Note that this method throws IllegalStateException if it is invoked after the response has already been committed. For example:

PrintWriter writer = response.getWriter(); writer.println("One more thing. "); writer.close(); String location = "https://www.codejava.net"; response.sendRedirect(location);

Here, the writer.close() statement commits the response so the call to sendRedirect() below causes an IllegalStateException is thrown:

java.lang.IllegalStateException: Cannot call sendRedirect() after the response has been committed

So you should pay attention to this behavior when using sendRedirect() . Call to sendRedirect() should be the last statement in the workflow.

About the Author:

Nam Ha Minh is certified Java programmer (SCJP and SCWCD). He started programming with Java in the time of Java 1.4 and has been falling in love with Java since then. Make friend with him on Facebook and watch his Java videos you YouTube.

Источник

Оцените статью