帝国系统怎样做网站地图,新乡网站建设制作公司,合肥seo整站优化,wordpress原图对比插件Java Web基础教程
1. Servlet基础
1.1 什么是Servlet
Servlet是JavaEE中的标准组件之一#xff0c;专门用于处理客户端的HTTP请求。并且它必须依赖于Servlet容器#xff08;Tomcat就是一个标准的Servlet容器#xff09;才能运行。因为Servlet实例的创建和销毁都是由容器负…Java Web基础教程
1. Servlet基础
1.1 什么是Servlet
Servlet是JavaEE中的标准组件之一专门用于处理客户端的HTTP请求。并且它必须依赖于Servlet容器Tomcat就是一个标准的Servlet容器才能运行。因为Servlet实例的创建和销毁都是由容器负责管理的我们不能自行通过new关键去创建和使用Servlet。
1.2 编写一个简单的Servlet 在任意地方创建一个myweb文件夹这个文件夹相当于一个web项目根目录 在根目录下创建WEB-INF子目录 在WEB-INF目录下创建src和classes子目录 在src目录下编写一个类继承HttpServlet这个父类
public class HelloServlet extends HttpServlet {
}重写父类的service方法这个就是专门处理客户端请求的方法web容器会为这个方法传入两个参数HttpServletRequest和HttpServletResponse,并且这个方法还需要抛出ServletException和IOException给容器捕获
public class HelloServlet extends HttpServlet {public void service(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException{//设置响应类型及编码response.setContentType(text/html;charsetutf-8);//获取字符输出流输出html信息response.getWriter().println(h1Hello Servlet/h1)}
} 编译Servlet需要依赖servlet-api.jar文件,将它添加到classpath中
javac -cp d:\servlet-api.jar; HelloServlet.java将编译后的HelloServlet.class文件剪切到classes目录中 在WEB-INF目录下创建并编辑web.xml文件为servlet配置请求映射
?xml version1.0 encodingutf-8?
!-- 配置根节点 --
web-app!-- 配置servlet类 --servlet!-- 指定servlet的别名 --servlet-namehello/servlet-name!-- 指定Servlet的完整类名--servlet-classHelloServlet/servlet-class/servlet!-- 配置请求映射--servlet-mapping!-- 这里的servlet-name和上面的servlet-name要一一对应 --servlet-namehello/servlet-name!-- 配置请求映射的url,必须以“/”开头--url-pattern/hello/url-pattern/servlet-mapping
/web-app 将myweb项目拷贝到tomcat的webapps目录中,并执行bin目录下的startup.bat启动容器 打开浏览器在地址栏输入http://localhost:8080/myweb/hello访问Servlet
1.3 Servlet的请求处理流程
浏览器发起http的请求这个请求首先会被servlet容器Tomcat截获然后容器会根据web.xml文件中配置servlet的来找到相应的这个别名然后再根据这个别名找到具体Servlet的类然后容器会创建这个Servlet类的实例并调用service方法来处理这个请求。通常Servlet是以单实例多线程的方式处理客户端请求。
1.4 Servlet的生命周期
所谓的生命周期就是从Servlet的创建一直到它销毁的整个过程。并且它的这个生命周期都是由Servlet容器如Tomcat负责管理和维护的。
1.4.1 Servlet对象创建的过程
当第一次请求某个Servlet的时候容器会先查找之前有没有创建过这个Servlet的实例如果没有则创建一个并缓存起来。后续相同的请求都由这个缓存的对象来处理。注意这里说的是第一次请求时创建。另外一种情况则是在容器启动的时候就创建Servlet的实例在web.xml中为Servlet指定配置这个配置的值是一个整型哪一个Servlet配置的数值越小创建的优先级别越高
1.4.2 生命周期方法
方法名描述init在Servlet对象创建之后立即执行的初始化方法且只执行一次service核心的请求处理方法这个方法可以执行多次destroy容器准备销毁Servlet实例之前执行这个方法也是执行一次容器重启或关闭
1.5 HTTP报文组成
1.5.1 请求报文
请求行请求报文的第一行就是请求行。包括请求方法、请求URL地址、HTTP协议版本。
请求头请求行之后的信息就是请求头它是以“名称:内容”的格式体现。主要包括服务器主机地址及端口、连接状态、系统信息、编码、语言等等。
请求体请求头结束之后会有一个空行空行之后就是请求体的内容。通常使用POST提交的数据信息会存放在请求体当中然后传递给服务器。
1.5.2 响应报文
状态行主要包括HTTP协议、响应状态码例如200表示OK成功响应。
响应头主要包括服务器信息、响应的类型及编码、内容的长度、响应的时间等。
响应体服务端可以将信息数据携带到响应体中带回客户端。
1.6 HTTP请求方法
在HTTP/1.1协议中请求方法主要包括8个下面列举常用的请求方法进行说明。
方法说明GET向服务器请求指定的资源并返回响应主体。一般来说GET方法应该只用于数据的读取类似于查询POST向指定的服务器提交数据例如表单数据的提交、文件上传等,并且提交的数据会放入请求体中类似于新增PUT向服务器提交数据但是和POST有所区别。如果服务器不存在此资源的时候则执行新增如果存在则执行修改类似于修改DELETE根据uri的标识删除服务器上的某个资源类似于删除其他…
备注GET与POST区别 GET主要用于获取数据POST用于提交数据。 GET请求所带的参数是放在请求行的url地址后面而POST这是放在请求体中。 通常浏览器会对GET请求的url长度有所限制而POST提交的数据在请求体中可以提交更多的内容。 浏览器会对GET请求进行缓存。
1.7 Servlet的请求处理方法
方法说明service可以处理任何的请求类型doGet处理对应的GET请求doPost处理对应的POST请求doPut处理对应的PUT请求doDelete处理对应的DELETE请求其他…
说明通过HttpServlet的源代码得知默认的所有请求都会先经过service方法然后service方法根据请求的方法类型判断来决定交给doGet或者是doPost方法来处理请求。如果子类重写了父类的service方法同时还重写了其他的doXxx的方法那么只有service方法会处理请求其他方法将失效。
1.8 Request与Response对象
当web容器调用某个Servlet的Service方法时会创建一个HttpServletRequest和HttpServletRespinse对象作为参数传入到这个方法中那么我们可以通过HttpServletRequest来获取相关的请求内容等而响应客户端可以利用HttpServletResponse对象来完成。
1.8.1 HttpServletRequest常用API
方法说明getParameter(String name)获取请求参数根据请求参数的name指定getParameterValues(Spring name)获取相同name的请求参数返回的是字符串数组getParameterNames()获取所有的请求参数名称getParameterMap()获取所有请求参数包括参数名称和值getMethod()获取客户端的请求方法getHeader(String name)根据请求头的名称获取响应的信息getRemoteAddr()获取远程客户端的IP地址getServletPath()获取Servlet的请求地址也就是url-patterngetRequestURL()获取请求完整的URL地址getRealPath(String path) 废弃获取项目的绝对路径。这个方法在request对象中已废弃建议通过ServletContext对象获取其他…
1.8.2 HttpServletResponse常用API
方法说明setContentType(String str)设置响应内容的类型及编码getWriter()获取响应字符输出流getOutputStream()获取字节输出流setHeader(String name, String value)设置响应头信息如果存在响应头信息则执行更新addHeader(String name, String value)设置响应头不管存不存在都会新加入一个setStatus(int code)设置响应状态码其他…
1.8.3 常见的响应状态码
状态码说明200请求已成功302重定向401请求被禁止未授权404请求的资源不存在405请求行的方法不被支持500服务器内部错误其他…
1.9 Servlet之间的通信
1.9.1 转发
所谓转发就是在多个Servlet之间共享请求和响应对象所有参与转发过程的Servlet都可以共享同一个请求对象的信息在Servlet的API中转发的操作是由HttpServletRequest对象完成的。
转发的特点
URL地址栏不会发生改变转发的过程是在服务端自动完成
示例代码
public class ServletA extends HttpServlet{public void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException{//获取页面提交的参数String name request.getParameter(userName); //转发由HttpServletRequest完成//第一步先获取一个请求转发器RequestDispatcher//获取请求转发器的同时要告诉转发器转发到哪里转发给谁//如果要转发给ServletB那么就是对应ServletB的url-patternRequestDispatcher rd request.getRequestDispatcher(servletB);//调用转发器的forward方法执行转发,同时将request和response对象一并转发ServletBrd.forward(request, response);}
}public class ServletB extends HttpServlet{public void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {//这里可以获得同一个请求的参数String name request.getParameter(userName);System.out.println(ServletB获取请求参数name);}
}请求作用域
每一个请求对象都有一个独立的空间这个空间我们称之为请求作用域RequestScope。可以为当前这个请求携带额外的一些数据信息这些信息同样可以在多个Servlet之间进行共享。
示例代码
public class ServletA extends HttpServlet {public void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException{//在ServletA中为request对象设置请求作用域request.setAttribute(age, 35);}
}public class ServletB extends HttpServlet{public void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException{//在ServletB中获取统一个请求对象作用域的值Integer age (Integer)request.getAttribute(age);}
}1.9.2 重定向
重定向的机制和转发不同首先重定向是通过HttpServletResponse对象来完成。一次重定向的过程中会有两次请求和两次响应服务器在接收第一次请求后会先做一次302的响应302表示重定向状态码告诉客户端浏览器必须发起一个新的请求地址服务端再次接收这个请求处理最后再次响应客户端。由于会产生不同的请求对象因此并不同共享同一个请求中的参数。
重定向的特点
URL地址栏会发生改变重定向的操作是在客户端浏览器完成的
示例代码
方式一
public class ServletC extends HttpServlet {Overrideprotected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {//执行重定向//方式一设置302响应状态码并在响应头中添加location属性指定重定向的地址response.setStatus(302);response.addHeader(location, http://localhost:8080/ch06/servletD);}
}方式二
public class ServletC extends HttpServlet {Overrideprotected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {//执行重定向//方式二使用response的sendRedirect方法response.sendRedirect(servletD);}
}1.10 会话跟踪
由于HTTP协议是无状态的服务端并不会记录每一个客户端的状态因此如果想要实现服务器能记录客户端的状态的话那么就需要会话跟踪技术。
1.10.1 cookie
cookie是客户端浏览器内部的一个文本文件用于记录服务器发送过来的一些文本信息。可以在Servlet中创建Cookie对象在响应时将cookie写回浏览器。在接下来的每次请求中客户端会都把这个cookie信息带回给服务器服务器就可以获取cookie的信息达到会话跟踪的目的。由于cookie是保存在客户端浏览器也就是会话信息将由客户端维护。
设置cookie
public class SetCookieServlet extends HttpServlet{protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {//创建一个Cookie的实例Cookie cookie1 new Cookie(userId,10001);Cookie cookie2 new Cookie(age,21);//将cookie对象设置到响应对象中response.addCookie(cookie1);response.addCookie(cookie2);}
}获取cookie
public class GetCookieServlet extends HttpServlet{Overrideprotected void service(HttpServletRequest request, HttpServletResponse repsonse) throws ServletException, IOException {//cookie是通过request对象来得到的//从请求中可以获取多个cookie对象Cookie[] cookies request.getCookies();for (Cookie cookie : cookies) {//判断cookie只获取name为userId的cookie对象if(userId.equals(cookie.getName())) {System.out.println(cookie.getValue());}}}
}cookie保存中文
在保存cookie的时候如果需要保存中文那么中文信息需要经过编码后才可以写入cookie
示例代码
编码使用URLEncoder
String str URLEncoder.encode(张三, utf-8);
Cookie cookie new Cookie(userName, str);解码使用URLDecoder
String str URLDecoder.decode(cookie.getValue(), utf-8);
System.out.println(str);cookie的生命周期
默认cookie只会保存在浏览器进程的内存中并不会写入cookie文件如果关闭了浏览器那么浏览器的进程也就消失了那么对应的内存就会释放空间因此cookie也就销毁。如果想将cookie写入文件那么就必须设置cookie的生命时长一旦设置了生命时长那么就表示这个cookie会在文件中保留多长的时间到了这个时间之后浏览器就会自动销毁这个cookie。
设置cookie存活时间
Cookie cookie new Cookie(userId,10001);
//设置为0表示立即删除cookie
cookie.setMaxAge(0);
//设置为正数表示cookie在cookie文件的存活时间单位秒
cookie.setMaxAge(60*60);
//设置为-1表示cookie只保留在浏览器器的进程中关闭浏览器之后会销毁cookie
cookie.setMaxAge(-1);1.10.2 Session
Session是基于服务端来保存用户的信息这个是和cookie的最大区别。不同的客户端在请求服务器的时候服务器会为每一个客户端创建一个Session对象并保存在服务器端Session对象是每个客户端所独有的相互之间不能访问。服务器为了区别不同的Session属于哪一个客户端因此Session对象也有一个唯一标识叫做SessionID。需要注意的是这个SessionID是以cookie的机制保存在客户端浏览器。每次请求的时候浏览器都会把这个SessionID带回服务端服务端根据这个SessionID就可以找到对应的Session对象。注意session的创建是在第一次调用request.getSession()方法时创建的因为这个方法会判断之前有没有创建过Session如果有则直接使用没有则创建一个不会出现同一个客户端同时创建多个Session的情况。
示例代码
public class SessionServlet extends HttpServlet{Overrideprotected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {//HttpSession对象是在第一次调用request的getSession()方法时才会创建//注意getSession()的方法会先判断之前是否为客户端创建了session实例//如果创建了则使用之前创建好的Session对象没有则创建一个新的SessionHttpSession session request.getSession();//创建HttpSession的同时会创建一个唯一的标识SessionID//这个sessionId会保存在浏览器的cookie中每次请求会带回这个id找到相应的session对象String sessionId session.getId();System.out.println(sessionId);}
}session的生命周期
SessionId是保存在浏览器的cookie中但是不会写入cookie文件这也就表示当关闭浏览器之后SessionId就会销毁。SesisonId销毁以后服务端的Session就没有任何作用了。但是服务器并不会立刻销毁这个Session对象至于什么时候销毁是由服务器自己决定的。除非我们手动调用了session.invalidate() 方法服务器就会立即销毁这个session实例。
例如
HttpSession session request.getSession();
//立即销毁session
session.invalidate();Session默认也有存活时间服务器在创建Session的时候为Session设置默认的存活时间为30分钟如果在30分钟之内客户端没有发起任何请求到服务器那么服务器就会销毁这个Session对象。我们也可以设置Session的存活时间。可以为当前的Session设置也可以为全局服务器端的所有Session的Session设置。
设置当前Session的存活时间
HttpSession session request.getSession();
//设置当前Session的存活时间单位秒
session.setMaxInactiveInterval(3600);设置全局的Session的存活时间:
在web.xml中进行设置
!-- 设置全局Session的存活时间,单位分钟 --
session-configsession-timeout60/session-timeout
/session-configSession的作用域
当我们需要将一些数据信息存入Session的时候就需要操作Session作用域SessionScope它和请求作用域类似也有相应的setAttribute和getAttribute方法只不过Session作用域的范围要比请求作用域更宽。请求作用域在一次请求响应之后就会消失因为相应之后请求对象就会销毁。而Sesison对象只要浏览器不关闭或者Session对象未超时那么Session对象会一直驻留在服务器端因此不管重新请求多少次还是转发和重定向都可以从Session中获取之前保存的数据信息。
示例代码
User user new User();
user.setUid(1001);
user.setUserName(wangl);
HttpSession session request.getSession();
//将数据保存在会话作用域中
session.setAttribute(user, user);从会话作用域取值
HttpSession session request.getSession();
//取值
User user (Object)session.getAttribute(user);URL重写
浏览器是可以禁用cookie的一旦禁用了cookie那么SessionId将无法写入cookie的缓存中这样就导致无法实现会话跟踪了因此解决办法就是使用URL重写。URL重写的目的就是把SessionId在放在请求URL地址的后面提交回服务器类似GET请求后面带上参数而这个参数就是一个SessionId服务器会解析这个URL的地址并得到SessionId。
示例代码
//重写请求的URL地址这个地址后面会自动带上SessionId
String url response.encodeRedirectURL(/getUser);
//重定向URL
response.sendRedirect(url);浏览器地址演示
http://localhost:8080/ch07/getUser;jsessionid6F1BA8C92D7E5D7CC479ED8DD30D3ED0注意;号后面跟着就是SessionId
1.11 ServletContext
web容器在启动时会为每一个web应用创建唯一的上下文对象这个对象就是ServletContext这个上下文对象可以理解为是当前项目的一个共享内存空间为项目中的所有Servlet提供一个共享的区域。
常用API
方法说明getContextPath()获取项目的相对路径getRealPath(String path)获取项目的绝对路径getInitParameter(String name)获取上下文的初始化参数web.xml中配置的setAttribute(String name, String value)将数据放入上下文作用域getAttribute(String name)从上下文作用域中去获取数据
上下文作用域
上下文作用域是为当前项目所有Servlet提供的一个共享内存区域可以将需要的数据信息保存在作用域中。这个作用域的的范围是最大的只要容器没有停止它就会一直存在。
三种作用域比较
结合前面所学的作用域共有三个分别是请求作用域、会话作用域、上下文作用域。
范围从小到大来划分:
请求作用域 会话作用域 上下文作用域
1.12 过滤器
过滤器可以在请求到达servlet之前和servlet响应客户端之前进行拦截相当于一个拦截器。主要用于进行一些请求和响应的预处理操作。常用的场景包括用户的认证授权、统一请求字符编码等等。
1.12.1 编写过滤器
要实现一个过滤器必须实现一个FIlter接口只有实现了这个接口的类才称之为过滤器。
示例代码
public class DemoFilter implements Filter {...
}web.xml配置过滤器:
filterfilter-namedemoFilter/filter-namefilter-classedu.nf.ch09.filter.DemoFilter/filter-class!-- 初始化参数 --init-paramparam-nameparam/param-nameparam-valuehello/param-value/init-param/filterfilter-mappingfilter-namedemoFilter/filter-name!-- 什么请求可以经过此过滤器/*表示所有请求 --url-pattern/*/url-pattern/filter-mapping1.12.2 过滤器的生命周期
与Servlet类似Filter同样也是容器负责创建和销毁与Servlet的区别在于容器会在启动的时候最先创建所有的过滤器并执行init方法进行初始化。
生命周期方法
方法说明init初始化方法容器启动时执行一次doFilter请求过滤方法决定请求是否放行destroy容器销毁过滤器之前执行的方法
代码实例
public class DemoFilter implements Filter{Overridepublic void destroy() {System.out.println(准备销毁DemoFilter);}Overridepublic void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)throws IOException, ServletException {//FilterChain表示一个过滤链对象因为过滤器可能会存在多个//同时这个对象将决定是否放行当前请求//放行的话则请求会继续到达下一个过滤器或者servlet中System.out.println(请求经过DemoFileer..放行);chain.doFilter(request, response);System.out.println(响应前经过DemoFilter...);}Overridepublic void init(FilterConfig config) throws ServletException {String name config.getInitParameter(param);System.out.println(初始化DemoFilter获取初始化参数name);}
}1.12.3 过滤链
在一个web项目中可能存在多个过滤器当有多个过滤器存在的时候就会形成一个过滤链。请求会按照过滤器链的顺序一直传递下去最终到达某个Servlet来处理请求。注意过滤链的顺序是按照web.xml中的先后配置顺序决定的
配置示例
!-- 按先后顺序配置 --
!-- 配置第一个过滤器 --
filterfilter-namefirstFilter/filter-namefilter-classedu.nf.ch09.filter.FirstFilter/filter-class
/filter
filter-mappingfilter-namefirstFilter/filter-nameurl-pattern/*/url-pattern
/filter-mapping
!-- 配置第二个过滤器--
filterfilter-namesecondFilter/filter-namefilter-classedu.nf.ch09.filter.SecondFilter/filter-class
/filter
filter-mappingfilter-namesecondFilter/filter-nameurl-pattern/*/url-pattern
/filter-mapping1.13 监听器
监听器用于监听对象的上的事件发生在Servlet中监听器主要监听请求对象、会话对象、上下文对象以及监听这些对象的作用域操作。JavaEE为我们提供了一系列的监听器接口开发时按需实现相应的接口即可。
1.13.1 监听作用域对象的创建与销毁
监听器说明ServletRequestListener监听请求对象的创建和销毁HttpSesisonListener监听会话对象的创建和销毁ServletContextListener监听Servlet上下文对象的创建和销毁
代码示例
1.请求对象监听器
public class DemoRequestListener implements ServletRequestListener{/*** 当请求对象销毁后容器执行此方法* 销毁方法中同样也有一个ServletRequestEvent事件对象*/Overridepublic void requestDestroyed(ServletRequestEvent event) {//通过这个事件对象就可以获取当前的请求对象HttpServletRequest request (HttpServletRequest)event.getServletRequest();System.out.println(销毁请求对象...request);}/*** 当请求对象创建之后容器调用此方法* ServletRequestEvent这个参数就是一个事件对象*/Overridepublic void requestInitialized(ServletRequestEvent event) {//通过这个事件对象就可以获取当前的请求对象HttpServletRequest request (HttpServletRequest)event.getServletRequest();System.out.println(初始化了请求对象...request);}}web.xml配置
!-- 配置监听器 --listener!-- 指定监听器的完整类名 --listener-classedu.nf.ch10.listener.DemoRequestListener/listener-class/listener2.会话对象监听器
public class DemoSessionListener implements HttpSessionListener{/*** 监听HttpSession对象的创建* HttpSessionEvent参数是一个事件对象* 通过它可以获得当前的HttpSession*/Overridepublic void sessionCreated(HttpSessionEvent event) {HttpSession session event.getSession();System.out.println(创建了Session对象session);}/*** 监听HttpSession对象的销毁*/Overridepublic void sessionDestroyed(HttpSessionEvent event) {HttpSession session event.getSession();System.out.println(销毁了Session对象session);}
}注意当第一次调用了request.getSesison()方法创建Session时监听器才会起作用。
web.xml配置
listener!-- 指定监听器的完整类名 --listener-classedu.nf.ch10.listener.DemoSessionListener/listener-class/listener3.Servlet上下文监听器
public class DemoContextListener implements ServletContextListener{/*** 监听ServletContext的销毁*/Overridepublic void contextDestroyed(ServletContextEvent event) {//通过事件对象获取ServletContextServletContext sc event.getServletContext();System.out.println(销毁了ServletContext对象...sc);}/*** 监听SerlvetContext的创建*/Overridepublic void contextInitialized(ServletContextEvent event) {//通过事件对象获取ServletContextServletContext sc event.getServletContext();System.out.println(创建了ServletContext对象...sc);}
}web.xml
listener!-- 指定监听器的完整类名 --listener-classedu.nf.ch10.listener.DemoContextListener/listener-class/listener1.13.2 监听作用域的操作
监听器说明ServletRequestAttributeListener监听请求作用域的操作HttpSessionAttributeListener监听会话作用域的操作ServletContextAttributeListener监听Servlet上下文作用域的操作
示例代码
这里以HttpSessionAttributeListener说明其他作用于监听器用法相似。
public class DemoSessionAttributeListener implements HttpSessionAttributeListener{/*** 当有数据添加到会话作用域时执行此方法*/Overridepublic void attributeAdded(HttpSessionBindingEvent event) {//获取存入作用域的键和值System.out.println(存入会话作用域...event.getName() : event.getValue());}/*** 当从会话作用域移除数据时执行此方法*/Overridepublic void attributeRemoved(HttpSessionBindingEvent event) {System.out.println(移除会话作用域...event.getName() : event.getValue());}/*** 当替换了会话作用域中的某个数据时执行此方法*/Overridepublic void attributeReplaced(HttpSessionBindingEvent event) {HttpSession session event.getSession();//从session中获取的是替换之后的值System.out.println(替换的值 session.getAttribute(userName).toString());//注意这里event.getValue()获取到的是替换之前的值System.out.println(替换会话作用域...event.getName() : event.getValue());}
}web.xml
listener!-- 指定监听器的完整类名 --listener-classedu.nf.ch10.listener.DemoSessionAttributeListener/listener-class/listener1.14 注解配置
Servlet3.0开始提供了一系列的注解来配置Servlet、Fiilter、Listener等等。这种方式可以极大的简化在开发中大量的xml的配置。从这个版本开始web.xml可以不再需要使用相关的注解同样可以完成相应的配置。
注解说明WebServlet这个注解标识在类上用于配置Servlet。例如WebServlet(name“hello”, urlPatterns“/hello”) 也可简化配置WebServlet(“/hello”)。initParams属性设置Servlet的初始化参数。loadOnStartup设置容器启动时初始化Servlet。MultipartConfig这个注解标识在类上标识启用当前Servlet的文件上传功能。location属性设置文件上传的路径。maxFileSize属性限制单个文件上传的大小默认为-1表示没有限制。maxRequestSize属性限制一次请求上传总文件的大小默认为-1表示没有限制fileSizeThreshold属性表示当前数据量大于该值时内容将被写入文件。WebFilter这个注解标识在类上用于配置Filter。例如WebFilter(filterName“encode”,urlPatterns“/*”) 也可简化配置WebFilter(“/*”)initParams属性设置Servlet的初始化参数。WebListener这个注解标识在类上用于配置各种监听器
示例
Servlet配置示例
WebServlet(urlPatterns /hello,initParams {WebInitParam(namename, valueaaa)},loadOnStartup 0)
MultipartConfig(maxFileSize 5242880, maxRequestSize 104857600)
public class TestServlet extends HttpServlet {...
}文件上传配置示例
WebServlet(urlPatterns /hello)
MultipartConfig(maxFileSize 5242880, maxRequestSize 104857600)
public class TestServlet extends HttpServlet {...
}Filter配置示例
WebFilter(urlPatterns /*, initParams {WebInitParam(namename, valueaaa)})
public class TestFilter implements Filter {...
}Listener配置示例
WebListener
public class ApplicationListener implements ServletContextListener {...
}1.15 动态注册
从Servlet3.0开始支持ServletContext来动态注册相关的Servlet组件。例如可以在自定义的ServletContextListener中通过在contextInitialized方法中获取ServletContext对象来注册Servlet、Filter、Listener。
动态注册Servlet
public class TestServlet extends HttpServlet { ...
}WebListener
public class ApplicationListener implements ServletContextListener {Overridepublic void contextInitialized(ServletContextEvent sce) {//获取ServletContextServletContext sc sce.getServletContext();//动态注册Servlet返回动态注册器实例ServletRegistration.Dynamic registration sc.addServlet(testServlet, TestServlet.class);//映射请求urlregistration.addMapping(new String[]{/test});//初始化参数registration.setInitParameter(name, aaa);//启用文件上传registration.setMultipartConfig(new MultipartConfigElement(sc.getRealPath(/uplaod), 5242880, 104857600, 104857600));}}动态注册Filter
public class TestFilter implements Filter {...
}WebListener
public class ApplicationListener implements ServletContextListener {Overridepublic void contextInitialized(ServletContextEvent sce) {ServletContext sc sce.getServletContext();//动态注册FilterFilterRegistration.Dynamic registration sc.addFilter(testFilter, TestFilter.class);//设置初始化参数registration.setInitParameter(name, aaa);//请求映射配置//参数一设置过滤器拦截的类型FORWARDINCLUDEREQUESTERRORASYNC//EnumSet是Set接口的一个特别实现可用于对枚举类型进行特定的分组//参数二设置该过滤器是否放在当前web应用中已经存在的过滤器之后true表示之后false表示之前//参数三设置请求拦截的urlregistration.addMappingForUrlPatterns(EnumSet.of(DispatcherType.REQUEST), true, new String[]{/*});}
}动态注册Listener
public class UserSessionListener implements HttpSessionListener {...
}WebListener
public class ApplicationListener implements ServletContextListener {Overridepublic void contextInitialized(ServletContextEvent sce) {ServletContext sc sce.getServletContext();//动态注册Listenersc.addListener(UserSessionListener.class);}
}1.16 文件上传
从Servlet3.0开始提供了文件上传的功能操作起来更加的简单和方便。要想使用这个功能首先必须在web.xml或者使用注解开启Servlet的上传功能否则无效。
xml配置:
servletservlet-nameupload/servlet-nameservlet-classedu.nf.ch04.servlet.UploadServlet/servlet-class!-- 开启上传功能 --multipart-config/
/servlet
servlet-mappingservlet-nameupload/servlet-nameurl-pattern/upload/url-pattern
/servlet-mapping注解配置
WebServlet(/login)
MultipartConfig //开启上传功能
public class LoginServlet extends HttpServlet {...
}参数说明
参数说明location指定文件上传的目录maxFileSize限制单个文件上传的大小maxRequestSize限制一次请求上传总文件的大小fileSizeThreshold设置缓存的大小当达到缓存大小的时候会将内存的数据写入location指定的目录中也就是写入磁盘
文件上传的核心接口是Part通过HttpServletRequest对象可获得该接口的实现类对象。
//获取单个上传文件的Part
Part part request.getPart(name);
//获取多个上传文件的Part
CollectionPart cool request.getParts();常用API
方法说明getContentType()获取上传的文件类型getSize()获取上传文件的大小getSubmittedFileName()获取上文件的文件名write()将文件上传写入到指定位置
当客户端使用form表单来上传文件时必须将表单的enctype属性设置为multipart/form-data。
form methodpost actionupload enctypemultipart/form-data!-- input使用file类型 --input typefile namefile/
/form 案例
WebServlet(/upload)
MultipartConfig
public class UploadServlet extends HttpServlet {Overrideprotected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {//指定上传的路径String uploadPath /Users/wangl/uploads;//创建文件夹如果不存在的情况下File dir new File(uploadPath);if(!dir.exists()){dir.mkdir();}//上传单个文件参数对用input的name属性的值//Part part req.getPart(file);//uploadPath uploadPath / part.getSubmittedFileName();//执行上传//part.write(uploadPath);//获取文件的类型//System.out.println(part.getContentType());//获取文件的大小//System.out.println(part.getSize());//获取上传的文件名//System.out.println(part.getSubmittedFileName());//上传多个文件CollectionPart parts req.getParts();for (Part p : parts) {p.write(uploadPath / p.getSubmittedFileName());}}
}upload.html
!DOCTYPE html
html langen
headmeta charsetUTF-8titleTitle/title
/head
body
h2文件上传/h2form methodpost actionupload enctypemultipart/form-dataUsername:input typetext nameuserName/br/File1:input typefile namefile/br/File2:input typefile namefile/br/input typesubmit valuesubmit//form
/body
/html2. JSP基础
2.1 简介
JSP全名为Java Server Pages中文名叫java服务器页面是一种动态页面技术而HTML是属于静态页面。JSP可以在HTML中嵌入Java脚本代码因为JSP本质上还是一个Servlet因此JSP也必须依赖于web容器才能运行。JSP的出现并不是为了取代Servlet而是简化了Servlet的工作将Servlet中繁琐的视图呈现代码脱离出来交给JSP来完成让Servlet专注于请求的处理所以在开发中通常将JSP和Servlet结合一起使用。
2.2 JSP引擎
JSP引擎主要负责将JSP文件转义成一个Servlet的java源文件然后再通过javac将这个源文件编译成class字节码文件并装载到JVM中执行。JSP引擎的核心类是JspServlet位于Jasper.jar文件中并且在Tomcat的web.xml中也默认就配置好了这个类JspServlet就是一个Servlet。因此凡是以“.jsp”结尾的请求都会先经过JspServlet那么这个引擎就可以开始工作。通常引擎转义和编译后的文件放在容器的work工作目录中。
注意如果第一次访问JSP文件的时候由于work目录中并不存在源文件和字节码文件JSP引擎就必须完成这两个工作因此有可能在第一次访问JSP时会比较缓慢。当字节码编译出来加载后第二次访问时速度就会很快了。
2.3 JSP三大元素
2.3.1 指令元素
语法% %
指令说明page指令用于设置JSP页面的相关信息以及编码include指令用于静态包含其他的JSP页面代码,所谓静态包含就是在编译期将另外的JSP页面的代码合并到当前的JSP中最终只会产生一个Java源文件taglib指令这个指令用于引入标签库
2.3.2 动作元素
语法jsp:xxx
动作说明include动态包含其他JSP页面的内容所谓的动态包含是指在编译期将不同的JSP文件转义成不同的Java源文件然后在运行时才将目标内容包含到当前的JSP页面中forward相当于Servlet中的转发转发到其他的JSP页面或者Servletparam用于传递参数通常结合其他的动作一起使用例如转发时需要提交一些而外的参数useBean用于在JSP页面中使用JavaBean对象,通常结合setProperty和getProperty来使用完成bean对象的赋值和取值操作
2.3.3 脚本元素
脚本元素主要就是在JSP中嵌入Java脚本代码包括声明、表达式、Java脚本
声明语法%! %
表达式:% %
Java脚本 % %
示例
% page languagejava contentTypetext/html; charsetUTF-8pageEncodingUTF-8%
!DOCTYPE html PUBLIC -//W3C//DTD HTML 4.01 Transitional//EN http://www.w3.org/TR/html4/loose.dtd
html
head
meta http-equivContent-Type contenttext/html; charsetUTF-8
titleInsert title here/title
/head
body%-- 声明变量和方法这里声明的变量a是实例变量 --%%! int a 10;public void say(){System.out.println(hello);}%%-- 表达式,注意表达式后面是不允许有;号结束的 --%3 1 %31%br/%-- Java脚本,脚本代码最终会生成在servlet中的service方法中作为代码片段 --%table border1trthName/ththAge/th/tr% for(int i0;i5;i){%trtduser%i%/tdtd%10i%/td/tr%}%/table
/body
/html2.4 JSP内置对象
内置对象是在容器运行时将创建好的9个对象内嵌在JSP中在JSP里可以直接拿来使用的对象。
对象说明out字符流输出对象config等同于Servlet中的ServletConfigpage表示当前JSP页面等同于Servlet中的thisrequest等同于Servlet中的HttpServletRequestresponse等同于Servlet中的HttpServletResponsesession等同于Servlet中的HttpSessionapplication等同于Servlet中的ServletContextpageContext表示当前JSP页面的上下文对象exception表示当前JSP中的异常对象
示例代码
% page languagejava contentTypetext/html; charsetUTF-8pageEncodingUTF-8%
!DOCTYPE html PUBLIC -//W3C//DTD HTML 4.01 Transitional//EN http://www.w3.org/TR/html4/loose.dtd
html
head
meta http-equivContent-Type contenttext/html; charsetUTF-8
titleInsert title here/title
/head
body%-- 常用内置对象 --%%//使用request,API使用同HttpServletRequest一样request.getParameter(userName);request.setAttribute(user, user1);request.getAttribute(user);//使用session,API使用等同于HttpSessionsession.setAttribute(user, user2);session.getAttribute(user);session.getId();//使用response//response.sendRedirect(demo.jsp);//out对象等同于字符输出流对象在JSP页面输出相关内容out.println(hello world);//这个是输出在控制中System.out.println(hello);//使用application,等同于ServletContextapplication.setAttribute(userName, user3);//pageContext使用//从pageContext中获取相关的其他对象HttpServletRequest req (HttpServletRequest)pageContext.getRequest();HttpServletResponse res (HttpServletResponse)pageContext.getResponse();HttpSession ses pageContext.getSession();ServletConfig conf pageContext.getServletConfig();ServletContext sc pageContext.getServletContext();//也可以通过pageContext来统一设置不同的作用域//第三个参数表示要放入到哪个作用域是一个int类型的参数//1代表page作用域当前页面有效//2代表请求作用域//3代表会话作用域//4代表上下文作用域pageContext.setAttribute(userName, zhangsan, 2);//也可以指定中哪个作用域取出相应的值String name (String)pageContext.getAttribute(userName, 2);out.println(name);%
/body
/html2.5 EL表达式
ELExpression Language全称叫做表达式语言是JSP2.0推出的一种技术。主要简化了在JSP中使用Java脚本表达式。EL表达式的特点在于使用简单支持四则运算、逻辑运算等并且还可以对Servlet API中的对象进行数据访问。EL的语法: ${expression}
算数与逻辑运算
示例结果${11}2${2*2}4${11}true${25}false${32}true……
数据访问
1.使用“.”来访问
示例说明${param.参数名}获取请求参数的值,相当于使用request.getParameter()方法${requestScope.xxx}从请求作用域中访问数据${sessionScope.xxx}从会话作用域中访问数据${applicationScope.xxx}从上下文作用域中访问数据${xxx}不指定作用域范围时,默认按照作用域范围从小到大的顺序自动查找其他…
2.使用[]来访问
示例说明${requestScope[“userName”]}从请求作用域中取值${sessionScope[“userName”]}从会话作用域取值其他…同上
注意通常使用[]来访问数据的时候主要是访问一些特殊的名称例如request.setAttribute(“user.userName”)
这种方式如果使用${requestScope.user.userName}是无效的应改为${requestScope[user.userName]}
来访问。
2.6 JSTL
JSTL是JSP中的标准标签库主要用于取代JSP中大量的Java脚本代码让页面看起来更趋向于HTML。使用也很简单通常结合EL表达式一起使用。
核心标签库core说明c:out输出标签c:set声明某个变量并存入指定的作用域c:redirect重定向标签c:if条件判断c:forEach循环标签……
备注其他标签库请参阅相关官方文档