学习心得day04 MVC,Filter,Listener,JDBC

MVC,Filter,Listener,JDBC

1.MVC

m:model(模型)

V:view(视图)

C:controller(控制器)


解释框图

1.用户通过浏览器传递一个请求给客户端(view视图层将用户的数据传输给Controller控制器层)

2.Controller控制器层拿到用户的请求之后交给Model层中的(service)去处理相应的业务(例:登录请求)

3.service登录事务通过Dao访问JDBC查询用户是否存在

4.Dao将查询的结果返回登录的Service事务

5.Service登录事务将结果返回给控制器层Controller

6.控制层Controller将结果输出到视图层View

7.用户看到处理的结果(登录成功/登录失败)

2.Filter(重点)

Filter:过滤器

作用:过滤掉一些不需要的垃圾信息/统一处理乱码的问题/登录验证。。。

Filter实际上也是一种servlet

使用时需要实现java.servlet中的Filter接口

编写过滤器需要重写过滤器中的方法(共有三种)

1.init(初始化过滤器)

public class CharacterEncodingFilter implements Filter {
    //初始化 web服务器开启时候初始化
    public void init(FilterConfig filterConfig) throws ServletException {
        System.out.println("过滤器初始化");
    }

2.doFilter方法(过滤器主体)

  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");
        System.out.println("CharacterEncodingFilter执行前");
        filterChain.doFilter(servletRequest,servletResponse);//**将请求和响应给到下一个过滤器,如果不写,程序到这里就被拦截停止了
        System.out.println("CharacterEncodingFilter执行后");

    }

注意!

  • 方法中有三个参数,前两个是ServletRequest和servletResponse,第三个则是filterChain

  • filterChain值过滤器链:实际开发之后一个网页可能需要添加很多个过滤器而过滤器链filterChain则是将过滤器传递下去的方法(必须写

  • Filter中的ServletRequest和servletResponse没有Servlet中的HttpServletRequest和HttpServletRespon作用域广

例如:

//        servletRequest.get。。。 无法get到session 扩大它的对象到HttpServletRequest
        HttpServletRequest request= (HttpServletRequest) servletRequest;
        //将servletRequest强制转换成HttpServletRequest
        HttpServletResponse response= (HttpServletResponse) servletResponse;
        //将servletResponse强制转换成HttpServletResponse

3.destroy(过滤器销毁)

 //销毁 web服务器关闭的时候销毁
    public void destroy() {
        System.out.println("过滤器销毁");
    }
}

运行时在提示栏中看见过滤器初始化在web服务器开启的时候出现

而过滤器销毁则是在web服务器关闭的时候销毁

2.过滤器的一些常见应用

实现拦截未登录用户访问个人主页页面

1.创建一个登录页面 登录成功后跳转到主页中

Jsp登录页面

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>登录</title>
</head>
<body>
<form action="/Servlet/login"method="post">
    <input type="text" name="username">
    <input type="submit" value="登录">
</form>
</body>
</html>

Servlet实现登录业务

    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        String username = req.getParameter("username");
        if (username.equals("admin")){//用户登录成功之后跳转页面 并把用户的session记录下来
            resp.sendRedirect("/Sys/homepage.jsp");
            req.getSession().setAttribute("User_session",req.getSession().getId());
        }else{
            resp.sendRedirect("/error.jsp");
        }
    }
}

2.登录成功后进入主页 主页中包含了一个注销功能注销后返回登录页面

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>主页</title>
</head>
<body>
<h1>主页</h1>
<a href="/Servlet/logout">注销</a>
</body>
</html>
public class logout extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        Object User_session =req.getSession().getAttribute("User_session");//先获取浏览器的Session中的User_session
        if (User_session!=null) {//判断User_session是否存在
            req.getSession().removeAttribute("User_session");//存在便移除
            resp.sendRedirect("/Login.jsp");
        }else{
            resp.sendRedirect("/Login.jsp");
        }
    }

3.用户名错误则会跳转到错误页面

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
<h1>用户名错误</h1>
<a href="/Login.jsp">点击重试</a>
</body>
</html>

4.未登录的用户不能访问主页(用过滤器实现)

    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
//        servletRequest.get。。。 无法get到session 扩大它的对象到HttpServletRequest
        HttpServletRequest request= (HttpServletRequest) servletRequest;
        //将servletRequest强制转换成HttpServletRequest
        HttpServletResponse response= (HttpServletResponse) servletResponse;
        //将servletResponse强制转换成HttpServletResponse
        Object userSession = request.getSession().getAttribute("User_session");
        if (userSession==null){
            response.sendRedirect("/error.jsp");
        }
        filterChain.doFilter(servletRequest,servletResponse);
    }

