今日内容
周一
0 复习上周
1 本周计划
2 MVC和三层架构
3 Login案例
4 请求转发
5 重定向
0 复习昨日
1 jdbc五大步骤
- 注册驱动(反射)
- 获得连接
- 获得执行sql对象
- 执行SQL
- 关流
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)