Springboot整合 Thymeleaf增删改查一篇就够了

news2024/11/26 4:51:28

img
很早之前写过Thymeleaf的文章,所以重新温习一下,非前后端分离,仅仅只是学习

  • 官网: https://www.thymeleaf.org/

SpringBoot可以快速生成Spring应用,简化配置,自动装配,开箱即用。 JavaConfiguration java类来代替XML的配置。对常用的第三方库提供了配置方案,可以很容易的与Spring进行整合,快速进行企业级开发。

img

优势:不需要配置任何XML文件、内嵌tomcat、默认支持JSON,不需要进行转换、支持RESTful。

使用时:启动类必须覆盖所有与业务相关的类,即启动类所在的包必须是业务类所在包的同包或者⽗包,如果没有覆盖,业务类就不会⾃动装配到IoC容器中。

YAML是不同于Properties的另外⼀种⽂件格式,同样可以⽤来写配置⽂件,Spring Boot默认⽀持YAML格式,
YAML的优点在于编写简单,结构清晰,利⽤缩紧的形式来表示层级关系。
相⽐于Properties,YAML可以进⼀步简化配置⽂件的编写,更加⽅便。属性名和属性值之间必须⾄少⼀个空格。

如果Properties和YAML两种类型的⽂件同时存在,Properties的优先级更⾼。

配置⽂件除了可以放置在resources路径下之外,还有3个地⽅可以放置,优先级顺序如下所示:
1、根路径下的config中的配置⽂件
2、根路径下的配置⽂件
3、resources路径下的config中的配置⽂件
4、resources路径下的配置⽂件

可以直接在Handler中读取YAML⽂件中的数据,⽐如在业务⽅法中向客户端返回当前服务的端⼝信息。

@Value("${server.port}")
private String port;

JSP:动态网页技术,底层为Servlet,可在html代码中编写Java代码

JSP底层原理:它是一种中间层组件,开发者可以在这个组件中将java代码与html代码整合,由JSP引擎将组件转为Servlet,再把混合代码翻译为Servlet的响应语句,输出给客户端。

环境搭建

1、创建基于Maven的Web项⽬,pom.xml

 <!-- Spring项目转为SpringBoot-->
<parent>
    <artifactId>spring-boot-starter-parent</artifactId>
    <groupId>org.springframework.boot</groupId>
    <version>2.3.4.RELEASE</version>
</parent>

  <dependencies>
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-web</artifactId>
    </dependency>

    <!-- 引入Spring Boot 内嵌的Tomcat对jsp的解析包-->
    <dependency>
      <groupId>org.apache.tomcat.embed</groupId>
      <artifactId>tomcat-embed-jasper</artifactId>
      <version>9.0.33</version>   
      <!--报错 <version>7.0.59</version>-->
      <scope>provided</scope>
    </dependency>

    <!-- servlet 依赖的jar包start-->
    <dependency>
      <groupId>javax.servlet</groupId>
      <artifactId>servlet-api</artifactId>
      <version>2.3</version>
      <scope>provided</scope>
    </dependency>
    <!-- jsp 依赖的jar包start-->
    <dependency>
      <groupId>javax.servlet.jsp</groupId>
      <artifactId>javax.servlet.jsp-api</artifactId>
      <version>2.3.1</version>
    </dependency>
    <!-- jstl标签 依赖的jar包start-->
    <dependency>
      <groupId>javax.servlet</groupId>
      <artifactId>jstl</artifactId>
    </dependency>
  </dependencies>

2、创建Handler

@Controller
@RequestMapping("/hello")
public class HelloHandler {
    @GetMapping("/index")
    public ModelAndView index(){
        ModelAndView modelAndView = new ModelAndView("index");
        modelAndView.addObject("msg","hello springboot jsp");
        return modelAndView;
    }
}

3、JSP

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" %>
<%@ page isELIgnored="false" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
    <h2>${msg}</h2>
</body>
</html>

4、application.yml(配置视图解析器)

server:
  port: 8080
#springmvc视图解析器
spring:
  mvc:
    view:
      prefix: /
      suffix: .jsp

5、编写启动类Application.java

@SpringBootApplication
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}

6、更新web.xml,防止加载其他xml片段的时候包报错

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns="http://java.sun.com/xml/ns/javaee"
	xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
	version="3.0">
	<display-name>Archetype Created Web Application</display-name>
</web-app>

实际运用(crud)

1、pom.xml导入jstl依赖

报错: NoSuchMethodError: org.apache.tomcat.JarScanner.scan,只需要在Dependencies下找到自己引入的tomcat,比如我自己引入的是7.0.59,展开后下面9.0.33是springboot自带的,将版本改为9.0.33就可以了,问题解决!

