layui + SpringBoot 学习笔记

目录

1、layui 数据表格组件

2、案例

2.1、准备工作

2.1.1、创建 SpringBoot 项目并配置 application.yaml

2.1.2、准备数据库相关

2.1.3、创建与数据表对应的实体类、mapper

2.1.4、在主程序类扫描 mapper

2.1.5、配置 application.yml

2.1.6、测试

2.2、准备查询数据的接口

2.2.1、准备两个表对应的实体类

2.2.2、准备返回给浏览器的JSON格式的实体类

2.2.3、准备 mapper

2.2.4、准备 service 及其实现类

2.2.5、测试

2.2.6、准备 controller

2.3、页面查看数据

2.3.1、准备页面

2.3.2、跳转到页面的 controller

2.4、分页查看数据

2.4.1、页面分页请求地址格式

2.5、显示图片

2.5.1、创建图片存放的目录

2.5.2、修改页面表格代码


学习视频:【绝妙搭配】Spring Boot+Layui 快速搭建后台管理系统(单体应用+前后端分离)_哔哩哔哩_bilibili

1、layui 数据表格组件

这里使用的表格:Layui table 模块,开启合计行 - 在线演示

关于 table.render

            table.render({
                elem: '#test'   // id选择器
                ,url:'data.json'    // 数据来源的请求地址,这里已经将json数据保存到本地
                ,toolbar: '#toolbarDemo'
                ,title: '用户数据表'  // 导出为excel时的标题
                ,totalRow: true     // 是否统计总数
                ,cols: [
                    [
                        {type: 'checkbox', fixed: 'left'}   // 复选框
                        /*
                         * field:列
                         * title:列名
                         * sort:是否开启升序/降序排列
                         * totalRowText:统计总数的名字
                         * templet:追加标签
                         * totalRow:是否统计该列的总数
                         */
                        ,{field:'id', title:'商品ID', width:150, fixed: 'left', sort: true, totalRowText: '合计'}
                        ,{field:'name', title:'商品名称', width:120}
                        ,{field:'description', title:'商品描述', width:150}
                        ,{field:'price', title:'商品价格', width:150, sort: true, totalRow:true}
                        ,{field:'stock', title:'商品库存', width:150, sort: true, totalRow:true}
                        ,{field:'categorylevelone', title:'一级分类', width:150}
                        ,{field:'categoryleveltwo', title:'二级分类', width:150}
                        ,{field:'categorylevelthree', title:'三级分类', width:150}
                        ,{field:'file_name', title:'商品图片', width:150}
                        ,{fixed: 'right', title:'操作', toolbar: '#barDemo', width:150} // 与操作按钮绑定,每行都会出现编辑、删除按钮
                    ]
                ]
                ,page: true   // 是否开启分页条
            });

2、案例

2.1、准备工作

2.1.1、创建 SpringBoot 项目并配置 application.yaml

使用 Spring Initializr 创建项目,选择添加的依赖如下图

创建完成后在 pom.xml 手动导入 mybatis-plus 的依赖

        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>3.4.2</version>
        </dependency>

 配置 application.yaml

spring:
  datasource:
    driver-class-name: com.mysql.jdbc.Driver
    url: jdbc:mysql://localhost:3306/layui
    username: root
    password: 123456
  thymeleaf:
    prefix: classpath:/templates/
    suffix: .html
mybatis-plus:
  configuration:
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl   # 打印SQL语句

2.1.2、准备数据库相关

创建所需的数据库和数据表

CREATE DATABASE `layui`;

USE `layui`;

DROP TABLE IF EXISTS `product`;
/*!40101 SET @saved_cs_client     = @@character_set_client */;
/*!50503 SET character_set_client = utf8mb4 */;
CREATE TABLE `product` (
  `id` INT NOT NULL AUTO_INCREMENT COMMENT '主键',
  `name` VARCHAR(200) NOT NULL COMMENT '名称',
  `description` VARCHAR(1024) DEFAULT NULL COMMENT '描述',
  `price` FLOAT NOT NULL COMMENT '价格',
  `stock` INT NOT NULL COMMENT '库存',
  `categorylevelone_id` INT DEFAULT NULL COMMENT '分类1',
  `categoryleveltwo_id` INT DEFAULT NULL COMMENT '分类2',
  `categorylevelthree_id` INT DEFAULT NULL COMMENT '分类3',
  `file_name` VARCHAR(200) DEFAULT NULL COMMENT '文件名称',
  PRIMARY KEY (`id`),
  UNIQUE KEY `PK__EASYBUY___94F6E55132E0915F` (`id`)
) ENGINE=INNODB AUTO_INCREMENT=777 DEFAULT CHARSET=utf8;
/*!40101 SET character_set_client = @saved_cs_client */;

--
-- Dumping data for table `product`
--

LOCK TABLES `product` WRITE;
/*!40000 ALTER TABLE `product` DISABLE KEYS */;
INSERT INTO `product` VALUES (733,'香奈儿','好闻的香水!!!',152,978,548,654,655,'baby_1.jpg'),(734,'洗面奶','',152.5,10,548,654,655,'baby_2.jpg'),(735,'啫喱水','',152,959,548,654,655,'baby_3.jpg'),(736,'香水','',152,1000,548,654,655,'baby_4.jpg'),(737,'香水','',152,111,548,654,655,'baby_5.jpg'),(738,'润肤露','',45,99,548,654,655,'baby_6.jpg'),(739,'洁面装','',156,33,548,654,655,'bk_2.jpg'),(740,'电饭锅','',158,94,628,656,659,'bk_1.jpg'),(741,'婴儿喂奶装','',569,100,632,637,653,'bk_3.jpg'),(742,'坚果套餐','',158,1000,660,661,662,'bk_4.jpg'),(743,'超甜蜜崭','',589,1000,660,661,663,'bk_5.jpg'),(744,'华为2566','',589,1000,670,671,672,'de1.jpg'),(745,'荣耀3C','',589,92,670,671,672,'de2.jpg'),(746,'小米手环','',963,98,670,674,675,'de3.jpg'),(747,'华为2265','',896,1000,670,671,673,'de4.jpg'),(748,'越南坚果','',520,1,660,661,662,'de5.jpg'),(749,'日本进口马桶','',5866,100,628,657,0,'food_1.jpg'),(750,'联想Y系列','',569,894,670,690,691,'food_2.jpg'),(751,'脑白金1号','',589,1000,676,677,680,'food_3.jpg'),(752,'莫里斯按','',589,1000,676,678,0,'food_4.jpg'),(753,'三鹿好奶粉','',859,100,676,679,0,'food_5.jpg'),(754,'儿童牛奶','',5896,100,676,679,0,'food_6.jpg'),(755,'软沙发','',8596,99,628,696,0,'food_b1.jpg'),(756,'收纳盒','',5966,100,628,696,0,'food_b2.jpg'),(757,'洗衣液','',58,1000,628,696,0,'food_r.jpg'),(758,'红短沙发','',596,113,628,696,0,'fre_1.jpg'),(759,'新西兰奶粉','',5896,100,676,679,0,'fre_2.jpg'),(760,'婴儿车','',11000,100,681,682,687,'fre_3.jpg'),(761,'夏款婴儿车','',963,99,681,682,688,'fre_4.jpg'),(762,'抗压旅行箱','',569,1000,681,683,685,'fre_5.jpg'),(763,'透明手提箱','',8596,1000,681,683,684,'fre_6.jpg'),(764,'婴儿果粉','',5896,999,660,661,662,'milk_1.jpg'),(765,'椰子粉','',5963,1000,660,661,662,'milk_2.jpg'),(766,'坚果蛋糕','',200,98,660,661,663,'milk_3.jpg'),(767,'编制手提箱','',5896,1000,681,682,688,'milk_4.jpg'),(768,'纸箱','',5896,3,681,682,687,'milk_5.jpg'),(769,'健胃液','',152,1000,676,679,0,'milk_6.jpg'),(770,'联想NTC','',8596,100,670,671,673,'milk_7.jpg'),(771,'香水1',NULL,100,100,548,654,655,'milk_8.jpg'),(772,'香水2',NULL,100,100,548,654,655,'pro1.jpg'),(773,'香水3',NULL,100,100,548,654,655,'pro2.jpg'),(774,'香水4',NULL,100,100,548,654,655,'pro3.jpg'),(775,'香水5',NULL,100,100,548,654,655,'pro4.jpg'),(776,'香水6',NULL,1,1,548,654,655,'pro5.jpg');
/*!40000 ALTER TABLE `product` ENABLE KEYS */;
UNLOCK TABLES;

