Servlet概述 servlet是java编写的服务器端程序 servlet就是直接或间接实现javax.servlet.Servlet接口的一个类 servlet 通常通过 HTTP(超文本传输协议)接收和响应来自 Web 客户端的请求。 注意:tomcat 实现servlet和JSP,具有servlet和JSP的接口,如果需要源码,使用tomcat的源码即可 Servlet编写流程 1. 创建一个类并实现相关接口或继承相关类(Servlet接口,GenericServlet类,HttpServlet类) 2. 在web.xml中配置 <servlet> <servlet-name> 随便起个名,注意不要重复,一般为类名 <servlet-class> servlet的全限定名 </servlet> <servlet-mapping> <servlet-name> 上面的servlet-name <url-pattern> 以/开头,如/demo </servlet-mapping> 3. 访问路径 http://localhost:8080/项目名 + url-pattern的值 Servlet接口(javax.servlet) 定义所有 servlet 都必须实现的方法。 方法: destroy()销毁方法 getServletConfig() 返回ServletConfig对象,包含servlet的初始化参数信息 getServletInfo() 返回有关 servlet 的信息,比如作者、版本和版权。 init(ServletConfig) 初始化方法 service(ServletRequest,ServletResponse) 每次请求的执行方法 Servlet生命周期 init(ServletConfig) 初始化方法 service(ServletRequest,ServletRepsonse) 每次请求的执行方法 destroy() 销毁方法 init方法 初始化方法 调用者:tomcat (web服务器,web容器,servlet容器) 执行次数:1次 执行时间: 默认情况:第一次请求的开始,肯定在service方法之前 手动配置,在服务器启动时执行,在web.xml中配置 例: <servlet> <servlet-name> <servlet-class> <load-on-startup>0</load-on-startup> </servlet> 配置当前 servlet在服务器启动时执行init方法 取值:整型,(0 - 7)数字越小,优先级越高 参数 ServletConfig 对象,当前Servlet配置描述对象 接口:javax.servlet.ServletConfig 实现类:tomcat实现类,org.apache.catalina.core.StandardWrapperFacade 常用方法 获得servlet配置名称, web.xml <servlet><servlet-name> config.getServletName() 通过名称获得当前servlet的初始化参数的值,如果名称不存在返回null config.getInitParameter("username") 获得当前servlet的所有初始化参数的名称 config.getInitParameterNames() 例: Enumeration<String> allName = config.getInitParameterNames(); while(allName.hasMoreElements()){ String name = allName.nextElement(); String value = config.getInitParameter(name); System.out.println("all --> " + name + " : " + value); } 获得ServletContext对象 config.getServletContext(); service方法 每次请求的执行方法 调用者:tomcat 执行次数:每请求一次执行一次 执行时间:请求时 参数 ServletRequest 对象 接口:javax.servlet.ServletRequest 实现类:org.apache.catalina.connector.RequestFacade RequestFacade 实现了 HttpServletRequest接口, HttpServletRequest接口 继承了 ServletRequest接口 所以可以 HttpServletRequest request = (HttpServletRequest) req; ServletResponse对象 接口:javax.servlet.ServletResponse 实现类:org.apache.catalina.connector.ResponseFacade ResponseFacade 实现了 HttpServletResponse接口, HttpServletResponse接口 继承了 ServletResponse 所以可以 HttpServletResponse response = (HttpServletResponse) res; 结论 HttpServletRequest request = (HttpServletRequest) req; HttpServletResponse response = (HttpServletResponse) res; destroy方法 销毁方法 调用者:tomcat 执行次数:1次 执行时间:tomcat正常关闭 GenericServlet类 继承Servlet接口需要实现5个方法,但有的方法不需要 所以可以继承GenericServlet类,必须实现的方法只有service方法,其它方法按需要重写 抽象方法: service方法 注意: 需要重写初始化方法时,不要重写init(ServletConfig),要重写init()方法 因为GenericServlet类对参数进行了缓存(this.config = config),提供了一些便捷方法.如果重写了,也没有调用父类的方法,则如果别的地方使用了便捷方法会报错 GenericServlet类的init(ServletConfig)会自动调用init()方法 参数可以通过GenericServlet类的getServletConfig()方法获得 便捷方法: 可以直接用servlet对象调用getInitParameter和getServletContext方法(本来是ServletConfig类的方法) 此类是通用servlet实现类,与协议无关。 HttpServlet类 与HTTP协议有关的servlet实现。 HttpServlet 将service 方法 进行分流,分成了7种。根据不同的请求方式分别调用不同的方法 底层;HttpServletRequest.getMethod()获得请求方式:返回值POST | GET等 继承HttpServlet,并覆写doGet、doPost分别用于处理get请求和post 请求 Servlet访问路径配置 即<url-pattern>的值 1 完全匹配路径 例如:/page/oneServlet 2 不完全匹配路径(通配符匹配*) 例如:/page/* --> page目录所有路径 例如:/* --> 所有路径 3 扩展名匹配(*.xx) 例如:*.jsp --> 所有的jsp文件 例如:*.html --> 所有的html文件 总结,访问优先级:完全匹配路径 > 通配符匹配 > 扩展名匹配 > 缺省servlet/ 缺省servlet就是访问路径为/的servlet,当没有匹配上任何路径的时候,会执行缺省servlet. 一般不要配置缺省servlet,tomcat有默认实现. 即 获得请求路径(如/abc/123.html),读取相应文件,将文件发送给浏览器.如果没有读到文件,会返回404 浏览器是不能访问服务器本地文件的,都是通过缺省servlet返回资源的 配置Servlet的初始化参数 在web.xml中<servlet>中的<servlet-class>后添加<init-param> 例: <servlet> <servlet-name> <servlet-class> <init-param> <param-name>参数名</param-name> <param-value>参数值</param-value> </init-param> </servlet> 修改myeclipse的servlet模板 0 关闭myeclipse 1 查询myeclipse common目录 myeclipse安装,查看myeclipse.ini,通过第四行确定common目录的位置 2 查找文件,Common/plugins/com.genuitec.eclipse.wizards_*.jar 3 修改jar中的templates/Servlet.java文件(注意备份) 如: <aw:method name="doGet"> public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { this.doPost(request, response); } </aw:method> <aw:method name="doPost"> public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { request.setCharacterEncoding("utf-8"); } </aw:method> ServletContext类 Servlet上下文对象。Servlet管理者 此对象由tomcat在启动时创建,每一个web项目都对应一个ServletContext对象实例 Tomcat关闭时将释放资源--在tomcat启动之后一直存在于内存中。 获得方式 1 在servlet的doGet、doPost方法中使用 this.getServletConfig().getServletContext 或 this.getServletContext() 2 Servlet3.0 ServletRequest提供相应的方法 (了解) request.getServletContext() 常用方法 1 属性操作(内存管理) --xxxAttribute setAttribute(String name,Object value) ,给一个对象进行名称,并放入到内存中。 Object getAttribute(String name) ,通过给定的名称获得对象,如果没有获得数据返回null removeAttribute(String name) ,通过给定的名称移除对象 在多个servlet之间进行数据共享。因为服务器关闭时才释放资源,不建议将经常修改的内容放置此处。 2 管理资源 String getRealPath(java.lang.String path) 获得发布到tomcat下web项目中的文件的具体位置(绝对路径) 例如:getRealPath("/WEB-INF/web.xml") --> D:\java\tomcat\apache-tomcat-7.0.42\webapps\day04_demo\WEB-INF\web.xml InputStream getResourceAsStream(java.lang.String path) 获得发布到tomcat下web项目中的文件的资源流 Set<String> getResourcePaths(java.lang.String path) 获得指定目录下面的所有文件或目录的相对路径,返回Set集合 以上三个方法,参数都是以项目文件夹为根的相对路径 3 获取web项目的初始化参数 getInitParameter(java.lang.String name) 获得整个web项目的指定名称的初始化参数 getInitParameterNames() 获得整个web项目所有的初始化参数的名称 配置web项目的初始化参数 在根标签<web-app>下添加<context-param>标签 例: <context-param> <param-name>参数名</param-name> <param-value>参数值</param-value> </context-param> Servlet执行流程(单实例) 单实例,多线程 单实例,可能存在线程并发访问问题。尽量避免使用成员变量 MyEclipse执行可运行类的方式 如/sss/bin/cn/itcast/Test.class 先定位到项目根目录,然后设置classPath路径去执行 如: F:\workspaces\sss>java -cp F:\workspaces\sss\bin cn.itcast.Test 重定向 响应行:响应编号:302 响应头:存在一个location头 当浏览器接收到302后,将会向响应头中的location的值表示的路径再次发送一个请求 资源访问路径 使用java代码访问资源 绝对路径 相对路径(按方法区分) new File(string) 相对路径 不加/的相对路径:以 运行环境所在目录 为根 加/的相对路径: 以 运行环境所在目录的根目录 为根(即盘符的根) 运行环境 在MyEclipse中运行main方法时,运行环境为 项目目录 在命令行窗口运行main方法时,运行环境为 classPath文件夹(一般为项目目录下的bin目录) Class类的getResourceAsStream方法 和 Class类的getResource方法 不加/的相对路径:以 类文件所在目录 为根 加/的相对路径: 以 classPath目录 为根 ClassLoader类的getResourceAsStream方法(ClassLoader类的getResource方法加/的相对路径不会用) 不加/的相对路径:以 classPath目录 为根 加/的相对路径: 以 classPath目录 为根 ServletContext类的getRealPath方法 不加/的相对路径:以 项目文件夹 为根 加/的相对路径: 以 项目文件夹 为根 ServletContext类的getResourceAsStream方法 不加/的相对路径:以 项目发布文件夹 为根(对应MyEclipse中的WebRoot目录) 加/的相对路径: 以 项目发布文件夹 为根(对应MyEclipse中的WebRoot目录) HttpServletRequest类的getRequestDispatcher方法 不加/的相对路径:以 当前serlvet配置路径父路径 为根 加/的相对路径: 以 项目发布文件夹 为根(对应MyEclipse中的WebRoot目录) HttpServletResponse类的sendRedirect方法 不加/的相对路径:以 当前serlvet配置路径父路径 为根 加/的相对路径: 以 tomcat发布文件夹 为根(项目上一级文件夹) 小结 当使用相对路径时, 获得src下的资源 类名.class.getResourceAsStream("/名称") 类名.class.getClassLoader().getResourceAsStream("名称") 类名.class.getClassLoader().getResourceAsStream("/名称") 获得WebRoot下的资源 this.getServletContext().getResourceAsStream("名称"); this.getServletContext().getResourceAsStream("/名称"); 获得项目下的资源的绝对路径 java项目 类名.class.getResource("/classpath下面的资源").getPath() 类名.class.getResource("当前包下面的资源").getPath() web项目 this.getServletContext().getRealPath("/项目下路径") 当使用请求转发和重定向时,参数都要以/开头,请求转发不加项目名称,重定向前面要加项目名称 可通过this.getClass.getResource("/").getPath()获得项目classPath的路径 浏览器访问资源 完整路径 相对路径 不以/开头: 以 当前文件所在目录 为根 以/开头: 以 tomcat发布文件夹 为根(项目上一级文件夹) 注意: 相对路径中 ./ 为当前目录 ../ 为上一层目录,可以多层嵌套使用 HttpServletResponse接口(response) http协议的响应描述对象 常用方法: 响应行 修改状态码:setStatus(int sc) HttpServletResponse 提供状态码对应常量。 回顾:200正常、302重定向(localhost)、304未修改、404不存在、500服务器异常 响应头 setHeader(java.lang.String name, java.lang.String value)//设置响应头,name固定头,value响应值 setIntHeader(java.lang.String name, int value) //设置响应头,值为整形 setDateHeader(java.lang.String name, long date) //设置响应头,值为日期 sendRedirect(String location) //设置重定向的便捷方法,底层setStatus(302);setHeader("location","路径"); setContentType(java.lang.String type) //设置content-type的便捷方法,可用于设置编码,底层setHeader("content-type","text/html;charset=编码") 响应体 (流) ServletOutputStream getOutputStream() 获得字节流 PrintWriter getWriter() 获得字符流 注意: 1 如果流缓存已经被刷新(手动,自动缓存溢出8k) ,不能进行重定向。 2 流一般不用进行手动关闭,tomcat自动进行关流。 3 getOutputStream 和 getWriter 不能同时使用 String encodeURL(String url); //如果客户端禁用cookie,则session失效 //此方法可以把session的id添加到url后面,使服务器找到指定session //可在重定向或转发前处理url(在Servlet中使用前应先获取到session,否则无效) HttpServletRequest接口(request) http协议的请求描述对象 一次请求将创建一组request和response 常用方法 1 获得浏览器发送的请求参数的数据 String getParameter(java.lang.String name) ,通过参数名称获取参数值 String[] getParameterValues(java.lang.String name) ,通过参数名称获取一组值(String数组,通常用于多选框) Map<String,String[]> getParameterMap() 获得所有参数信息 2 属性操作 setAttribute / getAttribute /removeAttribute 注意: 属性操作是对request对象内存的操作.当进行请求转发时,parameter参数都会丢失,而request中的数据可以通过方法参数传递 parameter参数通过字符串传递,只能传递字符串,主要用于浏览器和服务器之间的数据传输 request是java对象,可以存任何类型的数据,用于服务器端的数据传输(请求转发或页面渲染) 3 常用方法 getScheme() //获得协议 getServerName() //获得服务器名称(域名) getRemoteAddr() //获得客户端ip getServerPort() //获得服务器端口 getContextPath() //获得项目名称 getServletPath() //获得Servlet的配置路径 getRequestURL() //获得请求全路径 getRequestURI() // "/"+项目名+Servlet配置路径 getQueryString() //获得请求路径中?后的字符串 getInputStream() //获得请求体 setCharacterEncoding(java.lang.String env) //设置post请求的中文编码 getRequestDispatcher(String url) //获得请求调度器,用于请求转发 中文乱码 参数传递的不同方式 表单提交post请求: 请求体,进行url编码 表单提交get请求: 请求行,进行url编码 超链接: 请求行,不进行url编码 地址栏直接输入: 请求行,不进行url编码,但是跟操作系统默认编码有关(其它都只跟页面编码有关) 表单的enctype 属性规定在发送到服务器之前应该如何对表单数据进行编码,默认值为application/x-www-form-urlencoded,所以表单数据会默认进行url编码表单的enctype 表单使用post请求但是在请求路径后跟?加的参数 是在请求行中传递的,不会进行url编码 url编码 处理请求行或请求体中的数据,用于传递非标准的字母和字符 js代码 url编码 : encodeURI(str,编码); //不对特殊字符编码 encodeURIComponent(str,编码); //对特殊字符编码,如 : / & = url解码 : decodeURI(str,编码); decodeURIComponent(str,编码); java代码 url编码 : java.net.URLEncoder.encode(str, 编码); url解码 : java.net.URLDecoder.decode(str, 编码); url编码规则(了解): 任何特殊的字符(就是那些不是简单的七位ASCII,如汉字)将以百分符%用十六进制编码,当然也包括象 =,&;,和 % 这些特殊的字符。 其实url编码就是一个字符ascii码的十六进制。不过稍微有些变动,需要在前面加上“%”。 比如“\”,它的ascii码是92,92的十六进制是5c,所以“\”的url编码就是%5c。“胡”的ascii码是-17670,十六进制是BAFA,url编码是“%BA%FA”。 注意 js的encodeURIComponent方法和java的encode方法效果相同 js的两个编码方法都可以用java的decode方法解码出原来的值 表单提交get请求进行的是encodeURI方法的编码 下面是js的encodeURI方法进行url编码的结果示例(编码为utf-8) 原字符串:userServlet?name=李凯昊&password=123 编码后 :userServlet?name=%E6%9D%8E%E5%87%AF%E6%98%8A&password=123 乱码处理(页面编码为utf-8) response对象 服务器:response.setContentType("text/html;charset=UTF-8"); 表单提交post请求 服务器:request.setCharacterEncoding("UTF-8"); 或:value = new String(value.getBytes("ISO-8859-1"),"UTF-8"); 或:value = URLDecoder.decode(URLEncoder.encode(value,"ISO8859-1"),"UTF-8"); 表单提交get请求,post请求路径后的参数,超链接 服务器:value = new String(value.getBytes("ISO-8859-1"),"UTF-8"); 或:value = URLDecoder.decode(URLEncoder.encode(value,"ISO8859-1"),"UTF-8"); 地址栏输入时路径后跟参数 服务器:value = new String(value.getBytes("ISO-8859-1"),"gbk"); 或:value = URLDecoder.decode(URLEncoder.encode(value,"ISO8859-1"),"gbk"); 终极方式(不推荐使用) 修改Tomcat配置文件conf/server.xml <Connector port="8080" protocol="HTTP/1.1" ... URIEncoding="UTF-8"> 还有一种可行的方式:用js控制提交数据时,可以先对数据进行两次url编码,然后在服务器接受数据时进行一次url解码即可(tomcat自动解码一次) 请求转发(forward) 将一次请求,转发到另一个servlet进行处理。是一次请求,地址栏不改变 RequestDispatcher 请求调度器 获得方式: ServletContext.getRequestDispatcher(java.lang.String) ServletRequest.getRequestDispatcher(java.lang.String) 方法: forward(ServletRequest request, ServletResponse response) 转发,可以涉及多个servlet,但浏览器只显示最后一个servlet输出内容。 include(ServletRequest request, ServletResponse response) 包含,可以涉及多个servlet,将多个servlet输出内容合并一起输出。 注意: 请求转发可以使用request属性进行数据的传递 转发之间使用的request对象是不同(类型也不一样),但数据是一致的。(底层克隆) 转发使用的response对象是同一个对象,不过前一个Servlet在转发前输出的内容不会发送到浏览器 当转发完成之后,需要回到转发触发的位置,继续执行程序,只是之后输出的数据不在浏览器中进行显示。 请求转发和重定向对比 请求转发: 是一次请求,可以通过request对象传递数据,地址栏地址不改变 重定向: 是两次请求,需要通过url传递参数,地址栏地址改变 请求转发和重定向的路径也不一样,请求转发的以/开头的相对路径不需要加项目名,而重定向需要 请求转发是request对象的方法,重定向是response的方法 会话概述 一个有限时间窗口内来自同一浏览器的请求标识为一个会话。 当一个未知的客户向Web应用程序发送第一个请求时就开始了一个会话。当客户明确结束会话(关闭浏览器)或服务器在一个预定义的时限内不从客户接受任何请求时,会话就结束了。 会话技术 cookie,浏览器端进行缓存数据的技术 session,服务器端进行缓存数据的技术 cookie cookie 是 servlet 发送到 Web 浏览器的少量信息,这些信息由浏览器保存,然后发送回服务器。cookie 的值可以唯一地标识客户端,因此 cookie 常用于会话管理。 Cookie类(javax.servlet.http) Cookie类是对http协议cookie进行描述的类 构造方法 new Cookie(String name,String value) 常用方法 getName() 获得名称 getValue() 获得值 setMaxAge(秒) 设置有效时间,单位为秒,时间到自动清空,不设置的话默认会话结束自动清空.如果值为0,表示删除cookie. setPath("/") 设置路径,将当前cookie路径修改为web站点根目录,默认值是servlet父路径.request携带的cookie是同级或父级的,不能携带子级的cookie 服务器发送cookie:response.addCookie(Cookie) 获得当前request携带所有的cookie信息:request.getCookies(); 注意: cookie中的数据存储到客户端,可以直接看到内容,所以不安全 浏览器只会发送cookie的name和value 服务器设置cookie的响应头示例: Set-Cookie: 键=值 浏览器发送cookie的响应头示例: Cookie: 键=值 cookie不支持中文(试试url编码后再存) 示例: //设置cookie Cookie a=new Cookie("password","123"); a.setMaxAge(60*60*24*7);//保存一周 a.setPath("/");//任何路径都可以访问到此cookie response.addCookie(a); //读取cookie Cookie []cookies=request.getCookies(); if(cookies!=null){ for(Cookie cookie : cookies){ out.println(cookie.getName()+"="+cookie.getValue()+"<br>"); } } //删除cookie Cookie[] cookies=request.getCookies(); for(Cookie cookie : cookies){ if(cookie.getName().equals("username")){ cookie.setMaxAge(0); } } session 概述 提供一种方式,跨多个页面请求或对 Web 站点的多次访问标识用户并存储有关该用户的信息。 服务器能够以多种方式维护会话,比如使用 cookie 或重写 URL。 (自动使用cookie标识会话,当客户端禁用cookie时,可以使用重写URL的方式) 当我们创建一个session,服务器自动创建cookie,将session的id发送给浏览器,每一次请求将session的id回传给服务器,request将通过session的id标识一个客户端。 获得方式 request.getSession() //如果服务器端没有缓存session,则创建,如果有,则获取引用 HttpSession接口(javax.servlet.http.HttpSession) HttpSession类是对http协议session进行描述的类 属性操作 setAttribute / getAttribute /removeAttribute 属性操作是对session对象内存的操作.可以实现在一个会话,多个请求之间存储获取数据 常用方法 void setMaxInactiveInterval(int time) 设置多少秒内未使用此session则删除此session void invalidate() 销毁session boolean isNew() 返回session是否是这次请求刚创建的 getId() 返回session的标识ID 注意: session默认为会话级别,即浏览器退出session失效,可通过setMaxInactiveInterval手动设置时间 默认情况下,每次请求会携带cookie:jsessionid:"sessionid的值",服务器根据sessionid值确定session session对象的销毁 1.过期了,默认值30分钟(可在web.xml中设置<session-config>)或setMaxInactiveInterval方法设置时间到期 2.执行session.invalidate()直接销毁 3.服务器非正常关闭。(正常关闭,会对session进行持久化存储,启动时再读取) 重写URL 如果客户端禁用cookie,则session失效,可使用重写url维护session. 会将session的id通过url回传给服务器,例:http://localhost:8080/day06/sessionAttribute2Servlet;jsessionid=B2AC41059935320C52B41808DB651A09 response的方法: encodeURL(java.lang.String url) ,处理指定URL,如果cookie失效,追加session的id;如果cookie不失效,不做任何操作。(必须先获取session,否则不追加) 示例: HttpSession session = request.getSession(); //必须先获取session String url = "/day06/encodeShowServlet"; url = response.encodeURL(url); response.getWriter().println("<a href='"+url+"'>点我</a> <br/>"); Servlet三种作用域(属性操作) servletContext , servlet上下文(管理者),一个web项目,多次会话,共享数据。(一个项目一块内存) 场景:记录在线人数、浏览次数 session,服务器会话技术,一次会话,多次请求,共享数据。(一个用户一块内存) 场景:用户的登录信息 request,请求,使用请求转发时,一次请求,多个Servlet,共享数据。(一个请求一块内存) 场景:查询数据,另一个servlet显示 在完成功能的前提下,尽量使用作用域小的,及时释放内存 验证码 生成图片工具类CheckNumUtils package elec.utils; import java.awt.Color; import java.awt.Font; import java.awt.Graphics; import java.awt.image.BufferedImage; import java.util.Random; import javax.imageio.ImageIO; import javax.servlet.http.HttpServletResponse; /** 验证码工具类 @author Administrator * */ public class CheckNumUtils { /** 生成验证码图片并发送到客户端 @param response @return 验证码 */ public static String createCheckImage(HttpServletResponse response) { //通知浏览器不缓存 response.setHeader("Pragma", "No-cache"); response.setHeader("Cache-Control", "no-cache"); response.setDateHeader("Expires", 0); //生成随机验证码 Random random = new Random(); String sRand = ""; for (int i = 0; i < 4; i++) { String rand = String.valueOf(random.nextInt(10)); sRand += rand; } // 在内存中创建图象 int width = 55; int height = 20; BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); // 获取图形上下文 Graphics g = image.getGraphics(); // 设定背景色 g.setColor(getRandColor(200, 250)); g.fillRect(0, 0, width, height); //设定字体 g.setFont(new Font("serif", Font.CENTER_BASELINE, 16)); //画边框 //g.setColor(new Color(1)); //g.drawRect(0,0,width-1,height-1); //画干扰线 g.setColor(getRandColor(160, 200)); for (int i = 0; i < 100; i++) { int x = random.nextInt(width); int y = random.nextInt(height); int xl = random.nextInt(12); int yl = random.nextInt(12); g.drawLine(x, y, x + xl, y + yl); } //画数字 for (int i = 0; i < 4; i++) { String rand = sRand.substring(i, i + 1); // 将认证码显示到图象中 g.setColor(new Color(20 + random.nextInt(110), 20 + random .nextInt(110), 20 + random.nextInt(110))); //调用函数出来的颜色相同,可能是因为种子太接近,所以只能直接生成 g.drawString(rand, 13 i + 6, 16); } // 图象生效 g.dispose(); // 输出图象到页面 try { ImageIO.write(image, "JPEG", response.getOutputStream()); response.getOutputStream().close(); } catch (Exception e) { } return sRand; } //给定范围获得随机颜色 private static Color getRandColor(int fc, int bc) { Random random = new Random(); if (fc > 255) fc = 255; if (bc > 255) bc = 255; int r = fc + random.nextInt(bc - fc); int g = fc + random.nextInt(bc - fc); int b = fc + random.nextInt(bc - fc); return new Color(r, g, b); } } 页面代码 <img id="checkImg" src="imageServlet"> 获取验证码 String checkNum = CheckNumUtils.createCheckImage(response); request.getSession().setAttribute("CHECK_NUMBER_KEY", checkNum); 验证验证码 String checkNumber = request.getParameter("checkNumber"); String sessionCheckNumber = (String) request.getSession().getAttribute("CHECK_NUMBER_KEY"); if(checkNumber == null || checkNumber.equals("")){ //请输入验证码 } if(!checkNumber.equalsIgnoreCase(sessionCheckNumber)){ //验证码错误 } 点击图片更换验证码 //checkImg为验证码图片 checkImg.οnclick=function(){ checkImg.src="imageServlet?time="+new Date(); }; 注意:一次性验证码可在每次验证验证码后就删除session中的数据,当再次验证时,如果session中为空,则为表单重复提交 JSP概述 JSP就是一个java类,也是一个servlet 特点:html代码嵌入java代码 JSP扩展名:*.jsp JSP执行流程 1 编写jsp页面 (a.jsp) 2 访问时web服务器(tomcat),tomcat完成以下步骤(在tomcat的web.xml中存在配置路径为*.jsp的servlet,实现类:org.apache.jasper.servlet.JspServlet) 2.1 读取jsp文件 2.2 通过jsp文件生成一个java文件 (也是servlet) 位置:%tomcat%\work\Catalina\localhost\day07\org\apache\jsp\a_jsp.java java源码:public final class a_jsp extends org.apache.jasper.runtime.HttpJspBase public abstract class HttpJspBase extends HttpServlet --> 【jsp就是servlet】 _jspService 相当于自定义servlet时doGet或doPost方法 2.3 将java文件编译生成class文件 2.4 运行class文件,相当于直接访问servlet,将需要输出的内容发送到浏览器。 3 访问jsp路径与访问html路径一致 JSP的脚本元素 声明 声明方法、字段等 格式:<%! java类体可以书写的内容 %> 表达式 将表达式的结果发送到浏览器,相当于在servlet中编写 out.print(表达式); 格式:<%= 表达式 %> 代码片段 格式:<% 方法体可以书写的内容 %> 注意: 脚本元素不能嵌套使用 声明标签声明的变量是成员变量,代码片段声明的变量是局部变量 面试题 <%=i%> //2输出成员 5 <%int i = 10;%> //3定义局部变量 <%=i%> //4输出局部变量 10 <%! int i = 5;%> //1 声明成员 <% i++; %> //5将局部+1 11 <%=i%> //6输出局部变量 11 <%=++this.i%> //7输出成员变量+1 6 JSP指令元素 指令元素:当前的页面的配置,辅助tomcat生成java源码。 格式:<%@ 指令名称 属性名称="属性值" ...%> 指令名称:page、include、taglib 指令书写 一个指令可以有多个属性 同一个指令可以书写多次,但一般一个页面,同样的属性只有出现一次。 1 page指令 当前jsp页面的配置信息 格式:<%@ page 属性名称="属性值" ...%> 属性 1 编码 pageEncoding : 用于配置当前页面的编码 contentType : 用于设置jsp生成servlet响应浏览器的编码 2 jsp缓存机制 autoFlush: 缓存是否自动刷新,缓存如果溢出,则自动刷新,默认为true. buffer :缓存大小,默认:8kb.不自动刷新,页面内容超过缓存大小的话会报错 3 常用(常见) language : 设置当前jsp可以嵌入的语言。默认值:java info : 描述信息,重写了servlet的getServletInfo()方法,返回描述信息 session : 确定当前jsp页面,是否可以直接使用 jsp内置对象session import : 给jsp导入需要包 分别导入 使用一个import导入,多个类之间使用逗号分隔 isELIgnored : 当前jsp页面是否忽略EL表达式的执行,默认:false 可以使用 extends : 确定jsp的父类,扩展 4 jsp错误处理机制 errorPage : 指定错误页面,当前jsp出现异常时,会跳到指定页面 isErrorPage : 确定当前页面是否是错误处理页.true时可以使用jsp内置变量exception 2 include指令 静态包含:一个jsp页面,包含另一个jsp页面,两个jsp生成一个java文件,再运行进行输出。 格式:<%@ include file="URL"%> 3 taglib 指令 作用:在当前jsp页面中引入指定的标签库 格式:<%@ taglib prefix="" uri="" %> uri : 用于确定标签库描述文件名称(有名称相当于有位置) prefix :当前标签库所有标签的使用前缀 prefix="m" --> <m:标签名称/> JSP注释 jsp格式:<%-- 注释内容 --%> java注释: // 单行注释 / ### */ 多行注释(块注释) /* ###*/ 文件注释(JavaDoc标准注释) html注释:<!-- html注释内容 --> 对比 jsp源码 java源码 html源码 jsp注释 有 无 无 java注释 有 有 无 html注释 有 有 有 web项目错误处理机制 统一管理错误(友好页面) 配置web.xml <error-page> <error-code>404</error-code> 异常状态码 和异常类型二选一 <exception-type> 异常类型 <location>/404.jsp</location> 位置 </error-page> JSP九大内置对象 内置对象可以直接使用 1 page , 当前对象(this) 2 config , servlet配置描述对象ServletConfig 3 application , 就是servlet上下文对象ServletContext 4 request ,请求对象HttpServletRequest 5 response , 响应对象HttpServletResponse 6 session ,会话HttpSession 7 out ,输出流JspWriter. 8 exception ,异常Throwable 9 pageContext , jsp页面上下文PageContext(jsp页面管理者) _jspService方法示例 public void _jspService(final javax.servlet.http.HttpServletRequest request, final javax.servlet.http.HttpServletResponse response) throws java.io.IOException, javax.servlet.ServletException { final javax.servlet.jsp.PageContext pageContext; javax.servlet.http.HttpSession session = null; final javax.servlet.ServletContext application; final javax.servlet.ServletConfig config; javax.servlet.jsp.JspWriter out = null; final java.lang.Object page = this; javax.servlet.jsp.JspWriter _jspx_out = null; javax.servlet.jsp.PageContext _jspx_page_context = null; 如果配置了是错误页面,则还有 java.lang.Throwable exception = org.apache.jasper.runtime,JspRuntimeLibrary.getThrowable(request); JSP四种作用域(属性操作) page ,当前页面(一个页面) 默认作用域 request ,一次请求,默认一个页面。但使用转发可以涉及页面 session,一次会话,多个请求。 application,一个web项目(应用) ,多次会话--一个web项目只有一个对象(ServletContext) JSP-out对象 类型JspWriter,但底层使用 out = response.getWriter(); 注意: <% out.print("aaa"); response.getWriter().print("bbb"); out.print("ccc"); %> 输出结果为 bbb aaa ccc(bbb不仅在aaa之前,而且在整个页面之前,<html>和文档声明之前) 原理: servlet和jsp有各自的缓存,而且jsp缓存会先刷新到servlet缓存,然后共同发送到浏览器. out.print为jsp缓存,而response.getWriter().print为servlet缓存.jsp缓存溢出才会被追加到servlet缓存. 可以在out.print("aaa");后手动刷新:out.flush();则会输出:aaa bbb ccc pageContext类 pageContext 是jsp 上下文对象(jsp页面管理者) api 1 提供其他8内置对象引用:getXxx() 2 管理jsp作用域 管理默认作用域 getAttribute(java.lang.String name) 获得page作用域指定名称的值 setAttribute(java.lang.String name, java.lang.Object value) 给page作用域设置值 removeAttribute(java.lang.String name) 移除所有作用域(page/request/session/application)指定名称的内容 管理指定作用域 getAttribute(java.lang.String name, int scope) 获得指定作用域值 removeAttribute(java.lang.String name, int scope) 移除指定作用域 setAttribute(java.lang.String name, java.lang.Object value, int scope) 给指定作用域设置内容 3 提供4常量 PAGE_SCOPE / REQUEST_SCOPE / SESSION_SCOPE / APPLIACTION_SCOPE 4 依次获得数据 findAttribute(java.lang.String name) 依次从page、request、session、application作用域获得数据 JavaBean POJO(Plain Old Java Objects)简单的Java对象 JavaBean 普通类,进行数据封装 必须提供setter方法和getter方法 setter方法进行数据添加(修改器),必须set开头,之后名称首字母大写 void setId(String id) getter方法进行数据获取(访问器),必须get开头,之后名称首字母大写 String getId() 提供无参构造(将使用反射创建对象) 属性(property)通过getter或setter方法获得 例如:getId -> Id --> id (去掉get或set前缀,首字母小写) JSP动作标签 JSP动作标签,通过<jsp:标签名称>使用 <jsp:include page="xxx">动态包含,生成两个java文件,只是把输出结果放到一块 <jsp:forward page="main.jsp" />请求转发 相关类 Servlet相关类 Servlet servlet父接口 GenericServlet servlet便捷父类,提供了一些便捷方法 HttpServlet http协议的servlet实现,提供doGet和doPost方法 ServletConfig 配置对象,可获得servlet初始化参数.(GenericServlet和HttpServlet都实现了此接口) RequestDispatcher 请求调度器,用于将资源发送到浏览器 ServletContext servlet上下文对象。Servlet管理者,可操作属性,管理资源,获得web项目初始化参数 ServletRequest 请求对象 HttpServletRequest http协议的请求描述对象 HttpServletRequestWrapper HttpServletRequest的装饰类,使开发者可以方便重写request的某个方法(而不是全部,通常要重写getParameter方法处理get请求的中文乱码) ServletResponse 响应对象 HttpServletResponse http协议的响应描述对象 HttpServletResponseWrapper HttpServletResponse的装饰类,使开发者可以方便重写response的某个方法(而不是全部,可以重写getWriter方法修改输出位置,实现页面静态化) HttpSession 会话对象,可在多个请求间进行数据共享 Cookie servlet 发送到 Web 浏览器保存的少量信息,可用来标识用户 JSP相关类 Servlet servlet父接口 GenericServlet servlet便捷父类,提供了一些便捷方法 HttpServlet http协议的servlet实现,提供doGet和doPost方法 HttpJspBase tomcat的HttpJspPage实现 JspPage JSP父接口 HttpJspPage http协议的JSP实现 HttpJspBase tomcat的HttpJspPage实现 JspContext JSP上下文对象 pageContext 提供了获得JSP九大内置对象的方法
Servlet-JSP
最新推荐文章于 2023-07-07 20:23:39 发布