day48_servlet

今日内容

周一
0 复习上周
1 本周计划
2 MVC和三层架构
3 Login案例
4 请求转发
5 重定向

0 复习昨日

1 jdbc五大步骤

  1. 注册驱动(反射)
  2. 获得连接
  3. 获得执行sql对象
  4. 执行SQL
  5. 关流
    2 什么是SQL注入
    通过SQL关键词,在执行SQL时出现不正常的情况
    3 PreparedStatement怎么使用,有什么特点
    怎么使用? 之前拼接sql参数的地方,现在使用?占位,经过预处理后,再给?处赋值
    有什么特点? 1) 执行时不需要再给executeQuery()传参数
    2) 可以避免SQL注入的问题
    3) 向?赋值的时候,自动给字符串拼接单引号
    mybatis # PreparedStatement ,字符串’’
    $ Statement
    4 什么是servlet
    servlet是运行在服务上的程序
    servlet主要功能是: 接收请求,做出响应

5 Http请求方式有哪些
get
post
6 Http请求报文都有哪些内容
请求头,请求行,请求正文(数据)

针对不同的请求方式,后台有哪些请求方法?
doGet()
doPost()
7 后台接收请求内容的方法有哪些
req.getMethod()
req.getRequestURL()
req.getRequestURI()
req.getParameter(name属性的值);//获得请求数据
req.getParameterValues();

8 前端如何发送数据
form表单,标签得设置name属性

		<form action="/day48/login" method="get">
		  <input type="text" name="username" />
		  <input type="text" name="password" />
		  <input type="submit" value="提交" />
		</form>

​ ajax
​ a标签

<a href="/day48/login?username=root&pwd=555">登录</a>

9 前端后后台之间如何映射?
通过web.xml配置8行代码

	<servlet>
		<servlet-name>servlet1</servlet-name>
		<servlet-class>c.f.s.MyServlet1</servlet-class>
	</servlet>
	<servlet-mapping>
		<servlet-name>servlet1</servlet-name>
		<url-parttern>*.do</url-parttern>
	</servlet-mapping>

1 MVC和三层架构

通过Login案例,一个LoginServlet中

  • 接收请求

  • 完成JDBC操作

  • 根据结果做出响应

    以上这种开发模式,不好,不便于后期迭代维护


在开发中有一个思想:“分而治之”

MVC思想

  • M model/模型
    • 模型主要是指javabean,有一些java类
    • 比如封装数据的类,User类
    • 比如其他功能类,UserService,UserDao
  • V view/视图
    • 视图就是页面,
    • 比如JSP/HTML
    • 为了展现数据
  • C controller/控制器
    • 控制器控制整个流程的走向
    • 控制页面跳转

三层架构: 是指开发中编码时项目结构,主要是指将不同的功能代码再细分

  • 控制层
    • servlet主要做控制
    • 控制页面跳转
  • 业务层
    • service层
    • 主要处理业务逻辑
  • 数据访问层
    • Dao层
    • 主要与数据库交互

2 Login案例

需求: HTML页面中输入框用户名和密码,登录

  • 登录成功给出提供,欢迎
  • 登录不成功,给出提示,用户名或密码错误

在这里插入图片描述

2.1 搭建环境

数据库环境

CREATE TABLE `tb_user` (
  `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '用户编号',
  `username` varchar(10) DEFAULT NULL COMMENT '用户名',
  `password` varchar(10) DEFAULT NULL COMMENT '密码',
  `phone` varchar(11) DEFAULT NULL COMMENT '手机号',
  `createTime` date DEFAULT NULL COMMENT '注册时间',
  `money` double(10,2) DEFAULT NULL COMMENT '账户余额',
  `sex` int(1) DEFAULT NULL COMMENT '性别 1男2女',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=24 DEFAULT CHARSET=utf8;

项目环境

  • 创建maven-web项目

  • 补全项目结构

  • 导入依赖

      <dependencies>
        <!-- servlet -->
        <dependency>
          <groupId>javax.servlet</groupId>
          <artifactId>javax.servlet-api</artifactId>
          <version>4.0.1</version>
        </dependency>
    
        <!-- servlet-jsp -->
        <dependency>
          <groupId>javax.servlet.jsp</groupId>
          <artifactId>javax.servlet.jsp-api</artifactId>
          <version>2.3.1</version>
        </dependency>
    
        <!-- mysql驱动 -->
        <dependency>
          <groupId>mysql</groupId>
          <artifactId>mysql-connector-java</artifactId>
          <version>5.1.47</version>
        </dependency>
        
        <!-- druid连接池 -->
        <dependency>
          <groupId>com.alibaba</groupId>
          <artifactId>druid</artifactId>
          <version>1.1.10</version>
        </dependency>
      </dependencies>
    
  • 项目必备的java包和类

    • 工具包和工具类
    • 实体类
    • 包结构

2.2 页面

登录页面

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<div>
    <form action="/day48/login" method="post">
        用户名<input type="text" name="username"><br>
        密码<input type="password" name="password"><br>
        <input type="submit" value="登录"><br>
    </form>
</div>
</body>
</html>

2.3 UserServlet

package com.qf.servlet;

import com.qf.model.User;
import com.qf.service.UserService;
import com.qf.service.impl.UserServiceImpl;

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.io.PrintWriter;

/**
 * --- 天道酬勤 ---
 *
 * @author QiuShiju
 * @desc 控制层
 */
public class UserLoginServlet extends HttpServlet {

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        // 防止乱码
        req.setCharacterEncoding("UTF-8");
        resp.setContentType("text/html;charset=UTF-8");

        // 1 接收请求
        String username = req.getParameter("username");
        String password = req.getParameter("password");

        // 2 调用业务层处理业务
        UserService userService = new UserServiceImpl( );
        User user = userService.login(username, password);

        // 3 根据结果做出响应
        PrintWriter out = resp.getWriter( );
        if (user != null) {
            // 响应登录成功
            // 应该是跳转一个页面来展现数据,而不是直接作出响应
            // 但是现在还没学,暂时还是使用手动响应
            out.write("<html>");
            out.write("<body>");
            out.write("<h1>");
            out.write("欢迎"+user.getUsername()+"登录");
            out.write("</h1>");
            out.write("</body>");
            out.write("</html>");
        } else {
            // 响应登录不成功
            out.write("<html>");
            out.write("<body>");
            out.write("<h1>");
            out.write("用户名或密码错误!");
            out.write("</h1>");
            out.write("</body>");
            out.write("</html>");
        }
    }
}

2.4 UserService

一般开发时,会将UserService以及UserDao设计成接口+实现类的形式

  • 可以先设计接口,规定项目的功能
  • 接口还可以松耦合,实现多态,易于代码扩展

UserService接口

package com.qf.service;

import com.qf.model.User;

import java.util.List;

/**
 * --- 天道酬勤 ---
 *
 * @author QiuShiju
 * @desc 用户的业务层处理
 */
public interface UserService {

    User login(String username, String password);

    // List<User> findAll();

    // boolean deleteUserById(int id);

}

UseServiceImpl

package com.qf.service.impl;

import com.qf.dao.UserDao;
import com.qf.dao.impl.UserDaoImpl;
import com.qf.model.User;
import com.qf.service.UserService;

/**
 * --- 天道酬勤 ---
 *
 * @author QiuShiju
 * @desc impl包,只用于存放实现类
 * 所有的实现类都应该是接口名+Impl来命名
 * 例如: UserServiceImpl
 * 通过这个名字,要得到两个信息
 * 1) 有一个接口UserService
 * 2) 有一个类UserServiceImpl
 * -----------------------------
 * Service层,是业务层,处理业务逻辑
 */
public class UserServiceImpl implements UserService {

    @Override
    public User login(String username, String password) {
        // 1 业务逻辑处理
        // 但是今天这个需求没有什么业务,就可以不做

        // 2 调用数据访问层操作数据库
        UserDao userDao = new UserDaoImpl();
        User user = userDao.login(username, password);

        // 业务层还可以对数据库返回的结果再处理

        return user;
    }
}

2.5 UserDao

UserDao接口

package com.qf.dao;

import com.qf.model.User;

/**
 * --- 天道酬勤 ---
 *
 * @author QiuShiju
 * @desc
 */
public interface UserDao {

    User login(String username, String password);

}

UserDaoImpl实现类

package com.qf.dao.impl;

import com.qf.dao.UserDao;
import com.qf.model.User;
import com.qf.util.DBUtil;

/**
 * --- 天道酬勤 ---
 *
 * @author QiuShiju
 * @desc
 */
public class UserDaoImpl implements UserDao {

    @Override
    public User login(String username, String password) {
        String sql = "select * from tb_user where username = ? and password = ?";
        User user = DBUtil.selectOne(sql, User.class, username, password);
        return user;
    }
}

这里使用了DBUtil,不习惯使用的话,也可以使用原始的JDBC自己操作

3 请求转发

请求对象HttpServletRequest

  • 请求的转发(将请求转发到其他的servlet)
  • 跳转页面
  • 请求域(存取数据)

请求转发的总结

  • 请求转发地址栏不动
  • 请求转发是服务器行为,是服务器内部动作
  • 浏览器只有一次请求
  • 可以当做请求域,数据可以在Servlet之间共享

在这里插入图片描述

3.1 请求转发

需求: 发出请求/a 映射AServlet,利用请求转发,将请求转发到BServlet

package com.qf.servlet;

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

/**
 * --- 天道酬勤 ---
 *
 * @author QiuShiju
 * @desc
 */
public class AServlet extends HttpServlet {

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

        System.out.println("AServlet.doGet..." );


        // 请求转发
        // path: 就是要转发的Servlet对应的映射路径
        // RequestDispatcher dispatcher = req.getRequestDispatcher("/b");
        // 执行转发
        // dispatcher.forward(req,resp);
        // 路径不需要写成 /项目名/b
        req.getRequestDispatcher("/b").forward(req,resp);
    }
}
package com.qf.servlet;

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

/**
 * --- 天道酬勤 ---
 *
 * @author QiuShiju
 * @desc
 */
public class BServlet extends HttpServlet {

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

        System.out.println("BServlet.doGet..." );

    }
}
<?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_3_1.xsd"
version="3.1">

    <!-- 映射AServlet -->
    <servlet>
        <servlet-name>aServlet</servlet-name>
        <servlet-class>com.qf.servlet.AServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>aServlet</servlet-name>
        <url-pattern>/a</url-pattern>
    </servlet-mapping>

    <!-- 映射BServlet -->
    <servlet>
        <servlet-name>bServlet</servlet-name>
        <servlet-class>com.qf.servlet.BServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>bServlet</servlet-name>
        <url-pattern>/b</url-pattern>
    </servlet-mapping>
</web-app>

3.2 请求域

请求域是指: HttpServletRequest对象相当于是容器,存取数据,可以在请求转发的几个类中共享数据.

  • 存储数据 req.setAttribute(key,value)
  • 取出数据 req.getAttribute(key)

请求域作用以及场景: 在多个Servlet请求转发的时候,用来传递数据

package com.qf.servlet;

import javax.servlet.RequestDispatcher;
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.util.Date;

/**
 * --- 天道酬勤 ---
 *
 * @author QiuShiju
 * @desc
 */
public class AServlet extends HttpServlet {

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

        System.out.println("AServlet.doGet..." );

        // 请求域
        // 存储数据到请求域
        req.setAttribute("username","jack");

        // 请求转发
        // path: 就是要转发的Servlet对应的映射路径
        // RequestDispatcher dispatcher = req.getRequestDispatcher("/b");
        // 执行转发
        // dispatcher.forward(req,resp);
        // 路径不需要写成 /项目名/b
        req.getRequestDispatcher("/b").forward(req,resp);
    }
}
package com.qf.servlet;

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

/**
 * --- 天道酬勤 ---
 *
 * @author QiuShiju
 * @desc
 */
public class BServlet extends HttpServlet {

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

        System.out.println("BServlet.doGet..." );

        // 请求域中取出数据
        String username = (String) req.getAttribute("username");

        System.out.println("username = " + username);
    }
}

3.3 跳转页面

在这里插入图片描述

4 重定向

重定向是HttpServletResponse对象完成一个动作

  • 可以将请求重新跳转至其他Servlet
  • 可以跳转页面

重定向总结:

  • 重定向是浏览器动作
  • 重定向地址栏会有变化
  • 是发出两次请求
  • 请求域中的数据在重定向后不能共享(因为是两次请求)

需求:

需求: 发出请求/a 映射AServlet,利用重定向,将请求重新发送请求到BServlet

public class AServlet extends HttpServlet {

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

        System.out.println("AServlet.doGet..." );

        // 请求域
        // 存储数据到请求域
        req.setAttribute("username","jack");

        // 请求转发
        // path: 就是要转发的Servlet对应的映射路径
        // RequestDispatcher dispatcher = req.getRequestDispatcher("/b");
        // 执行转发
        // dispatcher.forward(req,resp);
        // 路径不需要写成 /项目名/b,是因为请求转发是服务器动作
        // /b,即从服务器根路径开始访问,服务器的根路径自带项目名
        // http://localhost:8080/day48/b
        //req.getRequestDispatcher("/b").forward(req,resp);

        // 请求转发可以跳转页面
        // req.getRequestDispatcher("/404.html").forward(req,resp);


        // 重定向
        // 重定向是浏览器行为,发出/b请求,那就是从浏览器的根路径发出请求
        // 浏览器的根路径是端口: http://localhost:8080/b
        String contextPath = req.getContextPath( ); // 获得项目名 /day48
        System.out.println("contextPath = " + contextPath);

        // resp.sendRedirect(contextPath+"/b");
        resp.sendRedirect(contextPath+"/404.html");
    }
}

5 注解

JDK1.5后出现的技术,注解(Annotation),是一种注释,给程序注释然后程序运行给JVM中的java代码看的

  • @Override

注解文件既不是类也不是接口

5.1 创建注解文件

在这里插入图片描述

5.2 元注解

注解的注解就是元注解

5.2.1 @Target

@Target 目标,用来规定注解能用在什么位置

位置ElementType
包上PACKAGE
类/接口/数组/枚举上TYPE
成员变量/局部变量FIELD/LOCAL_VARIABLE
方法/构造方法METHOD/CONSTRUCTOR

5.2.2 @Retention

保留,指注解保留到什么时候,或者说叫保留至什么时候生效

ps: 如果是自定义注解,一般是为了通过反射技术读取注解,所以要定义保留策略为RUNTIME

保留策略解释
SOURCE源码阶段有效
CLASS编译后class中有效
RUNTIME运行时生效

5.3 注解参数

@Target({ElementType.METHOD,ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnno {
    // 注解的参数
    // 数据类型 参数名();
    // 一旦设置了参数,那么在使用注解时就必需给注解参数赋值
    // 除非给参数设置了默认值
    int a() default 0;

    // 当注解的参数名value,使用时可以省略
    String value() default "";

    String[] values() default "";

}

注解的参数都是为了通过反射技术去读取到注解参数中的值

5.4 实际应用

Servlet开发中也支持使用注解,大大提高开发效率

  • @WebServlet 注解,可以取代web.xml中[经典8行]代码

作业

login案例重写2遍 (注解)

通过代码演示记住 请求转发和重定向的特点

SQL15道题

牛客网-SQL专项 (每天2-3)
留策略解释
SOURCE源码阶段有效
CLASS编译后class中有效
RUNTIME运行时生效

5.3 注解参数

@Target({ElementType.METHOD,ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnno {
    // 注解的参数
    // 数据类型 参数名();
    // 一旦设置了参数,那么在使用注解时就必需给注解参数赋值
    // 除非给参数设置了默认值
    int a() default 0;

    // 当注解的参数名value,使用时可以省略
    String value() default "";

    String[] values() default "";

}

注解的参数都是为了通过反射技术去读取到注解参数中的值

5.4 实际应用

Servlet开发中也支持使用注解,大大提高开发效率

  • @WebServlet 注解,可以取代web.xml中[经典8行]代码

作业

login案例重写2遍 (注解)

通过代码演示记住 请求转发和重定向的特点

SQL15道题

牛客网-SQL专项 (每天2-3)
  • 22
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

师范大学通信大怨总

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

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

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

打赏作者

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

抵扣说明:

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

余额充值