简体   繁体   中英

Trouble mapping Ajax to Spring MVC Controller

Short version:

I need to know what to put here:

$(document).ready(function() {
    $('#orgSearch').autocomplete({
        // what do I put for "source" ???
        source : '/getOrgsViaAjax'
    });
});

and here:

// What do I put for the arguments in `@RequestMapping` ?
// What do I put as the arguments for the method?
// What do I name the method?

@RequestMapping(value = "/getOrgsViaAjax", method = RequestMethod.GET)
public @ResponseBody String getOrgsViaAjax(@RequestParam("term") String query) {
    ...
}

to get my Ajax autocomplete to work with a Spring MVC controller.


Long version:

I am trying to map Ajax autocomplete source tag with my Spring MVC controller, and I am unable to get anything to work.

What I've tried:

I have a Spring MVC controller that is similar to this:

@Controller
@RequestMapping("/PersonAffiliations.html")
public class PersonAffiliationsController extends BaseController {

    @RequestMapping(value = "/getOrgsViaAjax", method = RequestMethod.GET)
    public @ResponseBody String getOrgsViaAjax(@RequestParam("term") String query) {

        System.out.println("getOrgsViaAjax -- Here");
        return "{\"Test OrgOne\":\"42695847\",\"Test OrgTwo\":\"84920493\",\"Test OrgThree\":\"22222222\",\"Test OrgFour\":\"42226589\"}";
    }

    // The controller methods below all work
    // I included them here just incase they're causing my issues
    @RequestMapping(method = RequestMethod.GET)
    public String getPerson(Map model, HttpServletRequest request) {
        ...
        return "PersonAffiliations";
    }

    @RequestMapping(method = RequestMethod.POST)
    public String processForm(@Valid PersonForm objPersonForm, BindingResult result, Map model, HttpServletRequest request) {
        ...
        return "PersonAffiliations";            
    }

    @RequestMapping(params = "update", method = RequestMethod.POST)
    public String processNameForm(@Valid PersonAffiliationForm objPersonAffiliationForm, BindingResult result, Map model, HttpServletRequest request) {
        ...
        return "PersonAffiliations";            
    }

}

And a .jsp page that is similar to this:

<!DOCTYPE HTML><%@page language="java" contentType="text/html; charset=ISO-8859-1" pageEncoding="ISO-8859-1"%>
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form"%>
<%@ taglib uri = "http://java.sun.com/jsp/jstl/core" prefix = "c" %>
<html>
    <script src="resources/js/jquery-1.12.4.js"></script>
    <script src="resources/js/jquery-ui.js"></script>
    <script type="text/javascript">
        $(document).ready(function() {

            console.log("here");
            console.log('${pageContext.request.contextPath}');

            $('#orgSearch').autocomplete({
                source : '${pageContext.request.contextPath}/PersonAffiliations/getOrgsViaAjax'
            });
        });
    </script>
    <head>
        <title>Person Affiliation Editor</title>
        <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
    </head>
    <body>
        <form:form name="AddPersonAffiliationForm" action="PersonAffiliations.html" modelAttribute="BlankPersonAffiliationForm">
            ...
            <form:input id="orgDeptId" path="deptId" />
            <form autocomplete="off" id="searchOrgForm">
                <div class="autocomplete">
                    <input id="orgSearch" type="text" style="width:500px" name="orgSearch" placeholder="Organization" />
                </div>
            </form>


        </form:form>
    </body>
</html>

But the getOrgsViaAjax controller method never executes. Firebug says 404 .

On the .jsp side I've tried:

source : '${pageContext.request.contextPath}/PersonAffiliations/getOrgsViaAjax'

source : '${pageContext.request.contextPath}/PersonAffiliations//getOrgsViaAjax'

source : '/PersonAffiliations/getOrgsViaAjax'

source : '/getOrgsViaAjax'

source : '${pageContext.request.contextPath}/PersonAffiliations.html/getOrgsViaAjax'

source : '/PersonAffiliations.html/getOrgsViaAjax'

On the controller side I've tried:

