今日内容
周一
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 {@Overrideprotected 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 {@Overridepublic 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 {@Overridepublic 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 {@Overrideprotected 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);// 路径不需要写成 /项目名/breq.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 {@Overrideprotected 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 {@Overrideprotected 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);// 路径不需要写成 /项目名/breq.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 {@Overrideprotected 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 {@Overrideprotected 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/bString contextPath = req.getContextPath( ); // 获得项目名 /day48System.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)