tutorials / java-server / mvc

MVC

tutorial java server mvc

Now we know how to use servlets. A servlet looks like this:

import java.io.PrintWriter;
import java.io.IOException;
import java.util.Date;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class MyServlet extends HttpServlet {

	@Override
	public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException {
		PrintWriter out = response.getWriter();
		out.println("<!DOCTYPE html>");
		out.println("<html>");
		out.println("<head>");
		out.println("<title>My Web App</title>");
		out.println("</head>");
		out.println("<body>");
		out.println("<h1>My Web App</h1>");
		out.println("<p>The current time is: " + new Date().toString() + "</p>");
		out.println("</body>");
		out.println("</html>");
	}
}

And we know how to use JSP files. A JSP file looks like this:

<%@ page import="java.util.Date" %>
<!DOCTYPE html>
<html>
	<head>
		<title>My Web App</title>
	</head>
	<body>
		<h1>My Web App</h1>
		<p>The current time is: <%= new Date().toString() %></p>
	</body>
</html>

There are pros and cons to both approaches. Servlets make it easier to use Java code, but it can be very annoying to program HTML in them. On the other hand, JSP files make it easy to mix HTML and Java, but it can be annoying to include complicated logic inside a JSP file.

We can use a mix of both servlets and JSP files to get the best of both worlds: we can use servlets to execute our logic with Java code, and we can use JSP files to render a page using parameters generated from the servlet.

For example, let’s redo our above example to use a servlet that generates the current time and passes it as a parameter to a JSP file for rendering.

Here’s what our Servlet would look like:

import java.io.PrintWriter;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class DateServlet extends HttpServlet {

	@Override
	public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {

		// 5:12 PM on Saturday, June 3, 2017
		SimpleDateFormat dateFormat = new SimpleDateFormat("hh:mm aa 'on' EEEE, MMMM dd, yyyy");
		Date now = new Date();
		String formattedDate = dateFormat.format(now);

		request.setAttribute("date", formattedDate);
		request.getRequestDispatcher("dateView.jsp").forward(request,response);
	}
}

This code uses the SimpleDateFormat class to format the current time. It then uses the request.setAttribute() function to include the formatted date in the request, and then it uses the request.getRequestDispatcher("path/to/view.jsp").forward(request, response) function to send the request to a JSP file.

Next, we’d need need a dateView.jsp file that handles the request:

<!DOCTYPE html>
<html>
	<head>
		<title>Current Time</title>
	</head>
	<body>
		<h1>Current Time</h1>
		<p>The current time is <%= request.getAttribute("date") %></p>
	</body>
</html>

Notice the <%= request.getAttribute("date") %> expression, which gets the date attribute that the servlet added.

This allows us to keep our JSP code simple, and all of our logic in our servlets.

Tying it together, we’d need a web.xml file that mapped a request to the servlet:

<web-app>

	<servlet>
		<servlet-name>CurrentTimeServlet</servlet-name>
		<servlet-class>DateServlet</servlet-class>
	</servlet>

	<servlet-mapping>
		<servlet-name>CurrentTimeServlet</servlet-name>
		<url-pattern>/current-time</url-pattern>
	</servlet-mapping>

</web-app>

This XML creates a CurrentTimeServlet from our DateServlet class and then maps the /current-time URL to that servlet.

At this point, our directory structure should look like this:

And now if we navigate to http://localhost:8080/MyWebApp/current-time in our browser, we should see:

current time webpage

Expression Language

So far, we’ve been using a simplified version of web.xml just to keep it short. But now that we’re getting more complicated, we’re ready to use more advanced features. To activate them, let’s use a deployment descriptor in our web.xml file.

<web-app
	xmlns="http://xmlns.jcp.org/xml/ns/javaee"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
		http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
	version="3.1">

	<servlet>
		<servlet-name>CurrentTimeServlet</servlet-name>
		<servlet-class>DateServlet</servlet-class>
	</servlet>

	<servlet-mapping>
		<servlet-name>CurrentTimeServlet</servlet-name>
		<url-pattern>/current-time</url-pattern>
	</servlet-mapping>

</web-app>

The only thing that changes is the addition of attributes in the opening <web-app> tag. These tell the server that we want to use the latest features, including expression language in our JSP files.

Expression language (or EL) gives us a simplified syntax for doing things like accessing attributes. So now we can use ${date} instead of <%= request.getAttribute("date") %>:

<!DOCTYPE html>
<html>
	<head>
		<title>Current Time</title>
	</head>
	<body>
		<h1>Current Time</h1>
		<p>The current time is ${date}</p>
	</body>
</html>

Hiding JSP Files

Remember that uses can’t directly access stuff inside the WEB-INF directory. But because our dateView.jsp file is not inside the WEB-INF directory, it’s publicly available. That means users can visit http://localhost:8080/MyWebApp/dateView.jsp directly, which shows a page like this:

blank current time webpage

Notice that the current time is blank. Because we’re accessing the dateView.jsp file directly, the servlet wasn’t triggered, so it didn’t add the current time to the attributes. We probably want to prevent users from being able to see buggy pages like this, so let’s hide our JSP files.

We can do this by moving the dateView.jsp file inside the WEB-INF directory. Let’s put it inside a jsp folder, so our directory structure looks like this:

Now we would just need to change our DateServlet code to point to the new location of dateView.jsp:

import java.io.PrintWriter;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class DateServlet extends HttpServlet {

	@Override
	public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {

		// 5:12 PM on Saturday, June 3, 2017
		SimpleDateFormat dateFormat = new SimpleDateFormat("hh:mm aa 'on' EEEE, MMMM dd, yyyy");
		Date now = new Date();
		String formattedDate = dateFormat.format(now);

		request.setAttribute("date", formattedDate);
		request.getRequestDispatcher("/WEB-INF/jsp/dateView.jsp").forward(request,response);
	}
}

Notice how we now forward the request to /WEB-INF/jsp/dateView.jsp. Our code is allowed to access the WEB-INF directory, but users can’t see what’s inside it. This allows us to keep things mostly hidden from users.

MVC

This approach of using servlets to contain our logic and JSP files to contain our rendering code gets us closer to Model-View-Controller, or MVC.

MVC is the idea of separating your data from your logic from your rendering. It allows you to focus on one thing at a time, and makes debugging and making changes to one piece much easier. You can use this idea in any type of programming, but when developing server code it generall works like this:

You don’t have to worry about getting everything exactly correct, and concepts like MVC are more of a way of thinking about organization than it is a strict set of rules. But keeping your data, your logic, and your rendering separate will definitely make your life easier. And this approach of splitting your servlets and your JSP files will help with that.

Static Files

We can still use static files with this approach. So we can have an index.html file that looks like this:

<!DOCTYPE html>
<html>
	<head>
		<title>My Home Page</title>
	</head>
	<body>
		<h1>Welcome to my web page!</h1>
		<p>Click <a href="http://localhost:8080/MyWebApp/current-time">here</a> to see the current time.</p>
	</body>
</html>

Put this in your MyWebApp directory (not inside the WEB-INF folder), and then visit http://localhost:8080/MyWebApp/index.html to see a page like this:

static home page

Note that this static file links to our dynamic page that shows the current time. You can also go the other way and link from a dynamic page to static files. This allows us to load stuff like images and CSS files in our JSP views. Remember: the end result is just regular HTML, so anything you can do in HTML, you can do with servlets and JSP files.