Spring 3 і @Controller. Частина 1

квітня
23
2012
Мітки: controller java spring

Зміст

У першій частині статті розглянемо створення контролерів, використовуючи Spring Framework 3-ї версії і Spring MVC зокрема.

Абревіатура MVC в назві Spring MVC розшифровується як Model-view-controller. Моде́ль-вид-контро́лер (або Модель-вигляд-контролер, англ. Model-view-controller, MVC) — архітектурний шаблон, який використовується під час проектування та розробки програмного забезпечення.

Цей шаблон поділяє систему на три частини: модель даних, вигляд даних та керування. Застосовується для відокремлення даних (модель) від інтерфейсу користувача (вигляду) так, щоб зміни інтерфейсу користувача мінімально впливали на роботу з даними, а зміни в моделі даних могли здійснюватися без змін інтерфейсу користувача.

Мета шаблону — гнучкий дизайн програмного забезпечення, який повинен полегшувати подальші зміни чи розширення програм, а також надавати можливість повторного використання окремих компонент програми. Крім того використання цього шаблону у великих системах призводить до певної впорядкованості їх структури і робить їх зрозумілішими завдяки зменшенню складності.

Парадигрма програмування MVC не буде докладно описуватися в даній статті.

Отже, контролер в Spring MVC виконує роль (як не дивно :)) контролера в парадигмі програмування Model-View-Controller. Кожен запит перехоплюється глобальним Front-контролером, який за специфічними параметрами (URI, метод і/або заголовки запиту) визначає, якому з контролерів передати отриманий запит. Контролер обробляє запит і створює модель. Front-контролер заповнює відображення даними моделі і повертає отриманий результат браузеру. Нижче представлена ​​схема обробки запиту у Spring.

Рис 1. Обробка запиту в Spring Web MVC
Рис 1. Обробка запиту в Spring Web MVC

Найпростіший контролер виглядає наступним чином:


@Controller
public class SimpleController {
	@RequestMapping(value = "/simple1")
	public String simple1() {
		return "simple";
	}
}

Анотація @Controller служить для повідомлення Spring'у про те, що даний клас є bean'ом і його необхідно завантажити при старті програми. Анотацією @RequestMapping (value="/simple1") повідомляємо, що даний контролер буде обробляти запит, URI якого "/simple1".


return "simple";

- повідомляємо Front-контролеру, що ім'я відображення "simple" (за замовчуванням, це файл / WEB-INF/views/simple.jsp).

Ці ж операції можна зробити з використанням класу ModelAndView, який агрегує всі параметри моделі та ім'я відображення:


@Controller
public class SimpleController {
	@RequestMapping(value = "/simple2")
	public ModelAndView simple2() {
		ModelAndView mav = new ModelAndView();
		mav.setViewName("simple");
		return mav;
	}
}

jsp-файл і в першому, і в другому випадку може виглядати, наприклад, наступним чином:


<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<%@ page pageEncoding="UTF-8"%>
<%@ page session="false"%>
<html>
<head>
<title>SimpleController</title>
</head>
<body>
	<h1>SimpleController</h1>

	<P>Just text</P>
	<a href="${pageContext.request.contextPath}/" title="Back">Back</a>
</body>
</html>

У двох наведених вище прикладах контролери не передають ніяких даних відображенням, що буває дуже рідко. Тому розглянемо варіант з передачею даних від контролера відображенню за допомогою моделі.

Модель-відображення-контролер

Дані від контролера до відображення можуть передатися двома способами:


@RequestMapping(value = "/simplemodel1")
public String simpleModel1(Model model) {
	model.addAttribute("name", "John");
	model.addAttribute("path", "/simplemodel1");
	return SIMPLE_MODEL_VIEW_NAME;
}

або


@RequestMapping(value = "/simplemodel2")
public ModelAndView simpleModel2() {
	ModelAndView mav = new ModelAndView();
	mav.setViewName(SIMPLE_MODEL_VIEW_NAME);
	mav.addObject("name", "John");
	mav.addObject("path", "/simplemodel2");
	return mav;
}

У першому випадку модель передається методу у вигляді параметра. Метод повинен повернути назву відображення. У другому випадку метод сам створює об'єкт ModelAndView, який містить і модель, і ім'я відображення. Контролер повинен повернути цей об'єкт.

jsp-файл буде виглядати наступним чином:


<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<%@ page pageEncoding="UTF-8"%>
<%@ page session="false"%>
<html>
<head>
<title>${path} - SimpleModelController</title>
</head>
<body>
	<h1>${path} - SimpleModelController</h1>

	<P>Hi ${name}!</P>
	<a href="${pageContext.request.contextPath}/" title="Back">Back</a>
</body>
</html>

У даному прикладі контролер передає 2 параметра відображенню - name і path. Вони відображаються за допомогою конструкції ${_param_name_}. Наприклад:


<P>Hi ${name}!</P>

В даному випадку користувачеві передається наступний рядок


<P>Hi John!</P>

Тобто, вираз ${name} замінюється на John так як і в першому, і в другому методі контролера змінна моделі name заповнюється рядком John.


@RequestMapping(value = "/simplemodel1")
public String simpleModel1(Model model) {
        // ...
	model.addAttribute("name", "John");
        // ...
}

@RequestMapping(value = "/simplemodel2")
public ModelAndView simpleModel2() {
        // ...
	mav.addObject("name", "John");
        // ...
}

Анотація @RequestMapping при оголошенні класу контролера

Раніше ми розглядали тільки методи, які були помічені анотацією @RequestMapping. Також є можливість позначити клас за допомогою анотації @RequestMapping. Тоді всі методи будуть отримувати запити з URI, що буде починатись з рядка, вказаного в анотації @ RequestMapping перед оголошенням класу контролера. Наприклад:


package com.seostella.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
@RequestMapping("/rmc")
public class RequestMappedClassController {
	public static final String REQUEST_MAPPED_CLASS_VIEW_NAME = "request_mapped_class";
	
	@RequestMapping(value = "/test")
	public String requestMapped() {
		return REQUEST_MAPPED_CLASS_VIEW_NAME;
	}
}

Щоб метод requestMapped отримав управління, необхідно виконати запит виду "/rmc/test".

Метод запиту

Як і в більшості http-фреймворків, в Spring є можливість розподіляти запити за різними методами не тільки по параметрам, зазначеним у URI, але і використовуючи різні методи запиту. Наприклад:


@Controller
public class RequestMethodController {
	public static final String REQUEST_METHOD_VIEW_NAME = "request_method";
	
	@RequestMapping(value = "/requestmethod", method = RequestMethod.GET)
	public String requestMethodGet(Model model) {
		model.addAttribute("method", "get");
		return REQUEST_METHOD_VIEW_NAME;
	}

	@RequestMapping(value = "/requestmethod", method = RequestMethod.POST)
	public String requestMethodPost(Model model) {
		model.addAttribute("method", "post");
		return REQUEST_METHOD_VIEW_NAME;
	}
}

Щоб виконався метод requestMethodGet, достатньо в браузері звернеться за адресою /requestmethod. Для цього методу необхідною умовою є метод GET в HTTP-запиті. Саме GET-метод передається серверу, коли Ви переходите на сторінку, набираючи адресу в браузері.

Для того, щоб виконався другий метод requestMethodPost, необхідно передати йому POST-запит, а для цього необхідно скористатися, наприклад, наступною формою:


<form action="${pageContext.request.contextPath}/requestmethod"
	method="post">
	<input type="submit" value="requestmethod (post)">
</form>

Автозаповнення змінної із запиту або @PathVariable

В Spring є також можливість автозаповнення змінної, використовуючи адресу запиту. Розглянемо на прикладі:


@RequestMapping(value = "/pathvariable/{category}/{product}")
public String pathVariable(@PathVariable String category, @PathVariable("product") String productName, Model model) {
	
	model.addAttribute("categoryName", category);
	model.addAttribute("productName", productName);
	
	return "view_name";
}

Використовуючи даний код не потрібно піклуватися про те, як дістати рядок, розташований між pathvariable / і наступним слешем. Він буде автоматично поміщений в змінну category, завдяки анотації @PathVariable.

Ви можете замість строкового типу змінної category використовувати цілочисельний або будь-який інший стандартний тип - Spring перетворює рядок до потрібного типу автоматично. Наприклад:


@RequestMapping(value = "/pathvariable/{category}/{product}")
public String pathVariable(@PathVariable int category, @PathVariable("product") String productName, Model model) {
    // ...
}

Варто зауважити, що в анотації @PathVariable можна як вказувати назву змінної:


@PathVariable("product") String productName

так і не робити цього. У наступному випадку буде використовуватися назва змінної category:


@PathVariable String category

Також змінна може бути в анотації перед оголошенням класу. Тоді її можна отримати в будь-якому з методів контролера. Наприклад:


@Controller
@RequestMapping(value = "/category/{categoryName}")
public class ClassPathVariableController {
	
	public static final String PATH_VARIABLE_VIEW_NAME = "class_path_variable";
	
	@RequestMapping(value = "/product/{productName}")
	public String classPathVariable(@PathVariable String productName, 
			@PathVariable String categoryName, 
			Model model) {
		
		model.addAttribute("categoryName", categoryName);
		model.addAttribute("productName", productName);
		return PATH_VARIABLE_VIEW_NAME;
	}
}

Spring 3 і @Controller. Частина 2 >

Напишіть перше повідомлення!

Ви повинні увійти під своїм аккаунтом щоб залишати коментарі