Servlet
1、软件架构
a) c/s client/server 客户端/服务器
例如 : QQ 迅雷下载 LoL
优势:用户体验比较好
劣势: 需要下载安装 –》 更新
b) b/s browser/server 浏览器/服务器
例如:淘宝 京东 。。。
优势:不需要安装 不需更新
劣势:用户体验相对较差( 随着网速和技术的提生会越来越好 )
2、服务器
服务器就是一台配置比较高的主机
常用的服务器软件:
免费版:tomcat 、jetty
收费: weblogic...
3、tomcat
修改端口号:apache-tomcat-7.0.72\conf\server.xml
启动tomcat:apache-tomcat-7.0.72\bin\startup.bat
浏览器地址输入 http://localhost:6060
为什么要使用tomcat服务器
因为我们希望把自己电脑上的资源(html页面/图片)发布到互联网上 供其他上访问.
4、搭建第一个Servlet程序(不使用MyEclipse)
1).配置环境变量:classpath–安装目录\lib\servlet-api.jar
2). ..\webapps\项目名\WEB-INF\创建classes和lib
3).编写Servlet类
i. 第一种方法 实现 Servlet接口 //但需要重写三种方法,不太使用
ii. 第二种方法 继承HttpServlet //HttpServlet已经实现了Servlet接口
public class FirstServlet extends HttpServlet{
public void service(HttpServletRequest req,HttpServletResponse resp) //重写方法
throws ServletException,IOException{ //抛出两个异常
resp.setContentType("text/html;charset=utf-8"); //编码格式,打印中文
PrintWriter pw = resp.getWriter();
pw.println("哈哈哈");
pw.close();
}
}
4).带包编译
5).引入一个配置文件
复制 apache-tomcat-7.0.72\webapps\ROOT\WEB-INF 下的web.xml
到 项目\WEB-INF下,并编辑
<servlet>
<servlet-name>a</servlet-name> //给servlet起名字(规范:类名) 名字保持一致,方便一眼查询到执行哪个Java类
<servlet-class>com.FirstServlet</servlet-class> //类的路径:包名+类名
/*
1)load-on-startup元素标记容器是否在启动的时候就加载这个servlet(实例化并调用其init()方法)。
2)它的值必须是一个整数,表示servlet应该被载入的顺序
2)当值为0或者大于0时,表示容器在应用启动时就加载并初始化这个servlet;
3)当值小于0或者没有指定时,则表示容器在该servlet被选择时才会去加载。
4)正数的值越小,该servlet的优先级越高,应用启动时就越先加载。
5)当值相同时,容器就会自己选择顺序来加载。
*/
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping> //映射
<servlet-name>a</servlet-name> //和上面的名字要一致(规范:类名)
<url-pattern>/first</url-pattern> //资源的路径,根据这个路径找到servlet类(规范:/类名)
</servlet-mapping>
6).浏览器访问 http://localhost:6060/项目名/上面的名字(servlet-name)
5、项目的目录结构
webapps — 下面存放项目
| — day01 项目名称
|— html
|— 图片
|— CSS
|— WEB-INF
| — classes (被编译好的class文件)
| — lib ( 存放jar的,例如ojdbc6.jar)
| — web.xml (配置文件, 配置需要加载的servlet)
6、使用Myeclipse开发servlet程序
把tomcat和myclipse做一个关联
创建一个Web Project
把在myeclipse下创建的项目部署到tomcat下(add……)
部署:把项目写好放到tomcat下webapps文件夹下的过程
(可以复制DBUtils,jdbc.properties,jar包)
7、客户端向服务器发送请求的三种方式
a) 地址输入url 提交方式:get
b) 超链接 提交方式:get
请求服务器
c) form表单 提交方式:post 但必须把method属性定义为post
8、服务器端获取客户端提交的数据
a)request.getParameter(“key”);
根据key值获取value值
b)如果提交的数据有中文乱码,怎么设置
post提交方式:req.setCharacterEncoding(“UTF-8”);
get提交方式:修改tomcat下的server.xml,添加URIEncoding=”utf-8”
c)打印乱码
resp.setContentType(“text/html;charset=utf-8”);
9、路径
URL 统一资源定义符
格式:http://localhost:6060/projectname/url-pattern
协议://ip地址:端口号/项目/资源路径
URI 统一资源标志符
格式:/项目名/资源路径
URL-Pattern
格式:/资源路径
10、Servlet的生命周期
一个(XXXServlet)类的对象从被 创建 到 销毁 的过程
init() 初始化 load-on-startup / 访问URL / (构造方法)
service() 提供服务 访问URL
destroy() 销毁 tomcat正常退出服务的时候(stop server)
11、Servlet单实例
XXXServlet对象在tomcat服务器中只有一个
在XXXServet类 最好不要使用全局变量,因为多个用户(线程)会共享同一个变量。导致数据错乱.
如果要使用全局变量,为了保证我们多个用户数据安全,需要对该变量的操作加上同步
12、转发
把XXXServlet拆分:
XXXAction 负责 业务逻辑 //接收用户数据 和 查询数据 的代码
XXXView 负责 数据显示 //输出用户是否登陆成功的代码
转发:XXXAction --> XXXView
req.getRequestDispatcher("/XXXView").forward(req,resp); //获取请求的调度器 转发
在XXXAction存放数据
req.setAttribute(String name,Object o); //(key,value)
在XXXView中取出数据
Object o = req.getAttribute(String name); //(key)
13、Servlet中嵌套输出html
Servlet可以访问html页面 (静态的)
但是数据每天都不一样,所以我们要访问Servlet (动态的)
数据是动态的,html 需要让servlet输出
eg:输出table表
pw.println("<table border='1px' cellspacing=0 cellpadding='20px'>");
pw.println(" <tr>");
pw.println(" <td>id</td>");
pw.println(" <td>用户名</td>");
pw.println(" <td>密码</td>");
pw.println(" </tr>");
pw.println("</table>");
14、重定向
步骤:
客户端 –> 服务器端 //发送第一次请求
服务器端 –> 客户端 //响应 //此时有重定向代码
客户端 –> 服务器端 //发送第二次请求 //URL地址已经改变
服务器端 –> 客户端 //响应
两种重定向方法:
response.sendRedirect("/项目名/资源路径"); //此方法带参数/,那么浏览器会直接到服务器端下寻找
response.sendRedirect("资源路径"); //参数后面可以跟?,传递数据
转发和重定向的区别?
区别: 转发 重定向
①URL地址栏 不变 变化
②数据 可以传递 不可以传递
③发生的位置 发生在服务器 浏览器发起第二次
15、常量类
优势:
项目下有很多类 有一些经常出现的字符串 统一定义到常量类中。
方便后期维护
public class Constants{
public static final String A = “哈哈哈”;
……
}
16、会话管理与Cookies
会话管理
浏览器对服务器的两次请求,两者没有数据的关系,这不符合生活中的常理
即第一次请求的数据,不能用于第二次请求
因为,Http协议是无状态
Cookies
把一些浏览器操作的数据存储到了本地操作系统
特点:
1).一个站点只能保存20个cookie,每个cookie的大小不能超过4k
2).Cookies存储在用户的电脑上,安全性比较差
浏览器第一次请求,服务器端保存cookie,并响应回浏览器
Cookie c = new Cookie(key,value);
设置Cookie的过期时间
三种:
负数:浏览器关闭,清除Cookie
正数:代表一个过期时间,单位是秒(s)
c.setMaxAge(int expiry);
把Cookie对象存储到Response对象中
response.addCookie(c);
浏览器第二次请求,可以获取之前的cookie信息
Cookie[] cs = req.getCookies(); //取出来的可能是多个Cookie对象
for(Cookie c:cs){ //c代表每次取出来的Cookie对象
c.getName(); //getName()方法可以获取Cookie对象的key值
c.getValue(); //getValue()方法可以获取value值
}
17、URLEncoder和URLDecoder – HTML格式解码的实用工具类
异常信息:java.lang.IllegalArgumentException: Control character in cookie value or attribute.
出现上面的错误主要是cookie中存在中文或特殊符号造成的,tomcat7不支持导致。
即原因是有关中文编码的问题,中文采用的是unicode编码,而英文采用的是ASCII编码,
所以当COOkie保存中文的时候需要对中文进行编码,而且从Cookie中取出内容的时候也要进行解码,
编码和解码可以使用:
URLEncoder.encode(name, "utf-8"); //编码
URLDecoder.decode(cookies[i].getName(),"utf-8") //解码
-------------------------------------------------------------
Cookie cookie = new Cookie(
URLEncoder.encode("姓名","UTF-8"),
URLEncoder.encode("哈哈","UTF-8"));
response.addCookie(cookie);
Cookie[] cs = req.getCookies();
for(Cookie c:cs){
String cookieName = URLDecoder.decode(c.getName(),"UTF-8");
String cookieValue = URLDecoder.decode(c.getValue(),"UTF-8");
}
18、路径
request.getContextPath(); //获取 /项目名 格式:/projectName
html(浏览器):
person/servlet //相对路径
/projectName/person/servlet //绝对路径
重定向:
servlet //相对路径
/projectName/person/servlet //绝对路径
转发:
servlet //相对路径
/person/servlet //绝对路径
19、HttpSession
完成登陆之后短时间内不需要再次登陆
特点:session是把用户的数据存储在服务器端
使用:
登陆之后,把用户信息存储到session中
HttpSession session = request.getSession(); //创建Session对象,存储数据到Session中
session.setAttribute(key,value); //以key-value的形式保存数据到session中
判断session中是否有用户信息,如果有则不需要重新登陆,否则让用户重新登陆
HttpSession session = request.getSession(); //从session中获取之前存储的数据
session.getAttribute(key); //根据key值获取value值
原理:(Session对象是同一个)
浏览器第一次请求,(没有Cookie),创建Session对象,创建Cookie
服务器响应浏览器,返回Cookie,里面附带JSESSIONID(唯一标识符)和value(32位字符串)
浏览器第二次请求,携带Cookie,里面放着JSESSIONID
服务器会根据JSESSIONID对应的字符串获取相对应的session,从而找到的Session对象是同一个
20、Cookie和Session
相似之处:
保持浏览器和客户端之间的会话,跟踪用户信息
不同之处
(1).位置不同
Cookie保存在客户端的硬盘上(会被清理)
Session保存在服务器端的内存上(会被释放)
(2).存储内容不同
Cookie存储的内容量小,数据格式只能是字符串 //它会占用带宽下载,所以必须小
Session存储的内容量比较大,数据格式可以是任意类型
(3).
Cookie相对不安全 //存储在电脑硬盘上
Session相对安全
Session技术是借助Cookie技术来实现
21、include(包含)
头部界面多个页面相同
里面的数据显示可能不同 (eg:恭喜XXX登陆成功)
request.getRequestDispatcher("/XXXServlet").include(request,response)
其中,/XXXServlet 为被包含界面
22、ServletConfig 读取当前Servlet的配置信息
web.xml中的配置:
<servlet>
<servlet-name> XXXServlet </servlet-name>
<servlet-class> packageName.XXXServlet </servlet-class>
<init-param>
<param-name> name </param-name>
<param-value> 字符串 </param-value>
</init-param>
</servlet>
String s = super.getServletConfig().getInitParameter(key); //获取配置信息
//getServletConfig() 获取ServletConfig这个类的对象
//getInitParameter(key) 根据param-name(key)找param-value
23、ServletContext
所有用户共享同一个ServletContext
tomcat启动时创建,tomcat关闭后销毁
super.getServletContext().setAttribute(key,value); //存储ServletContext对象
Object o = super.getServletContext().getAttribute(key); //获取ServletContext对象
应用:
a)统计网站的访问人数
b)获取全局配置信息 (比ServletConfig获取范围大)
<context-param> //把编码方式配置为全局参数 web.xml
<param-name> name </param-name>
<param-value> value </param-value>
</context-param>
//获取全局配置
String s = super.getServletContext().getInitParameter(name);
24、作用域的对比
request 每次请求都是一个新的请求,不能获取之前保存的数据
req.setAttribute( key , value )
req.getAttribute( key)
HttpSession 每个用户都有一个Session对象,相互不会影响
ServletContext 所有用户共享一个对象
-----------------------------------------------------------------------
//向request中存储数据
req.setAttribute("username", "张三");
//向Session中存储数据 每个人都有一个Session对象
req.getSession().setAttribute("username", "张三");
//向ServletContext中存储数据
super.getServletContext().setAttribute("address", "郑州");
//向request中获取数据
String username = (String) req.getAttribute("username");
//从Session中获取数据
String username2 = (String) req.getSession().getAttribute("username");
//从ServletContext中获取数据
String username3 = (String) super.getServletContext().getAttribute("address");
25、Filter
创建Filter的步骤
a) 创建一个 MyFilter 实现 Filter 接口
b) 实现接口中的方法 init、doFilter、destroy
c) 编写doFilter()
d) 配置web.xml
<filter> //配置web.xml
<filter-name> name </filter-name>
<filter-class> packageName.MyFilter </filter-class>
</filter>
<filter-mapping>
<filter-name> name </filter-name>
<url-pattern> 要过滤的地址 </url-pattern> //过滤的地址写法:/*代表过滤所有 也可以写多行url-pattern代表过滤多个
</filter-mapping>
public class MyFilter implements Filter{ //实现 Filter 接口
public void init(FilterConfig filterConfig) throws ServletException {}
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
chain.doFilter(request, response); //可以继续执行本应该执行的请求
}
public void destroy() {}
}
过滤器默认只能拦截来自浏览器的请求
如果对转发进行过滤,需要在filter-mapping下加: //两个dispatcher的作用, 对请求和转发都进行过滤
<dispatcher>REQUEST</dispatcher>
<dispatcher>FORWARD</dispatcher>
26、