2、实体类User:id和name

3、Handler中创建业务⽅法,返回User对象

@Controller
@RequestMapping("/user")
public class UserHandler {
    @Autowired
    private UserService userService;

    @GetMapping("/findAll")
    public ModelAndView findAll(){
//        User user1 = new User(1, "jack");
//        User user2 = new User(2, "jack2");
//        List userList = Arrays.asList(user1, user2);
        ModelAndView modelAndView = new ModelAndView("findAll");
        modelAndView.addObject("userList",userService.findAll());
        return modelAndView;
    }

    @PostMapping("/save")
    public String save(User user){ //写一个save页面form
        userService.save(user);
        return "redirect:/user/findAll";
    }

    @GetMapping("/deleteById/{id}")
    public String deleteById(@PathVariable("id") Integer id){
        userService.deleteById(id);
        return "redirect:/user/findAll";
    }

    @GetMapping("/findById/{id}")
    public ModelAndView findById(@PathVariable("id") Integer id){
        ModelAndView modelAndView = new ModelAndView("update");
        modelAndView.addObject("user",userService.findById(id));
        return modelAndView;
    }
    @PostMapping("/update")
    public String update(User user){
        //写一个update页面form,但先要根据id查询数据,在修改
        userService.update(user);
        return "redirect:/user/findAll";
    }
}

4、Repository

public interface UserService {
    public Collection findAll();
    public User findById(Integer id);
    public void save(User user);
    public void deleteById(Integer id);
    public void update(User user);
}

5、Service

@Repository
public class UserRepositoryImpl implements UserRepository {
    public static Map map;
    static {
        map = new HashMap<>();
        map.put(1,new User(1,"jack1"));
        map.put(2,new User(2,"jack2"));
        map.put(3,new User(3,"jack3"));
    }

    @Override
    public Collection findAll() {
        return map.values();
    }

    @Override
    public User findById(Integer id) {
        return map.get(id);
    }

    @Override
    public void save(User user) {
        map.put(user.getId(),user);
    }

    @Override
    public void deleteById(Integer id) {
        map.remove(id);
    }

    @Override
    public void update(User user) {
        map.put(user.getId(),user);
    }
}

6、JSP

findAll.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" %>
<%@ page isELIgnored="false" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
<body>
    <table>
        <tr>
            <th>编号</th>
            <th>姓名</th>
            <th>操作</th>
        </tr>
        <c:forEach items="${userList}" var="users">
            <tr>
                <td>${users.id}</td>
                <td>${users.name}</td>
                <td>
                    <a href="/user/deleteById/${users.id}">删除</a>
                    <a href="/user/findById/${users.id}">修改</a>
                </td>
            </tr>
        </c:forEach>
    </table>
</body>
</html>

save.jsp

<form action="/user/save" method="post">
    <input type="text" name="id" />
    <input type="text" name="name" />
    <input type="submit" value="保存" />
</form>

update.jsp

<form action="/user/update" method="post">
    <input type="text" name="id" value="${user.id}" readonly />
    <input type="text" name="name" value="${user.name}" />
    <input type="submit" value="修改" />
</form>

Thymeleaf是⽬前较为流⾏的视图层技术,Spring Boot官⽅推荐使⽤Thymeleaf。
它可以实现前后端分离的交互方式,即视图与业务数据分开响应,还可以直接将服务端返回的数据生成为HTML文件,同时也可以处理XML、JavaScript、CSS等格式。

Thymeleaf最大的特点是既可以直接在浏览器打开(静态方法),也可以结合服务端,将业务数据填充到html后,动态生成的页面(动态方法)???

1 使用

1、创建Maven⼯程,不需要创建Web⼯程,pom.xml


    spring-boot-starter-parent
    org.springframework.boot
    2.3.4.RELEASE

        org.springframework.boot
        spring-boot-starter-web

        org.springframework.boot
        spring-boot-starter-thymeleaf

2、application.yml

classpath:一般用来指代"src/main/resources"下的资源路径,其本质其实是指项目打包后target的classes下的路径

spring:
  thymeleaf:
    prefix: classpath:/templates/  #模板路径
    suffix: .html                  #模板后缀
    servlet:
      content-type: text/html      #设置content-type
    encoding: utf-8                #编码格式
    mode: HTML5                    #校验h5格式
    cache: false                   #关闭缓存(在开发过程中可以立即看到修改后的结果)

3、创建Handler

@Controller
@RequestMapping("/hello")
public class HelloHandler {
    @GetMapping("/index")
    public ModelAndView index(){
        ModelAndView modelAndView = new ModelAndView("index");
        modelAndView.addObject("name","小明");
        return modelAndView;
    }
}

