【Servlet】Servlet基础、实战

Servlet

1).TomCat服务器

常见软件服务器产品:
tomcat   apache提供,java代码编写.(运行以来jvm环境);
apache   apache提供.LAMP软件架构.(Linux Apache MySQL PHP)
Nginx    服务器反向代理和负载均衡,集群服务器.
TomCat使用:
①部署静态资源.
    a在tomcat的webapps下新建文件夹(代表web项目)
    b将资源放入web文件夹中.
②启动tomcat
   `startup.bat`
③浏览器访问
常见异常:
①端口被占用
异常信息: socket bind faild  / JVM Bind
原因: tomcat使用端口被占用.
解决办法: 修改tomcat/conf/server.xml   `<connector port="端口">`
②404
    异常信息: 客户端请求的资源找不到?
    原因: 地址请求的资源和真正服务器的资源路径不符.(不存在, 路径写错了)
    解决办法:  按照请求路径和资源部署路径一个一个校对.
URL:
URL: 统一资源定位符.
注意: 服务器端每个资源(HTML CSS 图片  视频  程序其他资源),都有一个唯一的访问路径.
URL: http://ip:port/项目名/资源路径.
	应用: 浏览器地址栏
URI: `/项目名/资源路径`  本tomcat内部资源路径 
应用: form  a   link   img 
<img src="/项目名/图片资源路径"/>
<form action="/项目名...">
</form>
<a href="/项目名/资源路径"></a>
url-pattern: `/资源路径`  本项目内部资源

2).Servlet初始、及常见异常

概念: 一段Java程序,可以运行在tomcat端.
语法: Servlet标准.(接口) JavaEE标准(servlet-api.jar)
接口: interface Servlet{
 			init(){servlet对象创建的自动调用}
 			destroy(){servlet对象销毁的自动调用}
 			service(){//用户访问tomcat服务器的该程序,调用service方法.
 				// 用户请求后,执行的代码.
 			}
 		}
JavaEE提供类: HttpServlet 实现了Servlet接口.
自定义tomcat运行代码:
 	public class MyServlet extends HttpServlet{
 		public void service(){
 			//覆盖servlet的service方法.
 		}
 	}
开发第一个Servlet程序:
需求: 显示当前系统时间?
Servlet开发的具体步骤:
①手动部署servlet程序
编写Servlet程序
    导入servlet-api的jar.(编写编译java程序使用)
    public class FirstServlet extends HttpServlet{
       public void service(){
           // 1. 获得当前系统时间
           // 2. 将时间返回给浏览器(响应给浏览器)
			 //打印一字符串
			 PrintWriter pw = resp.getWriter();
			 pw.println(“这是一个字符串”);
       }
    }
②将servlet部署tomcat
   在tomcat/webapps下创建文件夹(web项目)
   在项目下创建创建WEB-INF/classes,将代码带包拷贝在classes下面
③在web.xml描述(全类名+访问路径)
   注册servlet信息:
		<servlet>
			<servlet-name>&名字&</servlet-name>
			<servlet-class>全类名</servlet-class>
		</servlet>
   映射servlet访问路径
		<servlet-mapping>
			<servlet-name>&名字&</servlet-name>
			<url-pattern>/servlet访问路径</url-pattern>
		</servlet-mapping>
④启动tomcat
⑤访问servlet,查看执行响应的结果.
   `http:ip:port/项目名/web.xml注册的servlet的访问url-pattern`
   `http://localhost:8989/web/firstDate`
常见异常[重点]
①405 `Method Not Allowed`
   原因: 方法调用错误
   解决办法:
   a. 方法名是否错误.
   b.  service方法内,不能调用父类的方法.
②访问servlet变成下载
   响应类型设置有问题
   `resp.setContentType("text/html;charset=UTF-8");`
③servlet修改后,没有变化.
   原因: servlet代码修改,tomcat需要重启,才能生效.
④500错误:
   a. classNotFundException: web.xml的servlet的全类名写错.
   b. 服务端java代码运行异常.
⑤404 错误;
   浏览器访问地址:
   不存在
   地址写错(浏览器地址栏, url-pattern不一致,)
   tomcat启动就报错(tomcat启动失败)

3).Servlet在MyEclipse中部署、Servlet运行原理、请求参数及请求方式

(1)MyEclipse开发部署Servlet
①新建web project
   > 创建web.xml
   > 自动创建好对应的目录结构(WEB-INF  classes  web.xml)
②编写servlet
③编写web.xml
④部署
     servers--tomcat8.x---右键---add deployment--选择项目部署
