Javadoc is great for scanning all of source files and creating HTML pages to view it. I was wondering if there is a similar tool that would go through all of your Spring controllers and collect all of the methods that have been annotated with @RequestMapping and produce a single HTML page listing them. Sort of like a pseudo site map for developers to ensure uniqueness and standardization across controllers.
I apologize if this question has been asked elsewhere already. I could not come up with an appropriate set of search terms that would provide a useful result.
The @RequestParam annotation is used with @RequestMapping to bind a web request parameter to the parameter of the handler method.
The @RequestMapping annotation can be applied to class-level and/or method-level in a controller. The class-level annotation maps a specific request path or pattern onto a controller. You can then apply additional method-level annotations to make mappings more specific to handler methods.
@RequestMapping is used at the class level while @GetMapping is used to connect the methods. This is also an important Spring MVC interview question to knowing how and when to use both RequestMapping and GetMapping is crucial for Java developers.
@RequestMapping fallback method: We can create a fallback method for the controller class to make sure we are catching all the client requests even though there are no matching handler methods. It is useful in sending custom 404 response pages to users when there are no handler methods for the request.
This is a very good question, I often miss (and implement) functionality like this.
What I'd do is run Maven (or ant) and execute a task after compilation that
But I guess this is a scenario, where annotation processing might also be a way to do it. Usually, you have to use some internal APIs to get stuff done in API, but using Filer.createResource(...)
it should actually possible to do it out of the box.
Here's a rudimentary implementation:
public class RequestMappingProcessor extends AbstractProcessor{
private final Map<String, String> map =
new TreeMap<String, String>();
private Filer filer;
@Override
public Set<String> getSupportedAnnotationTypes(){
return Collections.singleton(RequestMapping.class.getName());
}
@Override
public synchronized void init(
final ProcessingEnvironment processingEnv){
super.init(processingEnv);
filer = processingEnv.getFiler();
}
@Override
public boolean process(
final Set<? extends TypeElement> annotations,
final RoundEnvironment roundEnv){
for(final TypeElement annotatedElement : annotations){
final RequestMapping mapping =
annotatedElement.getAnnotation(
RequestMapping.class
);
if(mapping != null){
addMapping(mapping, annotatedElement, roundEnv);
}
}
assembleSiteMap();
return false;
}
private void assembleSiteMap(){
Writer writer = null;
boolean threw = false;
try{
final FileObject fileObject =
filer.createResource(
StandardLocation.CLASS_OUTPUT,
"html", "siteMap.html"
);
writer = fileObject.openWriter();
writer.append("<body>\n");
for(final Entry<String, String> entry : map.entrySet()){
writer
.append("<a href=\"")
.append(entry.getKey())
.append("\">")
.append("Path: ")
.append(entry.getKey())
.append(", method: ")
.append(entry.getValue())
.append("</a>\n");
}
writer.append("</body>\n");
} catch(final IOException e){
threw = true;
throw new IllegalStateException(e);
} finally{
// with commons/io: IOUtils.closeQuietly(writer)
// with Guava: Closeables.close(writer, rethrow)
// with plain Java this monstrosity:
try{
if(writer != null){
writer.close();
}
} catch(final IOException e){
if(!threw){
throw new IllegalStateException(e);
}
} finally{
}
}
}
private void addMapping(final RequestMapping mapping,
final TypeElement annotatedElement,
final RoundEnvironment roundEnv){
final String[] values = mapping.value();
for(final String value : values){
map.put(
value,
annotatedElement.getQualifiedName().toString()
);
}
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With