JavaEE
Servlet
Servlet生命周期
// 当一个类继承HttpServlet类时,那他就是一个servlet类
public class FirstServlet extends HttpServlet {
//当servlet第一次被载入容器时执行,只执行一次
//load-on-startup配置载入时机
@Override
public void init(){
System.out.println("Servlet初始化");
}
//每次请求都执行
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp){
System.out.println("Servlet被请求,当存在此方法时不会在执行doGet,doPost方法");
}
//关闭服务器Servlet被销毁时执行
@Override
public void destroy() {
System.out.println("Servlet被销毁");
}
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("我是GET请求方法");
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("我是POST请求方法");
}
}
配置servlet
<!-- Servlet配置 目的是让tomcat容器接纳Servlet
当输入URL,tomcat才能找到对应的Servlet -->
<servlet>
<!-- Servlet别名 -->
<servlet-name>FirstServlet</servlet-name>
<!-- Servlet全路径 -->
<servlet-class>com.test.hello.FirstServlet</servlet-class>
<!--
标记容器是否在启动的时候就加载这个servlet。
当值为0或者大于0时,表示容器在应用启动时就加载这个servlet;
当是一个负数时或者没有指定时,则指示容器在该servlet被第一次请求时才加载。
正数的值越小,启动该servlet的优先级越高。 -->
<load-on-startup>1</load-on-startup>
</servlet>
<!-- 路由-servlet映射规则 -->
<servlet-mapping>
<!-- 上面配置的别名 -->
<servlet-name>FirstServlet</servlet-name>
<!-- 路由 -->
<url-pattern>/</url-pattern>
</servlet-mapping>
请求路径优化
<% String basePath = request.getScheme()+":"+"//" //获取协议 +request.getServerName()+":" //获取域名 +request.getServerPort() //获取端口号 +request.getServletContext().getContextPath()+"/"; //获取工程目录 %> <form method="post" id="loginForm" action="<%=basePath %>login">
请求和响应
- 浏览器对服务器的一次访问称之为一次请求,请求用HttpServletRequest表示
- 服务器给浏览器的一次反馈称为一次响应,响应用HttpServletResponse表示
ServletContext与ServletConfig
- ServletContext对象表示整个JavaWeb工程
- ServletConfig表示某个Servlet的配置信息
@WebServlet("/ContextOne")
public class ContextOne extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
ServletContext context = this.getServletContext();
// 往context域对象中存放数据
context.setAttribute("username", "测试");
// 取出context域对象中的数据
Object result = context.getAttribute("username");
// 打印取出的结果
System.out.println("存放数据"+result);
ServletConfig sc = this.getServletConfig();
// 获取sc这个对象中封装的参数信息k-v
String n = sc.getInitParameter("year");
System.out.println("this year=" + n);
}
}
// 当这个Servlet被请求时,下面的参数会被封装到ServletConfig对象中
<servlet>
<servlet-name>ContextOne</servlet-name>
<servlet-class>ContextOne</servlet-class>
<init-param>
<param-name>year</param-name>
<param-value>2019</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>ContextOne</servlet-name>
<url-pattern>/context</url-pattern>
</servlet-mapping>
重定向/转发
- 转发调用的是HttpServletRequest对象方法
- 重定向调用的是HttpServletResponse对象方法
- 转发时URL地址不会变化 / 重定向会改变
- 转发浏览器请求一次服务器/重定向请求两次
// 传递参数
@WebServlet( "/ForWord")
public class ForWord extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 转发带数据给某个jsp页面
request.setAttribute("username", "王二麻子");
request.getRequestDispatcher("/demo.jsp").forward(request, response);
// 通过重定向带数据过去
// ServletContext sc = request.getServletContext();
// sc.setAttribute("goods", "娃娃");
// response.sendRedirect("/FirstServlet/demo.jsp");
}
}
//接收参数
<body>
<!-- 取出ForWord中传递过来的数据 -->
<%
String username = (String)request.getAttribute("username");
out.print(username);
%>
<%
String goods = (String)application.getAttribute("goods");
out.print(goods);
%>
</body>
JSP
基本原理
JSP的本质是Servlet,当用户向指定Servlet发送请求时,Servlet利用输出流动态生成HTML页面,包括每一个静态的HTML标签和所有在HTML页面中出现的内容。
注释
jsp注释不会输出到浏览器<%—注释内容--%>
html注释可以被看到
内置对象
- application: javax.servlet.ServletContext 的实例,该实例代表 JSP 所在的 Web 应用本身,可将信息保存在服务器中,直到服务器关闭,类似全局变量。
- getAttribute(String attName)
- setAttribute(String attName,String attValue)
- getlnitParameter(String paramName)等。
- config: javax.servlet.ServletConfig的实例,该实例代表该JSP的配置信息,主要作用是取得服务器的配置信息。
- getlnitParameter(String paramName)
- getlnitParameternames()等方法。
- exception: java.lang.Throwable的实例,该实例代表其他页面中的异常和错误。只有3贞面 是错误处理页面,即编译指令page的isErrorPage属性为true时,该对象才可以使用。
- getMessage()
- printStackTrace()等。
- out: javax.servlet.jsp.JspWriter的实例,该实例代表JSP页面的输出流,用于输出内容, 形成HTML页面。
- page:代表该页面本身,也就是Servlet中的this,其类型就是生成的 Servlet类,能用page的地方就可用this。
- pageContext: javax.servlet.jsp.PageContext的实例,该对象代表该JSP贞面上下文,该对象的作用是取得任何范围的参数。
- getServletContext()-- 获取application内置对象;
- getServletConfig()-- 获取config内置对象
- request: javax.servlet.http.HttpServletRequest 的实例,该对象封装了一次请求,客户端的请求参数都被封装在该对象里。这是一个常用的对象,获取客户端请求参数必须使用该对象。
- getParameter(String paramName)
- getParameterValues(String paramName)
- setAttribute(String attrName,Object attrValue)
- getAttribute(String attrName)
- setCharacterEncoding(String env)
- response: javax.servlet.http.HttpServletResponse 的实例,代表服务器对客户端的响应。 通常很少使用该对象直接响应,而是使用out对象,除非需要生成非字符响应。而response 对象常用于重定向,
- getOutputStream()
- sendRedirect(java.lang.String location)等。
- session: javax.servlet.http.HttpSession的实例,该对象代表一次会话。当客户端浏览器与站点建立连接时,会话开始;当客户端关闭浏览器时,会话结束。
- getAttribute(String attrName)
- setAttribute(String attrName, Object attrValue)
JSTL标签库
JSP页面前缀
<%@ page language="java" contentType="text/html; charset=utf-8"
pageEncoding="utf-8"%>
<%@ taglib uri='http://java.sun.com/jsp/jstl/core' prefix="c"%>
表达式控制标签
- out标签:用来输出数据对象(字符串、表达式)
<c:out value="字符串">
<c:out value="EL表达式">
- set标签:把某一个对象存在指定的域范围内
<c:set value="值" var="变量名"
[scope="page|request|session|application"]/>
<c:set var="变量名" [scope="page|request|session|application"]>
值
</c:set>
<c:set target="JavaBean对象" property="属性名">
值
</c:set>
含义:把一个值赋值给指定的JavaBean的属性名。
- remove标签:移除指定变量
•<c:remove var="变量名"
[scope="page|request|session|application"]/>
- catch标签:用于捕获嵌套在标签体中的内容抛出的异常
<c:catch var ="catchException">
<% int x = 5/0; %>
</c:catch>
<c:if test = "${catchException != null}">
<p>异常为 : ${catchException} <br />
发生了异常: ${catchException.message}</p>
</c:if>
流程控制标签
- if标签
<c:if test="<boolean>" var="<string>" scope="<string>">
test属性用于存放判断的条件,一般使用EL表达式来编写
var属性用来存放判断的结果,类型为true或false
scopes属性用来指定var属性存放的范围
</c:if>
<c:set var="salary" scope="session" value="${2000*2}"/>
<c:if test="${salary > 2000}">
<p>我的工资为: <c:out value="${salary}"/><p>
</c:if>
- choose标签、when标签、otherwise标签
<c:choose>
<c:when test="<boolean>">
...
</c:when>
<c:when test="<boolean>">
...
</c:when>
<c:otherwise>
...
</c:otherwise>
</c:choose>
循环标签
- forEach标签:迭代一个集合中的对象
<c:forEach
items="<object>" items指定要遍历的集合
begin="<int>" 起始位置 0=第一个元素,1=第二个元素
end="<int>" 终止位置
step="<int>" 循环的步长
var="<string>" 每个变量名字
varStatus="<string>"> 每个对象的状态
....
</c:forEach>
<c:forEach var="i" begin="1" end="5">
Item <c:out value="${i}"/><p>
</c:forEach>
<c:forEach items="${str}" var="s" begin="1" end="5" step="2" varStatus="status">
|每个变量的索引位置 int
<c:out value="index属性:${status.index}"></c:out>
|计数,这个变量是第几个 int
<c:out value="count属性:${status.count}"></c:out>
|这个元素是不是第一个 boolean
<c:out value="first属性:${status.first }"></c:out>
|这个元素是不是最后一个 boolean
<c:out value="last属性:${status.last }"></c:out>
|<br/>
</c:forEach>
- forTokens标签:通过指定分隔符将字符串分隔为一个数组然后迭代它们
<c:forTokens
items="<string>" items指定要遍历的字符串
delims="<string>" 指定分隔符
begin="<int>" 起始位置 0=第一个元素,1=第二个元素
end="<int>" 终止位置
step="<int>" 循环的步长
var="<string>" 每个变量名字
varStatus="<string>"> 每个对象的状态
....
</c:forTokens>
<c:forTokens items="google,runoob,taobao" delims="," var="name">
<c:out value="${name}"/><p>
</c:forTokens>
URL操作标签
import标签:该标签可以把其他静态或动态文件包含到本JSP页面
URL为资源的路径,当引用的资源不存在时系统会抛出异常,因此该语句应该放在<c:catch></c:catch>语句块中捕获
与<jsp:include>的区别
<jsp:include>只能包含同一个web应用中的文件
<c:import>可以包含其他web应用中的文件,甚至是网络上的资源
<c:import
url="<string>" 待导入资源的URL,可以是相对路径和绝对路径
var="<string>" 用于存储所引入的文本的变量
scope="<string>" var属性的作用域
varReader="<string>" 可选的用于提供java.io.Reader对象的变量
context="<string>" 当使用相对路径访问外部context资源时,context指定了这个资源的名字。
charEncoding="<string>"/>所引入的数据的字符编码集
<c:import var="data" url="http://www.baidu.com"/>
<c:out value="${data}"/> 会输出百度首页源代码
url标签,param标签:使用可选的查询参数来创造一个URL
<c:url
var="<string>" 代表URL的变量名
scope="<string>" var属性的作用域
value="<string>" URL值
context="<string>"/> 本地网络应用程序的名称
<c:param name="参数名" value="值"> 附加参数?
</c:url>
redirect标签:重定向url,可带参数
<c:redirect url=”url” [context=”context”]/>
<c:redirect url="<string>" [context=”context”]>
<c:param name="参数名" value="值">
</c:redirect>
其他
相对路径获取
${pageContext.request.contextPath}
页面拆分
<jsp:include page="/common/header.jsp" />
<jsp:include page="/common/menu.jsp" />
SpringMVC
<!-- 配置视图解析器,可以显式设置,也可以不设置,不设置会依据SpringMVC的默认设置 -->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="viewClass" value="org.springframework.web.servlet.view.JstlView" />
<property name="prefix" value="/WEB-INF/views/" />
<property name="suffix" value=".jsp" />
</bean>
<!--Servlet -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
Filter
实现对web资源的请求的拦截,完成特殊的操作,尤其是对请求的预处理
- Web资源权限访问控制
- 请求字符集编码处理
- 内容敏感字符词汇过滤
- 响应信息压缩
生命周期
- web应用启动时,服务器创建Filter的实例对象,以及对象的初始化操作--init()只运行一次
- 当请求访问与过滤器相关联的Web资源时,过滤器拦截请求,完成指定功能--doFilter()每次访问都执行
- Filter对象创建过会驻留内存,在web应用被移除或停止时销毁--destroy()
<!--第一步注册,指定过滤器唯一标识和指定的类-->
<filter>
<filter-name>CharacterEncodingFilter</filter-name>
<filter-class>filter.CharacterEncodingFilter</filter-class>
<!--配置过滤器初始化参数-->
<init-param>
<param-name>charset</param-name>
<param-value>UTF-8</param-value>
</init-param>
</filter>
<!--第二步配置映射,指定过滤器过滤哪些请求 *代表全部请求-->
<filter-mapping>
<filter-name>CharacterEncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
// filter-mapping子元素dispather,符合配置的访问方式才会触发过滤器,可以配置多项
<dispatcher>REQUEST</dispatcher>
</filter-mapping>
dispatcher
- REQUEST 默认方式(也就是直接访问这个页面)
- INCLUDE
<jsp:include page="/b.jsp"></jsp:include>
--------------------------------------------
<filter-mapping>
<filter-name>TestFilter</filter-name>
<url-pattern>/b.jsp</url-pattern>
<dispatcher>INCLUDE</dispatcher>
</filter-mapping>
//测试inlude访问
- FORWARD
<%request.getRequestDispatcher("/b.jsp").forward(request,response);%>
--------------------------------------------
<dispatcher>FORWARD</dispatcher>
//测试forward访问--请求转发时候触发
//重定向是REQUEST方式
<%response.sendRedirect(request.getContextPath()+"/b.jsp");%>
//测试重定向
- ERROR
<filter-mapping>
<filter-name>TestFilter</filter-name>
<url-pattern>/b.jsp</url-pattern>
<dispatcher>ERROR</dispatcher>
</filter-mapping>
<error-page>
<error-code>404</error-code>
<location>/b.jsp</location>
</error-page>
//测试404错误---访问一个不存在的资源
//或者在访问页面<%response.sendError(404); %>
过滤器链
在一个web应用中,多个过滤器组合称为一个过滤器链
调用顺序取决于过滤器在web.xml中的顺序
Listener
Servlet规范定义的一种特殊类;用于监听ServletContext,HttpSession,ServletRequest等域对象的创建,销毁及其属性发生变化的事件;监听器可以在事件发生前后进行一些操作
- 统计在线人数---监听session对象
- 页面访问量--监听request对象
- 应用启动时完成信息初始化工作---缓存
- 与Spring结合
<!--监听器配置-->
<listener>
<listener-class>listener.FirstListener</listener-class>
</listener>
------------------------------------
public class FirstListener implements ServletContextListener{
@Override
public void contextInitialized(ServletContextEvent sce) {
System.out.println("ContextListener init");
}
@Override
public void contextDestroyed(ServletContextEvent sce) {
System.out.println("ContextListener destroy");
}
}
//ContextListener init 应用启动触发
//ContextListener destroy 应用被移除触发(redeploy)
监听器分类
按监听对象
-
ServletContext对象监听器--上下文
-
HttpSession对象监听器------会话
-
ServletRequest对象监听器--请求
-
按事件分类
域对象自身的创建和销毁事件监听器 -
ServletContextListener
配置参数 <context-param> <param-name>app_name</param-name> <param-value>ServletContext监听器</param-value> </context-param> 获取配置 @Override public void contextInitialized(ServletContextEvent servletContextEvent) { String appName = servletContextEvent.getServletContext().getInitParameter("app_name"); System.out.println("init--------"+appName); } @Override public void contextDestroyed(ServletContextEvent servletContextEvent) { String appName = servletContextEvent.getServletContext().getInitParameter("app_name"); System.out.println("destroyed--------"+appName); }
-
HttpSessionListener
为了看到效果配置session有效期在web.xml <!--配置session过期时间 1分钟--> <session-config> <session-timeout>1</session-timeout> </session-config> -------------------------------------- @Override public void sessionCreated(HttpSessionEvent httpSessionEvent) { System.out.println("session init"); //获取sessionId String sessionId=httpSessionEvent.getSession().getId(); //获取session创建时间 Date createTime=new Date(httpSessionEvent.getSession().getCreationTime()); System.out.println("Id="+sessionId+" time:"+createTime); } @Override public void sessionDestroyed(HttpSessionEvent httpSessionEvent) { System.out.println("session destroy"); String sessionId=httpSessionEvent.getSession().getId(); System.out.println("Id="+sessionId); }
-
ServletRequestListener
@Override public void requestInitialized(ServletRequestEvent servletRequestEvent) { System.out.println("Request init"); HttpServletRequest hres = (HttpServletRequest)servletRequestEvent.getServletRequest(); String path =hres.getRequestURI(); System.out.println("请求路径"+path); } @Override public void requestDestroyed(ServletRequestEvent servletRequestEvent) { System.out.println("Request destory"); } --------------访问首页---------- 请求路径/FirstListener/index.jsp Request destory
域对象中属性的创建,替换,消除事件监听器
-
ServletContextAttributeListener(session/Request同理)
@Override public void attributeAdded(ServletContextAttributeEvent scae) { System.out.println("属性添加name:"+scae.getName()+" value"+scae.getValue()); } @Override public void attributeRemoved(ServletContextAttributeEvent scae) { System.out.println("属性删除name:"+scae.getName()+" value"+scae.getValue()); } @Override public void attributeReplaced(ServletContextAttributeEvent scae) { System.out.println("属性修改name:"+scae.getName()+" value"+scae.getValue()); } -------------------------------- <% application.setAttribute("goodName","相机");%>//1.jsp <% application.setAttribute("goodName","手机");%>//2.jsp <% application.removeAttribute("goodName");%>//3.jsp ------------------------------- 依次访问--说明传入参数是表示更改前的值 属性添加name:goodName value相机 属性修改name:goodName value相机 属性删除name:goodName value手机
-
绑定到session中某个对象的状态事件监听器--不需要在web.xml中注册
- HttpSessionBindingListener
public class FiveListener implements HttpSessionBindingListener {
//当监听器对象绑定至Http会话调用
@Override
public void valueBound(HttpSessionBindingEvent hsbe) {
System.out.println("绑定属性"+hsbe.getName());
}
//当监听器对象从http会话内修改,移除或会话销毁时调用
@Override
public void valueUnbound(HttpSessionBindingEvent hsbe) {
System.out.println("解除绑定"+hsbe.getName());
}
}
-------------------------
<% session.setAttribute("user", new FiveListener());%>//1.jsp
<%session.removeAttribute("user");%>//2.jsp
//依次访问
绑定属性user
解除绑定user