4、启动类

@SpringBootApplication
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class,args);
    }
}

5、templates目录下编写HTML

<!DOCTYPE html>
<html lang="en">
<!--引入标签-->
<html xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <!--name的值会覆盖hello-->
    <p th:text="${name}">hello</p>
</body>
</html>

2 注意

如果需要加载后台返回的业务数据,则需要在HTML⻚⾯中使⽤Thymeleaf模版标签来完成。

1、需要引⼊模版标签 <html xmlns:th="http://www.thymeleaf.org"></html>
2、通过特定的标签完成操作 <p th:text="${name}">hello</p>

Thymeleaf模版标签不同于JSTL,Thymeleaf模版标签是直接嵌⼊到HTML原⽣标签内部。

3 Thymeleaf常⽤标签【重点】

th:text用于文本的显示,将业务数据的值填充到html标签中。

th:if用于条件判断,对业务数据的值进行判断。成立,则显示内容。

<p th:if="${score>=90}">优秀</p>
<p th:if="${score<90}">不优秀</p>

th:unless也⽤作条件判断,逻辑与th:if恰好相反,如果条件不成⽴则显示,否则不显示。

th:switch th:case两个结合起来使⽤,⽤作多条件等值判断,

<div th:switch="${id}">
    <p th:case="1">a</p>
    <p th:case="2">b</p>
    <p th:case="3">c</p>
</div>

th:action⽤来指定请求的URL,相当于form表单中的action属性、【重点】

如果action的值直接写在HTML中,则需要使⽤@{}

<form th:action="@{/hello/login}" method="post">
<input type="submit"/></form>

如果是从后台传来的数据,则使⽤${}

@GetMapping("/redirect/{url}")
public Stringredirect(@PathVariable("url") String url, Model model){
	model.addAttribute("url","/hello/login");
	return url;
}
<form th:action="${url}" method="post">
<input type="submit"/></form>

th:each⽤来 遍历集合(类似foreach)

<table>
    <tr th:each="user:${userList}">
        <td th:text="${user.id}"></td>
        <td th:text="${user.name}"></td>
    </tr>
</table>

th:value⽤来给标签赋值

<input type="text" th:value="${idValue}"/>

th:src⽤来引⼊静态资源,相当于HTML原⽣标签img、script的src属性。

<img th:src="${src}"/>

如果src的值直接写在HTML中: <img th:src="@{/1.png}">

th:href⽤作设置超链接的href

List<User> list = Arrays.asList(new User(1,"jack"),new User(2,"tom"));
ModelAndView modelAndView = new ModelAndView("index");
modelAndView.addObject("list",list);
modelAndView.addObject("userName","tom");

<select>
    <option th:each="user:${list}"
            th:value="${user.id}"
            th:text="${user.name}"
            th:selected="${user.name == userName}">
    </option>
</select>

结合th:each来使⽤,⾸先 遍历list集合 动态创建option元素,根据每次遍历出的user.name与业务数据中的userName是否相等来决定是否要选择。

th:attr给HTML标签的任意属性赋值

<input th:attr="value=${attr}"/>
等价于
<input th:value="${attr}"/>

4 Thymeleaf对象

Thymeleaf支持访问Servlet Web的原生资源,HttpServletRequest、HttpServletResponse、HttpSession、ServletContext。

  • request:获取HttpServletRequest对象
  • response:获取HttpServletResponse对象
  • session:获取HttpSession对象
  • *servletContext:获取ServletContext对象
@GetMapping("/servlet")
public String servlet(HttpServletRequest request){
    request.setAttribute("value","request");
    request.getSession().setAttribute("value","session");
    request.getServletContext().setAttribute("value","servletContext");
    return "servletTest";
}
<p th:text="${#request.getAttribute('value')}"></p>
<p th:text="${#session.getAttribute('value')}"></p>
<p th:text="${#servletContext.getAttribute('value')}"></p>
<p th:text="${#response}"></p>

