Web Layer Features

Back

Loading concept...

๐Ÿšช The Web Layer: Your Appโ€™s Front Door

Imagine your Spring Boot application is a fancy hotel. Guests (HTTP requests) arrive at the front entrance, but before they reach their room (your controller), they pass through security, get their luggage handled, and receive directions. Thatโ€™s exactly what the Web Layer does!


๐Ÿ“ฆ File Upload Handling: The Luggage Service

Think of file uploads like guests bringing luggage to a hotel. The bellhop (Springโ€™s MultipartFile) takes it, checks it, and stores it safely.

How It Works

When someone uploads a file to your app, Spring catches it like a baseball glove catches a ball:

@PostMapping("/upload")
public String handleUpload(
    @RequestParam("file")
    MultipartFile file) {

    // Get file name
    String name = file.getOriginalFilename();

    // Get file size
    long size = file.getSize();

    // Save the file
    file.transferTo(new File("/uploads/" + name));

    return "Uploaded: " + name;
}

Setting Limits

You donโ€™t want someone bringing a truck-sized suitcase! Set limits in application.properties:

# Max file size: 10MB
spring.servlet.multipart.max-file-size=10MB

# Max request size: 50MB
spring.servlet.multipart.max-request-size=50MB

Quick Flow

graph TD A["๐Ÿ“ค User Uploads File"] --> B["๐Ÿงณ MultipartFile Catches It"] B --> C{๐Ÿ“ Size OK?} C -->|Yes| D["๐Ÿ’พ Save to Disk/Cloud"] C -->|No| E["โŒ Reject - Too Big!"] D --> F["โœ… Success Response"]

Key Points:

  • MultipartFile = Springโ€™s way to handle uploaded files
  • Always validate file size and type
  • Never trust the filename - sanitize it!

๐Ÿ–ผ๏ธ Static Resources: The Hotelโ€™s Decorations

Static resources are like the paintings, carpets, and furniture in our hotel - they donโ€™t change and are always there. These include CSS files, JavaScript, images, and fonts.

Where Spring Looks

By default, Spring Boot serves static files from these locations:

Location Priority
/META-INF/resources/ 1st
/resources/ 2nd
/static/ 3rd โญ Most common
/public/ 4th

Example Structure

src/main/resources/
โ””โ”€โ”€ static/
    โ”œโ”€โ”€ css/
    โ”‚   โ””โ”€โ”€ style.css
    โ”œโ”€โ”€ js/
    โ”‚   โ””โ”€โ”€ app.js
    โ””โ”€โ”€ images/
        โ””โ”€โ”€ logo.png

Access them directly:

  • http://localhost:8080/css/style.css
  • http://localhost:8080/images/logo.png

Custom Location

Want files from a different folder?

@Configuration
public class WebConfig
    implements WebMvcConfigurer {

    @Override
    public void addResourceHandlers(
        ResourceHandlerRegistry registry) {

        registry.addResourceHandler("/files/**")
            .addResourceLocations("file:/data/files/");
    }
}

Now /files/photo.jpg serves from /data/files/photo.jpg!


๐ŸŒ CORS Configuration: The Guest Pass System

CORS (Cross-Origin Resource Sharing) is like a guest pass system. When your frontend lives at frontend.com but your API lives at api.com, the browser says โ€œWait! Are you allowed to talk to each other?โ€

The Problem

graph LR A["๐Ÿ–ฅ๏ธ frontend.com"] -->|Request| B["๐Ÿ”’ Browser"] B -->|"Is api.com OK?"| C["๐ŸŒ api.com"] C -->|"Yes, allow frontend.com"| B B -->|โœ… Pass Request| C

Solution 1: Per-Controller

@RestController
@CrossOrigin(origins = "http://frontend.com")
public class MyController {

    @GetMapping("/data")
    public String getData() {
        return "Hello from API!";
    }
}

Solution 2: Global Configuration

@Configuration
public class CorsConfig
    implements WebMvcConfigurer {

    @Override
    public void addCorsMappings(
        CorsRegistry registry) {

        registry.addMapping("/api/**")
            .allowedOrigins("http://frontend.com")
            .allowedMethods("GET", "POST", "PUT")
            .allowedHeaders("*")
            .allowCredentials(true)
            .maxAge(3600);
    }
}

What Each Setting Means

Setting Purpose
allowedOrigins Who can talk to us
allowedMethods GET, POST, PUT, DELETE
allowedHeaders Which headers are OK
allowCredentials Allow cookies?
maxAge Cache preflight (seconds)

๐Ÿšฆ Filter vs Interceptor: Security Guards vs Concierge

This is where many developers get confused! Letโ€™s clear it up with our hotel analogy:

Servlet Filter = Security Guard ๐Ÿ›ก๏ธ

The security guard stands at the building entrance. They check EVERYONE - guests, delivery people, even staff. They work at the Servlet level, before Spring even sees the request.

@Component
public class LoggingFilter
    implements Filter {

    @Override
    public void doFilter(
        ServletRequest req,
        ServletResponse res,
        FilterChain chain) throws Exception {

        System.out.println("๐Ÿ‘ฎ Guard: Someone arrived!");

        // Let them through
        chain.doFilter(req, res);

        System.out.println("๐Ÿ‘ฎ Guard: Someone left!");
    }
}

