먼저 앞에서 만든 뷰를 가지고 컨트롤러 코드를 만드는데 이때 URL을 어떻게 가져갈지 구상해야합니다.

/base/code/list GET
/base/code/add GET 
/base/code/add POST
/base/code/update?id=23 GET 
/base/code/update?id=23 POST 
/base/code/delete?id=23 GET 
이전에는 이런식으로 썼었습니다. 그런데 이번에는 URL을 REST 스타일로 만들어 보고자 스프링 Roo 레퍼런스에 있는 그림을 참조했습니다.
http://static.springsource.org/spring-roo/reference/html/beginning.html
그래서 이번에는
/base/code/ GET
/base/code/form GET
/base/code POST
/base/code/{id}/form GET
/base/code/{id} PUT
/base/code/{id} DELETE
이런식으로 구성했습니다. 아직 하나 안만든건 view인데 그건 /base/code/{id} GET이 될겁니다. 
아직 익숙하지 않아서 잘 적응되고 있진 않은데 이렇게 만들어 두면 나중에 웹 서비스 별도로 만들 필요없이 저 런 RESTful URL과 스프링 3.0의 컨텐츠 네고 기능을 이용해서 모바일 용 앱을 만들때 한결 편할 것 같습니다.
암튼 이 다음은 스프링 3.0의 @Validation 기능을 적용하는 것인데 이때 하이버 벨리데이터를 의존성에 추가해 줬습니다.
        <!-- Validation -->
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>com.springsource.org.hibernate.validator</artifactId>
            <version>4.0.0.GA</version>
        </dependency>
        <dependency>
            <groupId>javax.xml.bind</groupId>
            <artifactId>com.springsource.javax.xml.bind</artifactId>
            <version>2.1.7</version>
        </dependency>
스프링 웹 설정은 변경한것이 없습니다.
<mvc:annotation-driven />
이게 전부이고 나머진 예외-뷰 설정과 컨텐츠 네고 설정 뿐입니다.
@Controller
@RequestMapping("/base/code/*")
@SessionAttributes("code")
public class CodeController {
    @Autowired CodeService codeService;
    @RequestMapping(value="mgt")
    public void mgt(Model model){
        model.addAttribute("searchParam", new CodeSearchParam());
    }
    @RequestMapping(method = RequestMethod.GET)
    public void list(Model model, CodeSearchParam searchParam, PageParam pageParam) {
        model.addAttribute("codeList", codeService.list(pageParam, searchParam));
    }
    @RequestMapping(value = "form", method = RequestMethod.GET)
    public String addForm(Model model){
        model.addAttribute("code", new Code());
        return "/base/code/new";
    }
    @RequestMapping(method = RequestMethod.POST)
    public String addFormSubmit(Model model, @Valid Code code, BindingResult result, SessionStatus status){
        if(result.hasErrors())
            return "base/code/new";
        status.setComplete();
        codeService.add(code);
        return  "redirect:/base/code/mgt";
    }
    @RequestMapping(value = "{id}/form", method = RequestMethod.GET)
    public String editForm(@PathVariable int id, Model model){
        model.addAttribute("code", codeService.getById(id));
        return "/base/code/edit";
    }
    @RequestMapping(value = "{id}", method = RequestMethod.PUT)
    public String editFormSubmit(Model model, @Valid Code code, BindingResult result, SessionStatus status){
        if(result.hasErrors())
            return "base/code/edit";
        status.setComplete();
        codeService.update(code);
        return  "redirect:/base/code/mgt";
    }
    @RequestMapping(value = "{id}", method = RequestMethod.DELETE)
    public String delete(@PathVariable int id){
        codeService.deleteBy(id);
        return  "redirect:/base/code/mgt";
    }
}
컨트롤러는 이렇게 구현했는데 URL을 클래스 선언부와 메서드 선언부에 분할해서 설정했습니다. 그래야 나중에 상위클래스로 빼서 프레임워크화 할 때 용이하기 때문입니다. 서비스와 DAO 코드는 간단하기 때문에 생략입니다.
참 컨트롤러에서 PUT, DELETE 같은 method를 사용하고 있는데 사실은 화면에서 넘어올땐 걍 POST일 뿐이고 _method라는 히든 파람을 스프링이 읽어서 적절한 애노테이션 핸들러를 찾아주게 되어 있습니다. 히든 파람으로 RESTfult 한 API를 만들기 위해서는 web.xml에 필터를 하나 등록해줘야 합니다.
<filter>
<filter-name>httpMethodFilter</filter-name>
<filter-class>org.springframework.web.filter.HiddenHttpMethodFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>httpMethodFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
자 그럼 오늘은 이만하고 내일은 Code에 새로운 속성들을 추가해 봐야겠습니다. 시간이 남으면 User 도메인 CRUD까지 구현해야겠네요. 그 다음부터는 드뎌 OSAF 3.0 코드가 조금씩 간추려 지겠군요.