1.servlet是否线程安全 (线程特性)
线程安全的指标
//1.是否有共享数据
//2.多线程对共享数据做写操作
servlet中 不要创建成员变量
servlet是单实例的 所以成员变量(不加static) 就会在多线程间共享
如果service()方法中 对成员变量有写操作 则线程不安全
servlet中非特殊情况 不要加锁 (直接降级为单线程 效率大大降低)
2.servlet中提供的域对象
javaEE j2EE java企业级应用 (web应用程序)
核心对象servlet servlet中还包含其他的对象 还有隐含的对象
域对象 是servlet中隐含的对象
域对象 是空的map (在程序运行时 共享数据使用)
通用的api
域对象.setAttribute("key",value);
域对象.getAttribute("key")
域的生效时机 和失效时机
1请求域 request域
request读+写
package com.javasm.controller;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@WebServlet("/requestDemo1")
public class RequestDemo1 extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//request域 service方法中的第一个参数 req
req.setAttribute("reqKey","reqVal");
//读取对象的格式 读到之后强转为实际类型
String reqKey =(String) req.getAttribute("reqKey");
System.out.println("demo1中读取:"+reqKey);
//调用指定路径servlet的service方法
req.getRequestDispatcher("requestDemo2").forward(req,resp);
}
}
request 只读取
package com.javasm.controller;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@WebServlet("/requestDemo2")
public class RequestDemo2 extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//request域 service方法中的第一个参数 req
//req.setAttribute("reqKey","reqVal");
//读取对象的格式 读到之后强转为实际类型
String reqKey =(String) req.getAttribute("reqKey");
System.out.println("demo2中读取:"+reqKey);
}
}
2会话域 session域
可以在多次请求间生效
对不同的浏览器进程 数据分开存储
session读+写
package com.javasm.controller;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
@WebServlet("/sessionDemo1")
public class SessionDemo1 extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//session域 多次请求间共享数据使用
//如果需要使用session对象 需要通过代码主动触发
HttpSession session = req.getSession();
session.setAttribute("sesKey","sesVal");
String sesKey =(String) session.getAttribute("sesKey");
System.out.println("demo1中读取:"+sesKey);
}
}
session只读取
package com.javasm.controller;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
@WebServlet("/sessionDemo2")
public class SessionDemo2 extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//session域 多次请求间共享数据使用
//如果需要使用session对象 需要通过代码主动触发
HttpSession session = req.getSession();
String sesKey =(String) session.getAttribute("sesKey");
System.out.println("demo2中读取:"+sesKey);
}
}
3服务器域 servletContext域
全局共享 写入之后 所有请求 所有浏览器都可以使用
servletContext读+写
package com.javasm.controller;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
@WebServlet("/ServletContextDemo1")
public class ServletContextDemo1 extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//ServletContext 服务器对象
ServletContext servletContext = req.getServletContext();
//ServletContext servletContext1 = this.getServletContext();
servletContext.setAttribute("sckey","scval");
String sckey =(String) servletContext.getAttribute("sckey");
System.out.println("demo1中读取:"+sckey);
}
}
servletContext只读取
package com.javasm.controller;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@WebServlet("/ServletContextDemo2")
public class ServletContextDemo2 extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//ServletContext 服务器对象
ServletContext servletContext = req.getServletContext();
//ServletContext servletContext1 = this.getServletContext();
String sckey =(String) servletContext.getAttribute("sckey");
System.out.println("demo2中读取:"+sckey);
}
}
3servlet中常用对象
3.1servletContext对象
servletContext对象 也叫application 是服务器对象
这是一个全局共享的对象 一般用来存放和共享服务器级别的全局参数
常用方法:
* getContextPath() 获取服务入口路径 /day10 方便拼路径使用
* getRealPath("/") 获取服务器实际代码路径 做本地IO操作时使用
* getInitParameter("charset") 通过web.xml 读取自定义公共参数
示例代码:
package com.javasm.controller2;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@WebServlet("/scDemo")
public class ServletContextDemo extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//servletContext对象 application 服务器对象
//全局共享的对象 全局数据
/*
* getContextPath() 获取服务入口路径 /day10 方便拼路径使用
* getRealPath("/") 获取服务器实际代码路径 做本地IO操作时使用
* getInitParameter("charset") 通过web.xml 读取自定义公共参数
* */
// 获取服务入口路径 /day10 方便拼路径使用
ServletContext servletContext = req.getServletContext();
System.out.println(servletContext.getContextPath());
// 获取服务器实际代码路径
//D:\develop\workspace\two\day10_servlet2\target
// \day10_servlet2-1.0-SNAPSHOT\ 做本地IO操作时使用
System.out.println(servletContext.getRealPath("/"));//括号当中要填路径,即可返回绝对路径
//通过web.xml 读取自定义公共参数
String initParameter = servletContext.getInitParameter("charset");
System.out.println(initParameter);
}
}
3.2servletConfig对象(了解)
servlet配置参数对象 可以获取servlet名称 等配置参数 现在的开发中基本用不到
3.3request对象(***)
HttpServletRequest 请求对象
两个作用:
1.解析请求报文 包含请求报文中的各种参数
2.做request域对象
常用方法:
//域对象 设置键值对
req.setAttribute("reqKey","reqVal");
//域对象读取键值对 注意要强转类型
String reqKey =(String) req.getAttribute("reqKey");
//指定字符编码 处理post请求时的请求乱码
req.setCharacterEncoding("utf-8");
//取请求参数
String 参数值 = req.getParameter("参数key");
//取请求同key参数 ?hobby=1&hobby=2&hobby=3 取出字符串数组
String[] hobbies = req.getParameterValues("hobby");
获取参数map 获取参数输入流 (了解)
//tomcat解析参数时 会把键值对存入map<String, String[]>
//单个参数也会存入数组
Map<String, String[]> parameterMap = req.getParameterMap();
//tomcat中允许 自己读取请求体中的数据 可以自己解析数据
//获得请求体部分的输入流
ServletInputStream inputStream = req.getInputStream();
获取请求头 (了解)
//自定义请求头 取自定义请求头(需搭配ajax使用)
String headerKey = req.getHeader("headerKey");
获取请求报文中的各种路径
//获取报文中路径中的数据
//获取协议
System.out.println(req.getScheme());
//获取主机名
System.out.println(req.getServerName());
//获取端口
System.out.println(req.getServerPort());
//获取服务器入口的根路径
System.out.println(req.getContextPath());
//URL 与 URI
//URL 统一资源定位符 http://localhost:8080/day10/reqDemo
System.out.println(req.getRequestURL());
//URI 统一资源标识符 /day10/reqDemo
System.out.println(req.getRequestURI());
//servlet配置的路径 匹配路径 /reqDemo
System.out.println(req.getServletPath());
请求转发
可以在servlet之间跳转 先执行servlet1 ---> servlet2
//请求转发 同一次请求 访问多个servlet时使用 可以让请求跳转
//请求跳转时 配合request域做数据共享 提供机制 一般搭配jsp使用
req.getRequestDispatcher("servlet2的路径").forward(req,resp);
示例代码:
package com.javasm.controller2;
import javax.servlet.ServletException;
import javax.servlet.ServletInputStream;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Map;
@WebServlet("/reqDemo")
public class RequestDemo extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//req HttpServletRequest
//1.解析请求报文 包含请求报文中的各种参数
//2.做request域对象
/*
//域对象 设置键值对
req.setAttribute("reqKey","reqVal");
//域对象读取键值对 注意要强转类型
String reqKey =(String) req.getAttribute("reqKey");
//取参数相关
//指定字符编码 处理post请求时的请求乱码
req.setCharacterEncoding("utf-8");
//取请求参数
String 参数值 = req.getParameter("参数key");
//取请求同key参数 ?hobby=1&hobby=2&hobby=3 取出字符串数组
String[] hobbies = req.getParameterValues("hobby");
//tomcat解析参数时 会把键值对存入map<String, String[]>
//单个参数也会存入数组
Map<String, String[]> parameterMap = req.getParameterMap();
//tomcat中允许 自己读取请求体中的数据 可以自己解析数据
//获得请求体部分的输入流
ServletInputStream inputStream = req.getInputStream();
//自定义请求头 取自定义请求头
String headerKey = req.getHeader("headerKey");
*
*
* */
// //tomcat解析参数时 会把键值对存入map<String, String[]>
// //单个参数也会存入数组
// Map<String, String[]> parameterMap = req.getParameterMap();
// System.out.println(parameterMap.get("name")[0]);
/* 获取参数的请求体输入流
可以自己解析请求体数据 配合其他工具 也可以直接解析为对象
与tomcat解析流数据互斥 流只能读一次
ServletInputStream inputStream = req.getInputStream();
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
String s = bufferedReader.readLine();
System.out.println(s);
String username = req.getParameter("username");
System.out.println(username);
*
*
* */
//读请求报文 只能读请求体 可以读post方式的请求体
//字符
//字节
//流只能读一次
ServletInputStream inputStream = req.getInputStream();
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
String s = bufferedReader.readLine();
System.out.println(s);
String username = req.getParameter("username");
System.out.println(username);
//获取报文中路径中的数据
//获取协议
System.out.println(req.getScheme());
//获取主机名
System.out.println(req.getServerName());
//获取端口
System.out.println(req.getServerPort());
//获取服务器入口的根路径
System.out.println(req.getContextPath());
//URL 与 URI
System.out.println(req.getRequestURL());//URL 统一资源定位符 http://localhost:8080/day10/reqDemo
System.out.println(req.getRequestURI());//URI 统一资源标识符 /day10/reqDemo
//servlet配置的路径 匹配路径 /reqDemo
System.out.println(req.getServletPath());
//请求转发 同一次请求 访问多个servlet时使用 可以让请求跳转
//请求跳转时 配合request域做数据共享 提供机制 一般搭配jsp使用
// req.getRequestDispatcher("地址").forward(req,resp);
}
}
3.4response对象(***)
HttpServletResponse 响应对象 控制响应报文相关的内容
常用方法
//设置返回数据格式
//resp.setContentType("application/json;charset=utf-8"); //返json
//resp.setContentType("text/html;charset=utf-8"); //返页面标签
resp.setContentType("text/html;charset=utf-8");
//获得输出流
//动态网页技术 数据是否动态生成
PrintWriter writer = resp.getWriter();
writer.print("这是一个动态页面<br>");
writer.print("<input type='text'>");
// writer.write();
// writer.println();
示例代码
package com.javasm.controller2;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
@WebServlet("/respDemo")
public class ResponseDemo extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("触发运行了....");
//返回页面标签
//设置返回数据格式
//resp.setContentType("application/json;charset=utf-8");
//resp.setContentType("text/html;charset=utf-8");
resp.setContentType("text/html;charset=utf-8");
//获得输出流
//动态网页技术 数据是否动态生成
PrintWriter writer = resp.getWriter();
writer.print("这是一个动态页面<br>");
writer.print("<input type='text'>");
// writer.write();
// writer.println();
writer.close();
}
}
3.5session对象(***)
HttpSession 会话对象 做域对象(缓存数据) 在同一个用户(浏览器)多次访问间共享数据
常用方法
//域对象 设置键值对
req.setAttribute("sesKey","sesVal");
//域对象读取键值对 注意要强转类型
String reqKey =(String) req.getAttribute("sesKey");
//删除键值对
req.removeAttribute("sesKey");
//获得session编号 用来检查是否同一个session对象
session.getId()
//设置session访问间隔 单位秒 超过间隔会重新创建session
session.setMaxInactiveInterval(5);
//直接设置session失效
session.invalidate();
示例代码
package com.javasm.controller2;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
@WebServlet("/sesDemo")
public class HttpSessionDemo extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//获得session对象 req.getSession()
HttpSession session = req.getSession();
//session编号 C03DDD56DF31BAB3EB6A41DB728815CF
//每个session都会起编号 如过session对象相同 编号是相同的
System.out.println(session.getId());
//MaxInactiveInterval 最大非活动周期 两次访问的间隔
//
//session.setMaxInactiveInterval(5);
session.invalidate();
/*
* session三种失效方式
* 1.浏览器关闭
* 2.超过访问间隔
* 3.直接设置session失效
*
* */
//session对象保留 但是sesison中的数据可以清除掉
//session.removeAttribute("key");
/*
* session使用场景
* 1.当缓存使用 把一些常用的数据存入session 服务端需要使用时 直接使用共享的数据
* 2.做访问控制
* 登录访问控制
*
* */
}
}
session常用场景
* session使用场景
* 1.当缓存使用 把一些常用的数据存入session 服务端需要使用时 直接使用共享的数据
* 2.做访问控制
* 登录访问控制
登录访问控制场景:
示例代码
登录服务 LoginServlet
package com.javasm.controller3;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
@WebServlet("/login")
public class LoginServlet extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//做登录....
System.out.println("登录代码执行了......");
HttpSession session = req.getSession();
session.setAttribute("loginUser","用户信息....");
}
}
用户服务 UserServlet
package com.javasm.controller3;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
@WebServlet("/user")
public class UserServlet extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//查用户信息 必须登录后使用
HttpSession session = req.getSession();
String loginUser =(String) session.getAttribute("loginUser");
if(loginUser!=null){
System.out.println("查询用户代码执行了......");
}else{
System.out.println("请先登录......");
}
}
}
商品服务 ProdServlet
package com.javasm.controller3;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@WebServlet("/prod")
public class ProdServlet extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//查商品信息 不需要登录
System.out.println("查询商品代码执行了......");
}
}
登出服务 LogoutServlet
package com.javasm.controller3;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
@WebServlet("/logout")
public class LogoutServlet extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//做登出....
System.out.println("登出代码执行了......");
HttpSession session = req.getSession();
//session.setAttribute("loginUser","用户信息....");
//session.invalidate();
session.removeAttribute("loginUser");
}
}