Move from serving a file to calculating an answer in Java. The browser sends two numbers after the question mark in the URL.
@RequestParam("a") reads the query parameter named a and converts it to int. The Java variable first receives that number. The same happens for b and second. @ResponseBody sends the returned number directly as response data. No HTML result page or template engine is used in this stage.
Requires JDK 21+ and Maven 3.9+. Extract the ZIP and open a terminal in spring-request-params, where pom.xml is located. First check java -version and mvn -version. Internet is needed for the first dependency download.
Set an available port in src/main/resources/application.properties. The default is 8081. Stop the previous stage with Ctrl+C before starting this one, or choose another port.
mvn spring-boot:run
Open http://localhost:8081/ in your browser. Replace the port if you changed it.
Open /add?a=10&b=20 and expect 30. Try /add?a=7&b=5 and expect 12. A missing or nonnumeric required value produces HTTP 400.
GET /add?a=10&b=20 -> add(10, 20) -> return 30 -> browser displays 30
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>4.1.1</version>
<relativePath/>
</parent>
<groupId>com.edupoly</groupId>
<artifactId>spring-request-params</artifactId>
<version>1.0.0</version>
<properties>
<java.version>21</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webmvc</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
package com.edupoly.hello;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class HelloApplication {
public static void main(String[] args) {
SpringApplication.run(HelloApplication.class, args);
}
}
# Change this number if the port is already in use.
server.port=8081
<!doctype html>
<html lang="en">
<head><meta charset="UTF-8"><title>About Us</title></head>
<body>
<h1>About Us</h1>
<p>This is our first Spring website.</p>
<a href="/">Home</a>
</body>
</html>
<!doctype html>
<html lang="en">
<head><meta charset="UTF-8"><title>Home</title></head>
<body>
<h1>Hello World</h1>
<a href="/aboutus.html">About Us</a>
</body>
</html>
package com.edupoly.hello;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
@Controller
public class PageController {
@GetMapping("/aboutus")
public String aboutUs() {
System.out.println("Someone requested the About Us page");
return "forward:/aboutus.html";
}
}
package com.edupoly.hello;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
@Controller
public class CalculatorController {
@GetMapping("/add")
@ResponseBody
public int add(@RequestParam("a") int first,
@RequestParam("b") int second) {
return first + second;
}
}
Focus: Read numbers from a request and send an answer directly.
| Term | Our concrete example | Its place in Spring |
|---|---|---|
| @RequestParam | a=10 and b=20 become the method arguments first and second. | Spring MVC binds named request parameters to Java method arguments. |
| Type conversion | The URL text "10" becomes a Java int value. | Spring MVC converts request text to the declared argument type. |
| @ResponseBody | The returned sum is sent directly to the browser. | Spring MVC writes the method result into the HTTP response body. |
You should now be able to say: Spring reads the query parameters, calls my Java method and sends its returned answer.
One small check: What changes if a is text such as abc instead of an integer?
These are the next learning steps, not additional projects already implemented in this bundle. Each proposed change gives the new terminology a concrete example.
| Next stage | One useful change | Words to learn when we make that change |
|---|---|---|
| 8. A separate product-file reader | Move the existing file-reading code into ProductFileReader and have Spring supply that object to ProductController through its constructor. Print object creation and request messages to observe reuse. | @Component, dependency, constructor injection, DI, IoC and default singleton scope. |
| 9. Product operations | Add ProductService for rules such as choosing products currently in stock. | @Service, business rule and separation of responsibilities. |
| 10. Product data access | Place file-based reading and lookup behind a product repository. | Repository pattern, @Repository and data access. |
| 11. MongoDB storage | Replace the text-file storage with MongoDB while keeping the page flow familiar. | @Document, ID, MongoRepository, persistence and CRUD. |
| 12. Explicit bean configuration | Supply a helper through a configured factory method and inspect how it is registered. | @Configuration, @Bean, factory method, bean definition and registry. |
Until Stage 8 is implemented, our examples do not demonstrate Spring injecting a separate ProductFileReader into ProductController. The current product controller still reads the file itself. Keep the original getInputStream() and try-with-resources code for that step.