一、Servlet里面的两个重要的对象
-
ServletConfig:某个serlvet的配置对象
获取初始化参数1). 获取ServletConfig对象呢?
GenericServlet:抽象的父类中:
public ServetConfig getServietConfig(){return this.config}2). ServletConfig:获取配置参数
ServletConfig config = this.getServletConfig();3). 获取初始化参数
String getInitParameter(String var1);//参数名称获取参数值
String value = config.getInitParameter(“encoding”);
System.out.println(value);
web.xml:
<?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_4_0.xsd"
version="4.0">
<!--servlet基本配置-->
<servlet>
<servlet-name>ServletConfigDemo</servlet-name>
<servlet-class>com.qf.servletconfig_01.ServletConfigDemo</servlet-class>
</servlet>
<!--servlet的映射配置-->
<servlet-mapping>
<servlet-name>ServletConfigDemo</servlet-name>
<url-pattern>/configDemo</url-pattern>
</servlet-mapping>
import javax.servlet.ServletConfig;
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.Enumeration;
/* ServletConfig对象 :Servlet的配置对象
*/
public class ServletConfigDemo extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
//ServletConfig:获取配置参数
ServletConfig config = this.getServletConfig();
//获取初始化参数
//String getInitParameter(String var1);//参数名称获取参数值
String value = config.getInitParameter("encoding");
System.out.println(value);
System.out.println("------------------------------------");
//public java.util.Enumeration<E> getInitParameterNames():获取servlet的所有初始化参数名称
Enumeration<String> ens = config.getInitParameterNames();
while(ens.hasMoreElements()){
String name = ens.nextElement();
String v = config.getInitParameter(name);
System.out.println(name+"---"+v);
}
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req,resp);
}
}
4). html:超文本标记语言
书写html标签:一定存在的标签
xml:可扩展标记语言 (作为配置文件去使用的!)
早期用来代替html语言,没有替代成功!
非常注重结构(必须有开始,有结束)
作为"小型数据库"
用户可以自定义标签
特点:一个xml文件有且只能有一个根标签
- ServletContext: (全局对象)
全局对象:ServletContext
每一个web应用程序都有自己的上下文: 工程名称
包含在url地址上
http://localhost:8080/EE_day36_war_exploded/
EE_day36_war_exploded:上下文路径
<!--全局参数-->
<context-param>
<param-name>AAA</param-name>
<param-value>AAA'value</param-value>
</context-param>
<!--一个servlet里面可以配置很多的初始化参数-->
<!--初始化参数-->
<init-param>
<!--参数名称-->
<param-name>encoding</param-name>
<!--参数值-->
<param-value>utf-8</param-value>
</init-param>
<init-param>
<param-name>path</param-name>
<param-value>d:/a.txt</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
作用1:1)加载全局参数
获取ServletContext对象
抽象的父类中
public ServletContext getServletContext() {
return this.getServletConfig().getServletContext();
}
ServletContext context = this.getServletContext();
加载全局参数(后期读取配置文件 : springmvc底层基于Servlet (前端控制器:DispatcherServlet))
String getInitParameter(String var1);:初始化的全局参数
Enumeration<String> getInitParameterNames();
String value = context.getInitParameter("AAA");//参数名称获取参数内容
System.out.println(value);///EE_day36_war_exploded
Http协议:将获取上下文路径的方法,封装在请求对象中
xx.jsp
<a href="${域对象获取上下路径}/login.jsp">超链接</a> 浏览器行为 (当前jsp页面中 的超链接,图像加载:带上上下文路径)
举例:
<servlet>
<servlet-name>ServletContextDemo</servlet-name>
<servlet-class>com.qf.servletcontext_02.ServletContextDemo</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>ServletContextDemo</servlet-name>
<url-pattern>/contextDemo</url-pattern>
</servlet-mapping>
public class ServletContextDemo extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
String path = request.getContextPath();
System.out.println(path);///EE_day36_war_exploded
}
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request,response);
}
}
作用2:2)可以获取上下路径
<%--
pageContext
getReuqest()---->Request对象
request--->称为 pageContext的bean对象(javabean导航)
HttpServletRequest
public String getContextPath() getXXX() ----xXX:就称为bean属性
contextPath--->称为HttpServletRequest的bean属性
--%>
<%-- <a href="${pageContext.request.contextPath}/login.jsp">登录</a>--%>
举例:
<servlet>
<servlet-name>ServletContextDemo2</servlet-name>
<servlet-class>com.qf.servletcontext_02.ServletContextDemo2</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>ServletContextDemo2</servlet-name>
<url-pattern>/contextDemo2</url-pattern>
</servlet-mapping>
public class ServletContextDemo2 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
//1)获取Servletcontext对象
ServletContext servletContext = this.getServletContext(); //全局对象
//2)String getContextPath():获取上下文路径
String path = servletContext.getContextPath();
System.out.println(path);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req,resp);
}
}
作用3:3)可以作为"域对象"
传递的数据可以在不同servlet之间通过域对象进行数据共享!
举例:
<servlet>
<servlet-name>ServletContextDemo3</servlet-name>
<servlet-class>com.qf.servletcontext_02.ServletContextDemo3</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>ServletContextDemo3</servlet-name>
<url-pattern>/demo1</url-pattern>
</servlet-mapping>
/* 域对象:可以在不同的servlet之间进行数据共享!
*/
public class ServletContextDemo3 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
//获取全局对象
ServletContext servletContext = this.getServletContext();
//给当前域对象添加属性和内容
//void setAttribute(String var1, Object var2);
List<String> list = new ArrayList<String>() ;
list.add("高圆圆") ;
list.add("文章") ;
list.add("马伊琍") ;
servletContext.setAttribute("list",list);//存储的属性名称 "见名知意"
System.out.println("保存成功...");
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req,resp);
}
}
举例:
<servlet>
<servlet-name>ServletContextDemo4</servlet-name>
<servlet-class>com.qf.servletcontext_02.ServletContextDemo4</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>ServletContextDemo4</servlet-name>
<url-pattern>/demo2</url-pattern>
</servlet-mapping>
public class ServletContextDemo4 extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
//获取全局对象
ServletContext servletContext = this.getServletContext();
// Object getAttribute(String var1);
List<String> list = (List<String>) servletContext.getAttribute("list");
for(String str:list){
System.out.println(str);
}
System.out.println("获取成功....");
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request,response);
}
}
作用4:4)有请求转发的作用
子实现类:
HttpServletRequest HttpServletRequestWrapper
HttpServletResponse HttpServletResponseWrapper
原理:
1)获取全局对象
ServletContext servletContext = this.getServletContext();
2)获取分发对象
RequestDispatcher getRequestDispatcher(String var1)
参数:客户端发送的请求 通过分发对象访问服务器的内部资源文件(servet,jsp,html)
服务器行为:通过服务器进行内部转发 路径: 无需带上下文路径
RequestDispatcher rd = servletContext.getRequestDispatcher("/WEB-INF/hello.html");
void forward(ServletRequest var1, ServletResponse var2) 转发到上面的地址上
rd.forward(request,response);
3).因为request对象本身域对象
request.setAttribute("XXX","XXX");
4).简写方式:ServletRequest接口中
RequestDispatcher getRequestDispatcher(String var1); 获取分发对象
举例:
<servlet>
<servlet-name>ServletContextDemo5</servlet-name>
<servlet-class>com.qf.servletcontext_02.ServletContextDemo5</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>ServletContextDemo5</servlet-name>
<url-pattern>/demo3</url-pattern>
</servlet-mapping>
public class ServletContextDemo5 extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
//因为request对象本身域对象
request.setAttribute("name","高圆圆");
//简写方式:ServletRequest接口中
//RequestDispatcher getRequestDispatcher(String var1); 获取分发对象
request.getRequestDispatcher("/get.jsp").forward(request,response);
System.out.println("请求转发已完成....");
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request,response);
}
}
- 域对象:从小到大
pageContext :page域 (在某个jsp页面下有效)
HttpServletRequest :request域 在一次请求有效
HttpSession session域: 在一次会话中有效
ServletContext applcation域 :范围最大的
二、请求转发的原理以及重定向原理
- 请求转发的原理:
web容器: 请求对象获取分发对象: RequestDispatcher里面的forward()来完成转发的请求
<%-- <%
String str = (String) request.getAttribute("name");
//System.out.println(str);
out.write(str);
%>--%>
优化:${requestScope.name}
扩展:
2. 重定向的原理—本质:响应头:location + 302(进一步请求)
1). 重定向:后台跳转页面的一种方式
2). 重定向原理(属于浏览器行为:需要带上下文路径)
设置使用响应头location头
void setHeader(String var1, String var2);
response.setHeader("location",request.getContextPath()+"/adv.html");
加上一个响应的状态:302(在一次请求)
void setStatus(int var1);
response.setStatus(302); //再次发送请求
优化:
在响应对象:ServletRseonse中
void sendRedirect(String var1) throws IOExceptio
举例:
<servlet>
<servlet-name>ResponDemo1</servlet-name>
<servlet-class>com.qf.response_03.ResponDemo1</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>ResponDemo1</servlet-name>
<url-pattern>/resDemo1</url-pattern>
</servlet-mapping>
public class ResponDemo1 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
System.out.println("开始解析...");
response.sendRedirect(request.getContextPath()+"/adv.html");
System.out.println("解析完成,准备通过浏览器再一次发送请求");
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req,resp);
}
}
-
响应头:
定时刷新头:refresh有定时刷新和经过多少秒后进行页面跳转
举例:
<servlet>
<servlet-name>ResponseDemo2</servlet-name>
<servlet-class>com.qf.response_03.ResponseDemo2</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>ResponseDemo2</servlet-name>
<url-pattern>/resDemo2</url-pattern>
</servlet-mapping>
public class ResponseDemo2 extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.setContentType("text/html;charset=utf-8");
// response.setHeader("refresh","3");//每3秒页面刷新
//经过多少秒后进行页面跳转
response.getWriter().write("注册成功!3秒后跳转主页");
response.setHeader("refresh","3;"+request.getContextPath()+"/index.jsp");
System.out.println("定时刷新");
}
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request,response);
}
}
-
注解的本质就是一个接口:interface
当前接口中的方法名----在注解中 叫"注解的属性"jdk提供很多的内置注解
@Override: 标记某个方法是否是否重写的方法(重写的类还是重写接口的方法)
@Deprecated:标记某个方法是否是过时的
@FunctionalInterface :标记某个接口是否是函数式接口
@SuppressWarnings:压制警告 (项目部署上线的时候:代码不能出现黄色警告线问题)
内置注解中会依赖于元注解
@Target:标记当前内置注解能够在哪个范围上使用
public @interface Target {
ElementType[] value(); 返回值类型:枚举数组
ElementType: 枚举规定的范围
TYPE, 类/接口上使用
FIELD, 成员变量上使用
METHD 成员方法上使用
}
@Retention:规定的注解的保留阶段(三个阶段)
public @interface Retention {
RetentionPolicy value();
}
RetentionPolicy:枚举
SOURCE, 编译阶段
CLASS, 类的加载阶段
RUNTIME 运行阶段 (我们自定义注解的时候:考虑运行阶段)
@Documented:文档相关的注解
注解中的属性----接口的方法名
定义注解中的属性的类型可以分为哪些?
基本数据类型
String类型
枚举类型
注解类型
以上类型的数组方式
注意事项:
如果当前注解有且仅有一个属性的时候,
并且名称value,那么给value属性是可以省略名称value,直接返类型赋值
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnno {
int age() ; //age属性:返回值类型 基本类型
String name() ; //name属性:返回值String类型
MyEnum my() ; //my属性:返回值枚举类型
String[] strs() ;//strs属性:返回值 数组
}
//抽象的人类
public abstract class Person {
public abstract void work() ;
}
@SuppressWarnings("all")
public class Worker extends Person {
@Override //内置注解
public void work() {
System.out.println("工人都需上班...");
}
/*@MyAnno()
public void eat(){
}*/
/*@Override //eat()并非重写方法
public void eat(){
System.out.println("工人都需要吃饭");
}*/
}
//如果某个接口中只有一个抽象方法的时候,标记这个接口为函数式接口
@FunctionalInterface
public interface Love {
void love() ;
// void method() ;
}
public enum MyEnum {
LEFT, //左
RIGHT;//右
}
//要使用MyAnno注解
@MyAnno(age=21,name="高圆圆",my=MyEnum.LEFT,strs = {"a","b","c"})
public @interface MyAnnotation2 {
}
使用注解优化:好处将相关的属性信息定义在注解中—通过反射执行
如何解析自定义注解呢?反射的方式完成
注解作用在哪个类上,获取当前字节码文件对象
Class clazz = Test.class ;
解析注解
Class类中public <A extends Annotation> A getAnnotation(Class<A> annotationClass)
参数为:当前注解类型的字节码文件对象
返回值:相当于获取到了MyAnnotation注解(接口)获取子实现类对象
MyAnnotation myAnnotation = (MyAnnotation) clazz.getAnnotation(MyAnnotation.class);
String className = myAnnotation.className(); //调用方法(注解中的属性)
String methodName = myAnnotation.methodName();
通过Class.forName(className)
Class myClazz = Class.forName(className);
System.out.println(myClazz); //class com.qf.annotation_05.Student
直接创建该类实例
Object obj = myClazz.newInstance();
System.out.println(obj);
myClazz获取成员方法Method
Method method = myClazz.getMethod(methodName);
调用
method.invoke(obj) ;
举例:
@Target(ElementType.TYPE) //作用在类上
//保留的运行阶段
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnnotation {
//定义两个 属性
String className() ;
String methodName() ;
}
public class Student {
public void love(){
System.out.println("love Java...");
}
}
public class Worker {
public void love(){
System.out.println("love Java,love Life...");
}
}
/* jdk提供的内置注解或者他们依赖的元注解 或者开发者自定义的注解都继承自己公共接口 Annotation
*/
@SuppressWarnings("all")
@MyAnnotation(className = "com.qf.annotation_05.Worker",methodName = "love")
public class Test {
public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {
//创建一个学生类
Student s = new Student() ;
s.love();
//工人类
Worker w = new Worker();
w.love();
System.out.println("---------------------------------");
//使用注解优化:好处将相关的属性信息定义在注解中---通过反射执行
//如何解析自定义注解呢?反射的方式完成
//注解作用在哪个类上,获取当前字节码文件对象
Class clazz = Test.class ;
//解析注解
//Class类中public <A extends Annotation> A getAnnotation(Class<A> annotationClass)
//参数为:当前注解类型的字节码文件对象
//返回值:相当于获取到了MyAnnotation注解(接口)获取子实现类对象
MyAnnotation myAnnotation = (MyAnnotation) clazz.getAnnotation(MyAnnotation.class);
String className = myAnnotation.className(); //调用方法(注解中的属性)
String methodName = myAnnotation.methodName();
//通过Class.forName(className)
Class myClazz = Class.forName(className);
//System.out.println(myClazz);//class com.qf.annotation_05.Student
//直接创建该类实例
Object obj = myClazz.newInstance();
//System.out.println(obj);
//myClazz获取成员方法Method
Method method = myClazz.getMethod(methodName);
//调用
method.invoke(obj) ;
}
}
三、jsp的基本使用
jsp脚本注释 是不会被解析的
而html注释:是会被解析
jsp:Java Server Page :Java服务页面(能够书写java代码的html页面)
jsp应用场景:主要通过servlet获取业务数据,在jsp做数据展示的!
jsp经历两个阶段 ----- 都有web容器来完成
1)翻译阶段
hello.jsp----->翻译成hello_jsp.java文件
2)编译阶段
hello_jsp.java---->通过jvm 进行编译hello_jsp.class
idea默认部署的web工程的所有的jsp文件:
C:\Users\zhangyang.IntelliJIdea2019.1\system\tomcat\Unnamed_EE_day36\work\Catalina\localhost\EE_day36_war_exploded\org\apache\jsp
举例:
<%--jsp的脚本
--%>
<%
//创建日期对象
Date date = new Date() ;
//后台输出
System.out.println(date); //日期格式
//向浏览器打印内容
out.println(date);
%>