Spring 3 и @Controller. Часть 1

апреля
23
2012
Метки: controller java spring

Содержание

В этой статье рассмотрим создание контроллеров при использовании Spring Framework 3-й версии и Spring MVC в частности.

Аббревиатура MVC в названии Spring MVC расшифровывается как 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

так и не делать этого. В следующем случае будет использоваться название, совпадающее с названием переменной:


@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 >

Напишите первое сообщение!

Вы должны войти под своим аккаунтом чтобы оставлять комментарии