在web.xml中配置

    <servlet>
    <servlet-name>login</servlet-name>
    <servlet-class>com.you.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.you.servlet.logout</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>logout</servlet-name>
        <url-pattern>/Servlet/logout</url-pattern>
    </servlet-mapping>
    <filter>
        <filter-name>LoginFilter</filter-name>
        <filter-class>com.you.Filter.LoginFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>LoginFilter</filter-name>
        <url-pattern>/Sys/*</url-pattern>
    </filter-mapping>

3.JDBC

1.什么是JDBC:java连接数据库

需要jar包的支持:

  • java.sql
  • javax.sql
  • mysql-conneter-java… 连接驱动(必须要导入)

实验环境搭建(创建数据库)

导入数据库依赖

 <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.19</version>
        </dependency>

2.实现JDBC的几大步骤

1.配置参数(Url username password)

  //配置信息
        String url="jdbc:mysql://localhost:3306/jdbc?serverTimezone=UTC";
        String username="root";
        String password="123";

2.用Class.forName()加载数据库驱动

 //加载驱动
        Class.forName("com.mysql.cj.jdbc.Driver");
//"com.mysql.cj.jdbc.Driver"在jdbc的依赖包中有Driver.class文件复制导入的包.Driver

3.连接数据库

 //连接数据库,代表数据库
        Connection connection = DriverManager.getConnection(url, username, password);

以上是公共部分

而写sql语句到数据库中有两种方案

普通方案:connection.createStatement

	//向数据库发送sql语句的对象statement:CRUD
        Statement statement = connection.createStatement();

        //编写sql语句
        String sql="select * from jdbc.people";


        //执行sql 返回一个rs 这是个结果集
        ResultSet rs = statement.executeQuery(sql);

预编译方案:connection.prepareStatement

       //编写预编译的sql语句
        String sql="insert into jdbc.people (id,name,age,address) value (?,?,?,?)";
        //先把预编译的sql语句传过去
  	   //3.获取statement对象用于传输sql语句,prepareStatement预编译
        PreparedStatement preparedStatement = connection.prepareStatement(sql);
        //预编译完成之后将具体值传进去
        preparedStatement.setInt(1,4);//给第一个占位符(?) 赋值为1
        preparedStatement.setString(2,"水");//给第二个占位符(?) 赋值为水
        preparedStatement.setInt(3,40);//给第三个占位符(?) 赋值为40
        preparedStatement.setString(4,"东南");//给第四个占位符(?) 赋值为东南
        //5.执行sql
        int i = preparedStatement.executeUpdate();

最后记得关闭sql资源(先开后关)

//6.关闭连接 释放资源(一定要做) 先开后关
        rs.close();
        statement.close();
        connection.close();

注意 执行sql语句这里

如果是增删改则使用executeUpdate();即可

而如果是查找则需要使用executeQuery(sql);

JDBC事务

事务:

要么都成功,要么都失败!

ACID原则:保证数据的安全。

事务的流程

开启事务
事务提交  commit()
事务回滚	rollback()
关闭事务
    

转账
A:1000
B:1000
A(900----100---B(1100)
    如果此时服务器断电了 会出现A-100而B并没有+100
    这时候就需要事务了
    将两个事件绑定在一起进行

这里插入一个新学习的知识点

Junit单元测试

1.导入Junit jar包

<!-- https://mvnrepository.com/artifact/junit/junit -->
<dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.13</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.junit.jupiter</groupId>
            <artifactId>junit-jupiter-api</artifactId>
            <version>RELEASE</version>
            <scope>compile</scope>
       /dependency>

简单使用

@Test注解只在方法中有效,只要加了注解的方法,就可以直接运行

public class JunitTest {
    @Test
    public void B(){
        System.out.println("junit测试");
    }
}

利用单元测试我们来实现一个转账事务的小Demo

首先在mysql中创建一个account表

其中包含了 id name money

开启事务的mysql流程

START TRANSACTION; #开启事务
update account set money = money-100 where jdbc.account.name='A';
update account set money = money+100 where jdbc.account.name='B';
COMMIT;

在commit之前使用rollback 可以回滚

应用:转账错误

 @Test
    public void B() {
        String url="jdbc:mysql://localhost:3306/jdbc?serverTimezone=UTC";
        String username="root";
        String password="123";
        Connection connection = null;
        //2.加载驱动 连接数据库
            try {
                Class.forName("com.mysql.cj.jdbc.Driver");

             connection = DriverManager.getConnection(url, username, password);
            //3.通知数据库开启事务 false开启;取反
            connection.setAutoCommit(false);
            String sql1 ="update account set money = money-100 where jdbc.account.name='A'";
            connection.prepareStatement(sql1).executeUpdate();

            //制造一个错误
           // int i =1/0;

            String sql2="update account set money = money+100 where jdbc.account.name='B'";
                connection.prepareStatement(sql2).executeUpdate();

            connection.commit();//以上两条sql都执行成功了,就会提交事务
            System.out.println("提交成功");
        } catch (Exception e) {
                try {
                    //如果出现异常就通知数据库回滚事务
                    connection.rollback();
                } catch (SQLException e1) {
                    e1.printStackTrace();
                }
                e.printStackTrace();
        }finally {
                try {
                    connection.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
    }
  • 0
    点赞
  • 0
    评论
  • 0
    收藏
  • 打赏
    打赏
  • 扫一扫,分享海报

©️2022 CSDN 皮肤主题:数字20 设计师:CSDN官方博客 返回首页

打赏作者

qq_41572324

你的鼓励将是我创作的最大动力

¥2 ¥4 ¥6 ¥10 ¥20
输入1-500的整数
余额支付 (余额:-- )
扫码支付
扫码支付:¥2
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值