[注意]Thymeleaf⽀持直接访问session, ${#request.getAttribute('name')}也可以简化 ${name}

5 Thymeleaf内置对象

dates:⽇期格式化、calendars:⽇期操作、numbers:数字格式化、
strings:字符串格式化、bools:boolean、arrays:数组内置对象、
lists:List集合内置对象、sets:Set集合内置对象、maps:Map集合内置对象

index.html:

date格式化:<span th:text="${#dates.format(date,'yyyy-MM-dd')}"></span><br/>
当前时间:<span th:text="${#dates.createNow()}"></span><br/>
当前日期:<span th:text="${#dates.createToday()}"></span><br/>
Calendar格式化:<span th:text="${#calendars.format(calendar,'yyyy-MM-dd')}"></span><br/>

number百分比格式化(小数点左右保留两位:0.06-->06.00%):
<span th:text="${#numbers.formatPercent(number,2,2)}"></span><br/>
boolean是否为true:<span th:text="${#bools.isTrue(boolean)}"></span><br/>

String类型的name是否为空:<span th:text="${#strings.isEmpty(string)}"></span><br/>
name的长度:<span th:text="${#strings.length(string)}"></span><br/>
String类型的name拼接:<span th:text="${#strings.concat('yu ',string)}"></span><br/>
String类型的name拼接:<span th:text="${#strings.concat(string,' yu')}"></span><br/>

arrays的⻓度:<span th:text="${#arrays.length(array)}"></span><br/>
arrays是否包含jack:<span th:text="${#arrays.contains(array,'jack')}"></span><br/>
List是否为空:<span th:text="${#lists.isEmpty(list)}"></span><br/>
List的⻓度:<span th:text="${#lists.size(list)}"></span><br/>

Set是否为空:<span th:text="${#sets.isEmpty(set)}"></span><br/>
Set的⻓度:<span  th:text="${#sets.size(set)}"></span><br/>
Map是否为空:<span th:text="${#maps.isEmpty(map)}"></span><br/>
Map⻓度:<span th:text="${#maps.size(map)}"></span><br/>

Handler:

@GetMapping("/inner")
public ModelAndView inner(){
    ModelAndView modelAndView = new ModelAndView("index");
    modelAndView.addObject("date",new Date()); //日期
    Calendar calendar = Calendar.getInstance();
    calendar.set(2022,4,27);
    modelAndView.addObject("calendar",calendar);

    modelAndView.addObject("number",0.06);
    modelAndView.addObject("string","hello world");
    modelAndView.addObject("boolean",true);
    modelAndView.addObject("array",Arrays.asList("jack","tom"));

    List list = new ArrayList<>();
    list.add(new User(1,"jack1"));
    list.add(new User(2,"tom1"));
    modelAndView.addObject("list",list);

    Set set = new HashSet<>();
    set.add(new User(1,"jack2"));
    set.add(new User(2,"tom2"));
    modelAndView.addObject("set",set);

    Map map = new HashMap<>();
    map.put(1,new User(1,"jack3"));
    map.put(2,new User(2,"tom3"));
    modelAndView.addObject("map",map);

    return modelAndView;
}

JdbcTemplate是Spring自带的JDBC模块组件,底层对JDBC进行了封装。用法与mybatis一样,需要自定义sql语句,它实现了数据库的连接,SQL语句的执行,结果集的封装。

缺点:灵活性比如mybatis,因为mybatis的SQL语句定义在xml配置文件中,更有利于维护和扩展。
而JdbcTemplate以硬编码的方式将SQL直接写在Java代码中,不利于维护扩展。

1、pom.xml


    org.springframework.boot
    spring-boot-starter-jdbc

    mysql
    mysql-connector-java

2、创建实体类

3、创建UserRepository接口以及实现类

@Repository
public class UserRepositoryImpl implements UserRepository {

    @Autowired
    private JdbcTemplate jdbcTemplate; //直接引入

    @Override
    public List findAll() {
        return jdbcTemplate.query(
                "select * from user",
                new BeanPropertyRowMapper<>(User.class)
        );
    }

    @Override
    public User findById(Integer id) {
        return jdbcTemplate.queryForObject(
                "select * from user where id = ?",
                new Object[]{id},
                new BeanPropertyRowMapper<>(User.class)
        );
    }

    @Override
    public void save(User user) {
        jdbcTemplate.update(
                "insert into user(username,password) values(?,?)",
                user.getUsername(),
                user.getPassword()
        );
    }

    @Override
    public void update(User user) {
        jdbcTemplate.update(
                "update user set username=?,password=? where id=? ",
                user.getUsername(),
                user.getPassword(),
                user.getId()
        );
    }

    @Override
    public void delete(Integer id) {
        jdbcTemplate.update(
                "delete from user where id=?",
                id
        );
    }
}

4、测试

@SpringBootTest
class SpringbootApplicationTests {
    @Autowired
    private UserRepositoryImpl userRepository;

    @Test
    void testJdbc() {
       List userList = userRepository.findAll();
       System.out.println(userList);
    }
}

query方法

1、 query(String sql, RowMapper<t> rowMapper)</t>

其中的RowMapper是一个接口,作用是解析结果集,将JDBC查询出来的ResultSet对象转化为POJO。

调用query方法时要指定类的结构 new BeanPropertyRowMapper<>(User.class)

@FunctionalInterface
public interface RowMapper {
    @Nullable
    T mapRow(ResultSet rs, int rowNum) throws SQLException;
}

2、 queryForObject(String sql, @Nullable Object[] args, RowMapper<t> rowMapper)</t>

该⽅法⽤来 查询⼀条数据,并将结果封装成⼀个POJO

update方法

增加、删除、修改的操作都可以调用个这个方法。

1、pom.xml(spring的web项目)


  org.springframework.boot
  spring-boot-starter-parent
  2.6.7

      org.springframework.boot
      spring-boot-starter-web

      mysql
      mysql-connector-java

      org.mybatis.spring.boot
      mybatis-spring-boot-starter
      2.2.2

2、application.yml

#端口
server:
  port: 8080
  tomcat:
    uri-encoding: UTF-8
###############################
mybatis:
  mapper-locations: classpath:/mapping/*.xml # mapper.xml文件的路径
  type-aliases-package: com.yu.entity  # 全限定名(包名+类名)起别名
###############################
spring:
  datasource:
    url: jdbc:mysql://127.0.0.1:3306/school?useSSL=false&characterEncoding=utf8&serverTimezone=GMT
    driver-class-name: com.mysql.cj.jdbc.Driver
    username: root
    password: 12345

3、实体类User

4、创建UserRepository接口

public interface UserRepository {
    public List findAll();
    public User findById(Integer id);
    public void save(User user);
    public void update(User user);
    public void delete(Integer id);
}

5、/resources/mapping创建UserRepository.xml【关注点】


        select * from user

        select * from user where id=#{id}

        insert into user(username,password) values(#{username},#{password})

        update user set username=#{usernamw},password=#{password} where id=#{id}

        delete from user where id=#{id}

6、创建Handler

@RestController
@RequestMapping("/user")
public class UserHandler {
    @Autowired
    private UserRepository userRepository;

    @GetMapping("/findAll")
    public List findAll(){
        return userRepository.findAll();
    }

    @GetMapping("/findById/{id}")
    public User findById(@PathVariable("id") Integer id){
        return userRepository.findById(id);
    }
    @PostMapping("/save")
    public int save(@RequestBody User user){
        return userRepository.save(user);
    }
    @PutMapping("/update")
    public int update(@RequestBody User user){
        return userRepository.update(user);
    }
    @DeleteMapping("/delete/{id}")
    public int delete(@PathVariable("id") Integer id){
        return userRepository.delete(id);
    }
}

7、创建启动类,扫描mapper

@SpringBootApplication
@MapperScan("com.yu.repository") #扫描mapper
public class SpringbootApplication {
    public static void main(String[] args) {
        SpringApplication.run(SpringbootApplication.class, args);
    }
}

总结:
1、注意application配置文件中,需要配置mybatis的mapper文件路径,以及别名。
2、在resources的mapping文件夹下创建对应的Mapper.xml文件(sql语句),还有命名空间
3、启动类添加注解: @MapperScan(“com.yu.repository”) 。作用是指定要变成实现类的接口所在的包,然后包下面的所有接口在编译之后都会生成相应的实现类。

JPA和Spring Data JPA的关系

JPA(java persistence API)java持久层规范。定义了一系列ORM接口,它本身不能直接使用,接口必须实现才能使用,Hibernate框架就是一个实现了JPA规范的框架。

Spring Data JPA是Spring框架提供的对JPA规范的抽象,通过约定的命名规范完成持久层接口的编写,
在不需要实现接口的情况下,就可以完成对数据库的操作。

简单理解:通过Spring Data JPA只需要定义接口而不需要实现,就能完成CRUD的操作。

Spring Data JPA本身并不是⼀个具体的实现,它只是⼀个抽象层,底层还是需要Hibernate这样的JPA来提供⽀持。
Hibernate 是一款全自动的 ORM 框架,它能够自动生成的 SQL 语句并自动执行,实现对数据库进行操作,

Spring Data JPA和Spring JdbcTemplate的关系

Spring JdbcTemplate是Spring框架提供的⼀套操作数据库的模版,
Spring Data JPA是JPA的抽象。

1、pom.xml

<!-- Spring Boot 集成 Spring Data JPA -->
<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>

2、application.yml

#端口
server:
  port: 8080
  tomcat:
    uri-encoding: UTF-8

spring:
  datasource:
    url: jdbc:mysql://127.0.0.1:3306/school?useSSL=false&characterEncoding=utf8&serverTimezone=GMT
    driver-class-name: com.mysql.cj.jdbc.Driver
    username: root
    password: 12345
    
  # 显示sql语句,并格式化 
  jpa: 
    show-sql: true
    properties:
      hibernate:
        format_sql: true

3、实体类。完成实体类与数据表的映射【重点】

import javax.persistence.*;
@Data
@Entity(name = "user")//将类与表名联系起来(name为表名)
public class User {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Integer id;

    @Column
    private String username;
    @Column
    private String password;
}

注解分析:

  • @Entity将实体类与数据表进行映射,其中name = "user"指定表名
  • @Id将实体类中的成员变量与数据表的主键进行映射,⼀般都是id
  • @GeneratedValue表示自动生成主键,strategy为主键选择生成策略(GenerationType.IDENTITY:主键由数据库自动生成(主要是自动增长型))
  • @Column将实体类中的成员变量与数据表的普通字段进行映射

4、创建UserRepository

只需要继承JpaRepository,不需要实现方法,也不需要写SQL语句。

import org.springframework.data.jpa.repository.JpaRepository;

public interface UserRepository extends JpaRepository {
} // 其中JpaRepository,一个指实体类,另一个是表的主键的类型

5、创建Handler

@RestController
@RequestMapping("/user")
public class UserHandler {
    @Autowired
    private UserRepository userRepository;

    @GetMapping("/findAll")
    public List findAll(){
        return userRepository.findAll();
    }
    @GetMapping("/findById/{id}")
    public User findById(@PathVariable("id") Integer id){
        return userRepository.findById(id).get(); //  Optional findById(ID id);防止空指针
    }

    @PostMapping("/save")
    public void save(@RequestBody User user){
        userRepository.save(user);
    }
    @PutMapping("/update")
    public void update(@RequestBody User user){
        userRepository.save(user);
    }
    @DeleteMapping("/deleteById/{id}")
    public void deleteById(@PathVariable("id") Integer id){
        userRepository.deleteById(id);
    }
}

6、【重点】在继承JpaRepsitory的基础上,开发者也可以自定义方法。

public interface UserRepository extends JpaRepository {
    // 这个自定义的方法要特别注意
    // By后面的为字段名的首字母大写。不能写其他的,例如findByName则报错
    public User findByUsername(String username);
}
@GetMapping("/findByUsername/{username}")
public User findByUsername(@PathVariable("username") String username){
    return userRepository.findByUsername(username);
}

Spring Security:利用Spring IoC/DI和AOP功能,为系统提供了声明式安全访问控制功能,减少了为系统安全而编写大量重复代码的工作。

整合Spring Security

1、创建spring的Maven⼯程,pom.xml

spring-boot-starter-parent 这是Spring Boot的父级依赖,这样当前的项目就是Spring Boot项目了。
spring-boot-starter-parent 是一个特殊的starter,它用来提供相关的Maven默认依赖。使用它之后,常用的包依赖可以省去version标签。

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.3.4.RELEASE</version>
</parent>

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-security</artifactId>
    </dependency>
    
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-thymeleaf</artifactId>
    </dependency>
</dependencies>

2、Handler

@Controller
public class SecurityHandler {
    @GetMapping("/index")
    public String index(){
        return "index";
    }
}

3、前端thymeleaf的html

<form method="post" action="/logout">
    <input type="submit" value="退出">
</form>

4、application.yml

spring:
  thymeleaf:
    prefix: classpath:/templates/
    suffix: .html

5、Application

@SpringBootApplication
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class,args);
    }
}

自定义用户密码(默认登录页面)

spring:
  thymeleaf:
    prefix: classpath:/templates/
    suffix: .html
  security:
    user:
      name: admin
      password: 12345

权限管理

用户---->角色---->权限:将权限交给角色,再把角色赋予用户。

举例:
定义两个资源:index.html、admin.html
定义两个角色:ADMIN可以访问index.html和admin.html、USER只能访问index.html

1、config包下面创建SecurityConfig类

@Configuration // 配置类
@EnableWebSecurity // 开启web安全验证
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    /**
     * 角色和资源的关系
     * @param http
     * @throws Exception
     */
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                .antMatchers("/admin").hasRole("ADMIN")
                .antMatchers("/index").access("hasRole('ADMIN') or hasRole('USER')")
                .anyRequest().authenticated()
                .and()
                .formLogin()
                .loginPage("/login")
                .permitAll()
                .and()
                .logout()
                .permitAll()
                .and()
                .csrf()
                .disable();
    }

    /**
     * 用户和角色的关系
     * @param auth
     * @throws Exception
     */
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.inMemoryAuthentication().passwordEncoder(new MyPasswordEncoder())
                .withUser("user").password(new MyPasswordEncoder()
                .encode("000")).roles("USER")
                .and()
                .withUser("admin").password(new MyPasswordEncoder()
                .encode("123")).roles("ADMIN","USER");
    }
}

2、自定义MyPassowrdEncoder

public class MyPasswordEncoder implements PasswordEncoder {
    @Override
    public String encode(CharSequence charSequence) {
        return charSequence.toString();
    }

    @Override
    public boolean matches(CharSequence charSequence, String s) {
        return s.equals(charSequence.toString());
    }
}

3、Handler

@Controller
public class SecurityHandler {
    @GetMapping("/index")
    public String index(){
        return "index";
    }

    @GetMapping("/admin")
    public String admin(){
        return "admin"; //转发到admin页面
    }
    @GetMapping("/login")
    public String login(){
        return "login";
    }
}

4、login.html

<html xmlns:th="http://www.thymeleaf.org">
<body>
    <!-- spring security的param.error -->
    <p th:if="${param.error}">
        用户名或密码错误
    </p>

    <form th:action="@{/login}" method="post">
        <!-- 这里的name必须是username -->
        用户名:<input type="text" name="username"><br/>
        密 码:<input type="password" name="password"><br/>
        <input type="submit" value="登录">
    </form>
</body>

5、index.html(USER、ADMIN)

<body>
    <p>欢迎回来</p>
    <form method="post" action="/logout">
        <input type="submit" value="退出">
    </form>
</body>

6、admin.html(ADMIN)

<body>
    <p>后台管理系统</p>
    <form method="post" action="/logout">
        <input type="submit" value="退出">
    </form>
