#Servlet--GenericServlet--HttpServlet
## 服务器软件
WebLogic --Oracle
WebSphere --BIM
Jboss --JBoss
Tomcate --apache需要运行在java虚拟机上,实现了几个Java EE规范,包括Java Servlet、Java Server Pages(JSP),
Java Expression Language和Java WebSocket等,这些都是下载Tomcat安装包默认提供的
## Tomcat实现的规范
Tomcat目录结构:
bin:二进制文件,tomcat的执行文件
confi:核心配置文件
lib:库文件
temp:临时文件
logs:服务器日志文件
webapps:部署项目的文件夹
work:运行时生成的文件
Servlet:Tomcat实现的规范中最重要的,web三大组件之一(Servlet,Filter,Listener)
快速定义一个Servlet:(javaEE1.5之前)1. 自定义一个类,实现Servlet接口 2. 去web.xml中注册一下,url-pattern
(javaEE1.5之后)1. 自定义一个类,实现Servlet接口 2. 写WebServlet注释
Servlet生命周期:
1.构造器方法:只会在第一次访问这个servlet的时候调用一次,调用一次就说明servlet是**单例**的,但是servlet是多线程的,
非线程安全的,也就是说在servlet中我们尽量不要在service方法中操作全局变量!
2.init方法:init方法只会在第一次访问servlet的时候调用一次,对servlet对象进行初始化操作!
3.service:service方法会在每次访问这个servlet的时候都调用一次,而且我们的业务逻辑也是写在这个service方法!
4.destroy方法::只会在我们的项目卸载的时候调用一次,也就是说在服务器关闭的时候调用一次!非正常关闭服务器不会被调用
Servlet执行原理:当浏览器输入http://127.0.0.1:8080/day13/myServlet01时,浏览器会解析url路径,解析web.xml文件,
<servlet>
<servlet-name>myservlet01</servlet-name>
<servlet-class>com.ithiema.web01.servlet.MyServlet01</servlet-class>
<!--1、Tomcat将全类名对应的字节码文件加载进内存,
2、创建对象
3、调用方法
-->
</servlet>
<servlet-mapping>
<servlet-name>myservlet01</servlet-name>
<url-pattern>/day13/myservlet01</url-pattern>
</servlet-mapping>
查找有没有如果有会找到servlet-class,根据全类名找到myServlet01这个实现类,tomcat会将字节码文件加载
进内存,并且创建其对象,调用其方法
Servlet何时被创建,何时被调用,何时被销毁?
第一次访问被创建,只要有访问就会被调用,服务器关闭被销毁
JSP规范实现:可以混合HTML与Java开发在一个文件中(.jsp),这种文件在第一次调用之后会被Tomcat的Jasper组件编译成一个servlet类,
在后续的操作中则可以直接使用此类。这种开发方式不灵活,一般少用。
> 我认为request和response都是服务器发出的
### Request:
**String path=request.getContextPath();//获取虚拟目录**
**String URI=request.getRequestURI();//获取URI**
String Parameter=request.getQueryString();//请求参数name=zhangsan
request.getMethod();//获取请求方式
request.getRequestDispatcher().forward(request,response);//转发-->跳转到另一个页面(Servlet/jsp/html)
**get和post通用的获取请求参数的方法**
**String s=request.getParameter("name对应的值");//获取请求参数的值**
String[] ParameterValue=request.getParametervalues("复选框对应的统一的name值");
Enumeration<String> Parametervalue=request.getParameterNames("提交的所有name对应的值");
request.getParameterMap();
BufferReader br=request.getReader();
ServletInputStream sis=request.getInputStream();//获取字节输入流,做文件上传
网页-->servlet-->tomcate8.0之前get中文乱码问题:String s=new String("中文".getByte("iso-8859-1"),"utf8");
网页-->servlet-->post中文乱码问题:request.setCharacterEncoding("utf8");
request域:转发的时候用,共享数据;范围:一次请求;
request.setAttribute("key","value");//设置属性和值
request.getAttribute("键","值");removeAttribute("键");
> servlet里三个域对象(request,session,servletContext),jsp里四个域对象(pageContext,request,session,application)
servlet路径的三种写法:完全路径匹配,目录匹配,扩展名匹配;
BeanUtils.populate(user,map);
### Response:
response.sendRedirect("/day15/MyResponse02");
location(路径):
response.setCharacterEncoding("utf8");设置流的编码,给数据编码
response.setHeader("content-type","text/html;charset=utf8");告诉浏览器用什么方式解析,给数据解码
response.setContentType("text/html;charset=utf8");这一句等于上边两句
response.setHeader("content-disposition","attachment;filename=xxx.jpg");服务器告诉浏览器以附件格式打开文件
response.setHeader("content-disposition");默认in-line,默认当前页面打开
response.setStatus(302);//设置状态码
字符输出流:PrintWriter pw=response.getWriter();
pw.writer(String s);
字节输出流:ServletOutputStream sos=response.getOutputStream();
os.writer();
> 转发和重定向的区别:
转发(request.getRequestDispatcher("").forward(request,response);):发生在服务器,浏览器请求一次,浏览器地址不发生变化;服务器内部跳转,路径不能加工程名
重定向(response.sendRedirect("/servlet/1.html");):发生在浏览器,浏览器请求两次,浏览器地址发生变化;浏览器跳转,所以要全路径,路径的工程名不能少
> 在html中一般使用相对路径,在jsp和servlet中一般使用绝对路径;
> 判断定义的路径是给谁用的?判断请求将来从哪儿发出
* 给客户端浏览器使用:需要加虚拟目录(项目的访问路径)
* 建议虚拟目录动态获取:request.getContextPath()
* <a> , <form> 重定向...
* 给服务器使用:不需要加虚拟目录
* 转发路径
### ServletContext:
域对象:范围整个web,服务器打开该对象就会被创建
作用:1.获取文件的真实路径,2.获取文件的mime类型,3.域对象,传递数据
获取MIME类型:互联网通信中定义的一种文件数据类型;大类型/小类型,如text/html
ServletContext sc = this.getServletContext();
ServletContext sc = request.getServletContext();
String realPath = sc.getRealPath("/"+file);
String mimeType = sc.getMimeType(fileName);//image/jpeg
response.setHeader("content-type",mimeType);
response.setHeader("content-disposition","attachment;filename="+fileName);
FileInputStream fis=new FileInputStream(realPath);
获取文件的真实路径:getRealPath();
获取ServletContext的两种方式:
request.getServletContext.var
this(httpServlet).getServletContext.var
### cookie
Cookie co=new Cookie("属性名","属性值");
response.addCookie(co);
String name=co.getName();
String value=co.getValue();
co.setValue("属性值");
Cookie[] cookies=request.getCookies();
指定cookie有效路径:cookie.setPath(String uri);
> 保存时间:默认关闭浏览器,cookie销毁
setMaxAge(int seconds);正数:存活时间;零:删除cookie;负数:默认值;
如果设置了存活时间为正数,在存活时间内访问了cookie则时间从访问时重新计算
> tomcat8之前cookie不可以存储中文:需要进行编码解码URlEncode.encode("中文","utf8");URLDecode.decode("","utf8");
> 默认 添加cookie的servlet的上一级虚拟目录之下的文件夹的资源可以共享cookie;--有效路径
要想同一个服务器,不同web项目共享数据则要设置:cookie对象.setPath("/");
要想不同服务器间共享cookie:cookie对象.setDomain(".baidu.com");
### session(存放在服务器中的cookie)
域对象:一次会话多次请求中,*** 默认30分钟过期 ***
> session的实现依赖于cookie;依赖于cookie中的JSESSIONID属性
Session session=request.getSession();
session.getAttribute();
session.setAttribute();
session.invalidate();
> session被销毁的三种方式:
1. session.invalidate();
2. 服务器被非正常关闭
3. 超时后被销毁
> session什么时候被创建:
请求到servlet中不一定会创建session,只有调用方法才创建
请求到jsp中一定会创建session,因为jsp内置了session对象,访问即创建
session.removeAttribute();
> session什么时候被销毁?
1. 浏览器关闭了,服务器没关闭,cookie销毁,JSESSIONID变了
2. 浏览器没关闭,服务器被关闭;正常关闭,session被序列化到硬盘中,开机后反序列化到服务器内存中
3.浏览器没关闭,网页也没操作,30分钟后就自动销毁
### JSP(Java Server Pages)
脚本类型:<%%>相当于servlet,写的内容会被翻译到service方法中 <%! %>定义成员变量,翻译到类中 <%= %>向页面输出
指令:<%@ 指令名 属性值="" 属性值=""%>
指令名:
page:配置jsp页面;contentType="";pageEncoding="";language="";buffer="";import="";
errorPage="fail.html";isErrorPage="true"-->exception.getMessage();
include:页面包含,导入页面的资源文件;<%@ include file="top.jsp"%>
taglib:导入资源;<%@ taglib prefix="自定义标签名" uri="" %>
注释:<%-- --%>可以注释jsp中所有代码,不会编译到java文件中
html注释可以存活在 源码阶段,被翻译后的SErvlet源码阶段,页面显示后的源码阶段
java的注释可以存活在源码阶段,被翻译后的Servlet源码阶段,
jsp注释只会存活在源码阶段,
内置对象(九种):
pageContext---->pageContext----域范围:当前页面;可以获取其他八个内置对象
request ---->HttpServletRequest
session ---->HttpSession
application---->ServletContext
response ---->HttpServletResponse
out ---->
config ---->获取servlet的配置信息
page ---->代表当前页面,或者说是当前页面翻译后的servlet
exception(isErrorPage="true")
> 为什么还要用pageContext获取其他八种对象?
因为jsp的九个内置对象只能在jsp脚本中使用,后期不会再jsp写脚本,所以只能使用pageContext来获取其他八个
替换jsp中java代码的两种方式:el表达式,jstl标签
#### EL表达式:${表达式};从取值,不能存值,从域里取值,如果属性名一样且没加域名,会从范围小的到范围大的查找
requestScope;sessionScope;pageContextScope;ApplicationScope
${requestScope.属性名} ${属性名}
对象:${requestScope.键名.属性名}本质上调用getter方法
list集合:${属性名[index]}
map集合:${属性名.key名称};${属性名["key名称"]}
${empty 属性名}判断是否为空,长度为0和null都返回true
${pageContext.request.contextPath}动态获取虚拟目录
11个隐式对象:pageContext,pageScope,requestScope,sessionScope,appliationScope,param,paramValues,
head,headValues,cookie,initParam
${cookie.username.value}
#### JSTL标签:
if标签
choose相当于switch语句
foreach:组合一:begin end var step varStatus
` 组合二:items="${list}" var="a" varStatus="s"--取值${a}foreach会把遍历出来的每一个值放入pageContext中
### MVC(Model View Controller):开发模式
Model ----> javaBean---->完成具体的业务逻辑
view ----> jsp ---->只作数据的展示
controller----> sevlet ---->获取用户输入;调用模型;将数据交给View展示
javaee开发模式:
1.jsp+javaBean没有实现前后端分离
2.jsp+javaBean+servlet就是现在的mvc模式
### 三层架构:开发模式;
web层:写servlet filter...接受参数,封装对象,调用service层方法,页面跳转
scrvice层:写普通的java类,完成各个业务的逻辑校验,调用dao层
dao层:操作数据库
### 用户管理系统遇到的问题及解决:
1.把网页数据提交到servlet可以使用链接href="/Servlet?属性名='属性值'";这种方式是通过GET方式进行传递;servlet中再通过
request.getParameter("属性名");获取数据
2.组合查询要使用动态sql才能满足查询
3.把数据库的每一条数据通过servlet的工具类进行封装成List<User>集合,通过request.setAttribute("","");传入jsp,再在jsp中通过
requestScope.users进行获取属性,把list集合中的数据进行展示到网页核心在<c:forEach></c:forEach>
4.不共享数据,就选择重定向
5.在js里把处理的值设为defaultChecked,defaultSelected 这样点击<input type="reset" />就不会变化了
6.有外键约束的两张表,次表先删除,主表才能删除对应的那一行,添加数据要先添加主表的数据,次表才能添加
## Filter
1.注解配置设置拦截方式:
REQUEST:dispatcherType=DispatcherType.Request默认的配置,有请求就会拦截
FORWARD:只有转发到该页面才会在转发的过程中拦截,直接访问不会拦截
INCLUDE:
ERROR:
ASYNC:
设置多种拦截方式::dispatcherType={DispatcherType.Request,DispatcherType.FORWARD}
** 如果手动添加了一个拦截方式,则只会执行添加的拦截方式,默认的会失效
2.web.xml配置是在<url-pattern>下面加<dispatcherType>REQUEST</dispatcherType>
3.过虑器链
过滤器1-->过滤器2-->资源执行-->过滤器2-->过滤器1
过滤器链执行的顺序是按两个java文件的排序,谁在前边先执行谁
web.xml则是谁的<url-partten>配置在上边,就先执行谁
4.增强方法的三种方法:继承、装饰者模式、动态代理;设计模式:通用的解决问题的方式,一种设计模式对应一种方式的最优解
动态代理:
装饰者模式:装饰者和被装饰者实现同一个接口,装饰者把需要增强的方法从被装饰者中拿出来封装成对象,然后增强
禁止在一个filter中放行多次--否则放行几次,就会在一个页面内出现几次原有页面
生命周期:服务器打开则创建,关闭则销毁;而servlet则是首次访问时创建
## Listener
listener优先于filter优先于servlet
域对象监听器创建和销毁:3个
域对象属性监听器:3个
javaBean监听器:2个
```java
<!--filter 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_3_1.xsd"
version="3.1">
<filter>
<filter-name>demo01</filter-name><!--这只是个虚拟文件名-->
<filter-class>cn.itcast.web.filter.FilterDemo01</filter-class>
</filter>
<filter-mapping>
<filter-name>demo01</filter-name>
<url-pattern>/hello.jsp</url-pattern>
</filter-mapping>
</web-app>
````
````java
<!--servlet 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_3_1.xsd"
version="3.1">
<servlet>
<servlet-name>demo02</servlet-name>
<servlet-class>cn.itcast.web.servlet.ServletDemo01</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>demo02</servlet-name>
<url-pattern>/day17/servletDemo01</url-pattern>
<dispatcherType>REQUEST</dispatcherType>
</servlet-mapping>
</web-app>
```