--
-- Table structure for table `product_category`
--

DROP TABLE IF EXISTS `product_category`;
/*!40101 SET @saved_cs_client     = @@character_set_client */;
/*!50503 SET character_set_client = utf8mb4 */;
CREATE TABLE `product_category` (
  `id` INT NOT NULL AUTO_INCREMENT COMMENT '主键',
  `name` VARCHAR(20) NOT NULL COMMENT '名称',
  `parent_id` INT NOT NULL COMMENT '父级目录id',
  `type` INT DEFAULT NULL COMMENT '级别(1:一级 2:二级 3:三级)',
  PRIMARY KEY (`id`),
  UNIQUE KEY `PK__EASYBUY___9EC2A4E236B12243` (`id`)
) ENGINE=INNODB AUTO_INCREMENT=697 DEFAULT CHARSET=utf8;
/*!40101 SET character_set_client = @saved_cs_client */;

--
-- Dumping data for table `product_category`
--

LOCK TABLES `product_category` WRITE;
/*!40000 ALTER TABLE `product_category` DISABLE KEYS */;
INSERT INTO `product_category` VALUES (548,'化妆品',0,1),(628,'家用商品',0,1),(654,'面部护理',548,2),(655,'少女派',654,3),(656,'餐具',628,2),(657,'卫具',628,2),(658,'叉子',656,3),(659,'锅',656,3),(660,'进口食品',0,1),(661,'零食/糖果/巧克力',660,2),(662,'坚果',661,3),(663,'蜜饯',661,3),(669,'孕期教育',546,3),(670,'电子商品',0,1),(671,'手机',670,2),(672,'华为手机',671,3),(673,'联想手机',671,3),(674,'手环',670,2),(675,'小米手环',674,3),(676,'保健食品',0,1),(677,'老年保健品',676,2),(678,'中年营养品',676,2),(679,'儿童保健品',676,2),(680,'脑白金',677,3),(681,'箱包',0,1),(682,'旅行箱',681,2),(683,'手提箱',681,2),(684,'大型',683,3),(685,'小型',683,3),(686,'中型',683,3),(687,'大型',682,3),(688,'中型',682,3),(689,'小型',682,3),(690,'电脑',670,2),(691,'联想电脑',690,3),(692,'刀叉',656,3),(693,'碗筷',656,3),(696,'客厅专用',628,2);
/*!40000 ALTER TABLE `product_category` ENABLE KEYS */;
UNLOCK TABLES;

--
-- Table structure for table `order_detail`
--

DROP TABLE IF EXISTS `order_detail`;
/*!40101 SET @saved_cs_client     = @@character_set_client */;
/*!50503 SET character_set_client = utf8mb4 */;
CREATE TABLE `order_detail` (
  `id` INT NOT NULL AUTO_INCREMENT COMMENT '主键',
  `order_id` INT NOT NULL COMMENT '订单主键',
  `product_id` INT NOT NULL COMMENT '商品主键',
  `quantity` INT NOT NULL COMMENT '数量',
  `cost` FLOAT NOT NULL COMMENT '消费',
  PRIMARY KEY (`id`),
  UNIQUE KEY `PK__EASYBUY___66E1BD8E2F10007B` (`id`)
) ENGINE=INNODB AUTO_INCREMENT=123 DEFAULT CHARSET=utf8;
/*!40101 SET character_set_client = @saved_cs_client */;

