0
点赞
收藏
分享

微信扫一扫

书城项目第八阶段:使用Filter过滤器实现后台的权限管理


书城项目第八阶段:使用Filter过滤器实现后台的权限管理

  • ​​7、书城第八阶段​​
  • ​​1、使用Filter过滤器拦截/pages/manager/所有内容,实现权限检查​​
  • ​​新建com.atguigu/filter/MangerFilter​​
  • ​​配置web.xml​​
  • ​​2、ThreadLocal的使用​​
  • ​​新建tmp/src/threadlocal/ThreadLocalTest​​
  • ​​新建threadlocal/OrderService​​
  • ​​新建threadlocal/OrderDao​​
  • ​​结果​​
  • ​​3、使用Filter和ThreadLocal组合管理事务​​
  • ​​3.1 使用ThreadLocal确保所有操作都使用同一个Connection来实现​​
  • ​​验证是否为同一线程​​
  • ​​修改 OrderServiceImpl 模拟错误​​
  • ​​结果 网页,添加购物车去结账​​
  • ​​原理​​
  • ​​修改 JdbcUtils​​
  • ​​修改 JdbcUtilsTest​​
  • ​​修改 BaseDao​​
  • ​​修改 OrderServlet​​
  • ​​结果 网页,添加购物车去结账​​
  • ​​3.2、使用Filter统一给所有Service方法都加上try-catch来实现管理事务​​
  • ​​新建 filter/TransactionFilter​​
  • ​​配置web.xml​​
  • ​​修改 OrderServlet​​
  • ​​修改 BaseServlet​​
  • ​​3.3、将所有异常都交给Tomcat,让Tomcat显示友好的错误信息页面​​
  • ​​新建 pages/error/error500.jsp​​
  • ​​并配置 web.xml​​
  • ​​修改 TransactionFilter​​
  • ​​新建error/error404.jsp​​
  • ​​配置web.xml​​

7、书城第八阶段

1、使用Filter过滤器拦截/pages/manager/所有内容,实现权限检查

新建com.atguigu/filter/MangerFilter

package com.atguigu.filter;

import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;

public class ManageFilter implements Filter {

@Override
public void init(FilterConfig filterConfig) throws ServletException {

}

@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
HttpServletRequest httpServletRequest= (HttpServletRequest) servletRequest;
Object user = httpServletRequest.getSession().getAttribute("user");
if (user==null){
httpServletRequest.getRequestDispatcher("/pages/user/login.jsp").forward(servletRequest,servletResponse);
}else {
filterChain.doFilter(servletRequest,servletResponse);
}

}

@Override
public void destroy() {

}
}

配置web.xml