Servlet生命周期  [面试]:
概念: servlet创建时机和活跃使用时机,销毁时机.
interface Servlet{
    init(){}	//对象创建执行
    service(){}	//浏览器请求到servlet,提供服务的运行的方法.
    destroy(){}	//对象销毁执行.
}
① servlet创建
   第一个浏览器访问servlet,对象会被创建
   一个Servlet类只会创建一个servlet对象.
②servlet服务
   浏览器每次访问都会调用service方法.
③servlet销毁
   tomcat关闭,销毁servlet对象
重点:
Servlet对象只有一个单实例,面向多线程(用户)访问,**线程不安全**.
①如果servlet有属性, service方法中对属性的操作,加锁.
②要求: Servlet中不要添加数据属性
(2)Servlet执行原理
浏览器向tomcat发出url的http请求: http://ip:port/web项目名/servlet的url-pattern
tomcat服务器:
①获得url的项目名, 从本tomcat下的webapps下找到对应文件夹.
②根据url中servlet的url-pattern,从web.xml找到 servlet-name, 找到servlet-class被访问的servlet的全类名
③Class<?> clazz = Class.forName("Servlet的全类名");//获得servlet的类对象.
④Servlet servlet = (Servlet)clazz.newInstance();//创建出了类的对象(Servlet),
   tomcat内部管理servlet
   Map<String,Servlet> map = ....;
   map.put("url-pattern",servlet);
⑤tomcat先调用 `servlet.init()`方法,(servlet第一被访问)
   map.contains("url-pattern")//--true;
⑥`servlet.service(req,resp)`调用servlet的service方法;
⑦服务器将响应结果返回给浏览器.
⑧浏览器发出第二次请求.
⑨tomcat会直接根据url-pattern,找到servlet对象,调用servlet.service方法.
   map.get("url中的url-pattern");
(3)Servlet请求参数
概念: 浏览器请求servlet携带的数据,叫做请求参数
Servlet接收请求参数:
`request.getParameter("表单元素的name")//接收名字对应单个数据的参数`
`request.getParameterValues("表单元素的name")//获得一个名字对应多个值,返回值String[]`
(4)浏览器请求Servlet的方式
①浏览器地址栏。也可以添加数据例如xxxx/xxxxxx/xxxx?username=“值”&password=“值”
②form表单(的action)请求Servlet
   `<form action="servlet的路径(URI)">`
③超链接的href.
   `<a href="servlet的路径(URI)"></a>`
补充小技巧:
使用浏览器监控浏览发出请求的请求参数 (F12调试)
名字=值;

4).请求参数乱码问题、Servlet请求转发、Request作用域、请求重定向(Redirect)、总结跳转方式

(1)请求参数乱码问题
①Post提交乱码:
了解: tomcat接收数据默认编码: `ISO-8859-1`
接收: req.setCharacterEncoding("UTF-8")
发送: resp.setContentType(“text/html;charset=UTF-8”);
注意: 设置编码,在接收请求参数之前设置
② Get提交乱码:
方式:
form action="" method="get"
超链接携带的数据.
浏览器发送请求参数
修改tomcat的conf/server.xml中`<connector URIEncoding=”UTF-8” />`
(2)Servlet各司其职
请求转发(foward)
作用: **多个Servlet配合完成一个功能**
核心特点:
①是服务器(当前web项目)内部发送的流程跳转*
②forward请求转发连接的多个servlet,处于一个请求过程中.
代码:
RequestDispatcher rdp = request.getRequestDispatcher("转发后的下一个servlet的url-pattern/其他资源的url-pattern路径");//获得转发器.
rdp.forward(req,resp);//foward转发.调用转发动作.
补充:
跳转情况: 
`servlet-->Servlet`
`servlet--->HTML(JSP)`
(3)Request作用域
概念: JavaEE提供的存储数据(命名属性)的空间.
命名属性: 名字---值
生命周期: 一次请求过程.[备注:请求转发的servlet正好处于一次请求过程]
存: `request.setAttribute("名字",值/数据/对象/xxx)`
取: `request.getAttribute("名字")`
(4)请求重定向(Redirect)
核心特点:
①服务器(web应用)外部跳转。
②通知浏览器,自动去请求下一个要跳转的页面或者Servlet(不需要用户操作)
③重定向连接的servlet或者资源,处于两个不同的请求过程。
④请求重定向后的页面和浏览器的地址一致。
代码实现:
resp.sendRedirect("/项目名/资源路径url-pattern");
    	    //通知浏览器自动请求"/项目名/资源路径url-pattern"
(5)总结跳转方式
请求转发(foward)            请求重定向(Redirect)                                        
原理(本质)  	服务器(Web项目)内部跳转 			服务器(Web项目)外部跳转                                     
请求过程 		1个请求过程					2个不同的请求过程
浏览器显示和地址 不一致						一致
作用域		可以使用request作用域传值		不能使用request作用域传值 [了解:地址?拼接数据] 
应用		servlet--->传递数据,使用request作用域,请求转发。一个业务功能中的多个资源要处于一个请求过程中,使用请求转发;servlet跳转的下一个资源属于另一个业务功能,使用请求重定向。 