</body>

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/373377.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【java基础】枚举类(enum)

文章目录基本介绍快速使用字段、方法、构造器枚举类方法toString方法valueOf方法values方法ordinal方法基本介绍 在java中有一种特殊的类型就是枚举类&#xff0c;对于一个有限的有固定值的集合&#xff0c;我们就可以考虑使用枚举类来进行表示&#xff0c;例如服装的大小为 小…

linux shell 入门学习笔记15 shell 条件测试

概念 shell的条件测试目的是得出真和假。 shell 提供的条件测试语法 test 命令 [] 中括号命令 语法*&#xff1a; test条件测试 test命令用来评估一个表达式&#xff0c;他的结果是真&#xff0c;还是假&#xff0c;如果条件为真&#xff0c;那么命令执行状态结果就为0&…

【蓝桥杯集训·周赛】AcWing 第92场周赛

文章目录第一题 AcWing 4864. 多边形一、题目1、原题链接2、题目描述二、解题报告1、思路分析2、时间复杂度3、代码详解第二题 AcWing 4865. 有效类型一、题目1、原题链接2、题目描述二、解题报告1、思路分析2、时间复杂度3、代码详解第三题 AcWing 4866. 最大数量一、题目1、原…

Spring之丐版IOC实现

文章目录IOC控制反转依赖注入Bean的自动装配方式丐版IOC实现BeanDefinition.javaResourceLoader.javaBeanRegister.javaBean和DI的注解BeanFactory.javaApplicationContext测试&#xff0c;实现在这里插入图片描述大家好&#xff0c;我是Leo。Spring核心中依赖注入和IOC容器是非…

