Spring 3 JSON and datatables

Spring 3 JSON and datatables

Don’t you just love JQuery. I’ve been using it with Jquery UI and Datatables.
I played about with some of this stuff (datatables) last year and was impressed with what I’d achieved – fetching tens of thousands of rows of data in a single JSON query – that datatables renders to the screen, makes it fully searchable. Great.
When I originally did this, I used the older style of configuring your Jackson mappers into the view resolver so that you could serve up json out of the request.
After reading about the inbuilt support for JSON in Spring 3, I simplified my spring context. But this meant the data being served back to datatables (which expects your JSON data to be in set format) wasn’t correct. I’ve read a number of blogs and the solution I came up with is a bit of a highbrid.

I don’t have time to outline all this in detail, so I will just post the relevant bits for reference.

Spring Context

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:mvc="http://www.springframework.org/schema/mvc"
    xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd
        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd">
 
    <!-- Scans the classpath of this application for @Components to deploy as beans -->
    <context:component-scan base-package="com.ubyfish.exampl.mvc" />
 
    <!-- Configures the @Controller programming model -->
    <mvc:annotation-driven />
 
    <!-- Forwards requests to the "/" resource to the "welcome" view -->
    <mvc:view-controller path="/" view-name="welcome"/>
 
    <!-- Configures Handler Interceptors --> 
    <mvc:interceptors>
        <!-- Changes the locale when a 'locale' request parameter is sent; e.g. /?locale=de -->
        <bean class="org.springframework.web.servlet.i18n.LocaleChangeInterceptor" />
    </mvc:interceptors>
 
    <!-- Handles HTTP GET requests for /resources/** by efficiently serving up static resources in the ${webappRoot}/resources/ directory -->
    <mvc:resources mapping="/resources/**" location="/resources/" />
 
    <!-- Saves a locale change using a cookie -->
    <bean id="localeResolver" class="org.springframework.web.servlet.i18n.CookieLocaleResolver" />
 
    <!-- Application Message Bundle -->
    <bean id="messageSource" class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
        <property name="basename" value="/WEB-INF/messages/messages" />
        <property name="cacheSeconds" value="0" />
    </bean>
 
    <!-- Resolves view names to protected .jsp resources within the /WEB-INF/views directory -->
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix" value="/WEB-INF/views/"/>
        <property name="suffix" value=".jsp"/>
    </bean>
     
    <import resource="controllers.xml" />
 
</beans>

Controller:


@Controller
@RequestMapping(value="/useradm")
public class UserAdminController {
     
     
    ....
     
    /**
    * Fetch a the user list from the service, and package up into a Map that is 
    * compatible with datatables.net
    */
     
    @RequestMapping(method={RequestMethod.POST,RequestMethod.GET} ,value="/fetchtableall")
    public @ResponseBody Map<String, Object[]> findAllForTableView(){
        try{
            Collection<UserBean> users = iamService.listUsers();  
            if (users == null) {
                throw new UserAdminException("Unable to fetch all users - ");
            }
            return Collections.singletonMap("aaData", getJSONForUser(users));
         
        }catch(ServiceException se){
            throw new UserAdminException("Unable to fetch all users  ");
        }
    }
     
    /**
    * I only want certain user info..
    */
    public Object[] getJSONForUser(Collection<UserBean> users){
        Object[] rdArray = new Object[users.size()];
        int i = 0;
        for(UserBean u:users){
            // [ name, id,arn,groups ]
            Object[] us = new String[]{u.getUser().getUserName(),u.getUser().getArn(),groupList(u.getGroups()),u.getUser().getUserId()}; 
            rdArray[i] = us;
            i++;            
        }
        return rdArray;
    }

The key bit in this controller is the @ResponseBody Map – it allows Spring to do it’s JSON magic. In the older world of wiring up your Jackson Mappers in the spring context, you could happily return a ModelAndView :

returnnewModelAndView("fetchall","aaData", getJSONForUser(users));

JSP

<%@ page session="false" %>
<%@ page language="java" contentType="text/html; charset=utf-8" pageEncoding="utf-8"%>
<%@ taglib uri="http://www.springframework.org/tags/form" prefix="form"%>
<!DOCTYPE html>
<html>
 
<style type="text/css" title="currentStyle">
    @import "resources/styles/redmond/jquery-ui-1.8.20.custom.css";
    @import "resources/styles/demo_page.css"; 
    @import "resources/styles/header.css"; 
    @import "resources/styles/demo_table_jui.css";
    @import "resources/styles/ColReorder.css";
</style>
 
<script type="text/javascript" src="resources/js/jquery-1.7.2.min.js"></script>
<script type="text/javascript" src="resources/js/jquery.dataTables.min.js"></script>
<script type="text/javascript" src="resources/js/ColReorder.min.js"></script>
 
<script type="text/javascript" src="resources/js/jquery-ui-1.8.20.custom.min.js"></script>
<script type="text/javascript">
 
$(document).ready( function () {
    $('#userinfo').dataTable( {
        "bJQueryUI": true,
        "sDom": '<"H"Tfr>t<"F"ip>',
        "sPaginationType": "full_numbers",
        "bProcessing": true,
        "sAjaxSource": 'useradm/fetchtableall.json',
        "aoColumnDefs": [ { "bVisible": false,  "aTargets": [ 1 ] },
                         {
                           "fnRender": function ( oObj,sVal ) {
                             return '<a href="usradm/fetch?' + sVal + '">edit</a>';
                           },
                           "bUseRendered": false,
                           "aTargets": [ 3 ]
                         }
                       ]  } );
} );    
 
 
....
 
<body id="dt_example">
<div id="container">
    <div class="full_width big">
        user administration
    </div>
 
    <div id="demo">
        <table cellpadding="0" cellspacing="0" border="0" class="display" id="userinfo">
        <thead>
            <tr>
                <th>Name</th>
                <th>Arn</th>
                <th>Groups</th>
                <th>Edit</th>
            </tr>
        </thead>
        <tbody>
        </tbody>
        <tfoot>
            <tr>
                <th>Name</th>
                <th>Arn</th>
                <th>Groups</th>
                <th>Edit</th>
            </tr>
        </tfoot>      
         
        </table>
    </div>
</div>



你可能感兴趣的:(Spring 3 JSON and datatables)