Spring MVC Вперед к JSP - PullRequest
       30

Spring MVC Вперед к JSP

2 голосов
/ 17 февраля 2011

В настоящее время мой web.xml настроен на перехват 404 и отправку их на мой контроллер Spring, который будет выполнять поиск по исходному URL-запросу.

Функциональность - все, что касается ловли и поискаgo, однако проблема начинает возникать, когда я пытаюсь вернуть представление.

<bean class="org.springframework.web.servlet.view.ContentNegotiatingViewResolver" p:order="1">
    <property name="mediaTypes">
        <map>
            <entry key="json" value="application/json" />
            <entry key="jsp" value="text/html" />
        </map>
    </property>

    <property name="defaultContentType" value="application/json" />
    <property name="favorPathExtension" value="true" />

    <property name="viewResolvers">
        <list>
            <bean class="org.springframework.web.servlet.view.BeanNameViewResolver" />
            <bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
                <property name="prefix" value="/WEB-INF/jsp/" />
                <property name="suffix" value="" />
            </bean>
        </list>
    </property>
    <property name="defaultViews">
        <list>
            <bean class="org.springframework.web.servlet.view.json.MappingJacksonJsonView" />
        </list>
    </property>
    <property name="ignoreAcceptHeader" value="true" />
</bean>

Это фрагмент моего файла конфигурации MVC.

Проблема заключается в определении пути к представлению.каталог /WEB-INF/jsp/.Используя регистратор в моей настройке JBoss, я вижу, что когда я тестирую этот контроллер поиска, переходя на несуществующую страницу, происходит следующее:

  1. Сервер не может найти запрос

  2. Запрос отправлен на страницу ошибки 404 (в данном случае мой контроллер поиска)

  3. Контроллер поиска выполняет поиск

  4. Контроллер поиска возвращает имя представления (для этой иллюстрации мы предположим, что возвращается test.jsp)

  5. Исходя из регистратора сервера, я вижу, что org.springframework.web.servlet.view.JstlViewинициализируется, как только мой поисковый контроллер возвращает имя представления (так что я могу предположить, что оно правильно выбирается InternalResourceViewResolver)

  6. Сервер пытается вернуть содержимое в браузер, что приводит к 404!

Меня смущает пара вещей:

  1. Я не уверен на 100%, почему это не разрешается, когда test.jspявно существует в каталоге /WEB-INF/jsp/.

  2. Даже если была какая-то другая проблемас чего бы это привело к 404?Разве страница 404 с ошибкой, которая приводит к другому 404, теоретически не может создать бесконечный цикл?

Спасибо за любую помощь или указатели!

Класс контроллера [неполный]:

@Controller
public class SiteMapController {

//--------------------------------------------------------------------------------------        
@Autowired(required=true)   
private SearchService search;

@Autowired(required=true)
private CatalogService catalog; 
//--------------------------------------------------------------------------------------

@RequestMapping(value = "/sitemap", method = RequestMethod.GET)
public String sitemap (HttpServletRequest request, HttpServletResponse response) {  
    String forwardPath = "";
    try {
        long startTime = System.nanoTime() / 1000000;
        String pathQuery = (String) request.getAttribute("javax.servlet.error.request_uri");

        Scanner pathScanner = new Scanner(pathQuery).useDelimiter("\\/");
        String context = pathScanner.next();
        List<ProductLightDTO> results = new ArrayList<ProductLightDTO>();
        StringBuilder query = new StringBuilder();
        String currentValue;
        while (pathScanner.hasNext()) {
            currentValue = pathScanner.next().toLowerCase();
            System.out.println(currentValue);
            if (query.length() > 0)
                query.append(" AND ");
            if (currentValue.contains("-")) {
                query.append("\"");
                query.append(currentValue.replace("-", " "));
                query.append("\"");
            }
            else {
                query.append(currentValue + "*");
            }
        }       

        //results.addAll(this.doSearch(query.toString()));

        System.out.println("Request: " + pathQuery);
        System.out.println("Built Query:" + query.toString());
        //System.out.println("Result size: " + results.size());     
        long totalTime = (System.nanoTime() / 1000000) - startTime;
        System.out.println("Total TTP: " + totalTime + "ms");

        if (results == null || results.size() == 0) {
            forwardPath = "home.jsp";
        }
        else if (results.size() == 1) {
            forwardPath = "product.jsp";
        }
        else {
            forwardPath = "category.jsp";
        }

    }
    catch (Exception ex) {
        System.err.println(ex);
    }

    System.out.println("Returning view: " + forwardPath);
    return forwardPath;
}
}