<filter>
<filter-name>ManageFilter</filter-name>
<filter-class>com.atguigu.filter.ManageFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>ManageFilter</filter-name>
<url-pattern>/pages/manager/*</url-pattern>
<url-pattern>/manager/bookServlet</url-pattern>
</filter-mapping>

2、ThreadLocal的使用

ThreadLocal的作用,它可以解决多线程的数据安全问题。
ThreadLocal它可以给当前线程关联一个数据(可以是普通变量,可以是对象,也可以是数组,集合)
Threadlocal的特点:
1、Threadlocal可以为当前线程关联一个数据。(它可以像Map一样存取数据,key为当前线程)
2、每一个Threadlocal对象,只能为当前线程关联一个数据,如果要为当前线程关联多个数据,就需要使用多个 Threadlocal对象实例。
3、每个Threadlocal对象实例定义的时候,一般都是static类型
4、Threadlocal中保存数据,在线程销毁后。会由JVM虚拟自动释放。

新建tmp/src/threadlocal/ThreadLocalTest

package threadlocal;

import java.util.Random;

public class ThreadLocalTest {
// public final static Map<String,Object> data=new ConcurrentHashMap<>();线程安全
// public final static Map<String,Object> data=new Hashtable<>();
public static ThreadLocal<Object> threadLocal=new ThreadLocal<>();
private static Random random=new Random();
public static class Task implements Runnable{

@Override
public void run() {

// threadLocal.set("abc");
// threadLocal.set("bbj");
// System.out.println(threadLocal.get());//bbj 覆盖



//在run方法中 ,随机生成一个变量(线程要关联的数据),然后一当前线程名为key保存到map中
Integer i = random.nextInt(1000);
//获取当前线程名
String name = Thread.currentThread().getName();
System.out.println("线程["+name+"]生成的随机数是:"+i);
// data.put(name,i);
threadLocal.set(i);
//模拟操作
// try {
// Thread.sleep(3000);
// } catch (InterruptedException e) {
// e.printStackTrace();
// }

new OrderService().createOrder();

//在Run方法结束之前,以当前线程名获取出数据并打印。查看是否可以取出操作
// Object o = data.get(name);
Object o=threadLocal.get();
System.out.println("线程["+name+"]快结束时取出关联的数据是:"+o);

}
}

public static void main(String[] args) {
for (int i = 0; i < 3; i++) {
new Thread(new Task()).start();
}
}
}

新建threadlocal/OrderService

package threadlocal;

public class OrderService {
public void createOrder(){
String name = Thread.currentThread().getName();
System.out.println("OrderService 当前线程["+name+"]中保存的数据是:"+ThreadLocalTest.threadLocal.get());
new OrderDao().saveOrder();

}
}

新建threadlocal/OrderDao

package threadlocal;

public class OrderDao {
public void saveOrder(){
String name = Thread.currentThread().getName();
// System.out.println("OrderDao 当前线程["+name+"]中保存的数据是:"+ThreadLocalTest.data.get(name));
System.out.println("OrderDao 当前线程["+name+"]中保存的数据是:"+ThreadLocalTest.threadLocal.get());

}
}

结果

书城项目第八阶段:使用Filter过滤器实现后台的权限管理_java

3、使用Filter和ThreadLocal组合管理事务

3.1 使用ThreadLocal确保所有操作都使用同一个Connection来实现

验证是否为同一线程

书城项目第八阶段:使用Filter过滤器实现后台的权限管理_书城_02

修改 OrderServiceImpl 模拟错误

package com.atguigu.service.impl;

import com.atguigu.dao.BookDao;
import com.atguigu.dao.OrderDao;
import com.atguigu.dao.OrderItemDao;
import com.atguigu.dao.impl.BookDaoImpl;
import com.atguigu.dao.impl.OrderDaoImpl;
import com.atguigu.dao.impl.OrderItemDaoImpl;
import com.atguigu.pojo.*;
import com.atguigu.service.OrderService;

import java.util.Date;
import java.util.List;
import java.util.Map;

public class OrderServiceImpl implements OrderService {
private OrderDao orderDao =new OrderDaoImpl();
private OrderItemDao orderItemDao=new OrderItemDaoImpl();
private BookDao bookDao=new BookDaoImpl();
@Override
public String createOrder(Cart cart, Integer userId) {

System.out.println("OrderServiceImpl 程序在["+Thread.currentThread().getName()+"]中");


//订单号==唯一性
String orderId=System.currentTimeMillis()+""+userId;
//创建一个订单对象
Order order=new Order(orderId,new Date(),cart.getTotalPrice(),0,userId);
//保存订单
orderDao.saveOrder(order);

//模拟错误
int i=12/0;

//遍历购物车中每一个商品项转换为订单保存到数据库
for (Map.Entry<Integer, CartItem>entry:cart.getItems().entrySet()) {
//获取购物车每一个商品项
CartItem cartItem=entry.getValue();
//转换为订单
OrderItem orderItem=new OrderItem(null,cartItem.getName(),cartItem.getCount(),cartItem.getPrice(),cartItem.getTotalPrice(),orderId);
//保存到数据库
orderItemDao.saveOrderItem(orderItem);

//更新库存和销量
Book book = bookDao.queryBookById(cartItem.getId());
book.setSales(book.getSales()+cartItem.getCount());
book.setStock(book.getStock()-cartItem.getCount());
bookDao.updateBook(book);
}
//清空购物车
cart.clear();

return orderId;
}

@Override
public List<Order> showAllOrders() {
return orderDao.queryOrders();
}

@Override
public int sendOrder(String orderId) {
return orderDao.changeOrderStatus(orderId,1);
}

@Override
public List<OrderItem> showOrderDetail(String orderId) {
return orderItemDao.queryOrderItemByOrderId(orderId);
}

@Override
public List<Order> showMyOrders(int userId) {
return orderDao.queryByUserId(userId);
}

@Override
public int receiverOrder(String orderId) {
return orderDao.changeOrderStatus(orderId,2);
}

}

结果 网页,添加购物车去结账

t_order表无记录
t_order_item有记录

原理

书城项目第八阶段:使用Filter过滤器实现后台的权限管理_java_03

修改 JdbcUtils

package com.atguigu.utils;

import com.alibaba.druid.pool.DruidDataSource;
import com.alibaba.druid.pool.DruidDataSourceFactory;

import java.io.InputStream;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.Properties;

public class JdbcUtils {

private static DruidDataSource dataSource;
private static ThreadLocal<Connection> conns=new ThreadLocal<>();
static {

try {
Properties properties=new Properties();
//读取jdbc.properties属性配置文件
InputStream inputStream = JdbcUtils.class.getClassLoader().getResourceAsStream("jdbc.properties");
//从流中加载数据
properties.load(inputStream);
//创建数据连接池
dataSource= (DruidDataSource) DruidDataSourceFactory.createDataSource(properties);//Ctrl+ALT+T

} catch (Exception e){
e.printStackTrace();
}
}


/**
* 获取数据库连接池中的连接
* @return 如果返回null,说明获取连接失败<br/> 有值就是获取连接成功
*/
public static Connection getConnection(){
Connection conn=conns.get();
if (conn==null){
try {
conn= dataSource.getConnection();//从数据库连接池中获取连接
conns.set(conn);//保存到ThreadLocal对象中,供后面的jdbc操作使用
conn.setAutoCommit(false);//设置为手动管理事务
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
return conn;
}

/**
* 提交事务,并关闭释放连接
*/
public static void commitAndClose(){
Connection connection=conns.get();
if (connection!=null){//如果不等于null,说明之前使用过连接,操作过数据库
try {
connection.commit();//提交 事务
} catch (SQLException throwables) {
throwables.printStackTrace();
}finally {
try {
connection.close();//关闭连接,释放资源
} catch (SQLException throwables) {
throwables.printStackTrace();
}

}

}
//一定要执行remove操作,否则就会出错。(因为Tomcat服务器底层使用了线程池技术)
conns.remove();
}

/**
* 回滚事务,并关闭释放连接
*/
public static void rollbackAndClose(){
Connection connection=conns.get();
if (connection!=null){//如果不等于null,说明之前使用过连接,操作过数据库
try {
connection.rollback();//回滚 事务
} catch (SQLException throwables) {
throwables.printStackTrace();
}finally {
try {
connection.close();//关闭连接,释放资源
} catch (SQLException throwables) {
throwables.printStackTrace();
}

}

}
//一定要执行remove操作,否则就会出错。(因为Tomcat服务器底层使用了线程池技术)
conns.remove();
}

/**
* 关闭连接,放回数据库连接池
* @param conn

public static void close(Connection conn){
if (conn!=null){
try {
conn.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
}
*/

}

修改 JdbcUtilsTest

package com.atguigu.test;

import org.junit.Test;

public class JdbcUtilsTest {
@Test
public void testJdbcUtils(){
// for (int i = 0; i < 100; i++) {
// Connection connection = JdbcUtils.getConnection();
// System.out.println(connection);
// JdbcUtils.close(connection);
// }
}

}

修改 BaseDao

package com.atguigu.dao;

import com.atguigu.utils.JdbcUtils;
import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.BeanHandler;
import org.apache.commons.dbutils.handlers.BeanListHandler;
import org.apache.commons.dbutils.handlers.ScalarHandler;

import java.sql.Connection;
import java.sql.SQLException;
import java.util.List;

public abstract class BaseDao {

//使用DbUtils操作数据库
private QueryRunner queryRunner=new QueryRunner();

/**
* update() 方法用来执行,Insert\Update\Delete语句
* @return 如果返回-1,说明执行失败<br/>返回其他表示影响的行数
*/
public int update(String sql,Object... args){
System.out.println("BaseDao 程序在["+Thread.currentThread().getName()+"]中");

Connection connection= JdbcUtils.getConnection();
try {
return queryRunner.update(connection,sql,args);
} catch (SQLException e) {
e.printStackTrace();
throw new RuntimeException(e);
}


}

/**
* 查询返回一个javabean的sql语句
* @param type 返回的对象类型
* @param sql 执行的sql语句
* @param args sql对应的参数值
* @param <T> 返回类型的泛型
* @return
*/
public <T> T queryForOne(Class<T> type,String sql,Object... args){
Connection con=JdbcUtils.getConnection();
try {
return queryRunner.query(con,sql,new BeanHandler<T>(type),args);
} catch (SQLException e) {
e.printStackTrace();
throw new RuntimeException(e);
}
}

/**
* 查询返回多个javabean的sql语句
* @param type 返回的对象类型
* @param sql 执行的sql语句
* @param args sql对应的参数值
* @param <T> 返回类型的泛型
* @return
*/
public <T>List<T> queryForList(Class<T> type,String sql,Object... args){
Connection con=JdbcUtils.getConnection();
try {
return queryRunner.query(con,sql,new BeanListHandler<T>(type),args);
} catch (SQLException e) {
e.printStackTrace();
throw new RuntimeException(e);
}
}

/**
* 执行返回一行一列的sql语句
* @param sql 执行的sql语句
* @param args sql对应的参数值
* @return
*/
public Object queryForSingleValue(String sql,Object... args){
Connection conn=JdbcUtils.getConnection();

try {
return queryRunner.query(conn,sql,new ScalarHandler(),args);
} catch (SQLException e) {
e.printStackTrace();
throw new RuntimeException(e);
}
}



}

修改 OrderServlet

package com.atguigu.web;

import com.atguigu.pojo.Cart;
import com.atguigu.pojo.User;
import com.atguigu.service.OrderService;
import com.atguigu.service.impl.OrderServiceImpl;
import com.atguigu.utils.JdbcUtils;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

public class OrderServlet extends BaseServlet {

private OrderService orderService = new OrderServiceImpl();

/**
* 生成订单
*
* @param req
* @param resp
* @throws ServletException
* @throws IOException
*/
public void createOrder(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//先获取Cart购物车对象
Cart cart = (Cart) req.getSession().getAttribute("cart"); //获取Userid
User loginUser = (User) req.getSession().getAttribute("user");
if (loginUser == null) {
req.getRequestDispatcher("/pages/user/login.jsp").forward(req, resp);
return;
}

System.out.println("OrderServlet 程序在["+Thread.currentThread().getName()+"]中");

Integer userId = loginUser.getId();
//调用orderservice.createorder(cart,userid);生成订单

String orderId = null;
try {
orderId = orderService.createOrder(cart, userId);
JdbcUtils.commitAndClose();//提交事务
} catch (Exception e) {
JdbcUtils.rollbackAndClose();//回滚事务
e.printStackTrace();
}

// req.setAttribute("orderId",orderId);
//请求转发至pages/cart/checkout.jsp
// req.getRequestDispatcher("/pages/cart/checkout.jsp").forward(req,resp);

req.getSession().setAttribute("orderId", orderId);
resp.sendRedirect(req.getContextPath() + "/pages/cart/checkout.jsp");
}

/**
* 查看所有订单
*
* @param req
* @param resp
* @throws ServletException
* @throws IOException
*/
public void showAllOrders(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

}

/**
* 发货
*
* @param req
* @param resp
* @throws ServletException
* @throws IOException
*/
public void sendOrder(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

}

/**
* 查看订单详情
*
* @param req
* @param resp
* @throws ServletException
* @throws IOException
*/
public void showOrderDetail(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

}

/**
* 查看我的订单
*
* @param req
* @param resp
* @throws ServletException
* @throws IOException
*/
public void showMyOrder(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

}

/**
* 签收订单/确认收货
*
* @param req
* @param resp
* @throws ServletException
* @throws IOException
*/
public void receiverOrder(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

}




}

结果 网页,添加购物车去结账

书城项目第八阶段:使用Filter过滤器实现后台的权限管理_javaweb_04

3.2、使用Filter统一给所有Service方法都加上try-catch来实现管理事务

书城项目第八阶段:使用Filter过滤器实现后台的权限管理_书城_05

新建 filter/TransactionFilter

package com.atguigu.web;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.lang.reflect.Method;

public abstract class BaseServlet extends HttpServlet {

@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doPost(req,resp);
}

protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String action=req.getParameter("action");
// System.out.println(action);


//action的value和调用的方法名是统一的
// if ("login".equals(action)){
System.out.println("处理登录的需求");
// login(req,resp);
// }else if ("regist".equals(action)){
System.out.println("处理注册的需求");
// regist(req,resp);
// }

//反射
try {
//获取action业务鉴别字符串,获取相应的业务方法 反射对象
Method method = this.getClass().getDeclaredMethod(action,HttpServletRequest.class,HttpServletResponse.class);

//调用目标业务方法
method.invoke(this,req,resp);

} catch (Exception e) {
e.printStackTrace();
throw new RuntimeException(e);//把异常抛给Filter过滤器
}


}



}

