添加MyBatis Plus依赖项:在您的pom.xml
文件中添加以下依赖项:
<dependencies>
<dependency>
<groupId>com.baomidougroupId>
<artifactId>mybatis-plus-boot-starterartifactId>
<version>最新版本version>
dependency>
dependencies>
配置数据库连接:在application.properties
或application.yml
文件中添加数据库连接的配置信息,例如:
spring.datasource.url=jdbc:mysql://localhost:3306/mydatabase
spring.datasource.username=root
spring.datasource.password=your_password
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
创建实体类:创建与数据库表对应的实体类。确保使用@TableName
注解标记实体类对应的表名,以便MyBatis Plus能够正确地映射。
import com.baomidou.mybatisplus.annotation.TableName;
@TableName("user")
public class User {
private Long id;
private String name;
private Integer age;
// 其他属性和方法...
}
创建Mapper接口:创建与实体类对应的Mapper接口,并继承BaseMapper
接口。MyBatis Plus将自动为您生成通用的CRUD方法。
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
public interface UserMapper extends BaseMapper<User> {
// 可以添加额外的自定义方法...
}
配置Mapper扫描:在Spring Boot的配置类中,使用@MapperScan
注解指定Mapper接口所在的包,以便自动扫描并注册Mapper Bean。
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.context.annotation.Configuration;
@Configuration
@MapperScan("com.example.mapper")
public class MyBatisConfig {
// 其他配置...
}
使用Mapper接口:在您的服务类或控制器中,通过依赖注入的方式使用Mapper接口,并调用相应的方法进行数据库操作。
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class UserService {
@Autowired
private UserMapper userMapper;
public User getUserById(Long id) {
return userMapper.selectById(id);
}
// 其他方法...
}
添加Redis依赖项:在您的pom.xml
文件中添加以下依赖项:
<dependencies>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-data-redisartifactId>
dependency>
dependencies>
配置Redis连接:在application.properties
或application.yml
文件中添加Redis连接的配置信息,例如:
spring.redis.host=localhost
spring.redis.port=6379
spring.redis.password=your_password
创建Redis配置类:在Spring Boot的配置类中,创建一个RedisConfig
类,并添加@Configuration
和@EnableCaching
注解,@EnableCaching
注解用于启用Spring的缓存支持。
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.annotation.Configuration;
@Configuration
@EnableCaching
public class RedisConfig {
// 其他配置...
}
使用Redis缓存:在您的服务类或控制器中,使用@Cacheable
、@CachePut
等注解来标记需要缓存的方法,@Cacheable
注解表示方法的结果将被缓存起来,@CachePut
注解表示方法的结果将被更新到缓存中。
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
@Service
public class UserService {
@Cacheable(value = "users", key = "#id")
public User getUserById(Long id) {
// 从数据库或其他数据源获取用户信息
return userRepository.findById(id);
}
@CachePut(value = "users", key = "#user.id")
public User saveUser(User user) {
// 保存用户信息到数据库或其他数据源
return userRepository.save(user);
}
// 其他方法...
}
使用RedisTemplate:如果需要更复杂的Redis操作,可以使用RedisTemplate
进行操作,通过redisTemplate
对象调用opsForValue()
方法来执行Redis操作。
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
@Service
public class UserService {
@Autowired
private RedisTemplate<String, Object> redisTemplate;
public void setValue(String key, Object value) {
redisTemplate.opsForValue().set(key, value);
}
public Object getValue(String key) {
return redisTemplate.opsForValue().get(key);
}
// 其他方法...
}
添加AOP依赖项:在您的pom.xml
文件中添加以下依赖项:
<dependencies>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-aopartifactId>
dependency>
dependencies>
创建一个切面类:创建一个类,使用@Aspect
注解来标记它作为切面类。在切面类中,您可以定义各种通知(Before、After、Around等)和切入点表达式。
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Component;
@Aspect
@Component
public class LoggingAspect {
@Before("execution(* com.example.demo.service.*.*(..))")
public void beforeAdvice() {
System.out.println("Before method execution");
}
}
在上面的示例中,创建了一个切面类LoggingAspect
,使用@Before
注解来定义一个前置通知。execution(* com.example.demo.service.*.*(..))
是切入点表达式,表示匹配com.example.demo.service
包中的所有方法。
启用AOP:在Spring Boot的配置类上添加@EnableAspectJAutoProxy
注解来启用AOP。
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
@Configuration
@EnableAspectJAutoProxy
public class AppConfig {
// 其他配置...
}
切入点表达式
execution(modifiers-pattern? ret-type-pattern declaring-type-pattern? name-pattern(param-pattern) throws-pattern?)
其中,各个部分的含义如下:
modifiers-pattern:表示方法的修饰符模式,如public、private、protected等,默认为*匹配任意修饰符。
ret-type-pattern:表示方法的返回类型模式,如void、int、java.lang.String等,默认为*匹配任意返回类型。
declaring-type-pattern:表示方法所在类的全限定名模式,如com.example.demo.service.*表示匹配com.example.demo.service包中的所有类,默认为*匹配任意类。
name-pattern:表示方法名模式,如save*表示匹配以save开头的方法名,默认为*匹配任意方法名。
param-pattern:表示方法参数模式,如(..)表示匹配任意参数列表,(java.lang.String)表示匹配只有一个String类型参数的方法。
throws-pattern:表示方法抛出异常类型模式,如java.lang.Exception表示匹配抛出Exception异常的方法,默认为*匹配任意异常类型。
下面是一些示例使用execution
的切入点表达式:
execution(public * com.example.demo.service.*.*(..)):
匹配com.example.demo.service包中所有公共方法。
execution(* com.example.demo.service.UserService.save*(..)):
匹配com.example.demo.service.UserService类中以save开头的所有方法。
execution(* com.example.demo.service.UserService.*(..)):
匹配com.example.demo.service.UserService类中的所有方法。
execution(* com.example.demo.service.UserService.*()):
匹配com.example.demo.service.UserService类中不带任何参数的方法。
execution(* com.example.demo.service.UserService.*(java.lang.String, ..)):
匹配com.example.demo.service.UserService类中第一个参数为String类型的方法。
execution(* com.example.demo.service.*.*(..) throws java.lang.Exception):
匹配所有抛出Exception异常的方法。
添加CORS依赖项:在您的pom.xml
文件中添加以下依赖项:
<dependencies>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-webartifactId>
dependency>
dependencies>
配置CORS:在Spring Boot的配置类中,添加WebMvcConfigurer
的实现类,并重写addCorsMappings
方法来配置CORS。
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class CorsConfig implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedOrigins("*")
.allowedMethods("GET", "POST", "PUT", "DELETE")
.allowedHeaders("*")
.allowCredentials(true)
.maxAge(3600);
}
}
在上面的示例中,允许所有来源(allowedOrigins("*")
),允许的HTTP方法(allowedMethods("GET", "POST", "PUT", "DELETE")
),允许所有请求头(allowedHeaders("*")
),启用跨域资源共享凭证(allowCredentials(true)
),并设置预检请求的最大缓存时间(maxAge(3600)
)。
使用HttpServletRequest对象:
@Controller
public class MyController {
@RequestMapping("/storeData")
public String storeData(HttpServletRequest request) {
request.setAttribute("myData", "Hello, World!");
return "redirect:/getData";
}
@RequestMapping("/getData")
public String getData(HttpServletRequest request, Model model) {
String data = (String) request.getAttribute("myData");
model.addAttribute("data", data);
return "myPage";
}
}
使用@SessionAttributes注解:
@Controller
@SessionAttributes("myData")
public class MyController {
@RequestMapping("/storeData")
public String storeData(Model model) {
model.addAttribute("myData", "Hello, World!");
return "redirect:/getData";
}
@RequestMapping("/getData")
public String getData(@ModelAttribute("myData") String data, Model model) {
model.addAttribute("data", data);
return "myPage";
}
}
使用HttpSession对象:
@Controller
public class MyController {
@RequestMapping("/storeData")
public String storeData(HttpSession session) {
session.setAttribute("myData", "Hello, World!");
return "redirect:/getData";
}
@RequestMapping("/getData")
public String getData(HttpSession session, Model model) {
String data = (String) session.getAttribute("myData");
model.addAttribute("data", data);
return "myPage";
}
}
使用@ModelAttribute注解:
@Controller
public class MyController {
@ModelAttribute("myData")
public String getMyData() {
return "Hello, World!";
}
@RequestMapping("/getData")
public String getData(@ModelAttribute("myData") String data, Model model) {
model.addAttribute("data", data);
return "myPage";
}
}
使用@SessionScoped注解:
@Component
@SessionScoped
public class MySessionBean implements Serializable {
private String myData;
public String getMyData() {
return myData;
}
public void setMyData(String myData) {
this.myData = myData;
}
}
@Controller
public class MyController {
@Autowired
private MySessionBean sessionBean;
@RequestMapping("/storeData")
public String storeData() {
sessionBean.setMyData("Hello, World!");
return "redirect:/getData";
}
@RequestMapping("/getData")
public String getData(Model model) {
String data = sessionBean.getMyData();
model.addAttribute("data", data);
return "myPage";
}
}
使用数据库或缓存:
@Controller
public class MyController {
@Autowired
private MyDataRepository dataRepository;
@RequestMapping("/storeData")
public String storeData() {
MyData myData = new MyData("Hello, World!");
dataRepository.save(myData);
return "redirect:/getData";
}
@RequestMapping("/getData")
public String getData(Model model) {
MyData myData = dataRepository.getMyData();
model.addAttribute("data", myData.getData());
return "myPage";
}
}
下表对比了上述6种Spring Boot中域对象共享数据的方式的优缺点及使用主义事项。
方式 | 优点 | 缺点 | 使用注意事项 |
---|---|---|---|
HttpServletRequest对象 | - 简单,直接使用Servlet API | - 需要显式地在控制器方法中传递HttpServletRequest对象 - 没有类型安全性 |
- 需要注意数据存储和获取的位置,避免覆盖或错误访问数据 - 需要处理异常情况,如请求未包含数据时的处理 |
@SessionAttributes注解 | - 使用简单,通过注解指定要共享的模型属性 - 数据存储在会话域中,可以在多个请求处理方法中共享 |
- 只能在控制器类级别上共享数据,无法在不同控制器之间共享 - 会话结束后,数据将被清除 - 不适用于非Web环境的应用程序(如REST API) |
- 将需要共享的数据定义为模型属性,并使用@ModelAttribute访问和修改数据 - 需要注意会话的生命周期,避免数据过早清除或过长保留 |
HttpSession对象 | - 使用简单,直接使用HttpSession对象 | - 需要显式地在控制器方法中传递HttpSession对象 - 没有类型安全性 |
- 需要注意数据存储和获取的位置,避免覆盖或错误访问数据 - 需要处理异常情况,如会话过期或不存在时的处理 |
@ModelAttribute注解 | - 使用简单,通过注解定义模型属性,并自动存储和获取数据 | - 只能在同一控制器类中共享数据 - 无法在不同的请求处理方法之间共享数据 |
- 将需要共享的数据定义为模型属性,并使用@ModelAttribute访问和修改数据 - 需要注意模型属性的作用域,避免数据过早清除或过长保留 |
@SessionScoped注解 | - 数据存储在会话级别的Spring Bean中,可以在多个控制器和服务之间共享 | - 需要在会话bean中管理共享数据的状态 - 需要手动创建和配置会话bean |
- 将共享的数据存储在会话bean中,并通过依赖注入在不同的控制器和服务中使用数据 - 需要注意会话bean的生命周期,避免数据过早销毁 |
使用数据库或缓存 | - 数据存储在持久化存储或缓存中,可以在不同的应用程序实例和会话之间共享 | - 需要引入数据库或缓存的依赖 - 需要定义数据模型和访问方法 - 需要处理并发访问和一致性问题 |
- 将共享的数据存储在数据库或缓存中,并通过依赖注入在不同的控制器和服务中使用数据 - 需要注意数据访问的性能和并发访问的安全性 |
创建一个自定义的 ResourceNotFoundException
异常类:
public class ResourceNotFoundException extends RuntimeException {
public ResourceNotFoundException(String message) {
super(message);
}
}
在控制器中抛出该异常
@RestController
public class UserController {
@GetMapping("/users/{id}")
public User getUser(@PathVariable Long id) {
User user = userRepository.findById(id);
if (user == null) {
throw new ResourceNotFoundException("User not found");
}
return user;
}
}
在全局异常处理器中处理 ResourceNotFoundException
异常:
@ControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(ResourceNotFoundException.class)
public ResponseEntity<String> handleResourceNotFoundException(ResourceNotFoundException ex) {
String errorMessage = "资源不存在";
return ResponseEntity.status(HttpStatus.NOT_FOUND).body(errorMessage);
}
@ExceptionHandler(Exception.class)
public ResponseEntity<String> handleException(Exception ex) {
String errorMessage = "发生了一个错误";
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(errorMessage);
}
}
在上面的代码中,在 GlobalExceptionHandler
类中添加了一个新的方法 handleResourceNotFoundException
,用于处理 ResourceNotFoundException
异常。在该方法中,返回了一个自定义的错误信息,并设置了响应的状态码为 404(NOT_FOUND)。
这样,当用户请求一个不存在的用户资源时,将会抛出 ResourceNotFoundException
异常,并由全局异常处理器捕获并处理,返回自定义的错误信息。
注意事项:
创建一个实现 javax.servlet.Filter
接口的自定义过滤器类。
public class CustomFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
// 初始化方法
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
// 在这里编写对请求的处理逻辑
// 继续调用过滤器链
chain.doFilter(request, response);
}
@Override
public void destroy() {
// 销毁方法
}
}
创建一个配置类,并在该类中注册并配置过滤器。
@Configuration
public class FilterConfig {
@Bean
public FilterRegistrationBean<CustomFilter> customFilterRegistration() {
FilterRegistrationBean<CustomFilter> registrationBean = new FilterRegistrationBean<>();
registrationBean.setFilter(new CustomFilter());
registrationBean.addUrlPatterns("/api/*"); // 指定过滤路径
registrationBean.setOrder(1); // 设置过滤器的顺序
return registrationBean;
}
}
在上述示例中,使用 FilterRegistrationBean
注册了 CustomFilter
过滤器,并使用 addUrlPatterns
方法指定了过滤路径为 /api/*
。还使用 setOrder
方法设置了过滤器的顺序为 1,这意味着它将在其他过滤器之前被执行。
在您的 Spring Boot 应用程序的入口类上添加 @ServletComponentScan
注解,以启用对 Filter
的扫描。
@SpringBootApplication
@ServletComponentScan
public class YourApplication {
public static void main(String[] args) {
SpringApplication.run(YourApplication.class, args);
}
}
创建实现 HandlerInterceptor
接口的自定义拦截器类。
public class CustomInterceptor1 implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
// 在请求处理之前执行的逻辑
return true; // 返回 true 表示继续执行后续的拦截器和请求处理方法
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
ModelAndView modelAndView) throws Exception {
// 请求处理之后但未渲染视图时执行的逻辑
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler,
Exception ex) throws Exception {
// 请求处理完成并且视图已渲染之后执行的逻辑
}
}
public class CustomInterceptor2 implements HandlerInterceptor {
// ... 自定义拦截器2的实现代码 ...
}
创建一个配置类,实现 WebMvcConfigurer
接口,并重写 addInterceptors
方法进行拦截器的配置。
@Configuration
public class InterceptorConfig implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new CustomInterceptor1()).addPathPatterns("/api/*"); // 指定拦截路径
registry.addInterceptor(new CustomInterceptor2()).addPathPatterns("/admin/*"); // 指定拦截路径
}
}
在上述示例中,分别创建了 CustomInterceptor1
和 CustomInterceptor2
拦截器,并使用 addPathPatterns
方法分别指定了它们的拦截路径为 /api/*
和 /admin/*
。