LINUX.ORG.RU

Spring MVC. Вспомнить забытое

 , ,


0

2

Доброго времени суток, уважаемый ЛОР. Давно не работал со спрингом, приходится вспоминать. Неожиданно возникла проблема.

Версию спринга тяну maven'ом с central (4.0.1.RELEASE)
web.xml:

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.5">
    <servlet>
        <servlet-name>dispatcher</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>dispatcher</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>/WEB-INF/dispatcher-servlet.xml</param-value>
    </context-param>
</web-app>

dispatcher-servlet.xml:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
           http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
           http://www.springframework.org/schema/context
           http://www.springframework.org/schema/context/spring-context-4.0.xsd
           http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd
           http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-4.0.xsd
           http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.0.xsd"

       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:tx="http://www.springframework.org/schema/mvc"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xmlns:mvc="http://www.springframework.org/schema/task"
       xmlns:context="http://www.springframework.org/schema/context">

    <mvc:annotation-driven />

    <bean id="sessionBean" class="net.test.spring.beans.SessionBean" scope="session" >
        <aop:scoped-proxy />
    </bean>

    <bean id="singletonBean" class="net.test.spring.beans.SingletonBean" >
        <property name="sessionBean" ref="sessionBean" />
    </bean>


</beans>

Контроллер:

package net.test.spring.controller;

import net.test.spring.beans.SessionBean;
import net.test.spring.beans.SingletonBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;

@org.springframework.stereotype.Controller
@RequestMapping(value = "api")
public class Controller {

    @Autowired
    public Controller(SingletonBean singletonBean) {
        this.singletonBean = singletonBean;
    }

    private SingletonBean singletonBean;

    @RequestMapping(value = "/bean", method = RequestMethod.GET)
    @ResponseBody
    public SessionBean getSessionBeanFromSingletonOne() {
        return singletonBean.getSessionBean();
    }
}

По адресу localhost:<port>/api/bean получаю:

eb 4, 2014 7:38:02 PM org.springframework.web.servlet.DispatcherServlet noHandlerFound
WARNING: No mapping found for HTTP request with URI [/api/bean] in DispatcherServlet with name 'dispatcher'

Задеплоено на tomcat, приложение контекста не имеет, причем пробовал его выставлять. Читать выхлоп умею. Не понимаю, почему так. Да, пробовал и «api» и «/api» в контроллере. Напомни, ЛОР, что я забыл? Спасибо.

★★

Последнее исправление: bytecode (всего исправлений: 2)

Ответ на: Збс от anonymous

Там что, заставляют людей писать на xml?

будто что-то плохое

anonymous
()
Ответ на: Збс от anonymous

В 4 уж точно не заставляют. Как вспомню, в чем проблема, буду переходить на аннотации. Алсо, а вы пробовали написать конфиг полностью на java? Смотрится, мягко говоря, как го*но.

bytecode ★★
() автор топика
Ответ на: комментарий от bytecode

У тебя 1) приложение в ROOT.war? 2) у тебя явно выставлено отсутствие префикса пути приложения?

Если нет, app name == названию war файла без .war

vertexua ★★★★★
()
Ответ на: комментарий от vertexua

Кстати, нет, не явно. Забыл про такую мелочь. Привык, что кто-то пишет скрипты автодеплоя и остается дернуть скрипт, чтобы всё легло на блюдечко. Завтра попробую, отрепорчу.

bytecode ★★
() автор топика

а кто будет в контекст добавлять пакет для автоматического поиска контроллеров?

maloi ★★★★★
()
Ответ на: комментарий от maloi

ну и ещё

    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>/WEB-INF/dispatcher-servlet.xml</param-value>
    </context-param>
в твоем случае ничего не делает, а если бы делал, то зря.

maloi ★★★★★
()
Ответ на: комментарий от bytecode

Это попытка пофлудить быа :)

Пугает меня такое количество xml. Зачем его столько много? Вы же его не вручную пишите, надеюсь?

generator ★★★
()
Ответ на: комментарий от crowbar

1. спринг - это не только IoC и DI, но и куча других библиотек

2. таки посмотрел на примеры picocontainer - не увидел чем оно проще спринга с включенным autowire.

maloi ★★★★★
()
Ответ на: комментарий от anonymous