@RequestMapping(value = "/getOrgsViaAjax", method = RequestMethod.GET)
public @ResponseBody String getOrgsViaAjax(@RequestParam("term") String query) {


@RequestMapping(value = "/getOrgsViaAjax")
public @ResponseBody String getOrgsViaAjax(@RequestParam("term") String query) {


@RequestMapping(value = "/getOrgsViaAjax")
public @ResponseBody String getOrgsViaAjax() {

But I can't seem to get anything right.

Firebug makes it clear that when I type anything into the input field (to be autocompleted), it is sending a request, but it always comes back 404 :

在此处输入图片说明

So it's clear that the autocomplete function is firing a request, but it's not mapped to the MVC controller

How do you get the source to match the RequestMapping in Spring MVC?


EDIT:

I'm not sure if this is relevant but I should note that there is a mvc-dispacher-servlet.xml that looks like this:

<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xmlns:mvc="http://www.springframework.org/schema/mvc"   
    xsi:schemaLocation="http://www.springframework.org/schema/beans 
    http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
    http://www.springframework.org/schema/mvc
    http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd">


    <bean name="/SearchPerson.html" 
        class="org.personhub.controller.SearchPersonController" />      

    <bean name="/authenticate.html" 
        class="org.personhub.controller.LogInController" />

    <bean name="/PersonSummary.html"
            class="org.personhub.controller.PersonSummaryController" />

    <bean name="/ManagePerson.html" 
        class="org.personhub.controller.ManagePersonController" />

    <bean name="/PersonNames.html" 
        class="org.personhub.controller.PersonNamesController" />

    <bean name="/PartyAddresses.html" 
        class="org.personhub.controller.PartyAddressesController" />

    <bean name="/PartyIdentifiers.html" 
        class="org.personhub.controller.PartyIdentifiersController" />

    <bean name="/PersonAffiliations.html" 
        class="org.personhub.controller.PersonAffiliationsController" />

    <bean name="/PartyContactMethods.html" 
        class="org.personhub.controller.PartyContactMethodsController" />

    <bean name = "Logout.html"
         class= "org.personhub.controller.LogOutController"> </bean>    

      <!--  <mvc:resources mapping="/resources/**" location="/resources/" /> -->
     <bean id="viewResolver"
        class="org.springframework.web.servlet.view.UrlBasedViewResolver">
        <property name="viewClass">
            <value>
                org.springframework.web.servlet.view.tiles3.TilesView
            </value>
        </property>
    </bean>

    <bean id="tilesConfigurer"  
        class="org.springframework.web.servlet.view.tiles3.TilesConfigurer">  
        <property name="definitions">  
            <list>  
                <value>/WEB-INF/tiles.xml</value>  
            </list>  
        </property>  
    </bean>  


</beans>

Edit:

As requested, here is the web.xml:

<?xml version="1.0" encoding="UTF-8"?>
<web-app id="WebApp_ID" version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
    <display-name>PersonHubWeb</display-name>
    <welcome-file-list>
        <welcome-file>LogIn.jsp</welcome-file>              
    </welcome-file-list>

    <servlet>
        <servlet-name>mvc-dispatcher</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <load-on-startup>1</load-on-startup>
    </servlet>


    <servlet>
        <servlet-name>PersonHubStart</servlet-name>
        <servlet-class>org.personhub.utils.StartUpServlet</servlet-class>
        <load-on-startup>3</load-on-startup>
    </servlet>

    <servlet-mapping>
        <servlet-name>mvc-dispatcher</servlet-name>     
        <url-pattern>*.html</url-pattern>
    </servlet-mapping>      

</web-app>

And just incase, here's the tiles.xml also:

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE tiles-definitions PUBLIC
  "-//Apache Software Foundation//DTD Tiles Configuration 3.0//EN" 
  "http://tiles.apache.org/dtds/tiles-config_3_0.dtd">
<tiles-definitions>
    <definition name="base.definition"
        template="/WEB-INF/pages/BaseLayout.jsp">
        <put-attribute name="title" value="Person Hub UI" />
        <put-attribute name="header" value="/WEB-INF/pages/Baseheader.jsp" />
        <put-attribute name="menu" value="/WEB-INF/pages/BaseMenu.jsp" />
        <put-attribute name="feedback" value="/WEB-INF/pages/BaseFeedback.jsp" />
        <put-attribute name="body" value="" />
        <put-attribute name="footer" value="/WEB-INF/pages/Basefooter.jsp" />
    </definition>


    <definition name="Search" template="/WEB-INF/pages/SearchLayout.jsp">
        <put-attribute name="title" value="Person Hub UI" />
        <put-attribute name="header" value="/WEB-INF/pages/SearchHeader.jsp" />     
        <put-attribute name="body" value="" />
        <put-attribute name="footer" value="/WEB-INF/pages/Basefooter.jsp" />
    </definition>   

    <definition name="PersonSearch" extends="Search">               
        <put-attribute name="body" value="/WEB-INF/pages/SearchPerson.jsp" />
    </definition>

    <definition name="PersonSummary" extends="base.definition">         
        <put-attribute name="body" value="/WEB-INF/pages/PersonSummary.jsp" />
    </definition>

    <definition name="ManagePerson" extends="base.definition">      
        <put-attribute name="body" value="/WEB-INF/pages/ManagePerson.jsp" />
    </definition>

    <definition name="PersonNames" extends="base.definition">       
        <put-attribute name="body" value="/WEB-INF/pages/PersonNames.jsp" />
    </definition>

    <definition name="PersonAffiliations" extends="base.definition">        
        <put-attribute name="body" value="/WEB-INF/pages/PersonAffiliations.jsp" />
    </definition>

    <definition name="PartyContactMethods" extends="base.definition">       
        <put-attribute name="body" value="/WEB-INF/pages/PartyContactMethods.jsp" />
    </definition>

    <definition name="PartyAddresses" extends="base.definition">

        <put-attribute name="body" value="/WEB-INF/pages/PartyAddresses.jsp" />
    </definition>

    <definition name="PartyIdentifiers" extends="base.definition">

        <put-attribute name="body" value="/WEB-INF/pages/PartyIdentifiers.jsp" />
    </definition>

</tiles-definitions>

Looking at set up you provided closely it appears your app is set up one way (web mvc) and you are tying to use it another way (rest web service).

You have to make few changes to make your application restful.

Create a new controller annotated with @RestController

@RestController
@RequestMapping("/personAffiliations")
public class PersonAffiliationsRestController {
   @RequestMapping(value = "/getOrgsViaAjax", method = RequestMethod.GET)
   public @ResponseBody String getOrgsViaAjax(@RequestParam("term") String query) {
     return "{\"Test OrgOne\":\"42695847\",\"Test OrgTwo\":\"84920493\",\"Test OrgThree\":\"22222222\",\"Test OrgFour\":\"42226589\"}";
   }
}

Register the controller in the mvc-dispatcher-servlet.xml

<bean name="/personAffiliations" class="org.personhub.controller.PersonAffiliationsRestController" />

Register a new url mapping for rest web services in web.xml

<servlet-mapping>
    <servlet-name>mvc-dispatcher</servlet-name>     
    <url-pattern>*.html</url-pattern>
    <url-pattern>/rest/*</url-pattern>
</servlet-mapping>  

Change source to use

'${pageContext.request.contextPath}/rest/personAffiliations/getOrgsViaAjax'

You register a servlet with "*.html" then so your servlet dispatcher only *.html suffix requests. That's why your other mapping methods work well. Because you have class level mapping @RequestMapping("/PersonAffiliations.html") and it ends with .html suffix.

But when you use @RequestMapping(value = "/getOrgsViaAjax") then your url become PersonAffiliations.html/getOrgsViaAjax . This doesn't end with *.html pattern. So it occurs 404 error.

Possible Solution

You add .html suffix both spring and autocomplete url as follows:

source : '${pageContext.request.contextPath}/PersonAffiliations.html/getOrgsViaAjax.html'

@RequestMapping(value = "/getOrgsViaAjax.html")
public @ResponseBody String getOrgsViaAjax(@RequestParam("term") String query) {
    ...
}

Change your mapping to @RequestMapping("/PersonAffiliations") .

You are currently requesting to /PersonAffiliations/getOrgsViaAjax instead of /PersonAffiliations.html/getOrgsViaAjax

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM