

Reduce Repetitive Code in Spring MVC Controllers
source link: https://lorenzo-dee.blogspot.com/2020/09/reduce-repetitive-code-in-spring-mvc.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

Reduce Repetitive Code in Spring MVC Controllers
After spending some time doing sustained engineering (a.k.a. maintaining legacy code), I ventured to reduce repetitive code in Spring MVC @Controller
s. I started with an abstract base controller class. But I soon found out that it was a dead-end because @RequestMapping
is not inherited from (or combined with) parent classes and/or interfaces (see Spring MVC @RequestMapping
Inheritance).
With some free time to further think about this, I took different approach.
@Controller
public
class
RepositoryCrudController {
private
final
Repositories repositories;
private
final
RepositoryInvokerFactory repositoryInvokerFactory;
// ...
@RequestMapping
(
"/{repository}"
)
String index(
@PathVariable
(
"repository"
) String repositoryKey,
Pageable pageable, Model model) {
// ... (only if repository has findAll(Pageable) method)
return
repositoryKey +
"/index"
;
}
@GetMapping
(
"/{repository}/{id}"
)
String show(
@PathVariable
(
"repository"
) String repositoryKey,
@PathVariable
(
"id"
) Object id, Model model) {
// ... (only if repository has findById method)
return
repositoryKey +
"/show"
;
}
@GetMapping
(path =
"/{repository}"
, param =
"create"
)
String create(...) {
// ... (only if repository has save method)
return
repositoryKey +
"/create"
;
}
@PostMapping
(
"/{repository}"
)
String save(...) {
// ... (only if repository has save method)
return
"redirect:/"
+ repositoryKey +
"/{id}"
;
}
@GetMapping
(path =
"/{repository}/{id}"
, param =
"edit"
)
// ... edit (only if repository has findById and save methods)
@PutMapping
(
"/{repository}/{id}"
)
// ... update (only if repository has save method)
// @DeleteMapping("/{repository}/{id}")
// ... delete (only if repository has deleteById method)
}
This approach is largely inspired by RepositoryEntityController
of Spring Data REST.
Instead of defining an abstract base controller class, I created a concrete controller class with the default (or repetitive) behavior. The default behavior relies on invoking methods on Spring Data repositories.
For custom controllers, instead of creating subclasses (of the abstract base class), the controller can simply define handler methods that behave differently. For example:
@Entity
public
class
Article {...}
// Spring Data JPA
public
interface
ArticleRepository
extends
CrudRepository<Article, ...> {...}
@Controller
@RequestMapping
(
"/articles"
)
public
class
ArticlesController {
// no need for index() handler method
// just set-up "articles/index" view
// no need for show() handler method
// just set-up "articles/show" view
@GetMapping
(param =
"create"
)
String create(Model model) {
// Do something that is _not_ *default* behavior
// e.g. provide options for dropdowns, or use form-backing object/JavaBean
// ...
return
"articles/create"
;
}
// no need for save() handler method
// just set-up "articles/show" view
@GetMapping
(path =
"/{id}"
, param =
"edit"
)
String edit(
@PathVariable
(
"id"
) ... id, Model model) {
// Do something that is _not_ *default* behavior
// e.g. provide options for dropdowns, or use form-backing object/JavaBean
// ...
return
"articles/edit"
;
}
// no need for update() handler method
// just set-up "articles/show" view
}
The above will work because Spring MVC chooses the more specific mapping first. When a GET /articles?create
request is received, the ArticlesController
will be chosen to handle it (and not RepositoryCrudController
). But if ArticlesController
handler methods were not defined, the GET /articles?create
request would have been handled by the RepositoryCrudController
.
With this simple fall-back controller that has the default behavior, developers (team mates) can then focus on the domain, creating views, or creating controllers with custom behavior (e.g. Ajax, Server-generated JavaScript Responses).
That's all for now.
No comments:
Post a Comment
Recommend
-
50
Spring MVC 温故而知新:从零开始
-
40
经过前面的 AOP (面向切面编程) 和 Transaction (事务管理),这次来到了 MVC (Web 应用,进行请求分发和处理) Spring MVC 定义: 分离了控制器(Controller)、模...
-
62
Spring MVC helps in building flexible and loosely coupled web applications. The Model-view-controller design pattern helps in seperating the business logic, presentation logic, and navigation logic. Models
-
62
MVC这个词儿,最早的定义应该是作为一种软件架构设计模式出现在软工里面的,即使用model、view、controller 来设计及定义web软件的。 Spring MVC 是指Java 当前阶段最大的开源项目Spring 对于MVC 做出了具体的实现,叫做Spring M...
-
55
1 介绍 Spring Web MVC是基于Servlet API构建的原始Web框架。 2 拦截器 2.1 定义 springmvc框架的一种拦截机制 2.2 使用 2.2.1 两步走 实现HandlerInterc...
-
34
摘要 本文旨在详细分析SpringMVC工作原理以及作为开发者如何基于SpringMVC做扩展。因为SpringMVC分析的文章比较多,所以本文重点讲解如何利用SpringMVC的扩展点实现我们的需求。 什么是Spring MVC SpringM...
-
10
java-version.com: What's new in Java 16? 15? Keep up to date! Spring MVC and MongoDB tutorial This tutorial (not...
-
10
I found two interesting presentations of Spring MVC 3 (part of Spring Framework, still in RC phase) Slides and a second presentation in
-
12
MVC Controllers are Dinosaurs - Embrace API Endpoints Date Published: 20 January 2021I've been programming web applications using the MVC pattern for a very long time. What's more, I've been helping companies dig t...
-
5
Simplifying repetitive administrative tasks by using low-code solutions: An overview March 17, 2022March 17, 2022 by Peter van der Woud...
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK