瑞吉外卖笔记(分析瑞吉外卖)
1.数据库环境搭建
创建数据库
create database reggie character set utf8mb4;
执行sql命令,注意该脚本不要放在中文目录中。
mysql > source D:/db_reggie.sql
2.maven项目创建
注意检查项目编码,jdk配置,maven配置。
3.定义pom.xml文件
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.4.5</version> <relativePath/> <!-- lookup parent from repository --> </parent> <groupId>com.itheima</groupId> <artifactId>reggie_take_out</artifactId> <version>1.0-SNAPSHOT</version> <properties> <java.version>1.8</java.version> </properties> <dependencies> <!--阿里云短信服务--> <dependency> <groupId>com.aliyun</groupId> <artifactId>aliyun-java-sdk-core</artifactId> <version>4.5.16</version> </dependency> <dependency> <groupId>com.aliyun</groupId> <artifactId>aliyun-java-sdk-dysmsapi</artifactId> <version>2.1.0</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> <scope>compile</scope> </dependency> <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-boot-starter</artifactId> <version>3.4.2</version> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>1.18.20</version> </dependency> <dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> <version>1.2.76</version> </dependency> <dependency> <groupId>commons-lang</groupId> <artifactId>commons-lang</artifactId> <version>2.6</version> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <scope>runtime</scope> </dependency> <!--MyBatis的分页插件--> <dependency> <groupId>com.github.pagehelper</groupId> <artifactId>pagehelper</artifactId> <version>5.1.10</version> </dependency> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid-spring-boot-starter</artifactId> <version>1.1.23</version> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> <version>2.4.5</version> </plugin> </plugins> <!-- 打包时拷贝MyBatis的映射文件 --> <resources> <resource> <directory>src/main/java</directory> <includes> <include>**/*.yml</include> <include>**/sqlmap/*.xml</include> </includes> <filtering>false</filtering> </resource> <resource> <directory>src/main/resources</directory> <includes> <include>**/*.*</include> </includes> <filtering>true</filtering> </resource> </resources> </build> </project>
4.定义springboot配置文件application.yml
server: port: 8080 spring: application: #应用的名称,可选 name: reggie_take_out datasource: druid: driver-class-name: com.mysql.cj.jdbc.Driver url: jdbc:mysql://localhost:3306/xuetoucloud?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=convertToNull&useSSL=false&allowPublicKeyRetrieval=true username: root password: caicai123 max-active: 100 initial-size: 1 max-wait: 60000 min-idle: 1 time-between-eviction-runs-millis: 60000 min-evictable-idle-time-millis: 300000 validation-query: select 'x' test-while-idle: true test-on-borrow: false test-on-return: false pool-prepared-statements: true max-open-prepared-statements: 50 max-pool-prepared-statement-per-connection-size: 20 mybatis-plus: mapper-locations: classpath:/mapper/**.xml configuration: #在映射实体或者属性时,将数据库中表名和字段名中的下划线去掉,按照驼峰命名法映射 map-underscore-to-camel-case: true log-impl: org.apache.ibatis.logging.stdout.StdOutImpl global-config: db-config: id-type: ASSIGN_ID reggie: path: D:\img\
5.启动类
package com.itheima.reggie; import lombok.extern.slf4j.Slf4j; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.web.servlet.ServletComponentScan; import org.springframework.transaction.annotation.EnableTransactionManagement; @Slf4j //@SpringBootApplication(scanBasePackages={"com.itheima.reggie"}) @SpringBootApplication @ServletComponentScan @EnableTransactionManagement public class ReggieApplication { public static void main(String[] args) { SpringApplication.run(ReggieApplication.class,args); log.info("项目启动成功..."); } }
6.配置静态资源映射,访问html、js、css等静态文件。
在config包添加配置
package com.itheima.reggie.config; import com.itheima.reggie.common.JacksonObjectMapper; import lombok.extern.slf4j.Slf4j; import org.springframework.context.annotation.Configuration; import org.springframework.http.converter.HttpMessageConverter; import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter; import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport; import java.util.List; @Slf4j @Configuration public class WebMvcConfig extends WebMvcConfigurationSupport { /** * 设置静态资源映射 * @param registry */ @Override protected void addResourceHandlers(ResourceHandlerRegistry registry) { log.info("开始进行静态资源映射..."); registry.addResourceHandler("/backend/**").addResourceLocations("classpath:/backend/"); registry.addResourceHandler("/front/**").addResourceLocations("classpath:/front/"); } /** * 扩展mvc框架的消息转换器 * @param converters */ @Override protected void extendMessageConverters(List<HttpMessageConverter<?>> converters) { log.info("扩展消息转换器..."); //创建消息转换器对象 MappingJackson2HttpMessageConverter messageConverter = new MappingJackson2HttpMessageConverter(); //设置对象转换器,底层使用Jackson将Java对象转为json messageConverter.setObjectMapper(new JacksonObjectMapper()); //将上面的消息转换器对象追加到mvc框架的转换器集合中 converters.add(0,messageConverter); } }
7.开发登陆功能
package com.itheima.reggie.controller; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.itheima.reggie.common.R; import com.itheima.reggie.entity.Employee; import com.itheima.reggie.service.EmployeeService; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang.StringUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.util.DigestUtils; import org.springframework.web.bind.annotation.*; import javax.servlet.http.HttpServletRequest; import java.time.LocalDateTime; @Slf4j @RestController @RequestMapping("/employee") public class EmployeeController { @Autowired private EmployeeService employeeService; /** * 员工登录 * @param request * @param employee * @return */ @PostMapping("/login") public R<Employee> login(HttpServletRequest request,@RequestBody Employee employee){ //1、将页面提交的密码password进行md5加密处理 String password = employee.getPassword(); password = DigestUtils.md5DigestAsHex(password.getBytes()); //2、根据页面提交的用户名username查询数据库 LambdaQueryWrapper<Employee> queryWrapper = new LambdaQueryWrapper<>(); queryWrapper.eq(Employee::getUsername,employee.getUsername()); Employee emp = employeeService.getOne(queryWrapper); //3、如果没有查询到则返回登录失败结果 if(emp == null){ return R.error("登录失败"); } //4、密码比对,如果不一致则返回登录失败结果 if(!emp.getPassword().equals(password)){ return R.error("登录失败"); } //5、查看员工状态,如果为已禁用状态,则返回员工已禁用结果 if(emp.getStatus() == 0){ return R.error("账号已禁用"); } //6、登录成功,将员工id存入Session并返回登录成功结果 request.getSession().setAttribute("employee",emp.getId()); return R.success(emp); } /** * 员工退出 * @param request * @return */ @PostMapping("/logout") public R<String> logout(HttpServletRequest request){ //清理Session中保存的当前登录员工的id request.getSession().removeAttribute("employee"); return R.success("退出成功"); } }
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>瑞吉外卖管理端</title> <link rel="shortcut icon" href="../../favicon.ico"> <!-- 引入样式 --> <link rel="stylesheet" href="../../plugins/element-ui/index.css" /> <link rel="stylesheet" href="../../styles/common.css"> <link rel="stylesheet" href="../../styles/login.css"> <link rel="stylesheet" href="../../styles/icon/iconfont.css" /> <style> .body{ min-width: 1366px; } </style> </head> <body> <div class="login" id="login-app"> <div class="login-box"> <img src="../../images/login/login-l.png" alt=""> <div class="login-form"> <el-form ref="loginForm" :model="loginForm" :rules="loginRules" > <div class="login-form-title"> <img src="../../images/login/logo.png" style="width:139px;height:42px;" alt="" /> </div> <el-form-item prop="username"> <el-input v-model="loginForm.username" type="text" auto-complete="off" placeholder="账号" maxlength="20" prefix-icon="iconfont icon-user" /> </el-form-item> <el-form-item prop="password"> <el-input v-model="loginForm.password" type="password" placeholder="密码" prefix-icon="iconfont icon-lock" maxlength="20" @keyup.enter.native="handleLogin" /> </el-form-item> <el-form-item style="width:100%;"> <el-button :loading="loading" class="login-btn" size="medium" type="primary" style="width:100%;" @click.native.prevent="handleLogin"> <span v-if="!loading">登录</span> <span v-else>登录中...</span> </el-button> </el-form-item> </el-form> </div> </div> </div> <!-- 开发环境版本,包含了有帮助的命令行警告 --> <script src="../../plugins/vue/vue.js"></script> <!-- 引入组件库 --> <script src="../../plugins/element-ui/index.js"></script> <!-- 引入axios --> <script src="../../plugins/axios/axios.min.js"></script> <script src="../../js/request.js"></script> <script src="../../js/validate.js"></script> <script src="../../api/login.js"></script> <script> new Vue({ el: '#login-app', data() { return { loginForm:{ username: 'admin', password: '123456' }, loading: false } }, computed: { loginRules() { const validateUsername = (rule, value, callback) => { if (value.length < 1 ) { callback(new Error('请输入用户名')) } else { callback() } } const validatePassword = (rule, value, callback) => { if (value.length < 6) { callback(new Error('密码必须在6位以上')) } else { callback() } } return { 'username': [{ 'validator': validateUsername, 'trigger': 'blur' }], 'password': [{ 'validator': validatePassword, 'trigger': 'blur' }] } } }, created() { }, methods: { async handleLogin() { this.$refs.loginForm.validate(async (valid) => { if (valid) { this.loading = true let res = await loginApi(this.loginForm) if (String(res.code) === '1') {//1表示登录成功 localStorage.setItem('userInfo',JSON.stringify(res.data)) window.location.href= '/backend/index.html' } else { this.$message.error(res.msg) this.loading = false } } }) } } }) </script> </body> </html>
function loginApi(data) { return $axios({ 'url': '/employee/login', 'method': 'post', data }) } function logoutApi(){ return $axios({ 'url': '/employee/logout', 'method': 'post', }) }
注意:localStorage在浏览器保存为json数据,表示用户已登录
localStorage.setItem('userInfo',JSON.stringify(res.data))
登陆成功之后做页面跳转
window.location.href= '/backend/index.html'
8.定义员工表实体类,用来和数据库映射
package com.itheima.reggie.entity; import com.baomidou.mybatisplus.annotation.FieldFill; import com.baomidou.mybatisplus.annotation.TableField; import lombok.Data; import java.io.Serializable; import java.time.LocalDateTime; /** * 员工实体 */ @Data public class Employee implements Serializable { private static final long serialVersionUID = 1L; private Long id; private String username; private String name; private String password; private String phone; private String sex; private String idNumber;//身份证号码 private Integer status; @TableField(fill = FieldFill.INSERT) //插入时填充字段 private LocalDateTime createTime; @TableField(fill = FieldFill.INSERT_UPDATE) //插入和更新时填充字段 private LocalDateTime updateTime; @TableField(fill = FieldFill.INSERT) //插入时填充字段 private Long createUser; @TableField(fill = FieldFill.INSERT_UPDATE) //插入和更新时填充字段 private Long updateUser; }
9.登陆代码开发,Controller,Service,Mapper
Controller
package com.itheima.reggie.controller; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.itheima.reggie.common.R; import com.itheima.reggie.entity.Employee; import com.itheima.reggie.service.EmployeeService; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang.StringUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.util.DigestUtils; import org.springframework.web.bind.annotation.*; import javax.servlet.http.HttpServletRequest; import java.time.LocalDateTime; @Slf4j @RestController @RequestMapping("/employee") public class EmployeeController { @Autowired private EmployeeService employeeService; /** * 员工登录 * @param request * @param employee * @return */ @PostMapping("/login") public R<Employee> login(HttpServletRequest request,@RequestBody Employee employee){ //1、将页面提交的密码password进行md5加密处理 String password = employee.getPassword(); password = DigestUtils.md5DigestAsHex(password.getBytes()); //2、根据页面提交的用户名username查询数据库 LambdaQueryWrapper<Employee> queryWrapper = new LambdaQueryWrapper<>(); queryWrapper.eq(Employee::getUsername,employee.getUsername()); Employee emp = employeeService.getOne(queryWrapper); //3、如果没有查询到则返回登录失败结果 if(emp == null){ return R.error("登录失败"); } //4、密码比对,如果不一致则返回登录失败结果 if(!emp.getPassword().equals(password)){ return R.error("登录失败"); } //5、查看员工状态,如果为已禁用状态,则返回员工已禁用结果 if(emp.getStatus() == 0){ return R.error("账号已禁用"); } //6、登录成功,将员工id存入Session并返回登录成功结果 request.getSession().setAttribute("employee",emp.getId()); return R.success(emp); } /** * 员工退出 * @param request * @return */ @PostMapping("/logout") public R<String> logout(HttpServletRequest request){ //清理Session中保存的当前登录员工的id request.getSession().removeAttribute("employee"); return R.success("退出成功"); } /** * 新增员工 * @param employee * @return */ @PostMapping public R<String> save(HttpServletRequest request,@RequestBody Employee employee){ log.info("新增员工,员工信息:{}",employee.toString()); //设置初始密码123456,需要进行md5加密处理 employee.setPassword(DigestUtils.md5DigestAsHex("123456".getBytes())); // employee.setCreateTime(LocalDateTime.now()); // employee.setUpdateTime(LocalDateTime.now()); // // //获得当前登录用户的id // Long empId = (Long) request.getSession().getAttribute("employee"); // employee.setCreateUser(empId); // employee.setUpdateUser(empId); employeeService.save(employee); return R.success("新增员工成功"); } /** * 员工信息分页查询 * @param page * @param pageSize * @param name * @return */ @GetMapping("/page") public R<Page> page(int page, int pageSize, String name){ log.info("page = {},pageSize = {},name = {}" ,page,pageSize,name); Long id = Thread.currentThread().getId(); log.info("线程ID{}",id); //构造分页构造器 Page pageInfo = new Page(page,pageSize); //构造条件构造器 LambdaQueryWrapper<Employee> queryWrapper = new LambdaQueryWrapper(); //添加过滤条件 queryWrapper.like(StringUtils.isNotEmpty(name),Employee::getName,name); //添加排序条件 queryWrapper.orderByDesc(Employee::getUpdateTime); //执行查询 employeeService.page(pageInfo,queryWrapper); return R.success(pageInfo); } /** * 根据id修改员工信息 * @param employee * @return */ @PutMapping public R<String> update(HttpServletRequest request,@RequestBody Employee employee){ log.info(employee.toString()); Long id = Thread.currentThread().getId(); log.info("线程ID{}",id); Long empId = (Long)request.getSession().getAttribute("employee"); //employee.setUpdateTime(LocalDateTime.now()); //employee.setUpdateUser(empId); employeeService.updateById(employee); return R.success("员工信息修改成功"); } /** * 根据id查询员工信息 * @param id * @return */ @GetMapping("/{id}") public R<Employee> getById(@PathVariable Long id){ log.info("根据id查询员工信息..."); Employee employee = employeeService.getById(id); if(employee != null){ return R.success(employee); } return R.error("没有查询到对应员工信息"); } }
Service
package com.itheima.reggie.service; import com.baomidou.mybatisplus.extension.service.IService; import com.itheima.reggie.entity.Employee; public interface EmployeeService extends IService<Employee> { }
EmployeeServiceImpl
package com.itheima.reggie.service.impl; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.itheima.reggie.entity.Employee; import com.itheima.reggie.mapper.EmployeeMapper; import com.itheima.reggie.service.EmployeeService; import org.springframework.stereotype.Service; @Service public class EmployeeServiceImpl extends ServiceImpl<EmployeeMapper,Employee> implements EmployeeService{ }
10.通用返回结果类
使用方式举例,
返回成功结果,return R.success(employee);
返回失败信息,return R.error("没有查询到对应员工信息");
定义编码code,1表示成功,0和其它数字为失败
package com.itheima.reggie.common; import lombok.Data; import java.util.HashMap; import java.util.Map; /** * 通用返回结果,服务端响应的数据最终都会封装成此对象 * @param <T> */ @Data public class R<T> { private Integer code; //编码:1成功,0和其它数字为失败 private String msg; //错误信息 private T data; //数据 private Map map = new HashMap(); //动态数据 public static <T> R<T> success(T object) { R<T> r = new R<T>(); r.data = object; r.code = 1; return r; } public static <T> R<T> error(String msg) { R r = new R(); r.msg = msg; r.code = 0; return r; } public R<T> add(String key, Object value) { this.map.put(key, value); return this; } }
@PostMapping("/login") public R<Employee> login(HttpServletRequest request,@RequestBody Employee employee){
post请求传递json数据,请加注解@RequestBody
//6、登录成功,将员工id存入Session并返回登录成功结果 request.getSession().setAttribute("employee",emp.getId()); return R.success(emp);
11.员工退出
/** * 员工退出 * @param request * @return */ @PostMapping("/logout") public R<String> logout(HttpServletRequest request){ //清理Session中保存的当前登录员工的id request.getSession().removeAttribute("employee"); return R.success("退出成功"); }
12.首页
使用vue中的data的menuList生成左侧导航
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta http-equiv="X-UA-Compatible" content="IE=edge" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>瑞吉外卖管理端</title> <link rel="shortcut icon" href="favicon.ico"> <!-- 引入样式 --> <link rel="stylesheet" href="plugins/element-ui/index.css" /> <link rel="stylesheet" href="styles/common.css" /> <link rel="stylesheet" href="styles/index.css" /> <link rel="stylesheet" href="styles/icon/iconfont.css" /> <style> .body{ min-width: 1366px; } .app-main{ height: calc(100% - 64px); } .app-main .divTmp{ width: 100%; height: 100%; } </style> </head> <body> <div class="app" id="app"> <div class="app-wrapper openSidebar clearfix"> <!-- sidebar --> <div class="sidebar-container"> <div class="logo"> <!-- <img src="images/logo.png" width="122.5" alt="" /> --> <img src="images/login/login-logo.png" alt="" style="width: 117px; height: 32px" /> </div> <el-scrollbar wrap-class="scrollbar-wrapper"> <el-menu :default-active="defAct" :unique-opened="false" :collapse-transition="false" background-color="#343744" text-color="#bfcbd9" active-text-color="#f4f4f5" > <div v-for="item in menuList" :key="item.id"> <el-submenu :index="item.id" v-if="item.children && item.children.length>0"> <template slot="title"> <i class="iconfont" :class="item.icon"></i> <span>{{item.name}}</span> </template> <el-menu-item v-for="sub in item.children" :index="sub.id" :key="sub.id" @click="menuHandle(sub,false)" > <i :class="iconfont" :class="sub.icon"></i> <span slot="title">{{sub.name}}</span> </el-menu-item > </el-submenu> <el-menu-item v-else :index="item.id" @click="menuHandle(item,false)"> <i class="iconfont" :class="item.icon"></i> <span slot="title">{{item.name}}</span> </el-menu-item> </div> </el-menu> </el-scrollbar> </div> <div class="main-container"> <!-- <navbar /> --> <div class="navbar"> <div class="head-lable"> <span v-if="goBackFlag" class="goBack" @click="goBack()" ><img src="images/icons/[email protected]" alt="" /> 返回</span > <span>{{headTitle}}</span> </div> <div class="right-menu"> <div class="avatar-wrapper">{{ userInfo.name }}</div> <!-- <div class="logout" @click="logout">退出</div> --> <img src="images/icons/[email protected]" class="outLogin" alt="退出" @click="logout" /> </div> </div> <div class="app-main" v-loading="loading"> <div class="divTmp" v-show="loading"></div> <iframe id="cIframe" class="c_iframe" name="cIframe" :src="iframeUrl" width="100%" height="auto" frameborder="0" v-show="!loading" ></iframe> </div> </div> </div> </div> <!-- 开发环境版本,包含了有帮助的命令行警告 --> <script src="plugins/vue/vue.js"></script> <!-- 引入组件库 --> <script src="plugins/element-ui/index.js"></script> <!-- 引入axios --> <script src="plugins/axios/axios.min.js"></script> <script src="js/request.js"></script> <script src="./api/login.js"></script> <script> new Vue({ el: '#app', data() { return { defAct: '2', menuActived: '2', userInfo: {}, menuList: [ // { // id: '1', // name: '门店管理', // children: [ { id: '2', name: '员工管理', url: 'page/member/list.html', icon: 'icon-member' }, { id: '3', name: '分类管理', url: 'page/category/list.html', icon: 'icon-category' }, { id: '4', name: '菜品管理', url: 'page/food/list.html', icon: 'icon-food' }, { id: '5', name: '套餐管理', url: 'page/combo/list.html', icon: 'icon-combo' }, { id: '6', name: '订单列表', url: 'page/order/list.html', icon: 'icon-order' }, { id: '7', name: '订单明细', url: 'page/order/list2.html', icon: 'icon-order' } // ], // }, ], iframeUrl: 'page/member/list.html', headTitle: '员工管理', goBackFlag: false, loading: true, timer: null } }, computed: {}, created() { const userInfo = window.localStorage.getItem('userInfo') if (userInfo) { this.userInfo = JSON.parse(userInfo) } this.closeLoading() }, beforeDestroy() { this.timer = null clearTimeout(this.timer) }, mounted() { window.menuHandle = this.menuHandle }, methods: { logout() { logoutApi().then((res)=>{ if(res.code === 1){ localStorage.removeItem('userInfo') window.location.href = '/backend/page/login/login.html' } }) }, goBack() { // window.location.href = 'javascript:history.go(-1)' const menu = this.menuList.find(item=>item.id===this.menuActived) // this.goBackFlag = false // this.headTitle = menu.name this.menuHandle(menu,false) }, menuHandle(item, goBackFlag) { this.loading = true this.menuActived = item.id this.iframeUrl = item.url this.headTitle = item.name this.goBackFlag = goBackFlag this.closeLoading() }, closeLoading(){ this.timer = null this.timer = setTimeout(()=>{ this.loading = false },1000) } } }) </script> </body> </html>
使用v-for遍历菜单列表生成菜单
<div v-for="item in menuList" :key="item.id"> <el-submenu :index="item.id" v-if="item.children && item.children.length>0"> <template slot="title"> <i class="iconfont" :class="item.icon"></i> <span>{{item.name}}</span> </template> <el-menu-item v-for="sub in item.children" :index="sub.id" :key="sub.id" @click="menuHandle(sub,false)" > <i :class="iconfont" :class="sub.icon"></i> <span slot="title">{{sub.name}}</span> </el-menu-item > </el-submenu> <el-menu-item v-else :index="item.id" @click="menuHandle(item,false)"> <i class="iconfont" :class="item.icon"></i> <span slot="title">{{item.name}}</span> </el-menu-item> </div>
菜单单击事件
menuHandle(item, goBackFlag) { this.loading = true this.menuActived = item.id this.iframeUrl = item.url this.headTitle = item.name this.goBackFlag = goBackFlag this.closeLoading() }
iframe显示网页
<div class="app-main" v-loading="loading"> <div class="divTmp" v-show="loading"></div> <iframe id="cIframe" class="c_iframe" name="cIframe" :src="iframeUrl" width="100%" height="auto" frameborder="0" v-show="!loading" ></iframe> </div>
13.禁止未登录进行访问
创建过滤器LoginCheckFilter
package com.itheima.reggie.filter; import com.alibaba.fastjson.JSON; import com.itheima.reggie.common.BaseContext; import com.itheima.reggie.common.R; import lombok.extern.slf4j.Slf4j; import org.springframework.util.AntPathMatcher; import javax.servlet.*; import javax.servlet.annotation.WebFilter; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; /** * 检查用户是否已经完成登录 */ @WebFilter(filterName = "loginCheckFilter",urlPatterns = "/*") @Slf4j public class LoginCheckFilter implements Filter{ //路径匹配器,支持通配符 public static final AntPathMatcher PATH_MATCHER = new AntPathMatcher(); @Override public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { HttpServletRequest request = (HttpServletRequest) servletRequest; HttpServletResponse response = (HttpServletResponse) servletResponse; //1、获取本次请求的URI String requestURI = request.getRequestURI();// /backend/index.html log.info("拦截到请求:{}",requestURI); //定义不需要处理的请求路径 String[] urls = new String[]{ "/employee/login", "/employee/logout", "/backend/**", "/front/**", "/common/**", "/user/sendMsg", "/user/login" }; //2、判断本次请求是否需要处理 boolean check = check(urls, requestURI); //3、如果不需要处理,则直接放行 if(check){ log.info("本次请求{}不需要处理",requestURI); filterChain.doFilter(request,response); return; } //4、判断登录状态,如果已登录,则直接放行 if(request.getSession().getAttribute("employee") != null){ log.info("用户已登录,用户id为:{}",request.getSession().getAttribute("employee")); Long id = Thread.currentThread().getId(); log.info("线程ID{}",id); BaseContext.setCurrentId((Long) request.getSession().getAttribute("employee")); filterChain.doFilter(request,response); return; } //4-2、判断登录状态,如果已登录,则直接放行 if(request.getSession().getAttribute("user") != null){ log.info("用户已登录,用户id为:{}",request.getSession().getAttribute("user")); Long userId = (Long) request.getSession().getAttribute("user"); BaseContext.setCurrentId(userId); filterChain.doFilter(request,response); return; } log.info("用户未登录"); //5、如果未登录则返回未登录结果,通过输出流方式向客户端页面响应数据 response.getWriter().write(JSON.toJSONString(R.error("NOTLOGIN"))); return; } /** * 路径匹配,检查本次请求是否需要放行 * @param urls * @param requestURI * @return */ public boolean check(String[] urls,String requestURI){ for (String url : urls) { boolean match = PATH_MATCHER.match(url, requestURI); if(match){ return true; } } return false; } }
在启动类添加@ServletComponentScan才能扫描过滤器。
@Slf4j //@SpringBootApplication(scanBasePackages={"com.itheima.reggie"}) @SpringBootApplication @ServletComponentScan @EnableTransactionManagement public class ReggieApplication { public static void main(String[] args) { SpringApplication.run(ReggieApplication.class,args); log.info("项目启动成功..."); } }
版权声明:
作者: freeclashnode
链接: https://www.freeclashnode.com/news/article-1739.htm
来源: FreeClashNode
文章版权归作者所有,未经允许请勿转载。
热门文章
- 9月1日|21M/S,Shadowrocket/SSR/V2ray/Clash免费节点订阅链接每天更新
- 9月15日|20.4M/S,Shadowrocket/V2ray/SSR/Clash免费节点订阅链接每天更新
- 8月31日|20.3M/S,V2ray/Shadowrocket/SSR/Clash免费节点订阅链接每天更新
- 8月30日|22.8M/S,SSR/Clash/Shadowrocket/V2ray免费节点订阅链接每天更新
- 8月29日|22.2M/S,V2ray/Clash/SSR/Shadowrocket免费节点订阅链接每天更新
- 8月24日|19.3M/S,Shadowrocket/V2ray/Clash/SSR免费节点订阅链接每天更新
- 9月2日|21.4M/S,SSR/Shadowrocket/Clash/V2ray免费节点订阅链接每天更新
- 8月28日|20.4M/S,SSR/Clash/Shadowrocket/V2ray免费节点订阅链接每天更新
- 8月27日|21.5M/S,Clash/V2ray/SSR/Shadowrocket免费节点订阅链接每天更新
- 9月16日|18M/S,SSR/Shadowrocket/Clash/V2ray免费节点订阅链接每天更新
最新文章
- 9月20日|19.4M/S,V2ray/SSR/Shadowrocket/Clash免费节点订阅链接每天更新
- 9月19日|23M/S,Clash/SSR/Shadowrocket/V2ray免费节点订阅链接每天更新
- 9月18日|22.9M/S,Clash/Shadowrocket/V2ray/SSR免费节点订阅链接每天更新
- 9月17日|21.6M/S,SSR/Shadowrocket/V2ray/Clash免费节点订阅链接每天更新
- 9月16日|18M/S,SSR/Shadowrocket/Clash/V2ray免费节点订阅链接每天更新
- 9月15日|20.4M/S,Shadowrocket/V2ray/SSR/Clash免费节点订阅链接每天更新
- 9月14日|20M/S,Shadowrocket/SSR/Clash/V2ray免费节点订阅链接每天更新
- 9月13日|22.3M/S,Shadowrocket/V2ray/Clash/SSR免费节点订阅链接每天更新
- 9月12日|22.9M/S,Clash/V2ray/Shadowrocket/SSR免费节点订阅链接每天更新
- 9月11日|20.4M/S,Shadowrocket/Clash/SSR/V2ray免费节点订阅链接每天更新