SpringBoot学习

简介: 【10月更文挑战第7天】Spring学习

创建第一个springboot项目

创建一个项目两种方式:

第一种方式:

去springboot官网)选中配置

第二种方式:

SpringBoot运行原理

1. pom.xml

父依赖

其中它主要是以来一个父项目,主要是管理项目的过滤及插件。

点进去,发现还有一个父依赖。

<parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>3.3.4</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>

这里管理了SpringBoot应用中所有依赖版本的地方,SpringBoot版本控制中心。

所以之后在导入依赖的时候,我们就不需要写版本了,但是如果导入的包没有在依赖管理中就需要手动配置版本。

依赖管理中的名称都叫spring-boot-starter-xxx

2. 主启动类

2.1 默认的启动类

package com.study.springboot1;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
//@SpringBootApplication 来标注一个主程序
//说明这是一个Spring Boot应用。
@SpringBootApplication
public class Springboot1Application {
       
    public static void main(String[] args) {
   
        //run()看着是一个方法,实际是启动一个服务
        SpringApplication.run(Springboot1Application.class, args);
    }
}

下面介绍一个这个启动类都做了什么

2.2 @SpringBootApplication

作用:标注在某个类上说明这个类是SpringBoot的主配置类,SpringBoot就应该运行这个类的main方法来启动SpringBoot应用。

进入这个注解可以看到上面还有很多其他注解。

