• SpringMVC+SpringBoot【理解版】


    目录

    什么是SpringMVC?

    什么是三层架构?

    SpringMVC的执行流程

    SpringMVC怎么样设定重定向和转发的

    SpringMVC如何对时间格式的参数进行格式化

    SpringMVC常用的注解有哪些

    Spring常用的注解

    SpringMVC如何配置拦截器

    一个简单的示例:

    过滤器和拦截器的区别?

    下面是Springboot实现过滤器和拦截器的案例:

    过滤器:

    拦截器示例:

    SpringMVC的Controller是单例还是多例,有没有并发安全问题,如何解决?

    RequestMapping 和 GetMapping有什么区别?

    使用 @RequestMapping:

    使用 @GetMapping:

    Session和cookie有什么区别

    Cookie的执行原理

    Session执行原理

    Session和Cookie的执行原理代码实例

    Cookie 的执行原理示例:

    Session 的执行原理示例:

    PreparedStatement和Statement的区别

    get和post请求的区别

    什么是Restful风格?

    什么是Springboot?

    springboot项目中如何获取配置文件中的内容

    1. 使用 @Value 注解(常用):

    2. 使用 Environment 对象:

    3. 使用 @ConfigurationProperties 注解:

    SpringBoot如何做全局异常的统一处理

    @SpringBootApplication注解的含义

    spring-boot-starter-parent的作用?

    spring-boot-starter-web的作用?

    spring-boot-starter的作用?

    SpringBoot中如何管理事务?


    什么是SpringMVC?

    SpringMVC是一个基于Java的Web框架,在SpringMVC中,应用程序的逻辑被分解成三个主要部分:

    MVC包含了Model模型、View视图、Controller控制层。

    1、模型(Model):用于对程序的业务逻辑和数据进行处理,然后传递给视图进行展示。

    2、视图(View):用于将数据展示给用户。

    3、控制层(Controller):用于接收用户的请求,根据请求的内容调用适当的模型和视图,并将处理结果返回给用户。

     

     

    MVC 架构程序的工作流程:
    (1)用户通过 View 页面向服务端提出请求,可以是表单请求、超链接请求、AJAX 请求等
    (2)服务端 Controller 控制器接收到请求后对请求进行解析,找到相应的 Model 对用户请求进行处理。
    (3)Model 处理后,将处理结果再交给 Controller。
    (4)Controller 在接到处理结果后,根据处理结果传递给 View 页面。页面经渲染(数据填充)后,再发送给客户端。

            假设我们要开发一个简单的图书管理系统,使用 Spring MVC 框架。我们将创建一个简单的示例来说明其中的 Model、View 和 Controller。

            1.Model(模型): 在这个示例中,模型表示图书的数据。我们可以创建一个 Book 类来表示图书对象,包含图书的标题、作者和出版日期等信息。

    1. public class Book {
    2. private String title;
    3. private String author;
    4. private LocalDate publicationDate;
    5. // 构造函数、getter 和 setter 等
    6. }

            2.View(视图): 视图负责展示数据给用户。在这个示例中,我们可以创建一个 JSP 视图来显示图书的信息。

    1. DOCTYPE html>
    2. <html>
    3. <head>
    4. <title>图书详情title>
    5. head>
    6. <body>
    7. <h1>图书详情h1>
    8. <p>标题:${book.title}p>
    9. <p>作者:${book.author}p>
    10. <p>出版日期:${book.publicationDate}p>
    11. body>
    12. html>

            3.Controller(控制器): 控制器处理用户请求,调用适当的模型和视图,并将结果返回给用户。在这个示例中,我们可以创建一个 Spring MVC 控制器来处理图书详情的请求。

    1. @Controller
    2. @RequestMapping("/books")
    3. public class BookController {
    4. @Autowired
    5. private BookService bookService;
    6. @GetMapping("/{id}")
    7. public String getBookDetails(@PathVariable Long id, Model model) {
    8. Book book = bookService.getBookById(id);
    9. model.addAttribute("book", book);
    10. return "bookDetails"; // 返回视图名
    11. }
    12. }

            在上述例子中,BookController是控制器类,使用@RequestingMapping定义了基础请求路径。getBookDetails方法处理/book/{id}请求,通过BookService 获取图书信息,然后将图书数据添加到模型中,最后返回视图名 "bookDetails"。

    综上所述,在这个示例中:

    • 模型是Book类,代表图书数据。
    • 视图是 JSP 视图,用于展示图书信息给用户。
    • 控制器是BookController类,处理用户请求,调用模型和视图,并将数据传递给视图。

    什么是三层架构

    • 表现层(Presentation Layer):用户界面(一是接收前端ajax请求,二是返回json数据给前端)【Controller】

    • 业务逻辑层(Business Logic Layer):接收前端的请求进行逻辑处理,然后与数据库进行交互。

    • 数据访问层(Data Access Layer):对数据库进行操作(针对数据的增添、删除、修改、查找等),并将获得的数据返回到上一层(也就是业务逻辑层)。

    SpringMVC的执行流程

    Springmvc框架的执行步骤
    第一步:用户发起请求到前端控制器(DispatcherServlet)。

    第二步:前端控制器请求处理器映射器查找Handler。

    第三步:处理器映射器向前端控制器返回Handler。

    第四步:前端控制器调用处理器适配器去执行Handler。

    第五步:处理器适配器去执行Handler。
    第六步: Handler执行完成给适配器返回ModelAndView

    第七步:处理器适配器向前端控制器返回ModelAndView(模型和视图),ModelAndView是springmvc框架的一个底层对象,包括Model和View。
    第八步:前端控制器请求视图解析器去进行View视图解析,根据逻辑图名解析成真正的视图(jsp)

    第九步:视图解析器向前端控制器返回View对象。
    第十步∶前端控制器进行视图渲染,向用户响应结果。

    SpringMVC怎么样设定重定向和转发的

            重定向(Redirect)是指从一个页面跳转到另一个页面,是不同的请求,无法共享request中的数据,地址栏会发生改变。它是客户端行为(客户端进行重定向)。

            转发(forward)是指从一个页面跳转到另一个页面,是相同的请求可以共享request中的数据,地址栏不会发生改变,它是服务器行为(在服务器内部进行转发的)

    springmvc默认是使用转发方式跳转的,且会经过视图解析器,我们也可以通过指定跳转方式,转发时在返回值前面加"forward:"关键字重定向时在返回值前面加"redirect:",且此时就不会再经过视图解析器

            重定向的使用方法:

    1. @RequestMapping("/redirectToPage")
    2. public String redirectToPage() {
    3. return "redirect:/newPage"; // 重定向到 /newPage 路径
    4. }

            转发的使用方法:

    1. @RequestMapping("/forwardToPage")
    2. public String forwardToPage() {
    3. return "forward:/anotherPage"; // 转发到 /anotherPage 路径
    4. }

    SpringMVC如何对时间格式的参数进行格式化

    第一种需求,后台接收前台页面返回的string类型时间,要转换成的Date类型数据,可以使用@DateTimeFormat注解来接收参数【后端接收前端String类型时间

     第二种需求,后台将Date类型数据返回给前台页面,默认是返回时间戳,如果想要优雅的格式,可以在模型的Date字段或get方法上使用@JsonFormat注解,记住要导入jackson的相关依赖 【前端接收后端传递的时间

    SpringMVC常用的注解有哪些

    @Controller:用来标识一个类为SpringMVC控制器。

    @RequestMapping:用来映射请求路径和参数。

    @GetMapping、@PostMapping、@PutMapping、@DeleteMapping: 用于指定特定 HTTP 方法的映射。

    @ResponseBody:将方法的返回值转换成json格式返回给调用方

    @RequestBody:接收前端存放在数据包中的请求体中的数据。用对象进行接收。

    @PathVariable:从请求路径中获取参数【user?id=1等】,通常用在restful接口中。

    @RequestParam:从请求参数中获取参数。

    @RestController【复合注解】 = @Controller + @ResponseBody 在Controller层进行使用

    @RestControllerAdvice:运用aop的思想,对全局异常做一些处理,比如结合@ExceptionHandler做全局异常捕获。

    Spring常用的注解

    @Component 及派生注解: 用于标识一个类为 Spring 组件,交由 Spring 容器管理。包括 @Controller、@Service、@Repository 等。

    @Autowired: 自动装配,用于将 Spring 容器中匹配的 Bean 自动注入到字段、方法参数、构造函数中。

    @Resource:自动装配,通过名字进行注入。

    @Qualifier: 结合 @Autowired 使用,指定注入的 Bean 名称,解决多个匹配类型 Bean 的冲突。

    @Configuration: 声明一个类为 Spring 配置类,可以在其中定义 Bean。

    @Bean: 在配置类中使用,将方法的返回值作为 Bean 注册到 Spring 容器。

    @Value: 用于注入属性值,支持从配置文件中读取

    @Transactional: 用于标识事务管理的方法或类,控制事务的提交和回滚。

    @Aspect: 声明一个切面,用于实现面向切面编程(AOP)。

    @Scheduled: 定时任务注解,用于指定方法定时执行。

    SpringMVC如何配置拦截器

    SpringMVC 的拦截器主要用于拦截用户的请求并做相应的处理,通常应用在权限验证、登录验证等功能上

    第1步,定义拦截器:通过自定义类实现 HandlerInterceptor 接口表明当前类是一个拦截器,并加上注解@component交给Spring容器进行管理,并且需要实现接口中的三个方法preHandler方法是在请求到达处理器(就是在去访问springmvc后端controller)之前执行,postHandle方法是在请求经过处理器之后、解析试图之前执行,afterCompletion方法是在视图渲染之后(modelAndView)、返回客户端之前执行。

    第2步,配置拦截器:在springmvc的配置文件xml中(如 dispatcher-servlet.xml),配置需要拦截的路径,配置需要放行的路径。【白名单的直接不会进入拦截器】

    一个简单的示例:

    步骤:

           1. 创建一个类实现 Spring 的 HandlerInterceptor 接口,该接口包含三个方法:preHandle、postHandle 和 afterCompletion。你可以根据需要实现这些方法来执行相应的操作。

            2.在 Spring 的配置文件(如 dispatcher-servlet.xml)中,配置拦截器并指定拦截的路径。

    示例:

    假设我们要创建一个简单的拦截器来记录请求的处理时间。

    1.创建一个拦截器类 ExecutionTimeInterceptor,实现 HandlerInterceptor 接口:

    1. import javax.servlet.http.HttpServletRequest;
    2. import javax.servlet.http.HttpServletResponse;
    3. import org.springframework.web.servlet.HandlerInterceptor;
    4. import org.springframework.web.servlet.ModelAndView;
    5. public class ExecutionTimeInterceptor implements HandlerInterceptor {
    6. private long startTime;
    7. @Override
    8. public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
    9. throws Exception {
    10. startTime = System.currentTimeMillis();
    11. return true;
    12. }
    13. @Override
    14. public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
    15. ModelAndView modelAndView) throws Exception {
    16. long endTime = System.currentTimeMillis();
    17. long executionTime = endTime - startTime;
    18. System.out.println("Request took " + executionTime + " milliseconds");
    19. }
    20. @Override
    21. public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
    22. throws Exception {
    23. // This method is called after the request has been completed
    24. }
    25. }

    2.配置拦截器在 Spring 的配置文件中(如 dispatcher-servlet.xml):

    1. <mvc:interceptors>
    2. <mvc:interceptor>
    3. <mvc:mapping path="/*"/>
    4. <bean class="com.example.ExecutionTimeInterceptor"/>
    5. mvc:interceptor>
    6. mvc:interceptors>

            在这个示例中,我们配置了一个拦截器来拦截所有路径,然后在 postHandle 方法中计算请求的执行时间并进行输出。

    过滤器和拦截器的区别?

    过滤器Filter:

    位置不同:基于Servlet的,在请求到达Servlet前后进行处理,作用于Servlet容器层面。

    功能不同:过滤器常用于请求和响应的处理,如字符编码转换,请求参数处理等;

    如何实现过滤器:实现Filter接口,重写;dofilter方法,在配置文件中web.xml进行配置过滤器,所有请求都会进行过滤:经过逻辑判断是否是登录请求和用户是否登录,才进行放行

    拦截器interceptor

    位置不同:基于SpringMVC(Controller)的,在请求到达Controller前后进行处理,作用于SpringMVC框架层面。

    功能不同:拦截器可常用于进入Controller之前或离开Controller之后执行一些特定的操作,如登录校验,权限验证,日志记录等。

    如何实现拦截器:实现HandlerInteceptor接口,重写三个方法prehandle,posthandle,aftercompletion()方法,在配置文件中配置拦截器,定义黑白名单。

    注:Servlet主要用于接收客户端(浏览器)发送的请求并生成响应。它运行在服务器端,可以处理各种类型的请求,如HTTP请求。

    下面是Springboot实现过滤器和拦截器的案例:

    过滤器:

    1.创建一个类,实现 javax.servlet.Filter 接口,并重写 doFilter 方法来实现过滤逻辑。

    2.使用 @Component 注解将该类标记为 Spring Bean,以便 Spring Boot 自动扫描并管理它。

    3.(可选)在 application.properties 或 application.yml 中配置过滤器的相关属性。

            1.创建一个过滤器类 CustomFilter,实现 javax.servlet.Filter 接口:

    1. import javax.servlet.Filter;
    2. import javax.servlet.FilterChain;
    3. import javax.servlet.FilterConfig;
    4. import javax.servlet.ServletException;
    5. import javax.servlet.ServletRequest;
    6. import javax.servlet.ServletResponse;
    7. import java.io.IOException;
    8. import org.springframework.stereotype.Component;
    9. @Component
    10. public class CustomFilter implements Filter {
    11. @Override
    12. public void init(FilterConfig filterConfig) throws ServletException {
    13. // 初始化方法
    14. }
    15. @Override
    16. public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
    17. throws IOException, ServletException {
    18. // 过滤逻辑
    19. System.out.println("Filter is processing the request...");
    20. // 继续处理请求
    21. chain.doFilter(request, response);
    22. // 在请求处理后执行一些操作
    23. System.out.println("Filter has processed the response...");
    24. }
    25. @Override
    26. public void destroy() {
    27. // 销毁方法
    28. }
    29. }

            2.在 Spring Boot 应用的启动类或配置类中,加上 @ServletComponentScan 注解,以便 Spring Boot 能够扫描到过滤器:

    1. import org.springframework.boot.SpringApplication;
    2. import org.springframework.boot.autoconfigure.SpringBootApplication;
    3. import org.springframework.boot.web.servlet.ServletComponentScan;
    4. @SpringBootApplication
    5. @ServletComponentScan
    6. public class YourSpringBootApplication {
    7. public static void main(String[] args) {
    8. SpringApplication.run(YourSpringBootApplication.class, args);
    9. }
    10. }

            在这个示例中,我们创建了一个名为 CustomFilter 的过滤器,并使用 @Component 注解将其标记为 Spring Bean。然后,在启动类中添加了 @ServletComponentScan 注解,以确保 Spring Boot 能够扫描到过滤器类。

    拦截器示例:

    1.在 Spring Boot 项目中实现一个拦截器非常简单,你只需要遵循以下步骤:

    2.创建一个类,实现 org.springframework.web.servlet.HandlerInterceptor 接口,并重写相应的方法来实现拦截逻辑。

    3.创建一个配置类,实现 org.springframework.web.servlet.config.annotation.WebMvcConfigurer 接口,并在其中注册你的拦截器。

            1.创建一个拦截器类 CustomInterceptor,实现 org.springframework.web.servlet.HandlerInterceptor 接口:

    1. import javax.servlet.http.HttpServletRequest;
    2. import javax.servlet.http.HttpServletResponse;
    3. import org.springframework.stereotype.Component;
    4. import org.springframework.web.servlet.HandlerInterceptor;
    5. import org.springframework.web.servlet.ModelAndView;
    6. @Component
    7. public class CustomInterceptor implements HandlerInterceptor {
    8. @Override
    9. public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
    10. throws Exception {
    11. System.out.println("Interceptor preHandle method is called");
    12. return true; // 返回 true 表示继续处理请求,返回 false 表示中断请求处理
    13. }
    14. @Override
    15. public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
    16. ModelAndView modelAndView) throws Exception {
    17. System.out.println("Interceptor postHandle method is called");
    18. }
    19. @Override
    20. public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
    21. throws Exception {
    22. System.out.println("Interceptor afterCompletion method is called");
    23. }
    24. }

            2.创建一个配置类 WebConfig,实现 WebMvcConfigurer 接口,并在其中注册拦截器:

    1. import org.springframework.context.annotation.Configuration;
    2. import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
    3. import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
    4. @Configuration
    5. public class WebConfig implements WebMvcConfigurer {
    6. @Override
    7. public void addInterceptors(InterceptorRegistry registry) {
    8. registry.addInterceptor(new CustomInterceptor())
    9. .addPathPatterns("/**"); // 拦截所有路径
    10. }
    11. }

            在这个示例中,我们创建了一个名为 CustomInterceptor 的拦截器,并使用 @Component 注解将其标记为 Spring Bean。然后,我们创建了一个配置类 WebConfig,在其中通过实现 WebMvcConfigurer 接口,注册了拦截器并指定拦截的路径。

    SpringMVC的Controller是单例还是多例,有没有并发安全问题,如何解决?

            在Spring中,bean默认都是单例的,controller也是交给spring容器管理的一个bean,因此在SpringMVC中,Controller也是单例的,这样可以提高性能(减少创建对象和垃圾回收的时间)和资源利用率。这就意味着当多个请求同时访问同一个控制器Controller实例,如果控制器中的方法或变量是共享的话,就可能造成并发问题,导致数据不一致问题。

    并发安全问题实例:

            展示了一个控制器中可能存在的共享状态。这个示例中,我们将创建一个简单的计数器,控制器的方法会增加计数器的值,这样多个请求同时访问时可能会导致并发问题。

    1. import org.springframework.stereotype.Controller;
    2. import org.springframework.web.bind.annotation.GetMapping;
    3. import org.springframework.web.bind.annotation.ResponseBody;
    4. @Controller
    5. public class SharedStateController {
    6. private int counter = 0; // 共享状态,可能导致并发问题
    7. @GetMapping("/incrementCounter")
    8. @ResponseBody
    9. public String incrementCounter() {
    10. counter++;
    11. return "Counter value: " + counter;
    12. }
    13. }

            在这个示例中,SharedStateController 控制器类有一个 counter 实例变量,用于存储计数器的值。每次调用 /incrementCounter 路径的请求都会增加计数器的值。由于控制器默认是单例的多个请求可能会同时访问和修改 counter 变量,从而导致并发问题。

    解决这些并发安全问题的方法有:

    1.避免共享状态: 在控制器中避免使用共享状态,尽量保持无状态的设计。如果必须使用共享状态,确保采用线程安全的方式进行访问和修改。

    2.使用局部变量: 在方法内部使用局部变量而不是实例变量,这样可以避免多个请求之间共享数据。

    3.同步机制synchronized: 对于需要共享状态的情况,可以使用同步机制来保证多个线程的安全访问。在方法或代码块中使用 synchronized 关键字来确保一次只有一个线程访问。

    4.使用线程安全的数据结构: 如果需要在控制器中存储一些共享状态,可以使用线程安全的数据结构,如 ConcurrentHashMap,来保证并发访问的安全性。

    5.控制器多例: 如果对并发安全性要求非常高,也可以将控制器配置为多例,这样每个请求都会创建一个新的控制器实例,避免共享状态问题。可以通过在控制器类上添加 @Scope("prototype") 注解来实现。

    下面是每个解决方法的基础代码案例:

    1.避免共享状态:
            避免在控制器中使用共享状态,尽量保持无状态的设计。

    1. @Controller
    2. public class NoSharedStateController {
    3. @GetMapping("/simple")
    4. public String simple() {
    5. // 没有共享状态的操作
    6. return "simple";
    7. }
    8. }

    2.使用局部变量:
            在方法内部使用局部变量而不是实例变量,确保每个线程都有自己的变量。

    1. @Controller
    2. public class LocalVariableController {
    3. @GetMapping("/local")
    4. public String local() {
    5. int localVar = 0; // 局部变量,每个线程都有自己的副本
    6. // 使用 localVar 进行操作
    7. return "local";
    8. }
    9. }

    3.同步机制synchronized:
            使用 synchronized 关键字确保同一时间只有一个线程访问。

    1. @Controller
    2. public class SynchronizedController {
    3. private int sharedCounter = 0;
    4. @GetMapping("/syncIncrement")
    5. public synchronized String syncIncrement() {
    6. sharedCounter++;
    7. return "counter";
    8. }
    9. }

    4.使用线程安全的数据结构:
            使用线程安全的数据结构,如 ConcurrentHashMap。

    1. import org.springframework.stereotype.Controller;
    2. import org.springframework.web.bind.annotation.GetMapping;
    3. import java.util.concurrent.ConcurrentHashMap;
    4. import java.util.concurrent.atomic.AtomicInteger;
    5. @Controller
    6. public class ThreadSafeDataStructureController {
    7. private ConcurrentHashMap counterMap = new ConcurrentHashMap<>();
    8. @GetMapping("/threadSafe")
    9. public String threadSafe() {
    10. String key = "counterKey";
    11. counterMap.putIfAbsent(key, new AtomicInteger(0));
    12. AtomicInteger counter = counterMap.get(key);
    13. counter.incrementAndGet();
    14. return "counter";
    15. }
    16. }

    5.控制器多例:
            将控制器配置为多例,每个请求创建一个新的实例。

    1. import org.springframework.context.annotation.Scope;
    2. import org.springframework.stereotype.Controller;
    3. import org.springframework.web.bind.annotation.GetMapping;
    4. @Controller
    5. @Scope("prototype") //将控制器设置成多例
    6. public class PrototypeController {
    7. private int counter = 0;
    8. @GetMapping("/prototypeIncrement")
    9. public String prototypeIncrement() {
    10. counter++;
    11. return "counter";
    12. }
    13. }

    RequestMapping 和 GetMapping有什么区别?

    @RequestMapping是一个通用的注解,用于接收HTTP请求映射到处理方法。它可以映射不同的HTTP请求(GET、POST、PUT、DELETE、PATCH等);

    而@GetMapping则是@RequestMapping的一个特定用法,专门用来将HTTP的GET请求映射到处理方法;


    使用 @RequestMapping:
    1. import org.springframework.stereotype.Controller;
    2. import org.springframework.web.bind.annotation.RequestMapping;
    3. import org.springframework.web.bind.annotation.ResponseBody;
    4. @Controller
    5. public class RequestMappingExampleController {
    6. @RequestMapping("/hello")
    7. @ResponseBody
    8. public String hello() {
    9. return "Hello, using @RequestMapping!";
    10. }
    11. }

    在这个示例中,/hello 路径的 GET 请求将映射到 hello() 方法。


    使用 @GetMapping:
    1. import org.springframework.stereotype.Controller;
    2. import org.springframework.web.bind.annotation.GetMapping;
    3. import org.springframework.web.bind.annotation.ResponseBody;
    4. @Controller
    5. public class GetMappingExampleController {
    6. @GetMapping("/greeting")
    7. @ResponseBody
    8. public String greeting() {
    9. return "Greetings, using @GetMapping!";
    10. }
    11. }

            在这个示例中,/greeting 路径的 GET 请求将映射到 greeting() 方法,与 @RequestMapping 不同,@GetMapping 只处理 GET 请求。

    Session和cookie有什么区别

    会话:就是客户端和服务端的多次请求和响应的一个过程。

    会话跟踪技术:在一次会话中,不同请求之间共享数据的技术

    突破口:数据保存在那儿。

    Cookie[生命周期-从创建的时候开始计算]--(登录记住我的功能)

    1.数据保存在客户端浏览器会话跟踪技术

    2.数据不太安全

    3.数据大小【单个cookie不超过4k-20个cookie】有限制,并且保存的数据只能是字符串。

    4.cookie可长期保存在客户端。

    注:操作中文要进行编码和解码

    编码:URLEncoder.encode("四川成都","UTF-8")

    解码:URLDecoder.decode(cookie.getValue(),"UTF-8")

    Session【生命周期-从不操作的时候开始计算】(实现登录拦截--整个会话都可以显示用户名)

    1.将数据保存在服务器端会话跟踪技术

    2.数据相对安全,可以存储敏感的数据。

    3.而且数据类型和大小没有限制。

    4.随会话的结束而将存储的数据进行销毁。

    但是如果服务器端保存的数据太多,会影响服务器的性能【所以服务器默认设置了Session的生命周期为30分钟

    拓展:HTTP是无状态的,就是说你这次访问服务器,关闭网页,再访问服务器,服务器是没有意识到又是你来访问。

    那怎样保证将我们保持登录?这就需要使用Cookie技术进行存储用户名和密码。

    说白了,cookie就是存储在浏览器的数据而已。

    Cookie的执行原理

    1.浏览器向服务器发送HTTP的请求。

    2.服务器进行认证成功,就会以set-cookie【例:name:张三,value:1234】的方式将cookie传回给浏览器

    3.浏览器就会将cookie保存起来。

    4.当后续浏览器再次请求服务器的时候,就会自动将cookie传递给服务器。

    5.服务器解析cookie,验证用户信息。

    Session执行原理

    1.当浏览器向服务器发送创建Session的请求的时候。服务器就会创建Session对象,然后为Session对象分配一个 jsessionid,再以Set-Cookie的方式将jsessionid传回给浏览器。

    2.浏览器将 jsessionid 保存起来。

    3.当后续浏览器再次访问服务器时,会自动的将jsessionid以cookie的方式传递给服务器。

    4.服务器就可以根据jsessionid找到session对象,获取session中的数据验证用户信息。

    Session和Cookie的执行原理代码实例

            以下是一个简化的代码示例,演示了 Cookie 和 Session 的执行原理。

    假设有一个简单的 Web 应用,用户在登录页面输入用户名和密码进行登录,然后展示欢迎页面。

    Cookie 的执行原理示例:

    1. import javax.servlet.http.Cookie;
    2. import javax.servlet.http.HttpServletResponse;
    3. @Controller
    4. public class CookieExampleController {
    5. @GetMapping("/loginWithCookie")
    6. public String loginWithCookie(HttpServletResponse response, Model model) {
    7. // 模拟用户登录成功,生成一个 Cookie
    8. Cookie userCookie = new Cookie("user", "john_doe");
    9. userCookie.setMaxAge(60 * 60 * 24); // 设置 Cookie 过期时间为一天
    10. response.addCookie(userCookie);
    11. model.addAttribute("message", "Logged in using Cookie!");
    12. return "welcome";
    13. }
    14. @GetMapping("/welcomeWithCookie")
    15. public String welcomeWithCookie(@CookieValue(name = "user", required = false) String user, Model model) {
    16. if (user != null) {
    17. model.addAttribute("message", "Welcome, " + user + "!");
    18. } else {
    19. model.addAttribute("message", "Please log in first.");
    20. }
    21. return "welcome";
    22. }
    23. }

    Session 的执行原理示例:

    1. import javax.servlet.http.HttpSession;
    2. @Controller
    3. public class SessionExampleController {
    4. @GetMapping("/loginWithSession")
    5. public String loginWithSession(HttpSession session, Model model) {
    6. // 模拟用户登录成功,将用户名存入 Session
    7. session.setAttribute("user", "jane_smith");
    8. model.addAttribute("message", "Logged in using Session!");
    9. return "welcome";
    10. }
    11. @GetMapping("/welcomeWithSession")
    12. public String welcomeWithSession(HttpSession session, Model model) {
    13. String user = (String) session.getAttribute("user");
    14. if (user != null) {
    15. model.addAttribute("message", "Welcome, " + user + "!");
    16. } else {
    17. model.addAttribute("message", "Please log in first.");
    18. }
    19. return "welcome";
    20. }
    21. }

            在这两个示例中,loginWithCookie 和 loginWithSession 方法模拟了用户登录成功后的操作。它们分别在 Cookie 和 Session 中存储用户信息。然后,welcomeWithCookie 和 welcomeWithSession 方法用于展示欢迎页面,从 Cookie 或 Session 中读取用户信息并显示。

    PreparedStatement和Statement的区别

    PreparedStatement接口继承了Statement接口。

    在java中,PreparedStatement和Statement都是用于执行sql查询和修改的接口。

    但也有一些不同之处:

    1.预编译和缓存:

    “Statement”:每次执行SQL查询时,都需要将SQL字符串发送到数据库进行解析和编译,然后再执行。当需要多次执行相同的查询条件时,这样执行效率就比较低。

    “PrepareStatement”:每次执行SQL查询时,SQL查询会被预编译并存储到数据库当中,就避免了每次都去数据库进行解析和编译,大大的提高了执行效率。

    2.sql注入问题:

    “Statement”:执行查询时,将参数值直接拼接到SQL字符串中,可能出现sql注入问题。

    “PrepareStatement”:执行查询时,会预编译使用占位符(例如:“?”)来表示参数,然后通过方法设置参数值,可以防止sql注入问题

    get和post请求的区别

    get请求

    将请求数据在地址栏url进行显示。

    数据不太安全。

    请求数据大小有限制-大约2kb(2048个字符)

    请求数据类型只能是文本字符,不能上传文件

    post请求

    将请求数据存放在请求体request body中。

    数据相对安全。

    请求数据大小没有限制。

    请求数据类型可以是任意类型,图片视频等,可以上传文件

    什么是Restful风格?

    Restful是一种接口编写规范。可以简单理解为:使用url请求地址定位资源用HTTP动词(GET,POST。DELETE。PUT。PATCH)描述请求操作。

    注意:区分一个请求是不是相同的请求:1 请求方式【HTTP动词】+url请求地址。

    什么是Springboot?

    定义:Springboot是一个简化配置(文件)和快速搭建项目的全新框架,目的就是用来简化Spring应用的初始搭建和开发过程

    注意:SpringBoot不是用来替换ssm的,只是用来简化配置、快速搭建和部署的全新框架

    优势:

    简单而言:SpringBoot使编码更简单,使配置更简单,使部署更简单,使监控更简单。

    • 快速启动:SpringBoot内置Web(tomcat)容器快速启动一个web项目main方法启动)不再每次都去等待tomcat启动。

    • 简化配置:Spring Boot提供了一种快速使用Spring的方式,简化xml配置(Mybatis除外-就是Mapper中写sql语句的),使用注解@SpringBootApplication加在主启动类上面提高开发效率

    • 入门容易:SpringBoot继承了原有Spring框架的优秀基因,写代码还是ssm代码

    1. /**
    2. * 课程的启动类
    3. * mapperscan在配置类中已经使用了
    4. * */
    5. //@SpringBootApplication(scanBasePackages = "cn.wmx") // 默认是扫描当前包及其子包,但是如果需要自定义扫描路径,就需要使用scanBasePackages
    6. @SpringBootApplication
    7. @EnableDiscoveryClient// @EnableEurekaClient 和 @EnableDiscoveryClient 的作用都是能够让注册中心发现、并扫描到该服务”
    8. // @EnableEurekaClient只适用于Eureka作为注册中心 @EnableDiscoveryClient 可以是其他注册中心。
    9. @EnableFeignClients // 开启feign接口的扫描
    10. @EnableCaching // 开启SpringCache[基于缓存的注解]
    11. public class CourseStarter {
    12. public static void main(String[] args) {
    13. SpringApplication.run(CourseStarter.class,args);
    14. }
    15. }

    springboot项目中如何获取配置文件中的内容

    在 Spring Boot 项目中,你可以使用 @Value 注解Environment 对象或者 @ConfigurationProperties 注解来获取配置文件中的内容。下面分别介绍这些方法的用法:

    1. 使用 @Value 注解(常用):

    @Value 注解可以用来注入单个属性的值。你可以在需要获取配置值的字段或方法上使用该注解。

    1. @Component
    2. @Data
    3. public class PlayEduConfig {
    4. @Value("${edu.limiter.limit}")
    5. private Long limiterLimit;
    6. }

    application.yml

    1. edu:
    2. core:
    3. testing: false
    4. limiter:
    5. duration: 60
    6. limit: 360

    2. 使用 Environment 对象:

    Environment 对象提供了一种在代码中访问配置属性的方法。

    1. import org.springframework.beans.factory.annotation.Autowired;
    2. import org.springframework.context.EnvironmentAware;
    3. import org.springframework.context.annotation.Configuration;
    4. import org.springframework.core.env.Environment;
    5. @Configuration
    6. public class MyConfiguration implements EnvironmentAware {
    7. private Environment environment;
    8. @Autowired
    9. public void setEnvironment(Environment environment) {
    10. this.environment = environment;
    11. }
    12. public void someMethod() {
    13. String appName = environment.getProperty("edu.limiter.limit");
    14. // ...
    15. }
    16. }

    3. 使用 @ConfigurationProperties 注解:

    @ConfigurationProperties 注解用于将配置属性映射到 Java 类中,然后通过 Spring Boot 自动将配置文件中的值注入到该类的字段中。

    1. import org.springframework.boot.context.properties.ConfigurationProperties;
    2. import org.springframework.stereotype.Component;
    3. @Component
    4. @ConfigurationProperties(prefix = "edu.limiter")
    5. public class MyAppProperties {
    6. private String limit;
    7. private String duration;
    8. // Getter and setters...
    9. // ...
    10. }

    这些方法中,使用 @ConfigurationProperties 注解是一个更强大的选项,特别适用于需要一次性注入多个配置属性的情况。

    SpringBoot如何做全局异常的统一处理

            我们使用了AOP(面向切面编程)的理念,通过自定义异常NotFoundException然后继承Exception。然后自定义一个名为ExceptionController类,类上加上注解@RestControllerAdvice(@ControllerAdvice 和 @ResponseBody 注解的结合,作用是:集中管理全部异常),自定义类中的方法上加上注解@ExceptionHandler(异常类.class-可以捕获的异常类),当@Controller注解下的接口出现异常就会进行匹配@ExceptionHandler(异常类.class)对应的异常类型,然后将错误信息和错误码进行封装返回给前台。这样就避免在Controller层写大量的try catch代码了。

    下面是一个代码举例说明:

    全局异常统一管理:

    1. /**
    2. *全局异常统一处理
    3. * 1.@RestControllerAdvice 的主要作用是集中管理全局异常处理
    4. * 2.@ExceptionHandler 注解标注的方法可以捕获和处理应用程序中抛出的异常
    5. **/
    6. @RestControllerAdvice
    7. @Slf4j
    8. public class ExceptionController {
    9. @ExceptionHandler(NotFoundException.class)
    10. public JsonResponse serviceExceptionHandler(NotFoundException e) {
    11. return JsonResponse.error(e.getMessage(), 404);
    12. }
    13. @ExceptionHandler(LimitException.class)
    14. public JsonResponse serviceExceptionHandler(LimitException e) {
    15. return JsonResponse.error("请稍后再试", 429);
    16. }
    17. }
    1. public class NotFoundException extends Exception {
    2. public NotFoundException() {
    3. super();
    4. }
    5. public NotFoundException(String message) {
    6. super(message);
    7. }
    8. public NotFoundException(String message, Throwable cause) {
    9. super(message, cause);
    10. }
    11. public NotFoundException(Throwable cause) {
    12. super(cause);
    13. }
    14. protected NotFoundException(
    15. String message,
    16. Throwable cause,
    17. boolean enableSuppression,
    18. boolean writableStackTrace) {
    19. super(message, cause, enableSuppression, writableStackTrace);
    20. }
    21. }

    业务代码:

    1. @GetMapping("/{id}")
    2. public JsonResponse edit(@PathVariable Integer id) throws NotFoundException {
    3. AdminUser adminUser = adminUserService.findOrFail(id);
    4. HashMap data = new HashMap<>();
    5. data.put("user", adminUser);
    6. return JsonResponse.data(data);
    7. }
    1. @Override
    2. public AdminUser findOrFail(Integer id) throws NotFoundException {
    3. AdminUser user = getOne(query().getWrapper().eq("id", id));
    4. if (user == null) {
    5. throw new NotFoundException("管理员不存在");
    6. }
    7. return user;
    8. }

    @SpringBootApplication注解的含义

            @SpringBootApplication注解用于标识当前类是SpringBoot的启动类。用于快速启动SpringBoot项目。@SpringBootApplication注解包含了以下三个注解的功能:

    • @ComponentScan注解:开启IOC自动扫描注解,默认扫描当前包及其子包中@Controller,@Service,@Repository,@Component等注解,并把这些bean加载到IOC容器当中。

    • @EnableAutoConfiguration注解:启用springboot自动配置,让SpringBoot根据项目的依赖和配置来自动配置Spring应用。

    • @SpringBootConfiguration注解:表示该类为springboot配置类。

    spring-boot-starter-parent的作用?

            spring-boot-starter-parent是SpringBoot的Maven父项目。

            作用:提供给springboot统一的依赖管理和插件管理和一些常用配置,帮助开发者快速构建和管理SpringBoot项目。

    pom.xml:

    1. <parent>
    2. <groupId>org.springframework.bootgroupId>
    3. <artifactId>spring-boot-starter-parentartifactId>
    4. <version>3.1.1version>
    5. <relativePath/>
    6. parent>

    spring-boot-starter-web的作用?

            作用:内置tomcat(可以快速启动项目)、SpringMVC的集成(快速搭建web层-表现层)、静态资源处理、模板引擎功能。让我们更专注于业务逻辑的开发。

    spring-boot-starter的作用?

            这是Springboot的核心启动器,用于简化和加速SpringBoot项目的开发。

    作用:

    1依赖管理:Starter预定义了一组相关的依赖库,他会自动引入所需的依赖版本。

    2自动配置:Starter包含了默认的配置项,从而减少了手动配置的工作。

    3功能模块:Starter提供了一种按需求进行加载功能的方式,比如web、数据访问、安全等。

    4.约定大于配置:Starter在一定程度上为项目提供了一些默认的约定。
           

    SpringBoot中如何管理事务?

            在Springboot中,可以注解@Transactional来标记需要进行事务管理的方法,从而对数据库数据进行管理。

  • 相关阅读:
    如何将github的项目部署到k8s?
    面试突击86:SpringBoot 事务不回滚?怎么解决?
    【Leetcode】881. Boats to Save People(配数学证明)
    gofly框架接口入参验证使用介绍
    微信小程序里配置less
    PowerPC技术与市场杂谈
    Wireshark TS | 网络路径不一致传输丢包问题
    贪心——122. 买卖股票的最佳时机 II
    Linux的firewalld防火墙学习笔记220929
    【C语言】扫雷小游戏(保姆教程)
  • 原文地址:https://blog.csdn.net/m0_64210833/article/details/126569379