JavaEE JSP, Servlet - MVC

Most jsp és servlet felhasználásával megpróbálunk MVC-szerű alkalmazást készíteni. Igyekezni fogunk szétválasztani a 3 réteget. Egy olyan applikációt fogunk készíteni amiben autóknak fogjuk bekérni adatait egy form-on és ezeket jelenítjük meg egy új lapon.

Készítsünk egy új dynamic web projecktet CarProject néven.

Készítsük el elsőnek a model réteget. Egy sima POJO-t(sima java osztály) fogunk csinálni:


A fájl tartalma nézzen ki így:
package org.project.car;

public class Car {
	private String carId;
	private String color;
	private String fuel;
	private String performance;
	
	public String getCarId() {
		return carId;
	}
	public void setCarId(String carId) {
		this.carId = carId;
	}
	public String getColor() {
		return color;
	}
	public void setColor(String color) {
		this.color = color;
	}
	public String getFuel() {
		return fuel;
	}
	public void setFuel(String fuel) {
		this.fuel = fuel;
	}
	public String getPerformance() {
		return performance;
	}
	public void setPerformance(String performance) {
		this.performance = performance;
	}
	
}
Definiáltunk pár változót és generáltunk hozzájuk get set metódusokat.

Készítsük el a view-ot. Hozzunk létre a webcontent mappába egy Form.jsp fájlt az alábbi tartalommal:
<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
    pageEncoding="ISO-8859-1"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Autó adatai</title>
</head>
<body>
<form action="Process.jsp" method="post">
	<br />Rendszám: <input type="text" name="carId" />
	<br />Szín: <input type="text" name="color" />
	<br />Üzemanyag típusa: <input type="text" name="fuel" />
	<br />Teljesítmény: <input type="text" name="performance" />
	<br /><input type="submit" />
</form>
</body>
</html>
Egy formot hoztunk létre pár mezővel, semmi izgalmast nem követtünk el.

Készítsünk egy Process.jsp fájlt a webcontent mappába. Itt most teszünk egy gyors kitérőt. Lehetőségünk van jsp-ből közvetlenül elérni a java osztályunkat amik az adatokat tárolják.
Ebben az esetben a következőképpen fog kinézni a Process.jsp fájlunk:
<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
    pageEncoding="ISO-8859-1"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Insert title here</title>
</head>
<body>
	<jsp:useBean id="car" class="org.project.car.Car" scope="request">
		<jsp:setProperty property="*" name="car" />
	</jsp:useBean>
	
	Rendszám: <jsp:getProperty property="carId" name="car" />
	Szín: <jsp:getProperty property="color" name="car" />
	Üzemanyag: <jsp:getProperty property="fuel" name="car" />
	Teljesítmény: <jsp:getProperty property="performance" name="car" />
	
</body>
</html>

Ami újdonság itt az az, hogy a jsp-ben használhatunk előre definiált metódusokat. Pl jsp:useBean -el példányosíthatunk egy java osztályt. A jsp:getProperty metódusokkal pedig elérhetjük az adatainkat. Ha elindítjuk a tomcat-et  http://localhost:8080/CarProject/Form.jsp ezt a form-ot kitöltve a Process.jsp oldalon megkapjuk a beírt adatainkat.

De ez ugye messze van még az mvc-től. Először is írjuk át a Form.jsp-ben a form actiont így:
 
<form action="Form" method="post">

Készítsünk egy servlet-et(végül is ez a controller, ha úgy nézzük):



Legyen a tartalma a következő:
package org.project.car.servlet;

import java.io.IOException;

import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.project.car.Car;
import org.project.car.service.CarService;

/**
 * Servlet implementation class CarServlet
 */
@WebServlet("/Form")
public class CarServlet extends HttpServlet {
	private static final long serialVersionUID = 1L;
       
	/**
	 * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
	 */
	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		String carId, color, fuel, performance;
		
		carId = request.getParameter("carId");
		color = request.getParameter("color");
		fuel = request.getParameter("fuel");
		performance = request.getParameter("performance");
		
		CarService carService = new CarService();		
		boolean result = carService.check(carId,color,fuel,performance);
		
		if (result){
			Car car = carService.getCarDetails(carId);
			request.setAttribute("car", car);
			RequestDispatcher dispatcher = request.getRequestDispatcher("Process.jsp");
			dispatcher.forward(request, response);
			return;
		}
		else {
			response.sendRedirect("Form.jsp");
			return;			
		}
	}

}

Itt a @WebServlet("/Form") annotáció a fontos, hogy belegyen állítva, ez ugyanaz, mint a Form.jsp action paramétere. A doPost metódust fogjuk használni. A request-ből kinyerjük az adatokat, majd példányosítunk egy service-t, aminek az egyik metódusával ellenőrizzük, hogy a mezők nem üresek-e. Ha nem üresek, akkor getCarDetails metudóssal lekérdezzük az adatokat a service-től. Ezután csak a Process.jsp-nek átadjuk az adatokat. Ha hiányoznak az adatok, mert mondjuk nem gépeltük be őket, akkor a Form.jsp-n maradunk. A carService osztályunk még hiányzik, úgyhogy csináljuk ezt is meg.



A tartalma legyen a következő:
 
package org.project.car.service;

import java.util.HashMap;

import org.project.car.Car;

public class CarService {
	HashMap<String, Car> cars = new HashMap<String, Car>();
	
	public CarService(){
	    Car car1 = new Car();
		car1.setCarId("dsa-123");
		car1.setColor("kék");
		car1.setFuel("benzin");
		car1.setPerformance("60");
		cars.put("dsa-123", car1);
	    Car car2 = new Car();
		car2.setCarId("fgh-435");
		car2.setColor("zöld");
		car2.setFuel("benzin");
		car2.setPerformance("120");
		cars.put("fgh-435", car2);
	}
	//check parameters are not empty
	public boolean check(String carId,String color, String fuel, String performance){
		
		if(carId == null || carId.trim() == "" || color == null || color.trim() == ""  
				|| fuel == null || fuel.trim() == "" || performance == null || performance.trim() == ""){
			
			return false;
		} 
		else{ 

			return true;
		}
	}
	
	// get car parameters
	public Car getCarDetails(String carId){
		Car car = new Car();
		car.setCarId(carId);
		car.setColor(cars.get(carId).getColor());
		car.setFuel(cars.get(carId).getFuel());
		car.setPerformance(cars.get(carId).getPerformance());
		
		return car;
	}
}
Itt a konstruktorban két példányt létrehoztunk az autók osztályból. A check metódus ellenőrzi, hogy nem-e maradt üres valamelyik mező. A getCarDetails pedig vissza adja a megfelelő carId alapján a 2 példányból a helyeset. Végül is mintha keresnénk a hash mapp-en belül. Na, de mi van ha mi nem keresni szeretnénk, hanem azt akarjuk visszakapni amit begépeltünk?
Akkor a tegyünk egy kis módosítást a check metóduson:
	//check parameters are not empty
	public boolean check(String carId,String color, String fuel, String performance){
		
		if(carId == null || carId.trim() == "" || color == null || color.trim() == ""  
				|| fuel == null || fuel.trim() == "" || performance == null || performance.trim() == ""){
			
			return false;
		} 
		else{ 
			// set new car parameters for cars hashmap 
			Car car = new Car();
			car.setCarId(carId);
			car.setColor(color);
			car.setFuel(fuel);
			car.setPerformance(performance);
			cars.put(carId,car); 
			return true;
		}
	}

Így már visszafogja adni azt amit begépeltünk adatokat. Végül így néz ki a könyvtárszerkezetünk:



Olvasnivaló:
https://hu.wikipedia.org/wiki/Modell-nézet-vezérlő
https://hu.wikipedia.org/wiki/Plain_Old_Java_Object
https://www.youtube.com/watch?v=b42CJ0r-1to&list=PLB9B7412C6A8CBCF7
2015.08.11.