2024-09-05

在Spring Boot中,自定义Spring MVC配置通常是通过实现WebMvcConfigurer接口来完成的。然而,如果你想继承一个已有的配置,例如WebMvcConfigurationSupport,那么你需要注意,如果继承了WebMvcConfigurationSupport,则意味着你将取代Spring Boot自动配置的所有Spring MVC特性。

如果你只是想添加一些自定义配置,而不是完全重写,那么实现WebMvcConfigurer接口是更好的选择。

下面是一个实现WebMvcConfigurer接口的简单例子:




import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
 
@Configuration
public class MyWebMvcConfigurer implements WebMvcConfigurer {
 
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        // 添加自定义拦截器
        registry.addInterceptor(...);
    }
 
    // 可以继续添加其他需要的配置方法
}

请注意,在大多数情况下,你不需要直接继承WebMvcConfigurationSupport,除非你需要完全控制Spring MVC的配置。

2024-09-05



import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
 
@RestController
@RequestMapping("/api/items")
public class ItemController {
 
    // 假设这是一个服务组件,用于处理业务逻辑
    @Autowired
    private ItemService itemService;
 
    // 获取所有商品列表(Restful风格的查询所有)
    @GetMapping
    public ResponseEntity<List<Item>> queryAllItems() {
        List<Item> items = itemService.queryAll();
        if (items.isEmpty()) {
            return new ResponseEntity<>(HttpStatus.NO_CONTENT);
        }
        return new ResponseEntity<>(items, HttpStatus.OK);
    }
 
    // 根据关键字查询商品列表(Restful风格的查询)
    @GetMapping("/search")
    public ResponseEntity<List<Item>> searchItemsByKeyword(@RequestParam String keyword) {
        List<Item> items = itemService.searchByKeyword(keyword);
        if (items.isEmpty()) {
            return new ResponseEntity<>(HttpStatus.NO_CONTENT);
        }
        return new ResponseEntity<>(items, HttpStatus.OK);
    }
 
    // 根据ID查询商品详情(Restful风格的查询单个)
    @GetMapping("/{id}")
    public ResponseEntity<Item> queryItemById(@PathVariable("id") Integer id) {
        Item item = itemService.queryById(id);
        if (item == null) {
            return new ResponseEntity<>(HttpStatus.NOT_FOUND);
        }
        return new ResponseEntity<>(item, HttpStatus.OK);
    }
}

这个代码示例展示了如何在Spring MVC中使用@RestController@GetMapping注解来创建支持Restful风格的控制器。它提供了三个基本的Restful操作:获取所有商品列表、根据关键字查询商品列表和根据ID查询商品详情。对于查询操作,它返回了相应的HTTP状态码,如HttpStatus.OKHttpStatus.NO_CONTENT,以表示请求的结果。

2024-09-05

Spring MVC 是一种基于 Java 的实现 MVC 设计模式的轻量级 Web 框架,它是 Spring 的一部分,为开发者提供了一个很好的、灵活的、容易理解的方式来开发 Web 应用程序。

问题:请实现一个简单的 Spring MVC 应用程序,包含一个控制器和一个视图。

解决方案:

  1. 首先,确保你的开发环境已经安装了 Spring Tool Suite (STS) 或者 IntelliJ IDEA 等支持 Spring 的 IDE。
  2. 创建一个新的 Spring Starter 项目,并添加 Web 依赖。
  3. 创建一个简单的控制器类,它将处理传入的 HTTP 请求并返回一个视图名称。
  4. 创建一个简单的视图,例如一个 HTML 页面,并将其放在正确的位置,这样 Spring 可以找到并渲染它。

以下是一个简单的例子:




// 控制器类
@Controller
public class HelloWorldController {
 
    @RequestMapping("/hello")
    public String hello(Model model) {
        model.addAttribute("message", "Hello World!");
        return "hello"; // 返回的视图名称
    }
}



<!-- 视图文件,位于 src/main/resources/templates/hello.html -->
<!DOCTYPE html>
<html>
<head>
    <title>Hello World</title>
</head>
<body>
    <h1>${message}</h1>
</body>
</html>

确保你的 Spring Boot 应用程序的主类上有 @EnableWebMvc 注解,并且你的项目已经配置了 Thymeleaf 或者你使用的其他模板引擎。




// 应用程序主类
@SpringBootApplication
public class HelloWorldApplication {
 
    public static void main(String[] args) {
        SpringApplication.run(HelloWorldApplication.class, args);
    }
}

启动应用程序,并导航到 /hello 路径,你应该能看到 "Hello World!" 消息。

2024-09-05

Spring Boot中的HandlerInterceptor可以用来在控制器方法执行前后进行一些操作,比如权限校验、日志记录等。

以下是一个简单的HandlerInterceptor实现示例:




import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
 