配置web.xml

<filter>
<filter-name>TransactionFilter</filter-name>
<filter-class>com.atguigu.filter.TransactionFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>TransactionFilter</filter-name>
<!-- /*当前工程下所有请求 -->
<url-pattern>/*</url-pattern>
</filter-mapping>

修改 OrderServlet

package com.atguigu.web;

import com.atguigu.pojo.Cart;
import com.atguigu.pojo.User;
import com.atguigu.service.OrderService;
import com.atguigu.service.impl.OrderServiceImpl;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

public class OrderServlet extends BaseServlet {

private OrderService orderService = new OrderServiceImpl();

/**
* 生成订单
*
* @param req
* @param resp
* @throws ServletException
* @throws IOException
*/
public void createOrder(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//先获取Cart购物车对象
Cart cart = (Cart) req.getSession().getAttribute("cart"); //获取Userid
User loginUser = (User) req.getSession().getAttribute("user");
if (loginUser == null) {
req.getRequestDispatcher("/pages/user/login.jsp").forward(req, resp);
return;
}

System.out.println("OrderServlet 程序在["+Thread.currentThread().getName()+"]中");

Integer userId = loginUser.getId();
//调用orderservice.createorder(cart,userid);生成订单

String orderId = orderService.createOrder(cart, userId);


// req.setAttribute("orderId",orderId);
//请求转发至pages/cart/checkout.jsp
// req.getRequestDispatcher("/pages/cart/checkout.jsp").forward(req,resp);

req.getSession().setAttribute("orderId", orderId);
resp.sendRedirect(req.getContextPath() + "/pages/cart/checkout.jsp");
}

