[Javaweb 05] MVC,过滤器实现未登录时保护某些页面不能访问

MVC,过滤器实现未登录时保护某些页面不能访问


1. MVC三层架构

MVC: Model View Controller 模型, 视图,控制器

1. 早期模型

servlet(包括CRUD代码)---> 数据库
弊端: 程序不利于维护
servlet的代码中: 处理请求,响应,视图跳转,处理JDBC、业务代码,处理逻辑代码等

2. MVC模型

View:

  • 展示数据
  • 给用户提供链接,用于发起Servlet请求

Controller: (Servlet)

  • 接收用户的请求req(请求参数,Session信息)
  • 交给业务层处理对应的代码
  • 控制视图的跳转

Model:

  • 业务处理:业务逻辑(Service层)
  • 数据持久层: CRUD(Dao层)

例子:

登录页面, 接收用户的登录请求(View)

处理用户的请求,如登录参数,username, psw(Controller也是Servlet)

交给业务层处理登录业务,判断密码是否正确(Model_业务层)

Dao查询数据库中的用户名密码是否正确(Model_Dao层)

2. Filter过滤器

用来过滤网站的数据, 如: 每个servlet在调用前都先调用处理中文乱码,登录验证过滤等。

过滤器中的方法doFilter(Request, Response, FilterChain)

实际应用中,过滤器不止一个,可以连接多个过滤器,所以在doFilter方法中,必须要写chain自己的方法。

1. 写类实现Filter接口

public class CharacterEncodingFilter implements Filter {
    // init方法在web服务器启动时就调用,需要随时监听需要过滤的页面
	public void init(FilterConfig filterConfig) throws ServletException {}
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        //过滤器要实现的目的代码
        servletRequest.setCharacterEncoding("utf-8");
        servletResponse.setCharacterEncoding("utf-8");
        servletResponse.setContentType("text/html;charset=UTF-8");
        //必须写,让请求继续走,(可能有别的过滤器), 如果不写,程序被拦截
        filterChain.doFilter(servletRequest, servletResponse);
    }
    // web服务器关闭的时候,才调用销毁
    public void destroy() {}
}

2. 在web.xml文件中配置

servlet文件:配置servlet和servlet-mapping, 在mapping时,配置两个路径:

<servlet></servlet>
<servlet-mapping>/show</servlet-mapping>
<servlet-mapping>/servlet/show</servlet-mapping>

filter文件: 路径配置含义: 过某个路径下的所有文件都走这个过滤器:

<filter></filter>
<filter-mapping>
    <filter-name>filterName</filter-name>
    <url-pattern>/servlet/*</url-pattern>
</filter-mapping>

当servlet走/show路径时,不经过过滤器,显示乱码

当servlet走/servlet/show路径时,经过过滤器,显示正常

3. Listener 监听器

去实现Listner的接口,很多lister接口,看需求实现

统计在线人数:

1. 实现listener接口:

// 涉及监听者模式
public class OnlineCountListener implements HttpSessionListener {
    //每创建一个session,就调用一次这个方法
    public void sessionCreated(HttpSessionEvent se) {//se代表session事件的对象
        ServletContext ctx = se.getSession().getServletContext();
        Integer onlineCount = (Integer) ctx.getAttribute("OnlineCount");
        if (onlineCount == null){
            onlineCount = new Integer(1);
        }else{
            int count = onlineCount.intValue();
            onlineCount = new Integer(count +1);
        }
        ctx.setAttribute("OnlineCount", onlineCount);
    }
    //每销毁一个session, 就调用一次
    public void sessionDestroyed(HttpSessionEvent se) {
        // 销毁代码相反,数量 --;
    }
}

2. web.xml配置

<listener>
    <listener-class>包.类</listener-class>
</listener>

去前端实现显示人数

4. Filter实现权限拦截(登录监听)


重点总结:

  1. 后端文件中,/表示当前项目的根目录,在页面跳转至中,如果在web目录下,直接用/文件名.jsp访问。其他的也按照文件目录或映射来走。一定要注意目录跳转!!!!
  2. 页面中,用户信息一般放在Session中,方便跳转或者重定向的时候携带数据过去。
  3. 可以在util包中创建一个Constant类,放置常用到的数据名称,如:session中的key值,以便于管理
  4. Constant类中定义的变量必须是public的!你吃了大亏

实现某些页面未登录无法直接访问到

1. 项目目录:

2. 前端界面

index.jsp和error.jsp在项目目录下,登入和登出界面需要保护,放在sys目录下

1. 登入界面 index.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
  <head>
    <title>$Title$</title>
  </head>
  <body>
  <form action="/servlet/login" method="post">
    <input type="text" name="userName">
    <input type="submit">
  </form>

  </body>
</html>

2. 错误界面 error.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
错误
<a href="index.jsp">登录</a>
</body>
</html>

3. 登入成功界面 succession.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
成功登录<br>
<a href="/servlet/logout">登出</a>
</body>
</html>

4. 登出成功界面 logoutSuccession.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
登出成功!
<a href="index.jsp">登录</a>
</body>
</html>

3. 业务代码:

业务代码都是servlet类,放入servlet包中

1. Login.java

public class Login extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        String userName = req.getParameter("userName");
        if("admin".equals(userName)){
            req.getSession().setAttribute("USER_SESSION", req.getSession().getId());
            resp.sendRedirect("/sys/succession.jsp");
        }else{
            resp.sendRedirect("/error.jsp");
        }
    }
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req, resp);
    }
}

2. Logout.java

public class Logout extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        Object user_session = req.getSession().getAttribute("USER_SESSION");
        if(user_session!=null){
            req.getSession().removeAttribute("USER_SESSION");
            resp.sendRedirect("/index.jsp");
        }
    }

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

4. 过滤器代码

过滤器都实现filter接口,放在filter包下

1. 中文乱码解决

public class CharacterChange implements Filter {
    public void init(FilterConfig filterConfig) throws ServletException {}
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        servletRequest.setCharacterEncoding("utf-8");
        servletResponse.setCharacterEncoding("utf-8");
        servletResponse.setContentType("text/html;charset=UTF-8");
        filterChain.doFilter(servletRequest,servletResponse);//重要,必须写,否则页面中断
    }
    public void destroy() {}
}

2. Sys文件夹保护

public class SysDirectorFilter implements Filter {
    public void init(FilterConfig filterConfig) throws ServletException {}
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        HttpServletRequest req = (HttpServletRequest) servletRequest;
        HttpServletResponse resp = (HttpServletResponse) servletResponse;
        if (req.getSession().getAttribute("USER_SESSION") == null){
            resp.sendRedirect("/index.jsp");
        }
        filterChain.doFilter(servletRequest,servletResponse);//重要,必须写,否则页面中断
    }
    public void destroy() {}
}

5. web.xml配置文件

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
         version="4.0">
    
    <servlet>
        <servlet-name>login</servlet-name>
        <servlet-class>com.roy.servlet.Login</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>login</servlet-name>
        <url-pattern>/servlet/login</url-pattern>
    </servlet-mapping>
    
    <servlet>
        <servlet-name>logout</servlet-name>
        <servlet-class>com.roy.servlet.Logout</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>logout</servlet-name>
        <url-pattern>/servlet/logout</url-pattern>
    </servlet-mapping>
<!--    字符串 过滤器-->
    <filter>
        <filter-name>character</filter-name>
        <filter-class>com.roy.Filter.CharacterChange</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>character</filter-name>
        <url-pattern>/servlet/*</url-pattern>
    </filter-mapping>
<!--    sys资源过滤器-->
    <filter>
        <filter-name>sysFilter</filter-name>
        <filter-class>com.roy.Filter.SysDirectorFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>sysFilter</filter-name>
        <url-pattern>/sys/*</url-pattern>
    </filter-mapping>
</web-app>

6. 改进添加的Util包中的 Constant类

public class Constant{
    //方便常用值的维护,如在session中get/set其中的key时,直接调用 Constant.USER_SESSION
    public final static String USER_SESSION = "USER_SESSION";
}
posted @ 2021-12-02 23:31  Roy2048  阅读(545)  评论(0)    收藏  举报