@Component
public class CustomInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
        // 在请求处理之前进行调用(Controller方法调用之前)
        System.out.println("Pre Handle");
        return true; // 如果返回false,则停止流程,api不会被调用
    }
 
    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) {
        // 请求处理之后进行调用,但是在视图被渲染之前(Controller方法调用之后)
        System.out.println("Post Handle");
    }
 
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {
        // 在整个请求结束之后调用,也就是在DispatcherServlet渲染了视图执行
        System.out.println("After Completion");
    }
}

为了让Spring Boot识别并应用这个拦截器,你需要定义一个WebMvcConfigurer并添加这个拦截器:




import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
 
@Configuration
public class WebConfig implements WebMvcConfigurer {
 
    @Autowired
    private CustomInterceptor customInterceptor;
 
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        // 添加拦截器,并设置拦截路径
        registry.addInterceptor(customInterceptor)
                .addPathPatterns("/**"); // 所有路径都被拦截
                //.excludePathPatterns("/login", "/error"); // 排除某些路径
    }
}

这样配置后,每次请求都会经过CustomInterceptor中定义的方法,你可以在preHandle方法中进行权限校验

2024-09-05



import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
 
@Controller
public class HelloWorldController {
 
    // 将此方法映射为处理GET类型请求的方法
    @RequestMapping("/hello")
    @ResponseBody // 表示返回的数据不是视图路径,而是直接返回数据
    public String hello() {
        return "Hello, Spring MVC!";
    }
}

这段代码定义了一个简单的Spring MVC控制器,它处理GET请求并返回一个字符串。@Controller注解表示这是一个控制器组件,@RequestMapping注解指定了请求的路径映射,@ResponseBody注解表示返回的字符串是响应的直接数据而不是视图名称。这个例子展示了Spring MVC的基本用法,非常适合初学者学习和理解。

2024-09-05

这是一个关于Spring MVC注解的全面指南,我们将会介绍最常用的一些注解,包括@Controller@RequestMapping@RequestParam@PathVariable@ModelAttribute@SessionAttributes@RequestBody@ResponseBody




@Controller
@RequestMapping("/books")
public class BookController {
 
    // 假设有一个服务层
    @Autowired
    private BookService bookService;
 
    // 映射GET请求到/books路径
    @RequestMapping(method = RequestMethod.GET)
    public String getBooks(Model model) {
        model.addAttribute("books", bookService.getAllBooks());
        return "books/list"; // 返回books/list.jsp视图
    }
 
    // 映射POST请求到/books/new路径,并接收表单数据
    @RequestMapping(value = "/new", method = RequestMethod.POST)
    public String newBook(@RequestParam("title") String title,
                          @RequestParam("author") String author,
                          RedirectAttributes redirectAttributes) {
        Book book = bookService.createBook(title, author);
        redirectAttributes.addFlashAttribute("message", "Book added successfully!");
        return "redirect:/books";
    }
 
    // 使用路径变量映射GET请求到/books/{id}
    @RequestMapping(value = "/{id}", method = RequestMethod.GET)
    public String getBook(@PathVariable("id") Long id, Model model) {
        model.addAttribute("book", bookService.getBookById(id));
        return "books/details"; // 返回books/details.jsp视图
    }
 
    // 使用@ModelAttribute注解映射请求到模型属性
    @ModelAttribute
    public void populateModel(@RequestParam(value = "id", required = false) Long id, Model model) {
        if (id != null) {
            model.addAttribute("book", bookService.getBookById(id));
        }
    }
 
    // 使用@SessionAttributes管理会话级属性
    @SessionAttributes("message")
 
    // 使用@RequestBody注解处理请求体中的JSON数据
    @RequestMapping(value = "/books", method = RequestMethod.POST)
    public ResponseEntity<?> createBook(@RequestBody Book book) {
        bookService.createBook(book);
        return new ResponseEntity<>("Book created", HttpStatus.CREATED);
    }
 
    // 使用@ResponseBody注解将Java对象转换为JSON响应体
    @RequestMapping(value = "/books/all", method = RequestMethod.GET)
    public @ResponseBody List<Book> getAllBooks() {
        return bookService.getAllBooks();
    }
}