JWT令牌

1.普通令牌的问题 客户端申请到令牌&#xff0c;接下来客户端携带令牌去访问资源&#xff0c;到资源服务器将会校验令牌的合法性。 从第4步开始说明&#xff1a; 1、客户端携带令牌访问资源服务获取资源。 2、资源服务远程请求认证服务校验令牌的合法性 3、如果令牌合…

QML Image and Text(图像和文字)

Image&#xff08;图片&#xff09; 图像类型显示图像。 格式&#xff1a; Image {source: "资源地址" } source&#xff1a;指定资源的地址 自动检测文件拓展名&#xff1a;source中的URL 指示不存在的本地文件或资源&#xff0c;则 Image 元素会尝试自动检测文件…

MVI 架构更佳实践:支持 LiveData 属性监听

前言MVI架构为了解决MVVM在逻辑复杂时需要写多个LiveData(可变不可变)的问题,使用ViewState对State集中管理&#xff0c;只需要订阅一个 ViewState 便可获取页面的所有状态通过集中管理ViewState&#xff0c;只需对外暴露一个LiveData&#xff0c;解决了MVVM模式下LiveData膨胀…

Linux_vim编辑器入门级详细教程

前言&#xff08;1&#xff09;vim编辑器其实本质上就是对文本进行编辑&#xff0c;比如在.c文件中改写程序&#xff0c;在.txt文件写笔记什么的。一般来说&#xff0c;我们可以在windows上对文本进行编译&#xff0c;然后上传给Linux。但是有时候我们可能只是对文本进行简单的…

MySQL运维