Interceptor = Concierge ๐ŸŽฉ

The concierge stands in the lobby, after security. They only deal with hotel guests (Spring MVC requests). They can see where guests are going and help them along the way.

@Component
public class LoggingInterceptor
    implements HandlerInterceptor {

    @Override
    public boolean preHandle(
        HttpServletRequest req,
        HttpServletResponse res,
        Object handler) {

        System.out.println("๐ŸŽฉ Concierge: Guest heading to "
            + req.getRequestURI());
        return true; // Let them proceed
    }

    @Override
    public void postHandle(...) {
        System.out.println("๐ŸŽฉ Concierge: Guest finished!");
    }
}

The Key Differences

graph TD A["๐Ÿ“จ HTTP Request"] --> B["๐Ÿ›ก๏ธ FILTER"] B --> C["๐ŸŒฑ Spring DispatcherServlet"] C --> D["๐ŸŽฉ INTERCEPTOR"] D --> E["๐ŸŽฏ Controller"] E --> D D --> C C --> B B --> F["๐Ÿ“ค HTTP Response"]
Feature Filter Interceptor
Level Servlet (low) Spring MVC (high)
Access to Request/Response only Handler, ModelAndView
Use for Logging, Encoding, Security Auth, Logging, Timing
Configured in FilterRegistrationBean WebMvcConfigurer

๐Ÿ”ง Servlet Filters: Deep Dive

Filters are the workhorses of request processing. They wrap around your entire application like layers of an onion.

Common Use Cases

  1. Logging - Track all requests
  2. Encoding - Set character encoding
  3. Security - Check tokens/headers
  4. Compression - Gzip responses

Creating a Filter

@Component
@Order(1) // Lower = runs first
public class AuthFilter implements Filter {

    @Override
    public void doFilter(
        ServletRequest request,
        ServletResponse response,
        FilterChain chain) throws Exception {

        HttpServletRequest req =
            (HttpServletRequest) request;

        String token = req.getHeader("Auth-Token");

        if (token == null) {
            HttpServletResponse res =
                (HttpServletResponse) response;
            res.setStatus(401);
            res.getWriter().write("No token!");
            return; // STOP here!
        }

        // Token exists, continue
        chain.doFilter(request, response);
    }
}

Registering with URL Patterns

@Configuration
public class FilterConfig {

    @Bean
    public FilterRegistrationBean<AuthFilter>
        authFilterRegistration() {

        FilterRegistrationBean<AuthFilter> bean =
            new FilterRegistrationBean<>();

        bean.setFilter(new AuthFilter());
        bean.addUrlPatterns("/api/*");
        bean.setOrder(1);

        return bean;
    }
}

Filter Chain Flow

graph TD A["๐Ÿ“จ Request"] --> B["Filter 1: Logging"] B --> C["Filter 2: Encoding"] C --> D["Filter 3: Auth"] D --> E["๐ŸŽฏ Your Controller"] E --> D D --> C C --> B B --> F["๐Ÿ“ค Response"]

Each filter can:

  • Modify the request before passing it on
  • Stop the chain (like auth failure)
  • Modify the response on the way back

๐ŸŽฏ Putting It All Together

Hereโ€™s how all these pieces work in a real Spring Boot app:

graph TD A["๐ŸŒ Browser Request"] --> B["๐Ÿ›ก๏ธ Servlet Filters"] B --> C{๐Ÿ“ Static Resource?} C -->|Yes| D["๐Ÿ–ผ๏ธ Serve File"] C -->|No| E["๐ŸŒฑ DispatcherServlet"] E --> F{๐ŸŒ CORS OK?} F -->|No| G["โŒ CORS Error"] F -->|Yes| H["๐ŸŽฉ Interceptors"] H --> I["๐ŸŽฏ Controller"] I --> J{๐Ÿ“ฆ File Upload?} J -->|Yes| K["๐Ÿ“ค MultipartFile"] J -->|No| L["๐Ÿ“ Regular Handler"]

๐Ÿš€ Quick Summary

Feature What It Does One-Line Example
File Upload Handle uploaded files @RequestParam MultipartFile file
Static Resources Serve CSS/JS/images Put in /static/ folder
CORS Allow cross-origin requests @CrossOrigin(origins="...")
Filter Low-level request processing implements Filter
Interceptor Spring-level request processing implements HandlerInterceptor

๐Ÿ’ก Remember This!

Filters are like security guards - they see everything and work at the door.

Interceptors are like concierges - they work inside Spring and know about your controllers.

CORS is like a guest pass - it says whoโ€™s allowed to talk to your API.

Static resources are like hotel decorations - always there, never changing.

File uploads are like luggage handling - catch, validate, store!

Youโ€™ve now mastered the Web Layer! ๐ŸŽ‰ Your Spring Boot hotel is ready to welcome guests (requests) with proper security, beautiful decorations, and excellent service!

Loading story...

Story - Premium Content

Please sign in to view this story and start learning.

Upgrade to Premium to unlock full access to all stories.

Stay Tuned!

Story is coming soon.

Story Preview

Story - Premium Content

Please sign in to view this concept and start learning.

Upgrade to Premium to unlock full access to all content.