Model View Controller - PawelBogdan/BecomeJavaHero GitHub Wiki

Table of contents

  1. Introduction
  2. Java servlets
  3. Spring MVC
  4. Exercises
  5. Sources

Introduction

Model-View-Controller is an architectural pattern describing way of implementing user interfaces for computer applications. According to this pattern we divide application into three layers:

  • Model - data used by application
  • View - way of displaying data
  • Controller - module which can manipulate on data

Connection between these layers is described in the following diagram: MVC-diagram
Source

Java servlets

Java introduced the servlets mechanism. We can use it to create web applications. We shortly create the simplest web applications.

Let's start with the simplest web app. We can create fully working web app using maven via archetype maven-archetype-webapp. Maven creates web application. We need some application server, for example tomcat, jboss or jetty. Fortunately, for developing purposes we can use maven plug-in, which runs light server and deploys our app. We need to add plugin inside build tag:

<plugin>
    <groupId>org.eclipse.jetty</groupId>
    <artifactId>jetty-maven-plugin</artifactId>
    <version>9.3.9.v20160517</version>
</plugin>

And run maven project with goal jetty:run, after a while we can visit page: http://127.0.0.1:8080 and see our web app.

Let's add our first servlet. To do this, we need to add dependency to our pom.xml file:

<dependency>
    <groupId>javax.servlet</groupId>
    <artifactId>servlet-api</artifactId>
    <version>2.5</version>
</dependency>

The simplest servlet is class extending HttpServlet, for example:

public class HelloWorldServelt extends HttpServlet {
	public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException {
		PrintWriter out = response.getWriter();
		out.println("<html>");
		out.println("    <body>");
		out.println("        Hello from Servlet");
		out.println("    </body>");
		out.println("</html>");
		out.flush();
		out.close();
	}
}

We need to change file web.xml:

<web-app>
  <display-name>Archetype Created Web Application</display-name>
  <servlet>
  	<servlet-name>HelloWorldServlet</servlet-name>
  	<servlet-class>pl.edu.bogdan.training.mvc.servlets.HelloWorldServelt</servlet-class>
  </servlet>
  <servlet-mapping>
  	<servlet-name>HelloWorldServlet</servlet-name>
  	<url-pattern>/HelloWorldServlet</url-pattern>
  </servlet-mapping>
</web-app>

And if we restart our jetty server, and visit page http://localhost:8080/HelloWorldServlet, we will see the page we wrote in servlet.

This method of generating web pages is very inconvenient. There is much simpler way. We need to create web page which should be displayed, for example page.jsp in directory src/main/webapp:

<html>
<head>
	<title>Servlet Web Page</title>
</head>
<body>
	<h3>Hello from servlet!!!!!!</h3>
</body>
</html>

We need to change our servlet:

public class HelloWorldServelt extends HttpServlet {
	public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
		response.setContentType("text/html");
        request.getRequestDispatcher("page.jsp").forward(request, response);
	}
}

And if we restart our jetty server, and visit page http://localhost:8080/HelloWorldServlet, we will see the page defined by page.jsp.

Of course, we can get parameters from html forms. Let's create simple form in page.jsp file:

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
	<title>Servlet Web Page</title>
</head>
<body>
	<h3>Hello from servlet!!!!!!</h3>
	<form action="/FormAnalyzer">
            <input type="text" name="text" value="Type here">
            <input type="submit" value="Submit">
        </form>
</body>
</html>

We provided /FormAnalyzer as action attribute. Now we need to add servlet:

public class FormAnalyzer extends HttpServlet {
	public void doGet(HttpServletRequest request, HttpServletResponse response) 
                        throws IOException, ServletException {
		response.setContentType("text/html");
		String text = request.getParameter("text");
		text = text.toUpperCase();
		request.setAttribute("text", text);
                request.getRequestDispatcher("result.jsp").forward(request, response);
	}
}

As we can see, this servlet displays page result.jsp:

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
	<title>Servlet Web Page</title>
</head>
<body>
	<h3>Hello, you sent: <b><%= request.getAttribute("text") %></b></h3>
</body>
</html>

We can put Java code inside tags <% %>.

Spring MVC

As we saw in previous section, adding new servlets is inconvenient. We can use Spring library, to create controllers much simpler. We need to create simple web application using maven archetype maven-archetype-webapp. Firstly we need to add some dependencies:

<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-web</artifactId>
    <version>5.0.1.RELEASE</version>
</dependency>
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-webmvc</artifactId>
    <version>5.0.1.RELEASE</version>
</dependency>
<dependency>
    <groupId>javax.servlet</groupId>
    <artifactId>javax.servlet-api</artifactId>
    <version>3.1.0</version>
</dependency>

Of course we can add jetty plug-in. For proper working of app we need to delete web.xml file. We need to add two configuration classes:

public class SpringMvcInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
	@Override
	protected Class<?>[] getRootConfigClasses() {
		return null;
	}

	@Override
	protected Class<?>[] getServletConfigClasses() {
		return new Class[] { SpringWebConfig.class };
	}

	@Override
	protected String[] getServletMappings() {
		return new String[] { "/" };
	}
}

and

@EnableWebMvc
@Configuration
@ComponentScan({ "pl.edu.bogdan.training.springmvc.*" })
public class SpringWebConfig extends WebMvcConfigurerAdapter {
	@Override
	public void addResourceHandlers(ResourceHandlerRegistry registry) {
		registry.addResourceHandler("/resources/**").addResourceLocations("/resources/");
	}

	@Bean
	public InternalResourceViewResolver viewResolver() {
		InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();
		viewResolver.setViewClass(JstlView.class);
		viewResolver.setPrefix("/WEB-INF/views/jsp/");
		viewResolver.setSuffix(".jsp");
		return viewResolver;
	}
}

We need to add any class annotated as @Controller with methods which serves specified paths

@Controller
public class Greeter {
	@RequestMapping("/greeting")
	public String greeting(@RequestParam(value = "name", required = false, defaultValue = "World") String name, Model model) {
		model.addAttribute("name", name);
		return "greeting";
	}
}

This method returns greeting which, according to configuration, displays page greeting.jps in directory webapp/views/jps:

<html>
<body>
	<h2>Hello, ${name}</h2>
	<% for (int i = 1; i <= 10; i++) {  %>
	<%= i %>
	<% } %>
</body>
</html>

Exercises

  1. Project Training005 is result of steps described in page. Change this application to write every letter in different colour.
  2. Change Training005 in that way, we provide number in form, and we display table with every factorial, something like that:
n n!
1 1
2 2
3 6
4 24
... ...
k k!
  1. Change Training006 to display n first elements of Fibonacci sequence.

Sources

  1. wikipedia - MVC
  2. tutorialspoint
  3. Documentation
  4. Spring tutorial
  5. mkyong tutorial
⚠️ **GitHub.com Fallback** ⚠️