/**
* 查看所有订单
*
* @param req
* @param resp
* @throws ServletException
* @throws IOException
*/
public void showAllOrders(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

}

/**
* 发货
*
* @param req
* @param resp
* @throws ServletException
* @throws IOException
*/
public void sendOrder(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

}

/**
* 查看订单详情
*
* @param req
* @param resp
* @throws ServletException
* @throws IOException
*/
public void showOrderDetail(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

}

/**
* 查看我的订单
*
* @param req
* @param resp
* @throws ServletException
* @throws IOException
*/
public void showMyOrder(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

}

/**
* 签收订单/确认收货
*
* @param req
* @param resp
* @throws ServletException
* @throws IOException
*/
public void receiverOrder(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

}




}

修改 BaseServlet

package com.atguigu.web;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.lang.reflect.Method;

public abstract class BaseServlet extends HttpServlet {

@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doPost(req,resp);
}

protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String action=req.getParameter("action");
// System.out.println(action);


//action的value和调用的方法名是统一的
// if ("login".equals(action)){
System.out.println("处理登录的需求");
// login(req,resp);
// }else if ("regist".equals(action)){
System.out.println("处理注册的需求");
// regist(req,resp);
// }

//反射
try {
//获取action业务鉴别字符串,获取相应的业务方法 反射对象
Method method = this.getClass().getDeclaredMethod(action,HttpServletRequest.class,HttpServletResponse.class);

//调用目标业务方法
method.invoke(this,req,resp);

} catch (Exception e) {
e.printStackTrace();
throw new RuntimeException(e);//把异常抛给Filter过滤器
}


}



}