@Target({
   ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(
    excludeFilters = {
   @Filter(
    type = FilterType.CUSTOM,
    classes = {
   TypeExcludeFilter.class}
), @Filter(
    type = FilterType.CUSTOM,
    classes = {
   AutoConfigurationExcludeFilter.class}
)}
)

2.3 @ComponentScan

这个注解我们之前见过,就是扫描包。

作用:自动扫描并加载符合条件的组件或者Bean,讲这个Bean定义加载到IOC容器中。

2.4 @SpringBootConfiguration

作用:SpringBoot的配置类注解,标注在某个类上,表示这是一个SpringBoot的配置类;

继续看这个注释里面有什么:

@Target({
   ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Configuration
@Indexed

这里@Configuration说明这是一个配置类,配置类就是对应的Spring的xml配置文件。

打开@Configuration注释

@Component

这里@Component,说明启动类本身也是Spring的一个组件,负责启动应用

@EnableAutoConfigur

作用:开启自动配置功能

打开这个注解:

@Target({
   ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage
@Import({
   AutoConfigurationImportSelector.class})

首先看到@Import({AutoConfigurationImportSelector.class})给容器导入组件,

@AutoConfigurationPackage自动配置包

Spring Boot-YAML配置注入

1.配置文件:

//丢给spring管理,注册bean容器中
@Component
@Data
@AllArgsConstructor
@NoArgsConstructor
@ToString
/*@ConfigurationProperties作用:
将配置我呢见中配置的每一个属性的值,映射到这个组件中。
告诉SpringBoot江本类中的所有属性和配置文件中相关的配置进行绑定。
参数prefix="dog",将配置文件中的person下面的所有属性一一对应
 */
@ConfigurationProperties(prefix = "dog")
public class Dog {
   
    private String name;
    private int age;
}
@Component//注册bean交给spring托管
@Data
@AllArgsConstructor
@NoArgsConstructor
@ToString
@ConfigurationProperties(prefix = "person")
public class Person {
   
    private String name;
    private Integer age;
    private Boolean happy;
    private Date birthday;
    private Map<String,Object> maps;
    private List<Object> lists;
    private Dog dog;
}
server:
  port: 8081
dog:
  name: 鸡蛋壳
  age: 3
person:
  age: 5
  name: 苏卿
  happy: true
  birthday: 2020/1/4
  maps: {
   1: a,2: b}
  lists: [q,b,c]
  dog: {
    name: d, age: 1 }
@SpringBootTest
class Springboot1ApplicationTests {
   

    @Autowired
    Person person;

    @Test
    void contextLoads() {
   
        System.out.println(person.toString());
    }
}

Spring Boot: Web开发静态资源处理

  1. 使用SpringBoot的步骤

员工管理系统

1. 准备工作

1.1 导入资源

将静态资源导入到resources文件夹里。

1.2 编写pojo实体类

员工表:

@Data
@NoArgsConstructor
public class Employee {
   
    private Integer id;
    private String lastName;
    private String email;
    private Integer gender; //性别 0 女, 1,男
    private Department department;
    private Date birth;

    public Employee(Integer id, String lastName, String email, Integer gender, Department department) {
   
        this.id = id;
        this.lastName = lastName;
        this.email = email;
        this.gender = gender;
        this.department = department;
        this.birth = new Date();
    }
}

部门表:

@Data
@AllArgsConstructor
@NoArgsConstructor
@ToString
public class Department {
   
    private int id;
    private String departmentName;
}

1.3 编写dao层

这里使用模拟数据库,并没有使用mysql数据库。

部门dao

@Repository 用于标注访问层(Dao层)的类。

与@Component注解相同,@Service和@Controller都予以理解为@Component注解的拓展,朱永都是在类上实例化bean,并把这个类交给spring容器进行管理。

@Repository
public class DepartmentDao {
   
    private static Map<Integer, Department> departments = null;
    static {
   
        departments = new HashMap<Integer, Department>();
        departments.put(101,new Department(101,"教学部"));
        departments.put(102,new Department(102,"市场部"));
        departments.put(103,new Department(103,"教研部"));
        departments.put(104,new Department(104,"运营部"));
        departments.put(105,new Department(105,"后勤部"));
    }
    public Collection<Department> findAll() {
   
        return departments.values();
    }
    public Department findById(Integer id) {
   
        return departments.get(id);
    }
}

员工dao

@Repository
public class EmployeeDao {
   
    private static Map<Integer, Employee> employees = null;
    private final DepartmentDao departmentDao;
    static {
   
        employees = new HashMap<Integer,Employee>(); //创建一个部门表

        employees.put(1001,new Employee(  1001,"AA","1622840727@qq.com",1,new Department(101,"教学部")));
        employees.put(1002,new Employee(  1002,"BB","2622840727@qq.com",0,new Department(102,"市场部")));
        employees.put(1003,new Employee(  1003,"CC","4622840727@qq.com",1,new Department(103,"教研部")));
        employees.put(1004,new Employee(  1004,"DD","5628440727@qq.com",0,new Department(104,"运营部")));
        employees.put(1005,new Employee(  1005,"FF","6022840727@qq.com",1,new Department(105,"后勤部")));
    }

    //逐渐自增
    private static Integer initId=1006;

    public EmployeeDao(DepartmentDao departmentDao) {
   
        this.departmentDao = departmentDao;
    }

    //添加一个新员工:
    public void addEmployee(Employee employee) {
   
        if (employee.getId() == null){
   
            employee.setId(initId++);
        }
        employee.setDepartment(departmentDao.findById(employee.getDepartment().getId()));
        employees.put(employee.getId(), employee);
    }
    //查询全部员工
    public Collection<Employee> getAllEmployees() {
   
        return employees.values();
    }
    //通过ID查询员工
    public Employee getEmployeeById(Integer id) {
   
        return employees.get(id);
    }
    //删除员工
    public void deleteEmployee(Integer id) {
   
        employees.remove(id);
    }
}

2. 首页实现:

2.1 引入Thymeleaf依赖

<dependency>
    <groupId>org.thymeleaf</groupId>
    <artifactId>thymeleaf-spring5</artifactId>
</dependency>
<dependency>
    <groupId>org.thymeleaf.extras</groupId>
    <artifactId>thymeleaf-extras-java8time</artifactId>
</dependency>

2.2 编写MyMVCConfig

@Configuration作用取代bean.xml配置文件注册bean对象

@Configuration
public class MyMVCConfig implements WebMvcConfigurer {
   
    @Override
    public void addViewControllers(ViewControllerRegistry registry) {
   
        registry.addViewController("/").setViewName("index");
        registry.addViewController("/index.html").setViewName("index");
        registry.addViewController("/main.html").setViewName("dashboard");
        registry.addViewController("/main").setViewName("dashboard");    
    }
}

这个可以对应理解为,在javaweb+jap中可以理解为servler-mapping映射成"/"

<!-- web.xml -->
<servlet>
    <servlet-name>indexServlet</servlet-name>
    <servlet-class>com.example.IndexServlet</servlet-class>
</servlet>
<servlet-mapping>
    <servlet-name>indexServlet</servlet-name>
    <url-pattern>/</url-pattern>
</servlet-mapping>
// IndexServlet.java
@WebServlet("/")
public class IndexServlet extends HttpServlet {
   
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
   
        request.getRequestDispatcher("/index.jsp").forward(request, response);
    }
}

在javamvc中可以理解成:使用@Controller注解定义一个控制器,并使用@RequestMapping注解来映射URL。

// IndexController.java
@Controller
public class IndexController {
   
    @RequestMapping("/")
    public String index() {
   
        return "index"; // 返回视图名称,对应于 /WEB-INF/views/index.jsp
    }
}

更改静态资源路径:

将所有静态资源都交给thymeleaf接管。@{}

例如:链接css文件时:<link th:href="@{/css/bootstrap.min.css}" rel="style,用@{}括起来。并在href前面加上th:

<head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
        <meta name="description" content="">
        <meta name="author" content="">
        <title>Signin Template for Bootstrap</title>
        <!-- Bootstrap core CSS -->
        <link th:href="@{/css/bootstrap.min.css}" rel="stylesheet">
        <!-- Custom styles for this template -->
        <link th:href="@{/css/signin.css}" rel="stylesheet">
    </head>

3. 页面国际化

首先需要将IDEA中的配置全部改成UTF-8

  1. resources资源文件下新建一个i18n目录,用于存放国际化配置文件。

  2. 创建login.properties文件,login_zh_CN.properties中文文件,login_en_US.rpoperties英文文件。然后会发现文件夹变了。

  3. 然后需要安装Resource Budle Editor这个插件,才能更快更清晰的配置。当然不安装也可以。安装后是下面这个样子。点击资源包,就可以同时配三个,默认-英语-中文。

    当然不安装也可以直接设置:三个文件中都这样对应着设置即可。

配置生效:

我们需要在springboot配置文件中关联到这个文件,

application.properties文件中加入:

spring.messages.basename=i18n.login

然后我们还需要对Spring,中的l在来自于前端点击配置的

<a class="btn btn-sm" th:href="@{/index.html(l='zh_CN')}">中文</a>
<a class="btn btn-sm" th:href="@{/index.html(l='en_US')}">English</a>

然后就是解析请求:

public class MyLocaleResolver implements LocaleResolver {
   
    //解析请求
    @Override
    public Locale resolveLocale(HttpServletRequest request) {
   
        // 获取请求中的语言参数
        String language = request.getParameter("l");
        Locale locale = Locale.getDefault();//如果没有就用默认的
        //如果请求的链接携带了国际化的参数
        if (!StringUtil.isNullOrEmpty(language)) {
   
            String[] s = language.split("_");//分割
            locale = new Locale(s[0], s[1]);
        }
        return locale;
    }
    @Override
    public void setLocale(HttpServletRequest request, HttpServletResponse response, Locale locale) {
   
    }
}

然后不要忘了将其配置到spring文件(MyMVCConfig.java)中:

//自定义的国际化
@Bean
public LocaleResolver localeResolver() {
   
    return new MyLocaleResolver();
}

4. 登录+拦截器

4.1 登录

禁用模板缓存

#禁用模板缓存 
spring.thymeleaf.cache=false
  1. 首先肯定要先将表单中添加一个提交事件

    <form class="form-signin" th:action="@{/user/login}">
       ……
    </form>
    
  2. 编写对应的Controller

    这里面的username和password对应着下面中的name标签提交都是携带name标签

    <input type="text" name="username" class="form-control" th:placeholder="#{login.username}" required="" autofocus="">
    <input type="password" name="password" class="form-control" th:placeholder="#{login.password}" required="">
    
    @Controller
    public class LoginController {
         
    
     @RequestMapping("/user/login")
     public String login(@RequestParam("username") String username,
                         @RequestParam("password") String password,
                         Model model, HttpSession session) {
         
         //具体的业务:
         if (!StringUtil.isNullOrEmpty(username)&&"123456".equals(password)) {
         
             session.setAttribute("loginUser", username);
             return "redirect:/main";
         }else {
         
             model.addAttribute("msg", "用户名错误或者密码错误");
             return "index";
        }
     }
    }
    
  3. 登录失败,将信息传送给前端。

    <p style="color: red" th:text="${msg}" th:if="${not #strings.isEmpty(msg)}"></p>优化
    
  4. 优化,登陆后链接变化,使其重定向到首页

    添加一个视图控制映射,加在自己的MyMVCConfig里面。

  5. 将Controller的代码改为重定向,就是这里,已经改过了。

    if (!StringUtil.isNullOrEmpty(username)&&"123456".equals(password)) {
         
             session.setAttribute("loginUser", username);
             return "redirect:/main";
         }else {
         
             model.addAttribute("msg", "用户名错误或者密码错误");
             return "index";
        }
    

4.2 登录拦截器

设置完上面,会发现一个问题:我们不登录,也可以直接访问到后台主页面,这是不允许的。所以我们添加拦截器。对没有登录的进行拦截。

  1. 在LoginController中添加Session.上面也已经写了。

    session.setAttribute("loginUser", username);
    
  2. 自定义个一个拦截器:

    public class LoginHandlerInterceptor implements HandlerInterceptor {
         
     @Override
     public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
         
         //登陆成功之后,应该有用户的session
         Object loginUser = request.getSession().getAttribute("loginUser");
         if (loginUser == null) {
         
             request.setAttribute("msg","没有权限,请先登录");
             request.getRequestDispatcher("/index.html").forward(request, response);
             return false;
         }else {
         
             return true;
         }
     }
    }
    
  3. 然后将拦截器配置到我们自己的SpringMVC配置类中(MyMVCConfig).

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
         
     registry.addInterceptor(new LoginHandlerInterceptor()).addPathPatterns("/**").excludePathPatterns("/index.html","/", "/user/login","/css/**","/js/**","/img/**");
    }
    
  4. 然后我们可以在后台获取用户登录的信息,这里我们选择只传递用户名

    [[${session.loginUser}]]
    

5. 展示员工列表。

设置跳转:编写前端,

<a th:class="${active=='list.html'?'nav-link active':'nav-link'}" th:href="@{/emps}">员工管理</a>

编写Controller层对应的th:href="@{/emps}"请求。

th:class="${active=='list.html'?'nav-link active':'nav-link'}"这个是在判断是否点击这个,如果点击这个显示蓝色,负责就正常颜色。为了凸显出我们在那个界面

@Controller
public class EmployeeController {
   
    @Autowired
    EmployeeDao employeeDao;
    @Autowired
    DepartmentDao departmentDao;
    @RequestMapping("/emps")
    public String lise(Model model) {
   
        Collection<Employee> employees = employeeDao.getAllEmployees();
        model.addAttribute("emps", employees);
        return "emp/list";
    }
}

公共元素抽离

我们看,每一个界面都有左边和上面这些公共元素,那么我们可以将其提取出来,封装一下,再拿来用时,直接插入或者替换即可。

例如我们将头部标签拿出来。

<!--顶部导航栏-->
<nav class="navbar navbar-dark sticky-top bg-dark flex-md-nowrap p-0" th:fragment="topbar">
    <a class="navbar-brand col-sm-3 col-md-2 mr-0" href="http://getbootstrap.com/docs/4.0/examples/dashboard/#">[[${session.loginUser}]]</a> <!--$取EL表达式-->
    <input class="form-control form-control-dark w-100" type="text" placeholder="Search" aria-label="Search">
    <ul class="navbar-nav px-3">
        <li class="nav-item text-nowrap">
            <a class="nav-link" href="http://getbootstrap.com/docs/4.0/examples/dashboard/#">注销</a>
        </li>
    </ul>
</nav>

然后我们在list页面引入,引入后就可以删除之前的了

<!--引入抽取的topbar--> 
<!--模板名 : 会使用thymeleaf的前后缀配置规则进行解析 使用~{模板::标签名}-->
<!--顶部导航栏-->
<div th:replace="~{commons/commons::topbar}"></div>

th:insert="~{commons/commons::topbar}"
首先th:insert表示要插入:

然后"~{}"这个是插入的表达式。
里面commons/commons,这个是公共元素在那个页面

topbar这个是要插入那个块。
插入块那边用th:fragment="topbar"来标记。

5.3 员工信息页面展示:

<thead>
    <tr>
        <th>id</th>
        <th>lastName</th>
        <th>email</th>
        <th>gender</th>
        <th>department</th>
        <th>birth</th>
        <th>操作</th>
    </tr>
</thead>
<tbody>
    <tr th:each="emp:${emps}">
        <td th:text="${emp.getEmail()}"></td>
        <td th:text="${emp.getId()}"></td>
        <td th:text="${emp.getLastName()}"></td>
        <td th:text="${emp.getGender()==0?'':''}"></td>
        <td th:text="${emp.department.getDepartmentName()}"></td>
        <td th:text="${#dates.format(emp.getBirth(), 'yyyy-MM-dd HH:mm:ss')}"></td>
        <td>
            <a class="btn btn-sm btn-primary" th:href="@{/emp/} + ${emp.getId()}">编辑</a>
            <a class="btn btn-sm btn-danger" th:href="@{/removeEmp/} + ${emp.getId()}">删除</a>
        </td>
    </tr>
</tbody>

6. 添加员工

前端表单

<h2><a class="btn btn-sm btn-success" th:href="@{/emp}">添加员工</a></h2>

编写对应的Controller

@GetMapping("/emp")
    public String add(Model model) {
   
        //查出所有部门的信息
        Collection<Department> departments = departmentDao.findAll();
        model.addAttribute("departments", departments);
        return "emp/add";
    }

添加前端页面

<div class="container-fluid">
    <div class="row">
    <!-- 侧边栏-->
    <div th:replace="~{commons/commons::sidebar(active='list.html')}"></div>
    <main role="main" class="col-md-9 ml-sm-auto col-lg-10 pt-3 px-4">
        <form th:action="@{/emp}" method="post">
            <div class="form-group">
                <label>姓名</label>
                <input name="lastName" type="text" class="form-control"  placeholder="姓名">
            </div>
            <div class="form-group">
                <label>Email</label>
                <input name="email" type="email" class="form-control" placeholder="Email">
            </div>
            <div class="form-group">
                <label>性别</label><br/>
                <div class="form-check form-check-inline">
                    <input name="gander" type="radio" class="form-check-input" value="1">
                    <label class="form-check-label"></label>
                </div>
                <div class="form-check form-check-inline">
                    <input name="gander" type="radio" class="form-check-input" value="0">
                    <label class="form-check-label"></label>
                </div>
            </div>
            <div class="form-group">
                <label>所属部门</label>
                <select class="form-control" name="department.id">
                    <option th:each="dept:${departments}" th:text="${dept.getDepartmentName()}" th:value="${dept.getId()}"></option>
                </select>
            </div>
            <div class="form-group">
                <label>生日</label>
                <input name="birth" type="text" class="form-control" placeholder="1975/01/01">
            </div>
            <button type="submit" class="btn btn-default">添加</button>
        </form>
    </main>
    </div>
</div>

编写Controller层

注意这里都是"/emp"但是一个是get,一个是post请求,是不同的。然后下面就是获取前端传过来的数据然后对模拟数据库进行操作,操作完,重定向到查询全部网站。

@PostMapping("/emp")
    public String addEmp(Employee employee,Model model) {
   
        employeeDao.addEmployee(employee);
        return "redirect:/emps";
    }

这是在前端中显示部门名称,而不是id,1,2,3,4,5这样用户不知道具体指代什么。

<select class="form-control" name="department.id">
    <option th:each="dept:${departments}" th:text="${dept.getDepartmentName()}" th:value="${dept.getId()}"></option>
</select>

修改时间格式:在application.properies中配置。从之前默认的的yyyy/MM/dd

spring.mvc.date-format=yyyy-MM-dd

修改员工信息

逻辑分析:

  • 点击修改按钮应该先跳转到修改页面,

  • 进入修改页面,原数据要显示在上面。修改完毕要返回列表页面。

  1. 前端设置跳转位置:
<a class="btn btn-sm btn-primary" th:href="@{/emp/} + ${emp.getId()}">编辑</a>
  1. 写Controller,在这里面,我们要通过id查到原数据,然后将原数据返回到修改页面,查部门消息是因为我们之后编辑部门时,能够显示出具体是什么部门,而不是单纯的id/

    // 去员工修改页面
     @GetMapping("/emp/{id}")
     public String toUpData(@PathVariable("id") Integer id, Model model){
         
         //查出原本数据
         Employee employee = employeeDao.getEmployeeById(id);
         model.addAttribute("emp", employee);
         //查所有的部门信息
         Collection<Department> departments = departmentDao.findAll();
         model.addAttribute("departments", departments);
         return "emp/update";
     }
    
  2. 编写修改页面。

    <div class="container-fluid">
             <div class="row">
                 <!-- 侧边栏-->
                 <div th:replace="~{commons/commons::sidebar(active='list.html')}"></div>
    
                 <main role="main" class="col-md-9 ml-sm-auto col-lg-10 pt-3 px-4">
                     <form th:action="@{/emp/update}" method="post">
                         <input type="hidden" name="id" th:value="${emp.getId()}">
                         <div class="form-group">
                             <label>姓名</label>
                             <input th:value="${emp.getLastName()}" name="lastName" type="text" class="form-control"  placeholder="姓名">
                         </div>
                         <div class="form-group">
                             <label>Email</label>
                             <input th:value="${emp.getEmail()}" name="email" type="email" class="form-control" placeholder="Email">
                         </div>
                         <div class="form-group">
                             <label>性别</label><br/>
                             <div class="form-check form-check-inline">
                                 <input th:checked="${emp.getGender()==1}" name="gander" type="radio" class="form-check-input" value="1">
                                 <label class="form-check-label"></label>
                             </div>
                             <div class="form-check form-check-inline">
                                 <input th:checked="${emp.getGender()==0}" name="gander" type="radio" class="form-check-input" value="0">
                                 <label class="form-check-label"></label>
                             </div>
                         </div>
                         <div class="form-group">
                             <label>所属部门</label>
                             <select class="form-control" name="department.id">
                                 <option th:selected="${dept.getId()==emp.getDepartment().getId()}" th:each="dept:${departments}" th:text="${dept.getDepartmentName()}" th:value="${dept.getId()}"></option>
                             </select>
                         </div>
                         <div class="form-group">
                             <label>生日</label>
                             <input th:value="${#dates.format(emp.getBirth(), 'yyyy/MM/dd HH:mm')}" name="birth" type="text" class="form-control" placeholder="1975-01-01">
                         </div>
                         <button type="submit" class="btn btn-default">修改</button>
                     </form>
                 </main>
             </div>
         </div>
    
  3. 编写修改的Controller

    @PostMapping("/emp/update")
     public String updateEmp(Employee employee,Model model){
         
         employeeDao.addEmployee(employee);
         return "redirect:/emps";
     }
    

删除员工

  1. list页面,提交地址:

    <a class="btn btn-sm btn-danger" th:href="@{/removeEmp/} + ${emp.getId()}">删除</a>
    
  2. 编写Controller

    //删除
     @RequestMapping("/removeEmp/{id}")
     public String delete(@PathVariable("id") Integer id, Model model) {
         
         employeeDao.deleteEmployee(id);
         return "redirect:/emps";
     }
    

404及注销

我们只需要命名为404.htmlspringboot就会自动帮我们使用了。

注销

  1. 注销请求地址

    <a class="nav-link" th:href="@{/user/logout}">注销</a>
    
  2. 对应的Controller,这里去除session也行,直接invalidate也行

    @RequestMapping("/user/logout")
     public String logout(HttpSession session) {
         
         session.removeAttribute("loginUser");
         //session.invalidate();
         return "redirect:/index.html";
     }
    

整合JDBC

目录
相关文章
|
9天前
|
前端开发 Java 开发者
Spring生态学习路径与源码深度探讨
【11月更文挑战第13天】Spring框架作为Java企业级开发中的核心框架,其丰富的生态系统和强大的功能吸引了无数开发者的关注。学习Spring生态不仅仅是掌握Spring Framework本身,更需要深入理解其周边组件和工具,以及源码的底层实现逻辑。本文将从Spring生态的学习路径入手,详细探讨如何系统地学习Spring,并深入解析各个重点的底层实现逻辑。
34 9
|
30天前
|
XML Java 数据格式
Spring学习
【10月更文挑战第6天】Spring学习
19 1
|
1月前
|
Java 测试技术 开发者
springboot学习四:Spring Boot profile多环境配置、devtools热部署
这篇文章主要介绍了如何在Spring Boot中进行多环境配置以及如何整合DevTools实现热部署,以提高开发效率。
56 2
|
1月前
|
前端开发 Java 程序员
springboot 学习十五:Spring Boot 优雅的集成Swagger2、Knife4j
这篇文章是关于如何在Spring Boot项目中集成Swagger2和Knife4j来生成和美化API接口文档的详细教程。
84 1
|
1月前
|
Java API Spring
springboot学习七:Spring Boot2.x 拦截器基础入门&实战项目场景实现
这篇文章是关于Spring Boot 2.x中拦截器的入门教程和实战项目场景实现的详细指南。
25 0
springboot学习七:Spring Boot2.x 拦截器基础入门&实战项目场景实现
|
1月前
|
Java API Spring
springboot学习六:Spring Boot2.x 过滤器基础入门&实战项目场景实现
这篇文章是关于Spring Boot 2.x中过滤器的基础知识和实战项目应用的教程。
23 0
springboot学习六:Spring Boot2.x 过滤器基础入门&实战项目场景实现
|
1月前
|
Java 关系型数据库 MySQL
springboot学习五:springboot整合Mybatis 连接 mysql数据库
这篇文章是关于如何使用Spring Boot整合MyBatis来连接MySQL数据库,并进行基本的增删改查操作的教程。
64 0
springboot学习五:springboot整合Mybatis 连接 mysql数据库
|
1月前
|
Java 关系型数据库 MySQL
springboot学习四:springboot链接mysql数据库,使用JdbcTemplate 操作mysql
这篇文章是关于如何使用Spring Boot框架通过JdbcTemplate操作MySQL数据库的教程。
24 0
springboot学习四:springboot链接mysql数据库,使用JdbcTemplate 操作mysql
|
1月前
|
Java 测试技术 Spring
springboot学习三:Spring Boot 配置文件语法、静态工具类读取配置文件、静态工具类读取配置文件
这篇文章介绍了Spring Boot中配置文件的语法、如何读取配置文件以及如何通过静态工具类读取配置文件。
46 0
springboot学习三:Spring Boot 配置文件语法、静态工具类读取配置文件、静态工具类读取配置文件
|
1月前
|
Java Maven Spring
springboot学习一:idea社区版本创建springboot项目的三种方式(第三种为主)
这篇文章介绍了在IntelliJ IDEA社区版中创建Spring Boot项目的三种方法,特别强调了第三种方法的详细步骤。
274 0
springboot学习一:idea社区版本创建springboot项目的三种方式(第三种为主)