--
-- Dumping data for table `order_detail`
--

LOCK TABLES `order_detail` WRITE;
/*!40000 ALTER TABLE `order_detail` DISABLE KEYS */;
INSERT INTO `order_detail` VALUES (115,133,735,4,608),(116,133,745,3,1767),(117,134,738,10,450),(118,134,739,66,10296),(119,134,758,10,5960),(120,134,735,33,5016),(121,134,740,6,948),(122,134,750,100,56900);
/*!40000 ALTER TABLE `order_detail` ENABLE KEYS */;
UNLOCK TABLES;

2.1.3、创建与数据表对应的实体类、mapper

Product 实体类

package com.zyj.layui.entity;

import lombok.Data;

/**
 * @Author zhang
 * @Date 2022/6/9 - 19:43
 * @Version 1.0
 */
@Data
public class Product {
    private Integer id;
    private String name;
    private String description;
    private Integer stock;
    private Float price;
    private Integer categoryleveloneId;
    private Integer categoryleveltwoId;
    private Integer categorylevelthreeId;
    private String fileName;
}

ProductMapper

package com.zyj.layui.mapper;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.zyj.layui.entity.Product;

/**
 * @Author zhang
 * @Date 2022/6/9 - 19:46
 * @Version 1.0
 */
public interface ProductMapper extends BaseMapper<Product> {
}

2.1.4、在主程序类扫描 mapper

@MapperScan("com.zyj.layui.mapper")

2.1.5、配置 application.yml

spring:
  datasource:
    driver-class-name: com.mysql.jdbc.Driver
    url: jdbc:mysql://localhost:3306/layui
    username: root
    password: 123456
mybatis-plus:
  configuration:
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl   # 打印SQL语句

2.1.6、测试

package com.zyj.layui.mapper;

import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

import static org.junit.jupiter.api.Assertions.*;

/**
 * @Author zhang
 * @Date 2022/6/9 - 19:50
 * @Version 1.0
 */
@SpringBootTest
class ProductMapperTest {

    @Autowired
    private ProductMapper productMapper;

    @Test
    public void test(){
        productMapper.selectList(null).forEach(System.out::println);
    }

}

2.2、准备查询数据的接口

2.2.1、准备两个表对应的实体类

Product

@Data
public class Product {
    private Integer id;
    private String name;
    private String description;
    private Float price;
    private Integer categoryleveloneId;
    private Integer categoryleveltwoId;
    private Integer categorylevelthreeId;
    private String fileName;
}

ProductCategory

@Data
public class ProductCategory {
    private Integer id;
    private String name;
}

2.2.2、准备返回给浏览器的JSON格式的实体类

由于浏览器显示的一级、二级、三级分类是字符串格式,这里创建 ProductVO,将一级、二级、三级分类设置为 String

ProductVO

@Data
public class ProductVO {
    private Integer id;
    private String name;
    private String description;
    private Float price;
    private String categorylevelone;
    private String categoryleveltwo;
    private String categorylevelthree;
    private String fileName;
}

DataVO

@Data
public class DataVO<T> {
    private Integer code;
    private String msg;
    private Integer count;
    private List<T> data;
}

2.2.3、准备 mapper

ProductMapper

@Repository
public interface ProductMapper extends BaseMapper<Product> {
}

ProductCategoryMapper

@Repository
public interface ProductCategoryMapper extends BaseMapper<ProductCategory> {
}

2.2.4、准备 service 及其实现类

ProductService

public interface ProductService {
    /**
     * 获取全部数据(JSON格式)
     * @return
     */
    public DataVO<ProductVO> findData();
}

ProductServiceImpl

@Service
public class ProductServiceImpl implements ProductService {

    @Autowired
    private ProductMapper productMapper;

    @Autowired
    private ProductCategoryMapper productCategoryMapper;

