1、cookie
-
Cookie,是为了辨别用户身份进行Session跟踪而储存在用户本地终端上的数据(通常经过加密),由用户客户端计算机暂时或永久保存的信息.
-
客户端技术(响应,请求)
- 从请求中拿到cookie对象
- 服务器响应给客户端cookie
Cookie[] cookies = req.getCookies();//可能存在多个cookie
cookie.getName();//获得cookie的key
cookie.getValue();//获得cookie的value
//新建cookie
new Cookie("lastLoginTime",System.currentTimeMillis()+"");
cookie.setMaxAge(24*60*60);//设置cookie有效时间
resp.addCookie(cookie);//响应给客户端
//保存用户上一次访问的时间
public class CookieDemo01 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//服务器告诉你来的时间,然后把这个时间封装成一个信件,下次带来信件就知道你来了
//解决中文乱码
resp.setContentType("text/html");
req.setCharacterEncoding("utf-8");
resp.setCharacterEncoding("utf-8");
PrintWriter out = resp.getWriter();
//Cookie,服务器端从客户端获取
Cookie[] cookies = req.getCookies();//可能存在多个cookie
//判断cookie是否存在
if (cookies!=null){
//如果存在
out.write("上一次访问的时间是:");
for (int i = 0; i < cookies.length; i++) {
Cookie cookie = cookies[i];
//获取cookie的名字
if (cookie.getName().equals("lastLoginTime")){
//获取cookie中的值
long lastLoginTime = Long.parseLong(cookie.getValue());
Date date = new Date(lastLoginTime);
out.write(date.toLocaleString());
}
}
}else {
out.write("第一次访问本站");
}
//服务器给客户端响应cookie
Cookie cookie = new Cookie("lastLoginTime",System.currentTimeMillis()+"");
//设置cookie有效期为一天
cookie.setMaxAge(24*60*60);
resp.addCookie(cookie);
}
-
cookie一般会保存在本地的用户目录下的appdata
-
一个cookie只能保存一个信息,一个web站点可以给浏览器发送多个cookie,最多存放20个cookie,cookie大小有限制4kb,300个cookie浏览器上限
-
关闭cookie:
- 不设置有效期,关闭浏览器自动失效
- 设置有效期为0
-
编码解码防止乱码
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
PrintWriter out = resp.getWriter();
Cookie[] cookies = req.getCookies();
if (cookies!=null){
out.write("上一次访问");
for (int i = 0; i < cookies.length; i++) {
Cookie cookie = cookies[i];
if (cookie.getName().equals("name")){
System.out.println(URLDecoder.decode(cookie.getValue()));
}
}
}else {
out.write("第一次访问");
}
Cookie cookie = new Cookie("name", URLEncoder.encode("刘想","UTF-8"));
resp.addCookie(cookie);
}
2、session(重点)
-
Session:在计算机中,尤其是在网络应用中,称为“会话控制”。Session对象存储特定用户会话所需的属性及配置信息
-
会话:打开浏览器点击很多超链接访问多个web资源,关闭浏览器,这个过程为一个会话
-
服务端给客户端一个信件,客户端下次访问服务端带上信件就可以了,cookie
-
服务器登记你来过,下次来我匹配你,session
-
服务器技术:可以把信息或者数据放在session中,session独占一个浏览器,只要浏览器不关闭,这个session就存在
-
用户登录后,整个网站都可以访问,保存用户的信息
2.1、常用方法
package com.liu.servlet;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
//session在打开浏览器的一瞬间就存在了
//跨servlet可以通过session或servletContext(少用)
public class SessionDemo01 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//乱码,以后可以在
resp.setContentType("text/html;charset=utf-8");
req.setCharacterEncoding("utf-8");
resp.setCharacterEncoding("utf-8");
//从请求得到session
HttpSession session = req.getSession();
//给session存东西,可以存一个对象
session.setAttribute("name",new Person("刘想",001,24));
//获取session的id
String id = session.getId();
//判断是不是新的
boolean aNew = session.isNew();
if (aNew){
resp.getWriter().write("session创建成功,ID:"+id);
}else {
resp.getWriter().write("session已经存在,ID:"+id);
}
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
package com.liu.servlet;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
public class SessionDemo02 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//乱码,以后可以在
resp.setContentType("text/html;charset=utf-8");
req.setCharacterEncoding("utf-8");
resp.setCharacterEncoding("utf-8");
//从请求得到session
HttpSession session = req.getSession();
Person person = (Person) session.getAttribute("name");
System.out.println(person.toString());
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
- 删除session(手动和自动两种方式)
<!--设置session的失效时间-->
<session-config>
<!--15分钟后失效,以分钟为单位-->
<session-timeout>15</session-timeout>
</session-config>
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
HttpSession session = req.getSession();
session.removeAttribute("name");
//手动注销session,在web.xml里默认注销session
session.invalidate(); //注销会立即生成一个session
}
2.2、session和cookie的区别
-
cookie是把用户的数据写给用户的浏览器,浏览器保存(可以保存多个)
-
session把用户的数据写到用户独占session中,服务器端保存(保存重要的信息,减少服务资源的浪费)
-
session对象由服务器创建
3、JSP
3.1、什么是JSP?
JavaServerPages:java服务器端页面
- 用于动态web开发,HTML只给用户提供静态数据,JSP页面可以嵌入Java代码
3.2、JSP原理
JSP怎么执行的:
-
代码层次没有问题
-
服务器内部工作
tomcat中有一个work目录
IDEA中使用tomcat会在IDEA中tomcat生产一个work目录
JSP本质上就是一个Servlet,源码分析:
//初始化
public void _jspInit() {
}
//销毁
public void _jspDestroy() {
}
//JSPService
public void _jspService(HttpServletRequest request, HttpServletResponse response) {}
-
判断请求
-
内置对象
final javax.servlet.jsp.PageContext pageContext; //页面上下文
javax.servlet.http.HttpSession session = null; //session
final javax.servlet.ServletContext application; //applicationContext
final javax.servlet.ServletConfig config; //config
javax.servlet.jsp.JspWriter out = null; //out
final java.lang.Object page = this; //page:当前页
javax.servlet.jsp.JspWriter _jspx_out = null;
javax.servlet.jsp.PageContext _jspx_page_context = null;
HttpServletRequest request // 请求
HttpServletResponse response //响应
- 输出页面前增加的代码
response.setContentType("text/html; charset=UTF-8"); //设置响应的页面类型
pageContext = _jspxFactory.getPageContext(this, request, response,
null, false, 8192, true);
_jspx_page_context = pageContext;
application = pageContext.getServletContext();
config = pageContext.getServletConfig();
out = pageContext.getOut();
_jspx_out = out;
- 以上的对象可以在JSP页面中直接使用
在JSP页面中:
- 只要是java代码就会原封不动的输出
- 如果是HTML代码就会被转换为
out.write("<html>\r\n");
out.write("name:");
3.3、JSP基础语法
- 导入依赖的jar包
<dependencies>
<!--Servlet 依赖-->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.5</version>
</dependency>
<!--JSP 依赖-->
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>javax.servlet.jsp-api</artifactId>
<version>2.3.3</version>
</dependency>
<!-- JSTL表达式的依赖 -->
<dependency>
<groupId>javax.servlet.jsp.jstl</groupId>
<artifactId>jstl-api</artifactId>
<version>1.2</version>
</dependency>
<!-- 标签库 -->
<dependency>
<groupId>taglibs</groupId>
<artifactId>standard</artifactId>
<version>1.1.2</version>
</dependency>
</dependencies>
JSP表达式
<%--JSP表达式
作用:用来将程序的输出,输出到客户端
<%= 变量或者表达式%>
--%>
<%= new java.util.Date()%>
<!--HTML注释-->
<%--JSP注释--%> JSP注释不会在客户端显示,HTML会!
<%JSP脚本%>
<%=%>
<%!声明%>
JSP脚本片段
<%--jsp脚本片段--%>
<%
int sum = 0;
for (int i = 1; i <= 100; i++) {
sum+=i;
}
out.println("<h1>Sum="+sum+"</h1>");//转换为html语言
%>
脚本片段的再实现
<%
int x = 10;
out.println(x);
%>
<p>这是一个JSP文档</p>
<%
int y = 10;
out.println(y);
%>
在代码中嵌入HTML
<%--在代码中嵌入HTML元素--%>
<%--${}:EL表达式,用于取值--%>
<%
for (int i = 0; i < 5; i++) {
%>
<h1>Hello World ${i}></h1>
<%
}
%>
JSP声明
: 会被编译到JSP生成Java类中,其他的均在_jspService方法中
<%!
static {
System.out.println("Loading Servlet!");
}
private int globalVar = 0;
public void liu(){
System.out.println("进入了方法");
}
%>
3.4、JSP指令
- 设置错误页面
<img src="../img/500.png" alt="500">
<img src="../img/404.png" alt="404">
<error-page>
<error-code>404</error-code>
<location>/error/404.jsp</location>
</error-page>
<error-page>
<error-code>500</error-code>
<location>/error/500.jsp</location>
</error-page>
- jsp标签
<%--@include会将两个页面合二为一--%>
<%@include file="common/header.jsp"%>
<h1>网页主体</h1>
<%@include file="common/footer.jsp"%>
<hr>
<%--jsp标签
jsp:include: 拼接页面,本质还是三个
--%>
<jsp:include page="common/header.jsp"/>
<h1>网页主体</h1>
<jsp:include page="common/footer.jsp"/>
3.5、九大内置对象
-
PageContext 存东西
-
Request 存东西
-
Response
-
Session 存东西
-
Application(ServletContext) 存东西
-
config(ServletConfig)
-
out
-
page(不用)
-
exception
从底层到高层(作用域):page–> request–> application
使用EL表达式输出 ${}
request:保存的数据只在一次请求中有效,客户端向服务器发送请求
session:客户端向服务器发送请求产生的数据,用户用完下次还会用
application:客户端向服务器发送请求产生的数据,一个用户用完其他用户还会用
<%--内置对象--%>
<%
pageContext.setAttribute("name1","liu1");//保存的数据只在一个页面中有效
request.setAttribute("name2","liu2");//保存的数据只在一次请求中有效,请求转发会携带整个数据
session.setAttribute("name3","liu3");//保存的数据在一次会话中有效,从打开浏览器到关闭浏览器
application.setAttribute("name4","liu4");//保存的数据在服务器中,从开启服务器到关闭服务器
%>
<%--脚片段中的代码会原封不动生成.jsp.java
要求:保证java语法的正确性
--%>
<%
//从pageContext取出,通过寻找方式来
//从底层到高层(作用域):page--> request--> application
//JVM:双亲委派机制:先从导的包找,再从类加载器找,再从rt.jar包找,都找不到就报ClassNotFound
String name1 = (String) pageContext.findAttribute("name1");
String name2 = (String) pageContext.findAttribute("name2");
String name3 = (String) pageContext.findAttribute("name3");
String name4 = (String) pageContext.findAttribute("name4");
String name5 = (String) pageContext.findAttribute("name5");
%>
<%--使用EL表达式输出 ${} --%>
<h1>取出的值为:</h1>
<h3>${name1}</h3>
<h3>${name2}</h3>
<h3>${name3}</h3>
<h3>${name4}</h3>
<h3> <%=name5%>></h3> <%--用EL表达式取不出null的值,用JSP语法取值会出现null--%>
3.6、JSP标签、JSTL标签、EL表达式
<!-- JSTL表达式的依赖 -->
<dependency>
<groupId>javax.servlet.jsp.jstl</groupId>
<artifactId>jstl-api</artifactId>
<version>1.2</version>
</dependency>
<!-- 标签库 -->
<dependency>
<groupId>taglibs</groupId>
<artifactId>standard</artifactId>
<version>1.1.2</version>
</dependency>
EL表达式:${}
- 获取数据
- 执行运算
- 获取web开发的常用对象
JSP标签
- jsp:include: 拼接页面
<%--jsp:include--%>
<%--http://localhost:8080/javaweb_jsp_war/jsptag.jsp?name=liuxiang&age=23--%>
<jsp:forward page="/jsptag2.jsp">
<jsp:param name="name" value="liuxiang"/>
<jsp:param name="age" value="23"/>
</jsp:forward>
JSTL表达式
JSTL标签库的使用就是为了弥补HTML标签的不足,自定义许多标签(去菜鸟教程)
核心标签
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
JSTL标签库使用步骤:
- 引入对应的taglib
- 看对应语法
- 在tomcat中也要引入相关的jar包,不然会报错
<h4>if测试</h4>
<hr>
<form action="coreif.jsp" method="get">
<%--EL表达式获取表单的数据${param.参数名}--%>
<input type="text" name="username" value="${param.username}">
<input type="submit" value="登录"/>
</form>
<%--判断如果提交的用户名是管理员,则登录成功--%>
<%--
if (request.getParameter("username").equals("admin")){
out.println("登录成功");
}
--%>
<c:if test="${param.username=='admin'}" var="isAdmin">
<c:out value="管理员登录"/>
</c:if>
<c:out value="${isAdmin}"></c:out>
<%--定义一个变量score,值为85--%>
<c:set var="score" value="85"/>
<c:choose>
<c:when test="${score>=90}">
成绩优秀
</c:when>
<c:when test="${score>=80}">
成绩良好
</c:when>
<c:when test="${score>=70}">
成绩一般
</c:when>
<c:when test="${score<=60}">
成绩不及格
</c:when>
</c:choose>
<%
ArrayList<String> people = new ArrayList<>();
people.add(0,"张三");
people.add(1,"李四");
people.add(2,"王五");
people.add(3,"赵六");
people.add(4,"田七");
request.setAttribute("list",people);
%>
<%--
var,每一次遍历的变量
items,要遍历的对象
begin,哪里
end,到哪里
step,步长
--%>
<c:forEach var="people" items="${list}">
<c:out value="${people}"/> <br>
</c:forEach>
<hr>
<c:forEach begin="1" end="3" step="2" var="people" items="${list}">
<c:out value="${people}"/>
</c:forEach>
格式化标签
<%@ taglib prefix="fmt"
uri="http://java.sun.com/jsp/jstl/fmt" %>
SQL标签
xml标签
4、JavaBean
实体类
JavaBean特定写法:
- 必须要有一个无参构造
- 属性必须私有化
- 必须有对应的get/set方法
一般用来和数据库的字段做映射 ORM;
ORM:对象关系映射-
- 表–>类
- 字段–>属性
- 行记录–>对象
id | name | age | address |
---|---|---|---|
1 | 张三 | 23 | 广州 |
2 | 王五 | 24 | 深圳 |
3 | 李四 | 25 | 深圳 |
class People{
private int id;
private String name;
private int age;
private String address;
}
class A{
new People("1","张三",23,"广州");
new People("2","李四",25,"深圳");
new People("3","王五",24,"深圳");
}
<%
// People people = new People();
// people.setAddress();
// people.setAge();
// people.setId();
// people.setName();
%>
<jsp:useBean id="people" class="com.liu.pojo.People" scope="page"/>
<jsp:setProperty name="people" property="address" value="广州"/>
<jsp:setProperty name="people" property="id" value="1"/>
<jsp:setProperty name="people" property="age" value="23"/>
<jsp:setProperty name="people" property="name" value="张三"/>
姓名: <jsp:getProperty name="people" property="name"/>
id: <jsp:getProperty name="people" property="id"/>
年龄: <jsp:getProperty name="people" property="age"/>
地址: <jsp:getProperty name="people" property="address"/>
5、三层架构
MVC:Model、view、Controller 模型、视图、控制器
- 用户直接访问控制层,控制层可以直接操作数据库
servlet -- CRUD -- 数据库
弊端:程序十分臃肿,不利于维护
servlet的代码中:处理请求,响应,视图跳转,处理JDBC,处理业务和逻辑代码
架构:没有什么是加一层解决不了的
程序员调用
|
JDBC
|
Mysql,Oracle...
- MVC三层架构
Model:
- 业务处理:业务逻辑(Service)
- 数据持久层:CRUD(Dao)
view:
- 展示数据
- 提供链接发起Servlet请求(a,form,img…)
Controller:
- 接收用户的请求:(requset)
- 交给一万五层处理对应的代码
- 控制视图的跳转
登录-->接收用户的请求-->处理请求(获取用户登录的参数)-->交给业务层处理登录业务--》Dao层查询用户名和密码是否正确-->数据库
6、过滤器Filter
Filter:过滤器用来过滤网站的数据
-
和Servlet一样,只是实现的接口不一样
-
处理中文乱码
-
登录验证
Filter开发步骤:
- 导包
<dependencies>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.5</version>
</dependency>
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>javax.servlet.jsp-api</artifactId>
<version>2.3.3</version>
</dependency>
<dependency>
<groupId>javax.servlet.jsp.jstl</groupId>
<artifactId>jstl-api</artifactId>
<version>1.2</version>
</dependency>
<dependency>
<groupId>taglibs</groupId>
<artifactId>standard</artifactId>
<version>1.1.2</version>
</dependency>
<!--连接数据库-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.47</version>
</dependency>
</dependencies>
- 继承接口不要错 Filter javax.servlet
public class CharacterEncodingFilter implements Filter {
//初始化:web启动就初始化了,随时监听
public void init(FilterConfig filterConfig) throws ServletException {
System.out.println("CharacterEncodingFilter初始化");
}
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");
//chain:链
/*
1.过滤中的所有代码,在过滤特定请求的时候都会执行
2.必须要让过滤器继续同行
chain.doFilter(request,response);
*/
System.out.println("CharacterEncodingFilter执行前...");
filterChain.doFilter(servletRequest,servletResponse);//让我们程序继续走,不写程序到这就停止了
System.out.println("CharacterEncodingFilter执行后...");
}
//销毁:web服务器关闭的时候过滤会销毁
public void destroy() {
System.out.println("CharacterEncodingFilter销毁");
}
}
- filter过滤器的xml配置
<filter>
<filter-name>CharacterEncodingFilter</filter-name>
<filter-class>com.liu.filter.CharacterEncodingFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>CharacterEncodingFilter</filter-name>
<!--只要是/servlet的任何请求都会经过这个过滤器-->
<url-pattern>/servlet/*</url-pattern>
</filter-mapping>
6.1、Filter实现权限拦截
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
HttpServletRequest request1 = (HttpServletRequest) request;
HttpServletResponse response1 = (HttpServletResponse) response;
if (request1.getSession().getAttribute(Constant.USER_SESSION)==null){
response1.sendRedirect("/error.jsp");
}
}
- 用户登录后向Session中放入用户的数据
- 进入主页的时候要判断用户是否已经登录,要求在过滤器中实现
7、监听器
- 继承监听器接口
//统计session,在线人数
public class OnlineCountListener implements HttpSessionListener {
//创建session监听,创建session就触发这个事件
public void sessionCreated(HttpSessionEvent se) {
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销毁:
手动销毁:se.getSession().invalidate();
自动销毁在xml文件里配置失效时间
*/
public void sessionDestroyed(HttpSessionEvent se) {
ServletContext ctx = se.getSession().getServletContext();
Integer onlineCount = (Integer) ctx.getAttribute("OnlineCount");
if (onlineCount==null){
onlineCount = new Integer(0);
}else {
int count = onlineCount.intValue();
onlineCount= new Integer(count-1);
}
ctx.setAttribute("OnlineCount",onlineCount);
}
}
- web.xml中注册监听器
<!--注册监听器-->
<listener>
<listener-class>com.liu.listener.OnlineCountListener</listener-class>
</listener>
8、JDBC复习
- 导入需要的jar包
<dependencies>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.47</version>
</dependency>
- 编写java代码
package com.liu.jdbc;
import java.sql.*;
import java.util.Date;
public class TestJdbc {
public static void main(String[] args) throws ClassNotFoundException, SQLException {
//配置信息
String url="jdbc:mysql://localhost:3306/jdbc?useUnicode=true&characterEncoding=utf8&useSSL=false";
String username= "root";
String password= "123456789";
//1.加载驱动
Class.forName("com.mysql.jdbc.Driver");
//2.连接数据库
Connection connection = DriverManager.getConnection(url, username, password);
// String sql1 = "insert into users(id,name ,password,email,birthday) values (?,?,?,?,?);";
// PreparedStatement preparedStatement = connection.prepareStatement(sql1);
// preparedStatement.setInt(1,2);
// preparedStatement.setString(2,"liuxiang");
// preparedStatement.setString(3,"123456");
// preparedStatement.setString(4,"23123@qq.com");
// preparedStatement.setDate(5,new java.sql.Date(new Date().getTime()));
//
// int i = preparedStatement.executeUpdate();
// if (i>0){
// System.out.println("插入成功");
// }
Statement statement = connection.createStatement();
String sql = "select * from users";
ResultSet resultSet = statement.executeQuery(sql);
while (resultSet.next()){
System.out.println("id=" + resultSet.getObject("id"));
System.out.println("name=" + resultSet.getObject("name"));
System.out.println("password=" + resultSet.getObject("password"));
System.out.println("email=" + resultSet.getObject("email"));
System.out.println("birthday=" + resultSet.getObject("birthday"));
}
resultSet.close();
statement.close();
connection.close();
}
}
- 事务
ACID原则,要么都成功,要么都失败!
123@qq.com");
// preparedStatement.setDate(5,new java.sql.Date(new Date().getTime()));
//
// int i = preparedStatement.executeUpdate();
// if (i>0){
// System.out.println(“插入成功”);
// }
Statement statement = connection.createStatement();
String sql = "select * from users";
ResultSet resultSet = statement.executeQuery(sql);
while (resultSet.next()){
System.out.println("id=" + resultSet.getObject("id"));
System.out.println("name=" + resultSet.getObject("name"));
System.out.println("password=" + resultSet.getObject("password"));
System.out.println("email=" + resultSet.getObject("email"));
System.out.println("birthday=" + resultSet.getObject("birthday"));
}
resultSet.close();
statement.close();
connection.close();
}
}
3. **事务**
**ACID原则,要么都成功,要么都失败!**