目录 1、日志 1、错误日志 2、二进制日志 3、查询日志 4、慢查询日志 2、主从复制 搭建 1、主库配置 2、从库配置 3、分库分表 1、简介 ​编辑 1、垂直拆分 2、水平拆分 3、实现技术 2、MyCat 3、MyCat使用和配置 配置 4、MyCat分片 1、垂直拆分 2、水平拆分…

线材-电子线载流能力

今天来讲的是关于电子线的一个小知识&#xff0c;可能只做板子的工程师遇到此方面的问题会比较少&#xff0c;做整机的工程师则必然会遇到此方面问题&#xff0c;那就是线材问题。 下面主要说下电子线的过电流能力。&#xff08;文末有工具下载&#xff09;电子线&#xff08;h…

vue3+rust个人博客建站日记2-确定需求

反思 有人说过我们正在临近代码的终结点。很快&#xff0c;代码就会自动产生出来&#xff0c;不需要再人工编写。程序员完全没用了&#xff0c;因为商务人士可以从规约直接生成程序。 扯淡&#xff01;我们永远抛不掉代码&#xff0c;因为代码呈现了需求的细节。在某些层面上&a…

CTFer成长之路之Python中的安全问题

Python中的安全问题CTF 1.Python里的SSRF 题目提示 尝试访问到容器内部的 8000 端口和 url path /api/internal/secret 即可获取 flag 访问url&#xff1a; http://f5704bb3-5869-4ecb-9bdc-58b022589224.node3.buuoj.cn/ 回显如下&#xff1a; 通过提示构造payload&…

Pytorch复习笔记--Conv2d和Linear的参数量和显存占用量比较

目录 1--nn.Conv2d()参数量的计算 2--nn.Linear()参数量计算 3--显存占用量比较 1--nn.Conv2d()参数量的计算 conv1 nn.Conv2d(in_channels3, out_channels64, kernel_size1) 计算公式&#xff1a; Param in_c * out_c * k * k out_c; in_c 表示输入通道维度&#xff1b…

微信小程序-1:比较两数的大小

程序来源》微信小程序开发教程&#xff08;第二章&#xff09; 主编&#xff1a;黄寿孟、易芳、陶延涛 ISBN&#xff1a; 9787566720788 程序运行结果&#xff1a; <!--index.wxml--> <view class"container"> <text>第一个数字&#xff1a;&…

从认知智能的角度认识ChatGPT的不足

OpenAI的ChatGPT带来了一些令人欣喜的成果&#xff0c;但是从认知智能的角度来看&#xff0c;也有很多不足。今天我就来为大家说一说。首先我会为大家简单介绍人工智能&#xff0c;认知智能&#xff0c;然后再分析ChatGPT的能力和不足&#xff0c;最后分享目前优秀的学术论文以…

网络应用之静态Web服务器

静态Web服务器-返回固定页面数据学习目标能够写出组装固定页面数据的响应报文1. 开发自己的静态Web服务器实现步骤:编写一个TCP服务端程序获取浏览器发送的http请求报文数据读取固定页面数据&#xff0c;把页面数据组装成HTTP响应报文数据发送给浏览器。HTTP响应报文数据发送完…

[11]云计算|简答题|案例分析|云交付|云部署|负载均衡器|时间戳

升级学校云系统我们学校要根据目前学生互联网在线学习、教师教学资源电子化、教学评价过程化精细化的需求&#xff0c;计划升级为云教学系统。请同学们根据学校发展实际考虑云交付模型包含哪些&#xff1f;云部署采用什么模型最合适&#xff1f;请具体说明。9月3日买电脑还是租…

python之并发编程

一、并发编程之多进程 1.multiprocessing模块介绍 python中的多线程无法利用多核优势&#xff0c;如果想要充分地使用多核CPU的资源&#xff08;os.cpu_count()查看&#xff09;&#xff0c;在python中大部分情况需要使用多进程。Python提供了multiprocessing。 multiprocess…

SEO优化:干货技巧分享,包新站1-15天100%收录首页

不管是老域名还是新域名&#xff0c;不管是多久没有收录首页的站&#xff0c;此法周期7-30天&#xff0c;包首页收录&#xff01;本人不喜欢空吹牛逼不实践的理论&#xff0c;公布具体操作&#xff1a;假如你想收录的域名是a.com&#xff0c;那么准备如下材料1.购买5-10个最便宜…

【Tomcat】Tomcat安装及环境配置

文章目录什么是Tomcat为什么我们需要用到Tomcattomcat下载及安装1、进入官网www.apache.org&#xff0c;找到Projects中的project List2、下载之后&#xff0c;解压3、找到tomcat目录下的startup.bat文件&#xff0c;双击之后最后结果出现多少多少秒&#xff0c;表示安装成功4、…