    /**
     * 获取全部数据(JSON格式)
     * @return
     */
    @Override
    public DataVO<ProductVO> findData() {
        DataVO<ProductVO> dataVO = new DataVO<>();
        dataVO.setCode(0);
        dataVO.setMsg("");
        dataVO.setCount(productMapper.selectCount(null));

        List<Product> productList = productMapper.selectList(null);
        List<ProductVO> productVOList = new ArrayList<>();
        for (Product product : productList) {
            // 获取对应商品的一、二、三级分类的字符串并封装
            ProductVO productVO = new ProductVO();
            BeanUtils.copyProperties(product,productVO);
            QueryWrapper wrapper = new QueryWrapper();
            wrapper.eq("id",product.getCategoryleveloneId());
            ProductCategory productCategory = productCategoryMapper.selectOne(wrapper);
            if(productCategory!=null){
                productVO.setCategorylevelone(productCategory.getName());
            }

            wrapper = new QueryWrapper();
            wrapper.eq("id",product.getCategoryleveltwoId());
            productCategory = productCategoryMapper.selectOne(wrapper);
            if(productCategory!=null) {
                productVO.setCategoryleveltwo(productCategory.getName());
            }

            wrapper = new QueryWrapper();
            wrapper.eq("id",product.getCategorylevelthreeId());
            productCategory = productCategoryMapper.selectOne(wrapper);
            if(productCategory!=null) {
                productVO.setCategorylevelthree(productCategory.getName());
            }
            productVOList.add(productVO);
        }

        dataVO.setData(productVOList);
        return dataVO;
    }
}

2.2.5、测试

@SpringBootTest
class ProductMapperTest {

    @Autowired
    private ProductMapper productMapper;

    @Test
    public void test(){
        productMapper.selectList(null).forEach(System.out::println);
    }

}

2.2.6、准备 controller

@RestController
public class ProductController {

    @Autowired
    private ProductService productService;

    @RequestMapping("/list")
    public DataVO<ProductVO> list(){
        return productService.findData();
    }

}

2.3、页面查看数据

2.3.1、准备页面

页面及静态资源位置如下

页面内容

<!DOCTYPE html>
<html>
<head>
    <title></title>
    <link rel="shortcut icon" href="../resources/favicon.ico" th:href="@{/static/favicon.ico}"/>

    <!-- 注意:项目正式环境请勿引用该地址 -->
    <link href="layui/css/layui.css" rel="stylesheet">
</head>

<body>
    <table class="layui-hide" id="test" lay-filter="test"></table>

    <script type="text/html" id="toolbarDemo">
        <div class="layui-btn-container">
            <button class="layui-btn layui-btn-sm" lay-event="getCheckData">获取选中行数据</button>
            <button class="layui-btn layui-btn-sm" lay-event="getCheckLength">获取选中数目</button>
            <button class="layui-btn layui-btn-sm" lay-event="isAll">验证是否全选</button>
        </div>
    </script>
    <script type="text/html" id="barDemo">
        <a class="layui-btn layui-btn-xs" lay-event="edit">编辑</a>
        <a class="layui-btn layui-btn-danger layui-btn-xs" lay-event="del">删除</a>
    </script>


    <!-- 注意:项目正式环境请勿引用该地址 -->
    <script src="layui/layui.js"></script>


    <script>
        layui.use('table', function(){
            var table = layui.table;

            //温馨提示:默认由前端自动合计当前行数据。从 layui 2.5.6 开始: 若接口直接返回了合计行数据,则优先读取接口合计行数据。
            //详见:/docs/modules/index.html#totalRow
            table.render({
                elem: '#test'   // id选择器
                ,url:'http://localhost:8080/list'    // 数据来源的请求地址,这里已经将json数据保存到本地
                ,toolbar: '#toolbarDemo'
                ,title: '用户数据表'  // 导出为excel时的标题
                ,totalRow: true     // 是否统计总数
                ,cols: [
                    [
                        {type: 'checkbox', fixed: 'left'}   // 复选框
                        /*
                         * field:列
                         * title:列名
                         * sort:是否开启升序/降序排列
                         * totalRowText:统计总数的名字
                         * templet:追加标签
                         * totalRow:是否统计该列的总数
                         */
                        ,{field:'id', title:'商品ID', width:150, fixed: 'left', sort: true, totalRowText: '合计'}
                        ,{field:'name', title:'商品名称', width:120}
                        ,{field:'description', title:'商品描述', width:150}
                        ,{field:'price', title:'商品价格', width:150, sort: true, totalRow:true}
                        ,{field:'stock', title:'商品库存', width:150, sort: true, totalRow:true}
                        ,{field:'categorylevelone', title:'一级分类', width:150}
                        ,{field:'categoryleveltwo', title:'二级分类', width:150}
                        ,{field:'categorylevelthree', title:'三级分类', width:150}
                        ,{field:'fileName', title:'商品图片', width:150}
                        ,{fixed: 'right', title:'操作', toolbar: '#barDemo', width:150} // 与操作按钮绑定,每行都会出现编辑、删除按钮
                    ]
                ]
                ,page: true   // 是否开启分页条
            });

            //工具栏事件
            table.on('toolbar(test)', function(obj){
                var checkStatus = index.checkStatus(obj.config.id);
                switch(obj.event){
                    case 'getCheckData':
                        var data = checkStatus.data; // 获取选中的行
                        layer.alert(JSON.stringify(data));
                        break;
                    case 'getCheckLength':
                        var data = checkStatus.data;
                        layer.msg('选中了:'+ data.length + ' 个');
                        break;
                    case 'isAll':
                        layer.msg(checkStatus.isAll ? '全选': '未全选')
                        break;
                };
            });

            //工具条事件,这里是通过表格的 lay-filter="test" 属性绑定
            table.on('tool(test)', function(obj){
                var data = obj.data;
                if(obj.event === 'detail'){
                    layer.msg('ID:'+ data.id + ' 的查看操作');
                } else if(obj.event === 'del'){
                    layer.confirm('真的删除行么', function(index){
                        obj.del();
                        layer.close(index);
                    });
                } else if(obj.event === 'edit'){
                    layer.alert('编辑行:<br>'+ JSON.stringify(data))
                }
            });
        });
    </script>
</body>

</html>

2.3.2、跳转到页面的 controller

@Controller
public class MyController {

    @RequestMapping("/{url}")
    public String toMain(@PathVariable("url") String url){
        return url;
    }

}

至此,运行后访问 localhost:8080/index 即可在页面获得数据

2.4、分页查看数据

2.4.1、页面分页请求地址格式

layui 使用点击分页栏时,会自动生成请求地址,例如 每页10条数据,请求第二页 时,请求地址为 http://localhost:8080/list?page=2&limit=10,如下图所示

 这样就可以通过编写对应接口实现分页

2.5、显示图片

注:若图片无法展开可以将表格的 width 改成一样

2.5.1、创建图片存放的目录

2.5.2、修改页面表格代码

方法一:

,{field:'fileName', title:'商品图片', templet: function (res){
	return '<img src="/images/' + res.fileName + '"/>';
}}

方法二:

① 定义一个标签

    <script type="text/html" id="img">
        <img src="images/{{d.fileName}}"/>
    </script>

② 修改表格