5).会话技术(Cookie、HttpSession)、Session实现原理、解决浏览器禁用Cookie后Session失效问题

会话技术
http协议: 无状态协议,(协议本身不会记录任何信息,两次信息传输之间没有任何关系)
概念: 客户端(浏览器)会话技术。
应用场景: 浏览器记录   登录验证  验证码  购物车(阉割版)
另一种解释: 浏览器和服务器之间,多次交互依然保存数据(状态)的一种机制。(每个浏览器一份)
(1)Cookie
概念: 服务器保存在浏览器上的一小段字符串[key=value]
工作机制:
①服务器tomcat创建
②保存在浏览器
③浏览器每次访问服务器,都会将服务器(web项目)保存在本浏览器上的cookie发送到服务器上。(发送当前服务器保存的cookie)
编码实现:
①创建: 
   Cookie cookie = new Cookie("key","value");
②将cookie存入浏览器
   response.addCookie(cookie);// 将cookie随着响应返回给浏览器.
③其他方法(设置生命周期,设置存活多久)
   cookie.setMaxAge(存活时间秒);
④获得浏览器请求携带的cookie信息?
   Cookie[] cs = req.getCookies();
   cs[0].getName();  //cookie的key
   cs[0].getValue();  //cookie的value
总结Cookie的特点
①存在浏览器上的一小段字符串
   >缺点: (数据不太安全)
   >优点: 分担服务器的压力。(不会占用服务器的任何资源)
②cookie只能保存字符串,不能保存中文。
③cookie生命周期: (跨多次请求)
   设置: setMaxAge(秒)
       	10  	存活10s
        0    	删除cookie
       	-1  		设置cookie浏览器关闭之前。
   默认: 浏览器关闭,cookie丢失。
④cookie和浏览器(用户)一一对应。
(2)HttpSession
概念: 服务器会话技术。
核心工作机制: 服务器为每个**浏览器分配的一个一一**对应的存储空间。
详细: 浏览器第一次访问web应用服务器,服务器分配一个session对象,该浏览器第二次后再访问,服务器直接将原有sessino对象分配给该浏览器。
HttpSession的特点:
①存放在服务器
②每个浏览器和session一一对应
③HttpSession的生命周期夸多次请求依然存在。
HttpSession 相关的API:
①属性: id. 
②获得session: `request.getSession()`
    浏览器第一次访问: 创建session对象。
    浏览器第二 三...次访问: 获得原有的session对象给你。

HttpSession作用
**作用域,存储命名属性**
存:`session.setAttribute("name",值)`
取: `session.getAttribute("name")`
移除:`session.removeAttribute("name")`
特点:
①浏览器一一对应
②跨多次请求依然存在
③存放在服务器
 	应用场景(强制登录/登录验证):
需求:某些资源(HTML,Servlet)的访问需要用户登录之后才能访问,否则,强制用户去登录页面登录?
基本思路: web项目服务器记住用户(登录)
Session失效时机(补充):
①浏览器关闭,session失效。
②session默认保留30分钟。 【浏览器和服务器之间,超过30分钟没有请求】
    --当前项目的web.xml中修改
   <session-config>
   		<session-timeout>60</session-timeout>
   </session-config>
③主动失效: `session.invalidate()`   将所有Session失效
   应用: 用户退出登录:
   `session.removeAttribute("user")`
   `sesssion.invalidate()`
Cookie和Session对比[笔试]
Session和Cookie的相同点
和浏览器一一对应。
生命周期跨多次请求依然存。
Session和Cookie的不同点:
Cookie:
存在浏览器
cookie只能存储字符串,不能存汉字.(缺点)
cookie数据容易通过浏览器直接查看,不太安全。(缺点)
Session:
存在于服务器端
session可以存对象,可以存入任何类型。(优点)
session数据保存服务器,相对安全。(优点)
session中数据过多,侵占服务器内存资源(对服务器运行造成压力)[缺点]
应用场景分析:
用户私密信息(Session)
用户浏览器过的商品信息(cookie保存)
(3)Session实现原理
机制:
浏览器第一请求服务器web项目,会为该浏览器创建一个session对象。获得session的id,并且将id以cookie的形式写回到浏览器。以后每次浏览器,请求服务器都会自动携带该cookie(JsessionId)信息,tomcat通过获得cookie中名字为jesessionid的cookie的value值,和内部所有的session对象匹配,找到对应的session对该浏览器使用。
内部代码咋实现(局部代码):
①浏览器第一请求服务器:
   HttpSession session = new XxxxSession();
   String id = session.getId();
   //将session保存在服务器内存中(集合)
   Map<String,HttpSession> map = new ConcurrentHashMap<String,HttpSession>();
   map.put(id,session);
   Cookie ck = new Cookie("jsessionid",id);
   resp.addCookie(ck);