Ответы [ 3 ]

2 голосов
/ 10 августа 2013

1. Я не уверен на 100%, почему это не решается, когда test.jsp явно существует в / WEB-INF / jsp / каталог.

Это потому, что вы сконфигурировали свой распознаватель представлений с suffix = "", поэтому файл должен иметь имя test (без расширения).

2. Даже если бы была какая-то другая проблема, почему это привело бы к 404? Не должно 404 страница ошибки, которая в результате еще 404 теоретически создать бесконечный цикл?

Я почти уверен, что это результат некоторой защиты от бесконечного цикла перенаправления весной MVC.

Примечание: в контроллерах, пружина ожидает имя вида в результате, поэтому test не test.jsp (или лучше, используйте ModelAndView)

1 голос
/ 17 февраля 2011

Я публикую это как ответ, потому что он слишком длинный, но, вероятно, это не ответ.

http://localhost:8080/webapp/servlet-mapping-url/controller-mapping/method-mapping

если метод вашего контроллера, который обрабатывает запрос, не возвращает строку имени представления или объект представления или запись непосредственно в выходной поток, диспетчер Spring должен разрешить имя представления в /WEB-INF/jsp/controller-mapping/method-mapping.jsp

Это означает, что jsp должен находиться в папке с именем /WEB-INF/jsp/controller-mapping/. Однако, если имя представления или объект представления возвращается методом контроллера, диспетчер Spring будет использовать его вместо этого.

Есть еще много возможных комбинаций картирования, но это наиболее распространенная. Если бы вы могли показать свой класс контроллера, это будет проще.

Обновление

Если вы используете DefaultAnnotationHandlerMapping, вы всегда должны отмечать свой класс @RequestMapping(value = "/mapping-string"). В противном случае пружинный диспетчер попытается забрать его, когда больше ничего не найдено.

Поскольку контроллер сопоставлен, вам придется изменить отображение метода на value = {"", "/"}

Для имени возвращаемого вида вам не нужно ставить .jsp.

Если имя возвращаемого вида - home, диспетчер пружин разрешит /WEB-INF/jsp/home.jsp

Если имя возвращаемого вида - path/home, диспетчер пружин разрешит /WEB-INF/jsp/path/home.jsp

P.S. Вы использовали слово forwardPath, но на самом деле это не форвард. Это просто имя вида.

@Controller
@RequestMapping(value = "/sitemap")
public class SiteMapController {

    @RequestMapping(value = {"", "/"}, method = RequestMethod.GET)
    public String sitemap (HttpServletRequest request, HttpServletResponse response) {  
            ...
            if (results == null || results.size() == 0) {
                forwardPath = "home";
            }
            else if (results.size() == 1) {
                forwardPath = "product";
            }
            else {
                forwardPath = "category";
            }
            ...
        return forwardPath;
    }
}
0 голосов
/ 22 сентября 2016

Попробуйте установить порядок для вашего ViewResolver.Например:

@Bean
public ViewResolver getViewResolver(){
  InternalResourceViewResolver resolver = new InternalResourceViewResolver();
  resolver.setViewClass(JstlView.class);
  resolver.setPrefix("/WEB-INF/jsp/");
  resolver.setSuffix(".jsp");
  resolver.setOrder(1);
  return resolver;
}
...