Servlet学习
来源:互联网 发布:mysql join 默认值 编辑:程序博客网 时间:2024/06/05 16:05
知识点:
△Tomcat在启动时会读取一系列的配置文件和jar文件,顺序如下:
i. Tomcat自己的conf/server.xml
ii. Tomcat自己的conf/web.xml
iii. Tomcat自己的tomcat-users.xml
iv. D:\apache-tomcat-7.0.30\conf\Catalina\localhost目录下的 *.xml
v. 加载webapps目录下的所有项目中的web.xml
△WEB-INF目录为安全目录,里面的所有资源必须在web.xml中进行配置,否则外面无法访问。
△有关路径中起始“/”的含义:
1)如果在前端页面(JSP页面)中,是代表Tomcat的根目录
2)如果在web.xml或servlet中,是代表项目根目录
3)项目根目录 = Tomcat根目录 + 项目名
4)无论是前面页面还是web.xml,servlet中,如果路径以“/”开始是绝对路径,否则是相对路径
△在JavaEE领域,sun公司只做接口或抽象类(标准),由各服务器产商(如Tomcat)来做实现。
我们做项目如写servlet,我们实现sun公司的接口或抽象类,则所有服务器都能兼容。
△我们项目中所用到的类有以下3个地方可以放(加载)
1) 加载:Tomcat根目录/项目名/WEB-INF/classes目录下 —-放:项目中的src目录
2) 加载:Tomcat根目录/项目名/WEB-INF/lib目录下 —-放:项目中的WebRoot/WEB-INF/lib目录
3) 加载(放):Tomcat根目录/lib <—所有项目共用的(Tomcat的运行环境)
※1※注意,法1中以.class(.java)的形式存在。法2和法3是以.jar的形式存在
※2※如果以上几个地方存在相同的类,则优先级是: classes > 项目下/WEB-INF/lib > Tomcat/lib
△我们开发servlet一般有3种方法
1)实现Servlet接口—最底层的
2)继承GenericServlet
GenericServlet类中有一个空参init()方法,其实是适配器模式中的一个技术细节:在带参init方法中帮我们把config赋好值,然后调用空参且空实现init()方法–该方法是专门给子类覆盖的。—在适配器中帮我们做一部分事情,然后调用我们的覆盖方法
3)继承HttpServlet—-最常用的方式(而且一般采用向导来开发)
注意,该方式下一定要覆盖对应的请求处理方法(如doGet(req,resp)或doPost(req,resp)等),否则会出现405错误(不支持相应的服务请求)。
△运行环境:
JavaSE中的运行环境通常是MyEclipse中。
JavaEE的运行环境是Tomcat容器。
△JavaEE项目中,资源存放的两个地方通常有两种:
1) src下,访问方式:通过类反射到classpath下去获取
2) WebRoot下,访问方式:String dir = getServletContext().getRealPath(“/imgs”);//参数可目录也可文件名
File file = new File(dir);
项目开发中Servlet的细节和知识点:
△web.xml配置文件
1).为Servlet配置服务提供路径,将项目中的前端请求和后台服务想连接起来。
连接到后台服务类
<servlet> <servlet-name>ServletContext</servlet-name> <servlet-class>cn.hncu.servlets.ServletContextDenmo</servlet-class> </servlet>
连接前端服务请求
<servlet-mapping> <servlet-name>ServletContext</servlet-name> <url-pattern>/count</url-pattern> </servlet-mapping>
1).为Servlet服务提供参数,
<init-param> <param-name>Charset</param-name> <param-value>UTF-8</param-value> </init-param>
后台设置参数并运用,可以达到修改配置文件到达维护的目的
(该参数是单独为此服务设置,也可以为所有服务设置)
public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType("text/html;charset=utf-8"); PrintWriter out = response.getWriter(); out.println("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">"); out.println("<HTML>"); out.println(" <HEAD><TITLE>A Servlet</TITLE></HEAD>"); out.println(" <BODY>"); ServletConfig config = this.getServletConfig(); String charset = config.getInitParameter("Charset"); request.setCharacterEncoding(charset); out.println("charset1"+charset+","+"charset2"+this.getInitParameter("Charset")); out.println("</br>"); Enumeration<String> it =this.getInitParameterNames(); while(it.hasMoreElements()){ String name = it.nextElement(); String value = config.getInitParameter(name); out.println(value+"</br>"); System.out.println(value); } response.setCharacterEncoding(charset); out.println(" </BODY>"); out.println("</HTML>"); out.flush(); out.close(); }
配置所有服务均可以调用的参数
<!-- 配置ServletContext作用域的初始化参数,所有servlet共享的 --> <context-param> <param-name>charset</param-name> <param-value>UTF-8</param-value> </context-param>
获取方法
/用在Web.xml中配置ServletContext作用域的初始化参数,来写成活的 String charset = getServletContext().getInitParameter("charset"); request.setCharacterEncoding(charset); System.out.println(">>>"+charset); String str = getInitParameter("charset");//获取的是当前servlet专用的 System.out.println("str:"+str);
△servlet的三种开发方式
第一种:直接通过实现Servlet接口的方式(最底层的开发方式)
@Override public void init(ServletConfig config) throws ServletException { System.out.println("1初始化"); } @Override public ServletConfig getServletConfig() { System.out.println("2读取该servlet在web.xml中的配置参数..."); return null; } @Override public void service(ServletRequest req, ServletResponse resp) throws ServletException, IOException { System.out.println("3--进行服务响应...."); } @Override public String getServletInfo() { System.out.println("很少用,一般是返回该servlet的信息如作者和版本等"); return null; } @Override public void destroy() { System.out.println("4--消亡了...."); }
需要重写几中方法:
service是请求一次调用一次。其他的方法是整个服务器启动一次调用一次。包括初始化,消亡等等。
第二种:通过继承GenericServlet类
1.只需要完成实现service方法即可(想对于第一种简单化了)
2.若需要初始化覆盖 init()方法即可。覆盖 init(ServletConfig config),必须要保留 super.init(config);否则会空指针异常。原因简单来说少了一句
this.config = config.
第三种:通过继承HttpServlet类(主要针对网络的HTTP协议的服务)
格局前端提交方式覆盖父类相应方法
例如常见的dopost doget doput 等等
利用Servlet完成几个功能来,熟悉Servlet的以下几个类
ServletConfig – 代表Servlet的初始化配置参数。
从服务器打开到下次启动前一直是同有个对象
ServletContext – 代表整个Web项目。
留言板功能实现代码
public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType("text/html;charset=utf-8"); PrintWriter out = response.getWriter(); out.println("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">"); out.println("<HTML>"); out.println(" <HEAD><TITLE>A Servlet</TITLE></HEAD>"); out.println(" <BODY>"); //获取表单提交的留言 //request.setCharacterEncoding("utf-8");//写死的 //用在Web.xml中配置ServletContext作用域的初始化参数,来写成活的 String charset = getServletContext().getInitParameter("charset"); request.setCharacterEncoding(charset); System.out.println(">>>"+charset); String str = getInitParameter("charset");//获取的是当前servlet专用的 System.out.println("str:"+str); String msg = request.getParameter("msg"); //留言板必须获取提交用户的信息(IP,time)----法律意识 String ip = request.getRemoteAddr(); SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss"); String time = sdf.format( new Date() ); //把当前用户的留言(来自表单)和原来的留言信息合并 if(msg!=null && !msg.trim().equals("") ){//当前用户提交有效留言 //如果要做得好一些,要把msg中非法的字符(如<、'、"、/>等)转换或替换 msg = msg.replaceAll("<", "<"); String msgs = (String) getServletContext().getAttribute("msgs"); if(msgs==null){ msg = time+" "+ip+": " + msg; getServletContext().setAttribute("msgs", msg); }else{ msgs = msgs + "<br/>"+ time+" "+ip+": " + msg; getServletContext().setAttribute("msgs", msgs); } } //输出留言合并后的留言信息 String info = (String) getServletContext().getAttribute("msgs"); String div = "<div style='border:1px solid red;width:600px;" + "height:400px;overflow:auto;'>"+info+"</div>"; if(info!=null){ out.println(div); } out.println("<hr/>");//分隔线 //输出留言表单 String form = "<form action='chat'method='post'>" + "留言:<input type='text' name='msg'/>" + "<input type='submit' value='发送'/>" + "</form>"; out.println(form); out.println(" </BODY>"); out.println("</HTML>"); out.flush(); out.close(); }
网站点击量统计:主要是因为ServletContext是同一个,服务器不关每次请求都是同一个。
public void doPost(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException { response.setContentType("text/html;charset=utf-8"); PrintWriter out = response.getWriter(); out.println("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">"); out.println("<HTML>"); out.println(" <HEAD><TITLE>A Servlet</TITLE></HEAD>"); out.println(" <BODY>"); ServletContext ctx = getServletContext(); Integer count = (Integer) ctx.getAttribute("count"); if(count==null){ count=1; }else{ count++; } getServletContext().setAttribute("count", count); out.println("点击量:"+count); out.println(" </BODY>"); out.println("</HTML>"); out.flush(); out.close(); }
设置一个默认见面: XML配置访问路径为 “/” 当在网站内前端发来请求服务不是XML已经配置好的服务时,就会通过“/” 映射到改服务
public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType("text/html;charset=utf-8"); PrintWriter out = response.getWriter(); out.println("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">"); out.println("<HTML>"); out.println(" <HEAD><TITLE>A Servlet</TITLE></HEAD>"); out.println(" <BODY>"); out.println("<font size=30 color=red>杯具了,您找的页面不存在!</font>"); out.println(" </BODY>"); out.println("</HTML>"); out.flush(); out.close(); }
从服务器下载文件: 要设置响应头,告诉浏览器是下载。同时要不下载的文件对拷过来传给前端。
public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //基本套路:从服务器本地硬盘地址中把文件读取出来,发送到前端(通过response) //为便于大家掌握文件下载技术的核心思想,只考虑文件名是死的情况(其实可以从前端提交的参数中读取) //※设置响应头,告诉浏览器用它的默认下载程序来接收后台发送的数据(有的浏览器是弹出下载窗口,也有的浏览器是启动迅雷) response.setContentType("application/force-download"); //如果不设置上面一句响应头,则浏览器是自己直接打开即浏览 //String fn="b.jpg"; String fn="过一会儿下课.jpg"; fn=URLEncoder.encode(fn,"UTF-8");//如果进行编码,则可以兼容中英文(其实英文可以不用编码,但编码对它没影响) //※设置响应头,告诉浏览器这个下载的文件名是什么 response.setHeader("Content-Disposition", "attachment;filename=\""+fn+"\""); //真正的文件数据发送在下面一段 String filename="/imgs/3.jpg"; String path = getServletContext().getRealPath(filename); System.out.println(path); //流拷贝 InputStream in = new FileInputStream(new File(path) ); OutputStream out = response.getOutputStream(); byte buf[] = new byte[512]; int len=0; while((len=in.read(buf))!=-1){ out.write(buf, 0, len); } in.close(); out.close(); }
获取参数的几种方法
//读取servlet中的初始化参数 //////////////法1////////////////// ServletConfig config = getServletConfig(); String charset = config.getInitParameter("charset"); String age = config.getInitParameter("age"); out.println("法1,charset:" + charset+" ,age:"+age); out.println("<br/>"); //////////////法2////////////////// String charset2 = this.getInitParameter("charset"); String age2 = this.getInitParameter("age"); out.println("法2,charset:" + charset2+" ,age:"+age2); out.println("<br/>"); /////////////法3:写活的---遍历参数名和值//////////////// out.println("-------法3-------<br/>"); Enumeration<String> en = this.getInitParameterNames(); while(en.hasMoreElements()){ String name = en.nextElement(); String value = getInitParameter(name); out.println(name+","+value+"<br/>"); }
读取服务器中某个项目中的全部文件:这儿以图片为例
public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType("text/html;charset=utf-8"); PrintWriter out = response.getWriter(); out.println("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">"); out.println("<HTML>"); out.println(" <HEAD><TITLE>A Servlet</TITLE></HEAD>"); out.println(" <BODY>"); /*过渡版,写死的 for(int i=1;i<10;i++){ String img = "<img width='200px' height='200px' src='imgs/"+i+".jpg'/><br/>"; out.println(img); } */ //写活的,到本地服务器的图片目录中把所有图片名遍历出来,然后拼接成<img>标记输出 /* File dir = new File("."); //这个目录是:Tomcat/bin String names[] = dir.list(); for(String name:names){ System.out.println(name); } */ //※※一个技术: 如果访问WebRoot下的资源文件 /*知识点讲解 ServletContext ctx = getServletContext(); String path1 = ctx.getContextPath(); //项目名---通过代码自动获取---活的 System.out.println("path1:"+path1); // "/servletDemo3" String path2 = ctx.getRealPath("/imgs"); //服务器磁盘的绝对路径(带盘符),,File只能用这种 System.out.println("path2:"+path2); // D:\apache-tomcat-7.0.30\webapps\servletDemo3\imgs */ String path = getServletContext().getRealPath("/imgs");//获取项目WebRoot下的“imgs”文件夹的绝对路径--带盘符 File dir = new File(path); String filenames[] = dir.list(); for(String filename: filenames){ String img = "<img width='200px' height='200px' src='imgs/"+filename+"'/>"; out.println(img); } out.println(" </BODY>"); out.println("</HTML>"); out.flush(); out.close(); }
线程安全:
//因为servlet是单例,所有浏览器(多用户,多线程)是共享这一个servlet的,也共享这个对象中的所有成员变量
//上面是通俗但不严谨的说法。严格来讲是多个请求(request)共享这个单例servlet。
private String name;
//由本例出现的多请求串数据(this.name)得出,如果我们以后不希望多个请求出现串数据的情况,不能把数据声明成servle类的成员变量,而应该声明成局部变量//当然,如果我们数据正好想让它共用,那么就声明成类的成员变量
服务器上帝资源文件明和路径尽量避免使用中文名,因为请求资源时会对路径名字进行编码。会导致错误
- servlet学习
- Servlet学习
- Servlet学习
- Servlet学习
- Servlet学习
- servlet学习
- Servlet学习
- servlet 学习
- servlet学习
- Servlet学习
- 学习servlet
- Servlet学习
- servlet学习
- Servlet学习
- Servlet学习
- Servlet学习
- Servlet学习
- Servlet学习
- SpringBoot的启动过程
- 第三场个人训练赛
- 改变FragmentDialog弹出框大小
- 20170709_网络层的题目、子网划分、子网掩码、CIDR技术
- HIVE和HBASE区别
- Servlet学习
- Volley是如何把response deliver到Main Thread的?
- Tomcat配置及使用
- TensorFlow读取tfrecords数据
- 玩转消息队列之C/C++代码
- SPOJ QTREE
- JVM内存模型
- 段落、链接、图片标签的使用
- HDU 1058