,{field:'fileName', title:'商品图片', width:150, templet: '#img'}

  • 1
    点赞
  • 30
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
Spring Boot 是一个快速开发框架,它提供了一系列的工具和插件,可以快速构建一个企业级的应用程序。而 Shiro 是一个强大而灵活的安全框架,可以提供身份验证、授权、密码加密、会话管理等功能。CAS 是一个单点登录(SSO)协议,可以实现用户在多个应用系统中使用同一个身份验证。 下面是一个简单的 Spring Boot + Shiro + CAS 的示例应用程序: 1. 创建一个 Spring Boot 应用程序,并添加依赖: ```xml <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-spring-boot-web-starter</artifactId> <version>1.5.3</version> </dependency> <dependency> <groupId>org.jasig.cas.client</groupId> <artifactId>cas-client-core</artifactId> <version>3.6.0</version> </dependency> ``` 2. 配置 Shiro: ```java @Configuration public class ShiroConfig { @Bean public CasRealm casRealm() { CasRealm realm = new CasRealm(); realm.setCasServerUrlPrefix("https://cas.example.com/cas"); realm.setCasService("https://myapp.example.com/cas"); realm.setDefaultRoles("user"); realm.setRoleAttributeNames("memberOf"); return realm; } @Bean public DefaultWebSecurityManager securityManager() { DefaultWebSecurityManager manager = new DefaultWebSecurityManager(); manager.setRealm(casRealm()); return manager; } @Bean public ShiroFilterFactoryBean shiroFilter() { ShiroFilterFactoryBean filter = new ShiroFilterFactoryBean(); filter.setSecurityManager(securityManager()); filter.setLoginUrl("https://cas.example.com/cas/login?service=https://myapp.example.com/cas"); filter.setSuccessUrl("/home"); filter.setUnauthorizedUrl("/403"); filter.setFilterChainDefinitionMap(Collections.singletonMap("/**", "authc")); return filter; } } ``` 3. 配置 CAS: ```java @Configuration public class CasConfig { @Bean public CasAuthenticationFilter casAuthenticationFilter() { CasAuthenticationFilter filter = new CasAuthenticationFilter(); filter.setCasServerLoginUrl("https://cas.example.com/cas/login"); filter.setServerName("https://myapp.example.com/cas"); filter.setAuthenticationSuccessHandler(authenticationSuccessHandler()); filter.setAuthenticationFailureHandler(authenticationFailureHandler()); return filter; } @Bean public SimpleUrlAuthenticationSuccessHandler authenticationSuccessHandler() { SimpleUrlAuthenticationSuccessHandler handler = new SimpleUrlAuthenticationSuccessHandler(); handler.setDefaultTargetUrl("/home"); handler.setAlwaysUseDefaultTargetUrl(true); return handler; } @Bean public SimpleUrlAuthenticationFailureHandler authenticationFailureHandler() { SimpleUrlAuthenticationFailureHandler handler = new SimpleUrlAuthenticationFailureHandler(); handler.setDefaultFailureUrl("/login?error=true"); return handler; } @Bean public FilterRegistrationBean<CasAuthenticationFilter> casFilterRegistrationBean() { FilterRegistrationBean<CasAuthenticationFilter> registration = new FilterRegistrationBean<>(); registration.setFilter(casAuthenticationFilter()); registration.addUrlPatterns("/*"); registration.setName("CAS Authentication Filter"); registration.setOrder(1); return registration; } @Bean public ServletListenerRegistrationBean<SingleSignOutHttpSessionListener> singleSignOutHttpSessionListener() { ServletListenerRegistrationBean<SingleSignOutHttpSessionListener> registration = new ServletListenerRegistrationBean<>(); registration.setListener(new SingleSignOutHttpSessionListener()); registration.setOrder(2); return registration; } @Bean public ServletRegistrationBean<Servlet> casValidationServletRegistrationBean() { ServletRegistrationBean<Servlet> registration = new ServletRegistrationBean<>(); registration.setServlet(new Cas20ProxyReceivingTicketValidationFilter()); registration.addUrlMappings("/cas/*"); registration.setName("CAS Validation Filter"); registration.setOrder(3); return registration; } } ``` 4. 创建一个 HomeController: ```java @Controller public class HomeController { @GetMapping("/home") public String home() { return "home"; } @GetMapping("/403") public String error403() { return "403"; } } ``` 5. 创建一个 CAS 认证服务器: ```java @SpringBootApplication public class CasServerApplication { public static void main(String[] args) { SpringApplication.run(CasServerApplication.class, args); } } ``` 6. 创建一个 CAS 客户端: ```java @SpringBootApplication @EnableScheduling public class CasClientApplication { public static void main(String[] args) { SpringApplication.run(CasClientApplication.class, args); } } ``` 这就是一个简单的 Spring Boot + Shiro + CAS 的示例应用程序。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值