在这个例子中,我们创建了一个简单的图书管理系统的控制器。我们使用了@Controller注解来标识这是一个控制器类,并用@RequestMapping来映射请求路径。我们还演示了如何使用@RequestParam来接收请求参数,@PathVariable来接收路径变量,以及如何使用@ModelAttribute来将请求参数绑定到Java对象。此外,我们还演示了如何使用\`@SessionAttribu

2024-09-05

在Spring MVC中,获取请求参数可以通过以下方式:

  1. 使用@RequestParam注解获取单个请求参数。
  2. 使用@RequestBody注解获取请求体中的数据(通常用于POST请求中的JSON或XML数据)。
  3. 使用HttpServletRequest对象获取所有请求参数。

以下是使用这些方法的示例代码:




import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletRequest;
import java.util.Map;
 
@RestController
@RequestMapping("/api")
public class ParameterController {
 
    // 使用@RequestParam获取单个请求参数
    @GetMapping("/param")
    public String getRequestParam(@RequestParam("param") String param) {
        return "Received param: " + param;
    }
 
    // 使用@RequestBody获取请求体中的JSON数据
    @PostMapping("/data")
    public String getRequestBody(@RequestBody String data) {
        return "Received data: " + data;
    }
 
    // 使用HttpServletRequest获取所有请求参数
    @GetMapping("/allParams")
    public String getAllRequestParams(HttpServletRequest request) {
        Map<String, String[]> params = request.getParameterMap();
        // 处理params...
        return "Received params: " + params.toString();
    }
}

在这个例子中,我们定义了一个控制器ParameterController,它包含了三个处理请求的方法,每个方法展示了一种获取请求参数的方式。

2024-09-05



import org.springframework.core.MethodParameter;
import org.springframework.http.MediaType;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;
 
@ControllerAdvice
public class CustomResponseBodyAdviceAdapter implements ResponseBodyAdvice<Object> {
 
    @Override
    public boolean supports(MethodParameter returnType, Class converterType) {
        return true; // 这里可以根据需要过滤应用此响应处理的方法
    }
 
    @Override
    public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType,
                                  Class selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) {
        // 这里可以对body进行处理,增加额外的信息或修改现有信息
        // 例如,添加一个额外的字段到JSON响应
        if (body instanceof Map) {
            Map<String, Object> map = (Map<String, Object>) body;
            map.put("additionalField", "additionalValue");
        }
        return body; // 返回处理后的body
    }
}

这个代码示例展示了如何实现ResponseBodyAdvice接口,并对响应体进行处理。在beforeBodyWrite方法中,你可以对响应体进行任何必要的修改,例如添加额外的信息或转换数据格式。这种方式对于全局添加响应处理逻辑非常有用,而不需要在每个控制器方法中重复相同的代码。

2024-09-04



import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport;
 
@Configuration
public class WebConfig extends WebMvcConfigurationSupport {
 
    @Override
    protected void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler("/**")
                .addResourceLocations("classpath:/static/")
                .addResourceLocations("classpath:/public/")
                .addResourceLocations("classpath:/resources/");
 
        // 如果你需要添加对其他目录的支持,可以继续添加 .addResourceLocations 方法
        // 例如添加对 /my_static/** 的支持
        // registry.addResourceHandler("/my_static/**")
        //        .addResourceLocations("file:./my_static/");
 
        super.addResourceHandlers(registry);
    }
}

这段代码定义了一个配置类 WebConfig,它扩展了 WebMvcConfigurationSupport 并覆盖了 addResourceHandlers 方法。这个方法用于添加资源处理器,以便 Spring Boot 应用能够正确地处理静态资源。这里使用了三个常用的静态资源目录:classpath:/static/, classpath:/public/classpath:/resources/,并且调用了 super.addResourceHandlers(registry) 以确保其他的资源处理器仍然有效。这样做可以避免使用 WebMvcConfigurationSupport 带来的问题,如 Spring Boot 自动配置失效。

2024-09-04

创建一个基础的Spring Boot项目通常包括以下步骤:

  1. 使用Spring Initializr(https://start.spring.io/)来生成项目骨架。
  2. 配置application.propertiesapplication.yml文件来设置项目属性。
  3. 配置日志记录。
  4. 配置数据库连接。
  5. 配置安全性,如Spring Security。
  6. 配置MVC特性,如视图解析器等。

以下是一些常见配置的示例:

application.properties 示例:




server.port=8080
spring.datasource.url=jdbc:mysql://localhost:3306/mydb
spring.datasource.username=myuser
spring.datasource.password=mypass
spring.jpa.hibernate.ddl-auto=update
logging.level.root=WARN

application.yml 示例:




server:
  port: 8080
spring:
  datasource:
    url: jdbc:mysql://localhost:3306/mydb
    username: myuser
    password: mypass
  jpa:
    hibernate:
      ddl-auto: update
logging:
  level:
    root: WARN

安全配置示例(使用Spring Security):




@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
            .authorizeRequests()
                .antMatchers("/", "/home").permitAll()
                .anyRequest().authenticated()
                .and()
            .formLogin()
                .loginPage("/login")
                .permitAll()
                .and()
            .logout()
                .permitAll();
    }
 
    @Autowired
    public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
        auth
            .inMemoryAuthentication()
                .withUser("user").password("password").roles("USER");
    }
}

MVC配置示例:




@Configuration
public class MvcConfig implements WebMvcConfigurer {
    @Override
    public void addViewControllers(ViewControllerRegistry registry) {
        registry.addViewController("/").setViewName("index");
        registry.addViewController("/hello").setViewName("hello");
        registry.addViewController("/login").setViewName("login");
    }
}

日志配置示例(使用Logback):




<configuration>
    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
        </encoder>
    </appender>
 
    <root level="info">
        <appender-ref ref="STDOUT" />