Кукарекнул? Ну окей, давай теперь по существу. В конфиге спринга:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
           http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
           http://www.springframework.org/schema/context
           http://www.springframework.org/schema/context/spring-context-4.0.xsd
           http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-4.0.xsd"

       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:mvc="http://www.springframework.org/schema/task"
       xmlns:context="http://www.springframework.org/schema/context">

    <mvc:annotation-driven />
    <context:annotation-config/>


</beans>
Выпилил даже context:component-scan.
Бины:
@Service
public class SingletonBean {
    ...
}

@Service
@Scope(value = WebApplicationContext.SCOPE_SESSION, proxyMode = ScopedProxyMode.TARGET_CLASS)
public class SessionBean {
    ...
}

На выходе получаем сабж. Давай, расскажи мне, что здесь не так. (:

bytecode ★★
() автор топика

В общем, помогла конфигурация на java:

public class Config extends AbstractAnnotationConfigDispatcherServletInitializer {

    @Override
    protected Class<?>[] getRootConfigClasses() {
        return new Class<?>[0];
    }

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

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

    @Configuration
    @EnableWebMvc
    @ComponentScan("net.test.spring")
    public static class WebAppConfig {

    }
}

Что меня ни разу не радует. Сейчас пара вопросов.
1. Нынче модно писать конфигурацию на java?
2. При объявлении бинов аннотациями @Controller/@Service/@Repository/@Component(в конце концов), но при отсутствии @ComponentScan в WebAppConfig примера выше, контейнер ничего не знает о бинах. Это нормально? Какой тогда сакральный смысл в этих аннотациях?
3. Может кто-нибудь ткнуть пальцем, почему пример из первого поста не работал? В моем понимании феншуй - это когда есть конфигурация на xml, в которой я пишу

<?xml version="1.0" encoding="UTF-8"?>
<beans ...>
    <mvc:annotation-driven />
    <context:annotation-config />
</beans>
после чего контейнер видит мои бины, помеченные описанными в вопросе 1 аннотациями. (Или я не прав и с моим чувством прекрасного что-то не так?)

bytecode ★★
() автор топика
Ответ на: комментарий от bytecode

Да, context:annotation-config тогда только был бы лишним в конфиге.

bytecode ★★
() автор топика
Ответ на: комментарий от maloi

Что ж, на вкус и цвет. Как бы то ни было, главное ехать, а не шашечки. Но мне кажется чертовски логичным держать XML (который на самом-то деле мне уже осточертел в этих тырпрайзах), в котором как минимум можно было бы сказать, что конфигурация будет на аннотациях. Всё, выдохнул.

bytecode ★★
() автор топика
Ответ на: комментарий от bytecode

В context:annotation-config нужно указать base-package="..." - пакет, в котором искать аннотированные бины.

в конфигурации на джаве ты это сделал, а в хмл - нет.

maloi ★★★★★
()
Ответ на: комментарий от maloi

Да, теперь уже понял. Спасибо за ответ. У меня остался наверное последний вопрос. Аннотации @Controller/@Service/@Repository/@Component вовсе не означают, что бины будут видны контейнеру, пока не будут явно заданы пакеты, в которых они описаны?

bytecode ★★
() автор топика
Ответ на: комментарий от bytecode

1. эта конструкция нужна для того, чтобы задать положение файла конфигурации для контекста приложения (applicationContext)

2. в твоем случае applicationContext не создается вовсе, поэтому указывать расположение конфигурации для него бессмысленно.

3. расположение конфигурации для applicationContext совпадает с расположение конфигурации сервлета, это означает, что если ты будешь создавать applicationContext, то бины из этой xml-ки создадутся два раза - в двух разных контекстах. скорее всего это не то что ты хотел. в простых случаях это не приведет к каким-либо проблемам, в сложных ты можешь не понять, почему у тебя, например, в session-бине значение пропадает.

пункт 3 - довольно распространенная ошибка, в интернетах не раз обсуждалась.

maloi ★★★★★
()
Ответ на: комментарий от maloi

Спасибо за разъяснения. Займусь чтением документации с нуля.

bytecode ★★
() автор топика
Ответ на: комментарий от bytecode

вообще любые аннотации в спринге не работают до тех пор, пока ты не укажешь явно, что хочешь их использовать.

да, для создания бинов с помощью аннотаций @Component и наследников нужно указать пакет, в котором их искать. (подпакеты тоже автоматически включаются поиск).

maloi ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.