1.Filter原理
1.编写DemoFilter类实现Filter接口
在web服务器启动时会自动创建filter对象,需要调用init方法(初始方法),只调用一次。destroy方法(销毁方法)也只调用一次,但是doFilter方法一次请求调用一次,会调用多次。
测试的代码如下:
package com.liuxiaocan.finalwork.Filter;
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import java.io.IOException;
@WebFilter(urlPatterns ="/*" )//定义过滤器要拦截什么请求,/*是所有请求
public class DemoFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
Filter.super.init(filterConfig);
System.out.println("初始化成功!!!!");
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
System.out.println("过滤启动!!!!");
}
@Override
public void destroy() {
Filter.super.destroy();
System.out.println("销毁成功!!!!");
}
}
当运行程序时会输出对应的语句表示过滤器已经初始化成功,访问前端页面时会运行doFilter方法,输出对应的语句。
Filter的放行操作代码:
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
System.out.println("过滤启动!!!!");
filterChain.doFilter(servletRequest,servletResponse);//放行操作,允许访问对应操作
}
2.过滤器的详细内容
1.过滤器的执行过程
在过滤器中放行以后访问了对应的接口以后还会回到过滤器中,但是是执行放行操作之后的步骤。
2.过滤器的拦截路径
拦截具体路径:
@WebFilter(urlPatterns ="/loginnn" )//定义过滤器要拦截什么请求,/*是所有请求
public class DemoFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
Filter.super.init(filterConfig);
System.out.println("初始化成功!!!!");
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
System.out.println("过滤启动!!!!");
filterChain.doFilter(servletRequest,servletResponse);//放行操作,允许访问对应操作
System.out.println("放行后!!!!");
}
@Override
public void destroy() {
Filter.super.destroy();
System.out.println("销毁成功!!!!");
}
}
登录成功后输出如下内容:
3.过滤器链
在一个web应用中配置了多个过滤器,多个过滤器就形成了一个过滤器链。在过滤器链的执行过程中,先执行第一个过滤器,再执行第二个过滤器,放行后先回到第二个过滤器,再回到第一个过滤器。执行顺序按照过滤器类名的排序。
2.实施登陆验证功能
先发起一个请求,获取请求路径,如果请求路径是登录路径则直接放行不用进行登陆验证。如果不是登录界面则获取请求头的令牌token,如果令牌存在且有效则直接放行,如果令牌不存在且令牌无效则返回未登录的提示。
测试Filter过滤器的功能:
package com.liuxiaocan.finalwork.Filter;
import com.alibaba.fastjson.JSONObject;
import com.liuxiaocan.finalwork.Pojo.Result;
import com.liuxiaocan.finalwork.Utils.JwtUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.StringUtils;
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@Slf4j
@WebFilter(urlPatterns = "/*")
public class LoginFilter implements Filter {
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
//获取请求路径
HttpServletRequest request=(HttpServletRequest) servletRequest;
HttpServletResponse response=(HttpServletResponse) servletResponse;
String requestURL = request.getRequestURL().toString();
log.info(requestURL);
//判断是不是登录路径
if(requestURL.contains("login")){
log.info("登录操作直接放行");
filterChain.doFilter(request,response);
return;//让代码不用继续执行
}
//获取请求头的token
String token = request.getHeader("token");
//判断token是否存在,不存在的处理过程
if(!StringUtils.hasLength(token)){
log.info("请求头为空");
Result r=Result.error("not_login");
//把r转化成json格式数据
String s = JSONObject.toJSONString(r);
response.getWriter().write(s);//响应json格式的字符串
return;
}
//校验jwt令牌是否有效
try {
JwtUtils.parseJWT(token);
}catch (Exception e){
e.printStackTrace();
log.info("解析失败!返回错误");
Result r=Result.error("not_login");
//把r转化成json格式数据
String s = JSONObject.toJSONString(r);
response.getWriter().write(s);//响应json格式的字符串
return;
}
//放行
log.info("成功放行!!!");
filterChain.doFilter(request, response);
}
}
实现前端页面之间的token传递:
show.html:
主要在分页展示接口中传递了token请求头,实现token的传递。在删除操作和搜索的接口也需要传递令牌实现认证。
show(){
axios(`/page/${this.pageSize}/${this.currentPage}`, { headers: {//传递token
'token': this.token
}}).then(r=>{
if(r.data.statusCode==1){
this.ComponentData=r.data.data.rows;
this.total=r.data.data.total;
}
}).catch(error=>{
console.error(error);
})
},
SSubmit(){
axios.get(`/search/${this.pageSize}/${this.currentPage}?cno=${this.form.cno}&cname=${this.form.cname}&csize=${this.form.csize}`,{
headers:{
'token':this.token,
}
}).then(r=>{
if(r.data.statusCode==1){
this.ComponentData=r.data.data.rows;
this.total=r.data.data.total;
}
}).catch(error=>{
console.error(error);
})
},
deleteall(){
if(window.confirm("确定要删除吗?")){
axios.post("/DeleteAll",
this.List,{headers: {
'token':this.token,
'Content-Type': 'application/json'
}}).then(r=>{
if(r.data.statusCode==1){
window.alert("删除成功!")
this.show();
}
}).catch(error=>{
console.error(error);
})
}
},
created(){
this.token= localStorage.getItem("Token") || ""//获取Token值
this.show();
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="./js/vue.js"></script>
<script src="./js/axios-0.18.0.js"></script>
<link rel="stylesheet" href="element-ui/index.css">
<script src="./element-ui/index.js"></script>
</head>
<body style="margin-top:0px;margin-left: 0px;margin-right: 0px">
<div id="app" >
<div v-if="token && token.trim()">
<el-menu
:default-active="activeIndex2"
class="el-menu-demo"
mode="horizontal"
@select="handleSelect"
background-color="#1C86EE"
text-color="#fff"
active-text-color="#C1CDCD">
<el-menu-item index="1">仓库信息</el-menu-item>
<el-menu-item index="2">
<el-link :underline="false" href="show.html" >零件信息</el-link>
</el-menu-item>
<el-menu-item index="3" >职工信息</el-menu-item>
<el-menu-item index="4">供应商信息</el-menu-item>
</el-menu>
<div style="text-align:center">
<h1 style="text-align: center">零件信息表</h1>
<p align="center">
<el-form :inline="true" :model="form" class="demo-form-inline">
<el-form-item label="零件号">
<el-input v-model="form.cno" placeholder="零件号"></el-input>
</el-form-item>
<el-form-item label="零件名">
<el-input v-model="form.cname" placeholder="零件名"></el-input>
</el-form-item>
<el-form-item label="尺寸">
<el-input v-model="form.csize" placeholder="尺寸"></el-input>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="SSubmit">查询</el-button>
</el-form-item>
</el-form>
</p>
</div>
<el-table
:data="ComponentData"
style="width: 80%;margin: auto " ref="multipleTable" @selection-change="handleSelectionChange">
<el-table-column type="selection" width="55" align="center">
</el-table-column>
<el-table-column
align="center"
label="零件号"
prop="cno">
</el-table-column>
<el-table-column
align="center"
label="零件名"
prop="cname">
</el-table-column>
<el-table-column
align="center"
label="尺寸"
prop="csize">
</el-table-column>
<el-table-column
align="center"
label="单价"
prop="cprice">
</el-table-column>
<el-table-column
align="center"
label="描述"
prop="ctext">
</el-table-column>
<el-table-column
align="center"
label="操作">
<!-- <template slot="header" slot-scope="scope">-->
<!-- <el-input-->
<!-- v-model="search"-->
<!-- size="mini"-->
<!-- placeholder="输入关键字搜索"/>-->
<!-- </template>-->
<template slot-scope="scope">
<el-button
size="mini"
type="success"
@click="handleEdit(scope.row)">编辑</el-button>
<el-button
size="mini"
type="danger"
@click="handleDelete(scope.row)">删除</el-button>
</template>
</el-table-column>
</el-table>
<div style="width: 80%;margin: auto;margin-top: 10px" ><el-button type="primary" plain v-on:click="JumpOff">添加零件</el-button>
<el-button type="danger" plain v-on:click="deleteall">批量删除</el-button>
</div>
<div style="text-align: center">
<el-pagination
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
:current-page.sync="currentPage"
:page-sizes="[5, 10, 15, 20,25]"
:page-size="pageSize"
layout="sizes, prev, pager, next"
:total="total">
</el-pagination>
</div>
</div>
<div v-if="!token">
<a href="first.html" style="text-decoration: none;">点击登录!!!</a>
</div>
</div>
<script>
new Vue({
el:"#app",
data(){
return{
ComponentData:[],
search:'',
currentPage: 1,// 当前页码
pageSize:5,
total:100,
index:'',
form:{
cno:'',
cname:'',
csize:''
},
multipleSelection: [],
List:[],
// login1:{
// }
token:''
}
},
methods:{
handleEdit(row) {
window.location.href="update.html?con="+row.cno;
},
handleDelete(row) {
if(window.confirm("你确定要删除这条数据吗?")){
axios.post(`/delete/${row.cno}`).then(r=>{
if(r.data.statusCode==1){
alert("删除成功!")
this.show();
}
}).catch(error=>{
console.error(error);
})
}
},
handleSizeChange(val) {
this.pageSize=val;
this.show();
},
handleCurrentChange(val) {
this.currentPage =val;
this.show();
},
show(){
axios(`/page/${this.pageSize}/${this.currentPage}`, { headers: {//传递token
'token': this.token
}}).then(r=>{
if(r.data.statusCode==1){
this.ComponentData=r.data.data.rows;
this.total=r.data.data.total;
}
}).catch(error=>{
console.error(error);
})
},
JumpOff(){
window.location.href="insert.html"
},
SSubmit(){
axios.get(`/search/${this.pageSize}/${this.currentPage}?cno=${this.form.cno}&cname=${this.form.cname}&csize=${this.form.csize}`,{
headers:{
'token':this.token,
}
}).then(r=>{
if(r.data.statusCode==1){
this.ComponentData=r.data.data.rows;
this.total=r.data.data.total;
}
}).catch(error=>{
console.error(error);
})
},
deleteall(){
if(window.confirm("确定要删除吗?")){
axios.post("/DeleteAll",
this.List,{headers: {
'token':this.token,
'Content-Type': 'application/json'
}}).then(r=>{
if(r.data.statusCode==1){
window.alert("删除成功!")
this.show();
}
}).catch(error=>{
console.error(error);
})
}
},
handleSelectionChange(val){
this.multipleSelection=val;
this.List = this.multipleSelection.map(m => m.cno);
}
},
created(){
this.token= localStorage.getItem("Token") || ""//获取Token值
this.show();
}
})
</script>
</body>
</html>
update.html修改变动的部分:
update(){
axios.post("/update",JSON.stringify(this.componentlist),{headers: {
'Content-Type': 'application/json',
'token':this.token
}}).then((r)=>{
if(r.data.statusCode==1){
location.href='show.html';
console.log(JSON.stringify(this.componentlist))
}
else{
console.log(r.data.message);
}
}).catch(error=>{
console.error(error);
})
}
},
insert.html修改的部分:
addP(){
if (Object.keys(this.Plist).length === 0) {
alert('请输入零件信息!');
return;
}
axios.post("/insert",this.Plist,{
headers:{
"token":this.token,
'Content-Type': 'application/json'
}
}).then(r=>{
console.log(r.data);
if(r.data.statusCode==1){
alert("插入成功!")
location.href='show.html';
}
else{
console.log(r.data.message);
}
}).catch(error=>{
console.error(error);
})
}
},
mounted(){
this.token=localStorage.getItem("Token") || ""
// axios.get("/login1").then(r=>{
// this.login=r.data;
// console.log(this.login);
// }).catch(error=>{
// console.log(error);
// })
}
})
3.Apifox的使用
自动生成接口文档如下:
生成的markdown文档: