Model View Controller - PawelBogdan/BecomeJavaHero GitHub Wiki
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:
Source
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 <% %>
.
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>
- Project
Training005
is result of steps described in page. Change this application to write every letter in different colour. - 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! |
- Change
Training006
to displayn
first elements of Fibonacci sequence.