②浏览器第二次(以后)请求服务器
   Cookie[] cks = req.getCookies();
   for(Cookie c:cks){
       if(c.getName().equals("jsessionid")){
           String sessionId = c.getValue();
           //根据sessionid找到对应的session对象
           HttpSession session = map.get(sessionId);
       }
   }
(4)用户禁用Cookie (了解)
 	导致session失效,解决办法?
总结:
对所有超链接+表单等一切请求服务器的url路径,全部进行url重写。
方法: `String 重写后的url = resp.encodeUrl(原url地址)`
纠错: 	 `重写url;jsessionid=1234asdf1234`;

6).Filter过滤器

Filter过滤器: Servlet中提供的技术,可以过滤浏览器发出的请求,并且决定放行请求还是中断请求。
编码步骤:
①自定义一个java类,实现Filter接口
   public class EncodingFilter implements Filter{
       init(){}
       destroy(){}
       //请求经过filter要执行的代码
       doFilter(FilterChain chain){
           //放行请求之前
           chain.doFilter(req,resp);//放行请求。中断:不要调用
           //响应回来的代码,例如:资源的控制
       }
   }
②在web.xml中注册信息
   <!-- 注册filter信息 -->
   <filter>
   		<filter-name>filter名字</filter-name>
        <filter-class>filter全限定名</filter-class>
   </filter>
   <filter-mapping>
   		<filter-name>filter名字</filter-name>
        <url-pattern>/被过滤请求的servlet或者html等资源的url-pattern</url-pattern>
   </filter-mapping>
生命周期(了解):
①创建:  tomcat启动
②销毁:tomcat关闭
Filter的url-pattern的写法:
①写多个<url-pattern>资源</url-pattern>
②`/*`---过滤所有请求(统配)  <url-pattern>/*</url-pattern>
③`*.do`---过滤请求以.do的请求,在要过滤的servlet的全类名后加”.do”
	然后配置filter:<url-pattern>*.do</url-pattern>
④`/xxxxooaa/*` ----过滤路径中的url-pattern部分,以/xxxxxooaa开头的请求
	<url-pattern>/目录/*</url-pattern>
	应用:
		可以为所有servlet设置编码格式

7).ServletContext容器、监听器(ServletContextListener/HttpSessionListener/ServletRequestListener)

(1)ServletContext
(容器)作用域: 一个web应用只有一个ServletContext对象。
创建:tomcat启动创建     销毁: tomcat关闭
编程:
① 获得servletContext对象:
   		`ServletContext ctx = session.getServletContext()`
② 存: `ctx.setAttribute("name",值)`
③ 取:  	`ctx.getAttribute("name")`
④移除:	`ctx.removeAttribute("name")`
全局参数:
web.xml启动加载完毕会将信息存入servletContext
1. 在web.xml书写常亮配置
   	<context-param>
       <param-name>encoding</param-name>
       <param-value>UTF-8</param-value>
  	</context-param>
2. 从servletContext中获得常亮配置
   	String value = ctx.getInitParameter("encoding");     //“UTF-8”
web应用内流的相对路径:
`String 真实路径 = ctx.getRealPath("/项目名下的相对路径")`
项目名的动态获取(补充):
String ctxtPath = request.getContextPath();// "/项目名"
使用: 跳转路径: /项目名
(2)监听器
事件编程模型
概念:
事件源: 发生事件的对象本身,源头。
事件: 具体发生事情事件。
监听器: 监听事件源上发生的具体的事件,如果发生,会触发对应的代码执行。
监听器:
SerletContextListener: 		监听ServletContext对象的创建和销毁
HttpSessionListener: 		监听HttpSession对象创建和销毁
ServletRequestListner: 	监听ServletRequest对象创建和销毁。
编码:
①自定义一个类实现ServletContextListener:
    public class MyContextListener implements ServletContextListener{
   	@Override
   	public void contextDestroyed(ServletContextEvent arg0) {
   		System.out.println("context----销毁!!!!!!!!!!!!");
   	}
   	@Override
   	public void contextInitialized(ServletContextEvent arg0) {
   		System.out.println("context----创建!!!!!!!!!!!!");
   	}}
②web.xml注册:
	<listener><listener-class>全类名</listener></listener>
应用:
需求: 监控在线用户数量?
在HttpSession监听器中,监听session创建与销毁。
原文地址:https://www.cnblogs.com/jwnming/p/13634885.html