3.3、将所有异常都交给Tomcat,让Tomcat显示友好的错误信息页面

在web.xml 中我们可以通过错误页面配置来进行管理。

新建 pages/error/error500.jsp

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>error500</title>

<%--静态包含 base标签,css样式,jquery文件 --%>
<%@ include file="/pages/common/head.jsp"%>

</head>
<body>
很抱歉,您访问的页面不存在,或已经被删除!!!<br>
<a href="index.jsp">返回首页</a>
</body>
</html>

并配置 web.xml

<!-- error-page标签配置,服务器出错之后,自动跳转的页面   -->
<error-page>
<!-- error-code是错误类型 -->
<error-code>500</error-code>
<!-- location标签表示,要跳转的页面路径-->
<location>/pages/error/error500.jsp</location>
</error-page>

修改 TransactionFilter

package com.atguigu.filter;

import com.atguigu.utils.JdbcUtils;

import javax.servlet.*;
import java.io.IOException;

public class TransactionFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {

}

@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
try {
filterChain.doFilter(servletRequest,servletResponse);
JdbcUtils.commitAndClose();//提交事务
} catch (Exception e) {
JdbcUtils.rollbackAndClose();//回滚事务
e.printStackTrace();
throw new RuntimeException(e);//把异常抛给Tomcat管理展示友好的错误页面
}
}

@Override
public void destroy() {

}
}

新建error/error404.jsp

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>error404</title>

<%--静态包含 base标签,css样式,jquery文件 --%>
<%@ include file="/pages/common/head.jsp"%>

</head>
<body>
很抱歉,您访问的页面不存在,或已经被删除!!!<br>
<a href="index.jsp">返回首页</a>
</body>
</html>

配置web.xml

<!-- error-page标签配置,服务器出错之后,自动跳转的页面   -->
<error-page>
<!-- error-code是错误类型 -->
<error-code>404</error-code>
<!-- location标签表示,要跳转的页面路径-->
<location>/pages/error/error404.jsp</location>
</error-page>


举报

相关推荐

0 条评论