博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
网站入门
阅读量:6789 次
发布时间:2019-06-26

本文共 35191 字,大约阅读时间需要 117 分钟。

第二章.创建web项目.file->new->web project.设置 java version 1.8设置 Target Tomcat8.0web项目下面src JAVA源码目录WebRoot 网站目录WEB-INF classes及lib目录.webroot下添加HTML.如何创建一个web项目,了解了web项目的一般结构.2.2部署web项目.1.创建web项目.在浏览器打开网页时, 汉字出现乱码?解决办法:手工修改html,在里 添加 
在tomcat目录下,
标签内最后添加
其中, docBase 指向 WebRoot目录的路径 ,path是网站的映射路径 注意是WebRoot的目录,不是项目目录第三章 Servletservlet 服务小程序.java web很重要的功能.在src下面的packge下面新建一个servlet每次记得修改tomcat的server.xml的docBaseServlet运行原理 get/servlet浏览器(客户端)--------------->Tomcat(服务器) <--------------- 200 OK 资源内容tomcat在接收到客户端请求后,会根据请求的资源路径URI,来分派给不同的Servlet来处理例如: /SimpleServlet ->my.SimpleServlet3.2 创建时间服务1.创建showtimeservlet服务.2.修改@WebServlet("/ShowTimeServlet")->@WebServlet("/showtime") //修改的就是uri的地址.3.doGet代码修改.response 是应答,request是请求.protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { SimpleDateFormat sdf =new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); String timestr =sdf.format(new Date()); //当前时间 response.getWriter().write("Now:" + timestr); //暂时不用中文避免乱码. }注意:1.uri区分大小写.servlet运行原理 get/servlet浏览器(客户端)--------------->Tomcat(服务器) <--------------- 200 OK 时间tomcat在接收到客户端请求后,会根据请求的资源路径URI,来分派给不同的Servlet来处理例如: /SimpleServlet ->my.SimpleServlet/showtime->my.ShowTimeServlet.doGet()可以修改返回数值和方法.3.3 生成HTML添加一个Servlet,用于生成HTML页面.-添加HtmlServlet-映射URI为 /test/1.html (称为映射路径)//映射路径 @WebServlet("/test/1.html") protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setCharacterEncoding("UTF-8"); //设置字符集编码 response.setContentType("text/html"); //设置内容格式 PrintWriter out =response.getWriter(); out.write(" 如何"); //返回客户端的数据 }servlet运行原理 get/test/1.html浏览器(客户端)--------------->Tomcat(服务器) <--------------- 200 OK 时间1.一个URI 可能是一个文件,也可能是一个Servlet2.客户端不能区分,也没必要区分3.如果既不是Servlet,又不是文件,返回404错误4.如果即是Servlet,又是文件呢.3.4 生成JavaScriptJscript@WebServlet("/sample.js")public class JscriptServlet extends HttpServlet{ protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setCharacterEncoding("UTF-8"); // 设置字符集编码 response.setContentType("text/plain"); // 设置内容格式 PrintWriter out = response.getWriter(); // 返回一行javaScript文本 out.write("var author='仁豪'; "); out.write("var name='yyf'; "); }}写一个.java文件创建html,导入juery.js,
RH.html
此外tomcat的配置
docBase写到WebRoot一级目录才行.4.1 POJO简单的java类.-属性:简单类型 int String boolean...-方法:Getter/SetterPOJO类可以重写toString()4.2 JSON javascript对象的文本化表示jar包放在WebRoot下面的WEB-INF 下面的lib里面,自动bulid pathJSON多用于数据传输{"id":20111111, //示例"name":"仁豪","phone":"1300099";}使用JSON-ORG 或者jsonlib来操作JSON其中,大括号表示一个JSON对象。在这个对象里,包含4个字段。例如,"id" 字段的值为 20180001,是数字类型 ( Number )"name" 字段的值为 "邵", 是字符串类型 ( String ) "sex" 字段的值为 true,是布尔类型 (Boolean)可以很直观的发现,如果值是一个String,则应该用双引号,如"邵发"如果值是一个Number,则不加双引号,如20180001如果值是一个Boolean,则应该是 true 或者是 false, 不加双引号加入JSON-java JSON-lib JSONObject jobj = new JSONObject(); jobj.put("id", 20180001); // Integer jobj.put("name", "邵发"); // String jobj.put("sex", true); // Boolean jobj.put("cellphone", "13810012345"); // String String jsonstr = jobj.toString(2); System.out.println(jsonstr);JSONObject里的字段显示顺序是无关的,谁先上、谁在下不影响最终结果。 // POJO -> JSONObject // 如果是POJO对象 ( 已经添加了 getter ),则可以直接转成JSONObject public static void test3() { Student stu = new Student("邵发", 1238909, true, "13810012345"); JSONObject j = new JSONObject(stu); String jsonstr = j.toString(2); // 缩进2 System.out.println(jsonstr); }JSON的语法格式用JSON可以表示Object信息,以一对大括号包围,里面可以多个字段。例如:{ "name": "邵发", "id": 1208439, "sex": true, "phone": "13810012345"}语法要点:- 以大括号包围- 字段名称要加双引号- 字段的值可以为String, Integer, Boolean, Array, null 等类型- 每个字段以逗号分隔 (最后一个字段末尾不能加逗号)- 字段的顺序无关注:JSONObject在概念上对应于Java里的Mappublic class TestJson{ public static void test1() { Student pojo =new Student(20180001,"仁豪",true,"13800000"); JSONObject jobj =new JSONObject(pojo); String js =jobj.toString(2); //縮放為2是 System.out.println(js); } public static void test2() { ArrayList
students = new ArrayList(); students.add(new Student(20180001,"仁豪",true,"13800000")); students.add(new Student(20180002,"x",true,"138000001")); students.add(new Student(20180003,"y",true,"138000002")); students.add(new Student(20180004,"z",true,"138000003")); JSONArray jarray =new JSONArray(students); System.out.println(jarray.toString(2)); } public static void main(String[] args) { test2(); }}直接添加一个main方法,单元测试.4.3使用jsonpublic class StudentQuery extends HttpServlet{ protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { ArrayList
students = new ArrayList(); students.add(new Student(20180001,"仁豪",true,"13800000")); students.add(new Student(20180002,"x",true,"138000001")); students.add(new Student(20180003,"y",true,"138000002")); students.add(new Student(20180004,"z",true,"138000003")); JSONArray jarray =new JSONArray(students); response.setCharacterEncoding("UTF-8"); response.setContentType("text/plain"); //設置內容格式 PrintWriter out = response.getWriter(); //返回javascript文本 out.write(jarray.toString(2)); }}4.4 web项目的调试java调试的一般方法.1.打印调试.2.单步调试两者结合使用.单步调试.以debug方式运行服务器点debug下面的debug configurations选择tomcat8.0下面的source(来源)add,javaproject勾选目标project文件夹,然后ok ,apply,close.然后在代码添加断点,在浏览器输入地址.myeclipse弹出提示是否切换debug页面.如果关闭,在Windows,show view里面找source not found ,第三方jar不用管.web项目的调试,被调试的主体其实是tomcat程序,tomcat程序会间接的调用我们的servlet代码.第五章 5.1 数据查询.查询和显示数据库中的数据.模拟:一个假的数据库.DemoDb:用于模拟一个数据库.实现一个查询功能,可以返回所有数据行.URL查询.@WebServlet("/QueryAll")public class QueryAll extends HttpServlet{ protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { List
rows = DemoDb.i.list(); // List -> JSONArray JSONArray result = new JSONArray(rows); // 返回应答数据 response.setCharacterEncoding("UTF-8"); response.setContentType("text/plain"); Writer writer = response.getWriter(); writer.write( result.toString(2)); writer.close(); }}5.2 URL参数按学号范围进行查询.比如,查询20180001-20180004.客户端需要把请求的参数发给服务器.请求可以附在URL末尾例如:http://127.0.0.1:8080/demo/QueryById?from=20180001&to=20180004URL参数的写法规则:1.以问号引导QueryById?xxxxx2.多个参数对中间用&分开示例:?key1=value1&key2=value2&key3=value33.中文参数比较复杂.使用request.getParameter("...")获取URL的参数.@WebServlet("/QueryById")public class QueryById extends HttpServlet{ protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //从request 里取得参数 String strFrom = request.getParameter("from"); String strTo = request.getParameter("to"); //参数处理 int from = Integer.valueOf(strFrom); int to = Integer.valueOf(strTo); //数据查询 List
rows = DemoDb.i.list(from, to); //List->JSONArray JSONArray result = new JSONArray(rows); //返回应答数据 response.setCharacterEncoding("UTF-8"); response.setContentType("text/plain"); Writer writer = response.getWriter(); writer.write(result.toString(2)); writer.close(); }}5.3 HTTP网络抓包演示请求/应答模式.

 

 

Wireshark 网络鲨鱼.可以抓取本机和其他机器的数据交互.HTTP协议:应答数据.HTTP/1.1 200状态码.200-OK,可以访问403-Forbidden 无权访问404-Not Found 资源不存在Content-Length:287表示正文部分的长度为287字节正文内容    头部按行定义,每行末行为\r\n    头部与正文之间有一个空行.5.4    Chrome浏览器抓包请求/应答 模式.-F12,开发者工具.-切换到network面板.headers表示请求 response应答.第六章6.1    AJAX后台提供的服务(接口),前台如何调用?http://127.0.0.1:8080/demo6/QueryAllhttp://127.0.0.1:8080/demo6/QueryById?from=1&to=10000000前端希望取得后台数据,并且显示在页面上.AJAX,一种在网页上调用后台接口的方式.后台接口:指后台代码实现的服务类似 /demo/QueryAll    /demo/QueryByIdjQuery里提供的AJAX调用方法.示例: $.ajax({...参数...})其中,-$.ajax()等同于jQuery.ajax()-参数里面是一个JS对象test.htmltest.html
$.ajax()参数是一个JS对象,其中的属性:type:'GET'url:接口地址,使用相对路径success:当服务器返回应答时,调用此function处理(回调方法)注意:url容易写错!不要加IP,也不要加前缀.6.2 处理返回的数据.显示返回的数据当AJAX完成时,回调方法被调用,前端页面应处理并显示服务器的返回的数据.演示:-可以在HBuilder里进行HTML页面编辑-最基本的JS字符串拼接处理. 6.3 参数查询.在用ajax()访问后台接口时,可以附加请求参数示例: $.ajax({ type:'GET', url:'QueryById', data:req, .... }1 添加用户输入控件
-
2 ajax() 里添加请求参数 function query() { // 请求参数 var req = {}; req.from = $('.toolbar .from').val().trim(); //.trim()去掉两边的空格. req.to = $('.toolbar .to').val().trim(); $.ajax({ type:'GET', /* 请求类型 GET / POST */ url:'QueryById', /* 服务URI, 用相对地址 */ data: req, /* 附加请求参数 */ dataType: 'json', /* 期望服务器返回的数据类型 */ success: function(resp){ /* 已经将服务器返回的数据转成 JS对象 */ //console.log(resp); showResult(resp); } }); }注: ajax()会自动的把 data 里的数据构造成 ?from=xxx&to=yyy 的形式附加在 URL后面6.4 中文URL编码示例:添加一个QueryByName服务,实现按学生的姓名查询.此时,需要把一个中文参数传递到后台.//后台的姓名查询servlet@WebServlet("/QueryByName")public class QueryByName extends HttpServlet{ protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //从request里取得参数 String filter = request.getParameter("filter"); //数据查询 List
rows = DemoDb.i.list(filter); //List->JSONArray JSONArray result = new JSONArray(rows); response.setCharacterEncoding("UTF-8"); response.setContentType("text/plain"); Writer writer= response.getWriter(); writer.write( result.toString(2)); writer.close(); }}//前端script function query() { // 请求参数 var req = {}; req.filter = $('.toolbar .filter').val().trim(); //.trim()去掉两边的空格. $.ajax({ type:'GET', /* 请求类型 GET / POST */ url:'QueryByName', /* 服务URI, 用相对地址 */ data: req, /* 附加请求参数 */ dataType: 'json', /* 期望服务器返回的数据类型 */ success: function(resp){ /* 已经将服务器返回的数据转成 JS对象 */ //console.log(resp); showResult(resp); } }); }中文不能直接放在URL里,例如:http://xx.x.x/QueryById?filter=张这样是不支持的,必须把中文字符转成百分号形式的编码.在Chrome里观测Http交互数据.URL编码:'张'->'%E5%BC%A0'URL解码:'%E5%BC%A0'->'张'注:以上均为UTF-8编码.public class UTF{ // '张'->'%E5%BC%A0' public static void testEncode() throws Exception { String str = "张"; String query = URLEncoder.encode(str, "UTF-8"); System.out.println("编码后:" + query); } // '%E5%BC%A0'->'张' public static void testDecode() throws Exception { String str = "%E5%BC%A0"; String query = URLDecoder.decode(str, "UTF-8"); System.out.println("编码后:" + query); } public static void main(String[] args) throws Exception { testEncode(); testDecode(); }}小结:-需要明白URL里的百分号形式编码-在框架未能正确处理URL编码的时候,应该会自己实现中文的URL编码/解码6.5 异步调用ajax()默认是异步方式:-不等待服务器返回结果,立刻返回.-当服务器返回结果时,调用回调方法进行处理.可以想象,与服务器的交互实在另外一个线程里处理的.6.6 浏览器抓包调试前端问题,还是后台问题,如何界定第一步:浏览器抓包确定问题是前台还是后台第二步:单步调试如果前端问题,在前端单步调试JavaScript如果后台问题,在后台单步调试Java代码.第七章 7.1表单表单,是一种最原始的前后台数据交互方式.
...
例:
//添加一个AddSutdent.java的Servlet. 学号:
姓名:
手机:
后台servlet,注意这里使用的是servlet的doPost方法.@WebServlet("/AddStudent")public class AddStudent extends HttpServlet{ protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // 因为请求字段里的中文数据,所以要显式设置一下字符编码 request.setCharacterEncoding("UTF-8"); // 从请求里提取参数字段的值 int id = Integer.valueOf(request.getParameter("id")); String name = request.getParameter("name"); String phone = request.getParameter("phone"); boolean sex = "male".equals(request.getParameter("sex")); // 添加到数据库 Student s = new Student(id, name, sex, phone); DemoDb.i.add( s ); // 返回应答数据 JSONObject jresp = new JSONObject(); jresp.put("error", 0); // 错误码,0表示成功 jresp.put("reason", "OK"); // 错误原因描述, 如果没有错误则提示OK response.setCharacterEncoding("UTF-8"); response.setContentType("text/plain"); Writer writer = response.getWriter(); writer.write( jresp.toString(2)); writer.close(); }}添加一个servlet处理表单请求:对应关系:AddSutdent->对应action='AddStudent'doPost()->对应method='POST'request.getParameter("xxx")->对应name='xxx'介绍了表单方式来提交数据.此种方法,以后基本不会用到.7.2 表单抓包POST方式的特点:1.第一行为POST2.数据时放在HTTP正文部分的提交数据3.正文仍要用URL编码7.3 AJAX POST使用ajax()也可以发送POST请求演示:$.ajax({ type:'post', //请求类型GET/POST url:'AddStudent',//服务URI,相对地址 data:req, //附加请求参数 ...});示例:
学号:
姓名:
手机:
性别:
以后,将以$.ajax()来发送post第八章 RESTful8.1 RESTfulRESTful,一种通用的前台后台交互方式(注:此术语本身没哟严格的定义)RESTful一般是指这种方式:1.使用HTTP POST(或者GET)进行数据交互2.请求数据和应答数据均为JSON格式(或XML)客户端 请求数据:JSON给服务器服务器 应答数据:JSON给客户端请求和应答都是JSON格式,其交互数据为JSON格式,则称为RESTful.8.2 RESTful的接口实现前端:在发送请求时,把请求转成JSON字符串var jsonstr = JSON.stringify(req);$.ajax({ type:'POST', url:'AddStudent', data:jsonstr, //JSON字符串});RESTful后台实现后台:手工读取请求数据,转成JSONObject,然后再做处理String reqText = readAsText(request.getInputStream(),"UTF-8");JSONObject jreq = new JSONObject(reqText);实现AddStudent@WebServlet("/AddStudent")public class AddStudent extends HttpServlet{ protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // 读取请求数据, 转成字符串 String reqText = readAsText(request.getInputStream(), "UTF-8"); // 转成 JSON JSONObject jreq = new JSONObject(reqText); // 处理请求数据 int id = jreq.getInt("id"); String name = jreq.getString("name"); String phone = jreq.getString("phone"); boolean sex = "male".equals( jreq.getString("sex")); Student s = new Student(id, name, sex, phone); DemoDb.i.add( s ); // 返回应答数据 JSONObject jresp = new JSONObject(); jresp.put("error", 0); // 错误码,0表示成功 jresp.put("reason", "OK"); // 错误原因描述, 如果没有错误则提示OK response.setCharacterEncoding("UTF-8"); response.setContentType("text/plain"); Writer writer = response.getWriter(); writer.write( jresp.toString(2)); writer.close(); } // 流操作在后面的《网络编程篇》里讲解,属于高级课程,暂不要求大家掌握 // 大家只需要知道 这个方法实现的功能就行:功能就是从streamIn里读取数据转成字符串 public String readAsText(InputStream streamIn, String charset) throws IOException { ByteArrayOutputStream cache = new ByteArrayOutputStream(1024*16); byte[] data = new byte[1024]; while (true) { int n = streamIn.read(data); // n: 实际读取的字节数 if(n < 0) break; // 连接已经断开 if(n == 0) continue;// 数据未完 // TODO: 要防止超时 // 缓存起来 cache.write(data, 0, n); if(cache.size() > 1024*512) // 上限, 最多读取512K break; } return cache.toString(charset); }}前端使用ajax(),后台使用servlet.8.3 RESTful附加URL参数的处理一般来说,使用RESTful接口时,所有的请求参数直接放在请求数据JSON中即可但有的时候,还有少许参数是放在URL里的.前端处理在AJAX请求里,需要把参数字符串附加在URL末尾$.ajax({ type:'POST', url:'AddStudent?mode=admin&token=12930289', data:jsonstr, //json字符串 .....});后台处理在Servlet里,需取出查询字符串,自己解析String query = request.getQueryString();HashMap queryParams = parseQuery(query); // 读取请求数据, 转成字符串 String reqText = readAsText(request.getInputStream(), "UTF-8"); // 转成 JSON JSONObject jreq = new JSONObject(reqText); //URL末尾,由问号引导的字符串(在RESTful中也可能有部分参数在URL里) //例如 mode=admin&token=12930289 String query=request.getQueryString(); HashMap
queryParms= parseQuery(query); public HashMap
parseQuery(String query) { HashMap
params = new HashMap
(); String[] ppp = query.split("&"); // 用&分隔 for(String p : ppp) { String[] kv = p.split("="); // key=value String key = kv[0]; String value = ""; if(key.length() > 1) value = kv[1]; // 有时候参数里传的是空值 params.put(key, value); // TODO: value 视情况进行 URLDecoder } return params; }8.4 通用RESTful服务框架.AfRestfulService:实现RESTful服务接口的支持的通用基础类.使用方法.1.新建一个子类,继承于AfRestfulService2.重写execute()方法3.添加映射路径@WebService("/path_of_your_service")添加一个class AddBookService extends AfRestfulService由于继承于一个抽象类,需要添加add unimplemented methods重写execute()方法,由于是创建的class类,需要手动添加映射路径@WebServlet("/AddBook")@WebServlet("/AddBook")public class AddBookService extends AfRestfulService{ @Override protected Object execute(HttpServletRequest httpReq, HttpServletResponse httpResp, JSONObject jreq, HashMap
queryParams) throws Exception { String title = jreq.getString("title"); String author = jreq.getString("author"); String isbn = jreq.getString("isbn"); String press = jreq.getString("press"); // 后台处理部分 .. 省略 ... System.out.println("书名:" + title + ",作者: " + author + ", ISBN: " + isbn + ",出版社:" + press); return null; // JSONArray, JSONObject , }}介绍了AfRestfulService的使用,可以用于快速实现一个RESTful服务接口所有网站相关的基础API封装在af.web.*里9.1 学生管理-新增与列表1.1 后台添加 StudentListService,映射路径 /StudentListDemoDb里添加 save() 与 load() 方法数据实际存储位置 c:\webdata\ 目录,使用JSON格式存储1.2 前台新建list.html包含 js/jquery.min.js 和 js / afquery.js 使用 Af.rest () 来调用 RESTful 接口 (Af.rest() 在 afquery.js 里定义)使用 AfTemplate来处理数据 ( AfTemplate在 afquery.js里定义)( AfTemplate 的使用说明在本文档的第三部分)二、增加记录2.1 后台新建 StudentAddService ,映射到 /StudentAdd保存数据到 DemoDb2.2 前台新建 add.html调用 Af.rest() 与后台交互三、AfTemplate 使用说明为了方便格式化HTML,所以提供一个AfTemplate 工具,在afquery.js 里定义。示例, var html = "
"; var tp = new AfTemplate(html); var data = { id: 1234, title: '阿发你好', }; var output = tp.replace(data); console.log(output);则输出为:
其中,html为模板,data为数据 AfTemplate负责把模板中的变量{#VVV} 替代成数据的值( html + data => output)9.2 学生管理-删除一、 删除记录1 后台修改 DemoDb : 增加 remove(id) 方法,用于删除一个学生的记录新增 StudentRemoveService : 映射到 /StudentRemove2 前台修改 list.html :(1) 表格增加一列
(2) 点删除按钮时,删除本行function doRemove ( e ){}代码:添加一个新的 webservlet.@WebServlet("/StudentRemove")public class StudentRemoveService extends AfRestfulService{ @Override protected Object execute(HttpServletRequest httpReq, HttpServletResponse httpResp, JSONObject jreq, HashMap
queryParams) throws Exception { int id = jreq.getInt("id"); if( DemoDb.i.remove(id)) { DemoDb.i.save(); // 数据有变化时,调用 save()同步到文件 } return null; }}在list页面添加删除按钮的方法. //e:DOM元素对象,即被点击的按钮 function doRemove(e) { var req={}; req.id=$(e).attr("data"); //取得'data'属性 Af.rest("StudentRemove", req, function(data) { //删除该行 $(e).parent().parent().remove(); alert("删除成功"); }) }// DemoDB里实现按学号删除 public boolean remove(int id) { Iterator
iter = data.iterator(); while(iter.hasNext()) { Student s = iter.next(); if(s.getId() == id) { iter.remove(); return true; } } return false; }9.3 查询功能.写一个webservlet@WebServlet("/StudentQuery")public class StudentQueryService extends AfRestfulService{ @Override protected Object execute(HttpServletRequest httpReq, HttpServletResponse httpResp, JSONObject jreq, HashMap
queryParams) throws Exception { String name =jreq.getString("filter"); List
rows = DemoDb.i.list(name); JSONArray result =new JSONArray(rows); return result; }}写一个query方法 function query() { // 请求参数 var req = {}; req.filter =$('.toolbar .filter').val().trim(); Af.rest("StudentQuery", req, function(data){ // 后台传回来的 error , reason 在 afquery.js 里已经解出 // 这里只需要处理 data showResult(data); }); }查询方法 // 按名字查询 public List
list(String name) { List
result = new ArrayList
(); for(Student s: data) { if(s.name.indexOf( name ) >=0 ) { result.add( s ); } } return result; }10.1 XML方式配置Servlet的配置方式有两种:-注解方式@WebServlet("/Example")-XML方式(web.xml)新建一个webproject,选择jdk1.8+tomcat8.0然后next,next勾选Generate web.xml deployment descriptor在webroot下面的web-inf下面有一个web.xmlweb.xml有source和design两种模式,source是源码模式
Example1
my.Example1
Example1
/Example1
加载过程XML方式:-tomcat启动后-加载WEB-INF\web.xml里的Servlet注解方式:-tomcat启动-扫描WEB-INF\classes下的Servletxml方式:可读性高注解方式:操作简单web.xml是一个必须掌握的配置文件
:指定默认页即http://127.0.0.1:8080/demol/ URL里不指下文件名时默认加载的文件web.xml时应该保持存在的,因为以后还需要添加其他配置10.2 Serlvet实例现在有一个Servlet:"/Example1"->my.Example1考虑:当用户多次访问该服务时,后台创建了几个Example1对象?验证在my.Example1的构造方法里添加打印构造观察:-当tomcat启动时,会立刻创建Example1对象?-当用户访问该服务时.-当用户再次访问该服务时.Servlet实例Tomcat启动时,会创建一个全局的列表servletConfigList{ "/Example1","my.Example1",servlet(null) "/Example2","my.Example2",servlet(null) ...}默认在启动时,不会立即创建Servlet实例当Tomcat接收到访问时:1.检查URI2.找到servletConfigList,创建实例 servlet = new my.Example1()3.处理请求 servlet.doGet()/doPost()当客户端再次访问该URL时,会怎么处理.随应用启动一个WEB项目称为Web Application可以配置Servlet在应用启动时实例化
Example1
my.Example1
1
//添加load-on-startup
Example1
/Example1
或者@WebServlet(name="Example2",urlPatterns="/Example2",loadOnStartup=1)规则:1.
表示,当该应用被启动时,自动创建Servlet实例,其数字表示启动顺序.2.当存在多个自启动Servlet时,数字越小越优先启动.3.如果没有
配置,则默认不会创建实例,直到第一次被访问时才创建实例.-默认情况下,第一次访问才创建-该实例不会销毁,直到应用关闭-可以配置成一启动就创建.另外知道了怎么检查一个类是单例还是多例10.3 Servlet生命周期Lifecycle指一个对象何时被创建,何时被销毁生命周期的回调init():在创建对象后,调用此方法进行初始化-----------doGet():当用户以GET方式访问此服务时调用doPost():当用户以POST方式访问此服务时调用-----------destroy():应用退出前,调用此方法做善后处理 10.4 Tomcat请求处理流程并发访问:指多路客户端同时访问同一台服务器Tomcat服务器支持多路并发访问多个用户可以同时访问一个Tomcat服务器当接收到一个请求时,会创建一个线程来处理该请求new Thread(){ //以下为伪代码 run(){ if(匹配servlet路径)servlet.doGet/doPost() else if(匹配本地文件)读取文件内容发送给客户端 else "404 Not Found" }}注意单凭一个路径,不能判定是Servlet还是文件例如:/images/1230.jpg 看上去是一个文件,但也可能是一个服务/SimpleQuery 它看上去是一个服务,但也可能是只是一个文件小结提到了多线程处理的概念,每一个请求都在各自的线程里处理的.第十一章11.1 线程重入指多个线程同时运行同一对象的同一方法.对于Servlet来说,要求doPost()/doGet()可重入.比如:/Example1=>my.Example1当多个客户端同时访问/Example1时-找到匹配的Servlet对象s-创建多个线程-每个线程里都调用s.doPost()方法显示,此时要求doPost()方法可以重入不可重入最简单的原则简单原则:在Servlet的所有方法里,均不使用类的属性很简单,如果不使用属性,就不会产生重入的问题.不把数据存到属性里,直接传递调用.11.2 单例多例转换单例转多例,时一种更简单的办法,可以保证doPost()是可以重入的.@WebServlet("/Example2")public class Example2 extends HttpServlet{ protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { new ServiceHandler(request,response).handle(); }}public class ServiceHandler{ HttpServletRequest request; HttpServletResponse response; public ServiceHandler(HttpServletRequest request,HttpServletResponse response) { this.request =request; this.response=response; } public void handle()throws ServletException, IOException { }}Example2:单例,仅一个实例ServiceHandler:多例,每个线程创建一个实例单例转多例的设计方法,把所有的处理放在多例ServiceHandler里,就可以即好,又简单的避免"不可重入"问题在ServiceHandler类里,可以随意使用自己的属性,不会产生问题.12.1 本地文件web项目里,文件的路径可以指定绝对路径,也可以指定相对路径绝对路径:例如 C:/webdata/student.json相对路径. 示例:实现一个功能,在页面输入标题和内容后将数据保存到文件.-保存到data\目录下-每次根据标题创建一个文件创建Sava.html,前端页面,实现sava function
创建一个Servlet SaveContent实现存储@WebServlet("/SaveContent")public class ServletSaveContent extends AfRestfulService{ @Override protected Object execute(HttpServletRequest httpReq, HttpServletResponse httpResp, JSONObject jreq, HashMap
queryParams) throws Exception { //取得参数 String title =jreq.getString("title"); String content=jreq.getString("content"); //获取项目实际路径 String webrootPath =httpReq.getServletContext().getRealPath("/"); File webroot = new File(webrootPath); //存储到$(webroot)/data/xxx.txt File dataDir=new File(webroot,"data/"); dataDir.mkdirs(); File f=new File(dataDir,title+".txt"); AfTextFile.write(f, content, "UTF-8"); return null; }}可以在代码获取当前项目的部署路径 使用httpReq.getServletContext().getRealPath("/"); //path路径注:web项目没有"当前目录"的概念.12.2 资源文件在Java项目里,资源文件是指存放在Classpath里的文件非源码文件就称为资源文件resource(资源)演示:在src下的xml文件,会被MyEclipse自动拷贝到classes目录下(注:也可以使用jpg txt等文件类型试验)资源文件路径:和类路径类似例如:/config.xml /my/example/logo.png在项目里添加一个配置文件/course.xml 配置有课程的信息.InputStream stream = getClass().getResourceAsStream("/course.xml")SAXReader reader =new SAXReader();Document doc =reader.read(stream);stream.close();可以在程序里访问资源文件InputStream stream = getClass().getResourceAsStream("/course.xml")-资源文件是只读的-资源文件路径和类路径写法相同-程序实际访问不是src下的文件,而是classes下的文件.第十三章 通用服务框架13.1通用的Web服务框架,使用这个框架可以很快捷的添加web服务.添加AfGenericService,并在web.xml里添加配置注意:(1)URI匹配规则:*.api表示所有后缀为*.api的请求都由这个Servlet处理(2)
表示当应用被加载时就创建Servlet实例
AfGenericService
af.web.service.AfGenericService
1
AfGenericService
*.api
http://127.0.0.1:8080/demo/de1.api任意以.api结尾的都由AfGenericService处理.public class AfGenericService extends HttpServlet{ protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doPost(request, response); } protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // 处理请求数据 try{ handleRequest(request, response); } catch(Exception e) { e.printStackTrace(); response.sendError(500, e.getMessage()); return; } } private void handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception { // 从URL中解析API的名字 // servletPath: "/.../hello.api" String servletPath = request.getServletPath(); int p1 = servletPath.lastIndexOf('/'); int p2 = servletPath.lastIndexOf('.'); String apiName = servletPath.substring(p1 + 1, p2); //substring(a,b)从a开始取直到b之前 System.out.println("服务名:" + apiName); // 发送应答给客户端 response.setCharacterEncoding("UTF-8"); response.setContentType("text/plain"); //response.setHeader("Connection", "close"); Writer writer = response.getWriter(); writer.write( "OK,收到您的请求 :" + apiName ); writer.close(); }}13.2 通用服务框架2单例转多例的设计方法,根据不同的服务名,创建不同得到对象来处理.对应关系:Hello.api->my.HelloApiHowOld.api->my.HowOldApiAreYouGood.api->my.AreYourGood.api // 根据服务名, 创建不同的实例进行处理 ( 单例 -> 多例 ) AfGenericApi instance = null; if("Hello".equals(apiName)) instance = new HelloApi(); else if("HowOld".equals(apiName)) instance = new HowOldApi(); else if("AreYouGood".equals(apiName)) instance = new AreYouGoodApi(); else if("Time".equals(apiName)) instance = new WhatTimeNowApi(); else throw new Exception("不支持这个服务: " + apiName); // 读取请求数据 和 URL里的参数 String charset = "UTF-8"; String strReq = AfServiceUtils.readAsText(request.getInputStream(), charset, MAX_REQUEST_SIZE); String query = request.getQueryString(); HashMap
queryParams = AfServiceUtils.parseQuery(query, charset); // 读取请求数据, 转成字符串, 转成 JSON instance.httpReq = request; instance.httpResp = response; instance.queryParams = queryParams; instance.charset = charset; String strResp = instance.execute(strReq); // 具体的请求处理在execute()里api继承于抽象类AfGenericApi在各个api中重写execute().13.3 通用服务框架3使用反射技术改造框架 创建xml,new file,选择目录src下面创建af-service.xml 右键properties other UTF-8用af-service.xml来描述对应关系:Hello.api->my.HelloApiHowOld.api->my.HowOldApiAreYouGood.api->my.AreYourGood.apiaf-service.xml
然后在AfGenericService中重写init()方法. //init():在创建对象后,调用此方法进行初始化 @Override public void init() throws ServletException { //从xml配置文件中读取配置 try { loadConfig(); }catch(Exception e) { e.printStackTrace(); throw new Error("af-service.xml 格式不正确!启动终止启动!"); } }再添加一个loadConfig()方法来实现读取 // 从 af-service.xml 中获取配置 private void loadConfig() throws Exception { InputStream stream = this.getClass().getResourceAsStream( "/af-service.xml"); SAXReader reader = new SAXReader(); Document doc = reader.read(stream); stream.close(); Element root = doc.getRootElement(); List
xServiceList = root.elements("service"); for (Element e : xServiceList) { String name = e.attributeValue("name"); String clazzName = e.attributeValue("class"); configs.put(name, new ConfigItem(name, clazzName)); } protected HashMap
configs = new HashMap
();af-config.xml中的配置项 // af-service.xml 中的配置项 class ConfigItem { public String name; // 服务接口名 public String clazzName; // 类名 public Class clazz; // 类的实体 public String charset = "UTF-8"; public ConfigItem(String name, String clazzName) { this.name = name; this.clazzName = clazzName; } }框架代码和业务代码分离在af.web.service.*里不再包含my.*里的类13.4 通用服务框架4 //AfRestfulApi代码未看.基本通用服务框架,来实现RESTful接口:RESTful的特点:请求JSON,应用JSON所以,建立一个AfRestfulApi作为基类统一处理添加RESTful接口步骤:1.创建一个类,继承于AfRestfulApi2.在af-service.xml里添加描述13.5 通用服务框架的使用如何在一个新的web项目下使用af-web-1.0.jar13.6使用afservice框架改造9.4学生管理系统afweb.jar里不仅包含afservice,还将包含其他框架.14.1 创建JSPJSP, Java Server PageJava服务端页面,一种前端和后端混合的开发方式.历史上曾经流行的JSP,PHP,ASP三大服务端页面之一.新建JSP页面在WebRoot目录下,右键,新建一个JSP页面观察JSP的内容形式:-整体上还是HTML-部分以<% %>引起来的内容,时特殊代码.<%@page import="java.text.SimpleDateFormat"%><%@ page language="java" import="java.util.*" pageEncoding="ISO-8859-1"%><%String path = request.getContextPath();String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";%>
My JSP 'showtime.jsp' starting page
<% SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); String timestr =sdf.format(System.currentTimeMillis()); out.write(timestr); //PrintWriter %> This is my JSP page.
JSP是一种在HTML中嵌入JAVA代码的页面<% %>中间的是特殊代码14.2 JSP运行原理1.tomcat会把每一个JSP文件自动转换为Java类(观察tomcat\work\目录下的生成物)2.客户端请求*.jsp时,由*.class进行处理所以,JSP本质上就是ServletJSP所有的规则,都是为了方便转换为JAVA代码例如:<%@ %>用于设置页面的参数<% %>直接代码<%= %>变量引用上下文对象:request ,response, outJSP的缺陷开发效率问题:前端代码和后端代码混杂,不利于开发管理运行效率问题:生成Java代码运行效率低.JSP技术只能是一种历史.14.3 JSP代码分离<%@ %>用于设置页面的参数(放在页面顶部)<%@ page language="java" import="java.util.*" pageEncoding="ISO-8859-1"%>language语言,import导入的包,pageEncoding字符集格式,如果需要使用中文应该使用"UTF-8"<% %>直接代码(应杜绝使用)<%= %>变量引用上下文对象:request ,response, out
包含另一个页面如果一定要使用JSP,那么java代码尽量不要写在JSP里面,减少HTML和java代码的混杂1.新建一个Java类my.jsp.JspSupport //Support支持public class JspSupport { HttpServletRequest request; public JspSupport(HttpServletRequest request) { this.request = request; } public JSONArray getList() { List
rows = DemoDb.i.list(); return new JSONArray(rows); }}把相关的处理放在Java类里。例如,添加一个 getList() 方法,返回所有学生的数据。2 在JSP里引用先在顶上指定字符集,并导入 my.jsp.*<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%><%@ page import="my.jsp.*"%>然后var data = <%= new JspSupport(request).getList() %>;这样,就在最大程度上对 HTML 与 Java代码进行了分离。介绍了JSP代码分离的实现方法把业务代码放在Java类里,添加方法:-输入参数request,response-返回值JSONObject/JSONArray这样就可以最大程度上分离了HTML和Java代码.第15章15.1 JavaWeb和JDBCJavaWeb:用于Java实现的网站后台JDBC:用Java实现的与数据库交互一般情况下,网站的数据要存储在数据库里在JavaWeb里使用JDBC技术,是自然而然的事情.一般网站的构架客户端浏览器1------->互客户端浏览器2------->联------>Web服务器(Tomcat)<---->数据库(MySQL)客户端浏览器3------->网15.2 数据库支持(afsql)一,数据库的设计导入数据库 af_school.sql二,在Web项目中添加数据库支持1.在WEB-INF\lib目录下添加jar包2.在src目录下添加c3p0-config.xml并修改里面的数据库配置:数据库IP,数据库名,用户名,密码等3.新建packge,添加C3P0Factory4.生成POJO类打开POJO生成器,生成POJO类,把生成的Java拷贝到项目里.15.3 数据库测试写一个TestDb.javapackage my.dbutil;import java.util.List;import my.db.*;public class TestDb{ public static void listStudent()throws Exception { String sql="select * from student"; List
rows =C3P0Factory.executeQuery(sql, Student.class); System.out.println("获取到:" + rows.size()); } public static void addStudnet()throws Exception { Student s =new Student(); s.setId(20180100); s.setName("xxxx"); s.setSex(false); s.setPhone("13996000000"); C3P0Factory.insert(s); } public static void main(String[] args) { try { addStudent(); listStudent(); }catch(Exception e) { e.printStackTrace(); } }}获取到:1215.4 RESTful框架支持-WEB-INF\lib-web.xml-af-service.xml-添加API...15.5 网站的一般架构一般网站的构架客户端浏览器1------->互客户端浏览器2------->联------>Web服务器(Tomcat)<---->数据库(MySQL)客户端浏览器3------->网 公网服务器客户端:浏览器,app等.客户端为什么不直接访问数据库服务器16.1 文件的上传文件上传:即通过网页的方式,打开文件对话框,选择文件并上传到服务器比如:发生email时选择附件,修改用户头像等..前端:使用
后端:使用Servlet接收文件数据(借助apache commons工具类解析请求数据)一,前端//encode type
注意:
标签要添加一个属性 enctype
定义提交按钮。提交按钮用于向服务器发送表单数据。数据会发送到表单的 action 属性中指定的页面。
用于文件上传。
文件选择按钮,用于打开文件对话框当点submit按钮时,浏览器会自行将文件传给后台二,后端1.添加commons库的支持commons-fileupload-1.3.1.jarcommons-io-2.4.jar都是apache.org提供的基础开发包,免费开源.2.添加FileUploadService小结:1.浏览器会把文件的数据传递到后台.数据的格式是HTTP POST multi-part2.后台创建Servlet,处理POST请求使用apache commons fileupload 的API来解析请求数据,存储到本地文件里16.2 JS文件上传使用JavaScript可以实现文件上传(不再使用标签)优点:-可以显示上传进度,可以取消上传-界面更加灵活,美观.后台代码不变,添加upload2.html.
styple='display:none' 隐藏onchange='fileSelcted()'表示点击时触发小结:学习了使用JS控制文件上传的原理在这个原理的基础上,可以灵活的实现多种形式的上传.比如,多个文件同时上传...

 

16.3    JS文件上传工具JS文件上传工具类:AfFileUploader(在afquery.js里提供)-文件上传-进度及事件-支持取消操作uploader.cancelUpload()-支持上传条判断(如文件大小判断)1 包含 jquery 和 afquery        2 添加一个     3 创建 AfFileUploader        var uploader = new AfFileUploader();        uploader.setButton('.filebutton');  // 设置file input控件        uploader.setUploadUrl('FileUploadService'); // 设置服务URL        uploader.setLogEnabled( false );        uploader.setObserver(observer); // 设置监听器4 创建 AfFileUploader 的监听器         var observer = {};                // 上传事件处理 'start' 'progress' 'complete' 'error' 'abort'        observer.uploadHandleEvent = function( msg , uploader)         {            if(msg == 'progress')            {                Af.log("进度: " + uploader.progress);            }            else if(msg == 'complete')            {                Af.log("完成上传");            }        }                // 上传前的检查        observer.uploadTestFile = function ( uploader)         {            if(uploader.file.size > 1000000)            {                alert("文件太大!");                return false;            }            return true;        }5 打开文件选择框        function selectFile()        {            uploader.openFileDialog();        }16.4    上传路径在本例中,上传路径放在WebRoot/upload/下放在这有什么好处文件的绝对URL绝对URL:/demo1601/upload/123.jpg其中,/demo1601称为ContextPath,是部署应用的时候配置的值.提供一个简便的处理办法,直接把上传的文件放在WebRoot目录下,以便直接访问.也可以存在WebRoot目录之外.17.1    通用文件上传框架通用文件上传框架(单例转多例)AfFileUploadServiceAfFileUploadHandler映射路径*.upload,根据不同的服务名交给不能的Handler来处理.下载项目源码,对照文字教程.注:- 调试网页时注意浏览器强制刷新 CTRL + F5 - 请拷贝示例项目下的 afquery.js 到你的项目 ( 不同章节的afquery.js 可能略有差异 ,以本章节的为准 )1 web.xml配置 web.xml,映射路径 *.upload    
AfFileUploadService
af.web.fileupload.AfFileUploadService
1
AfFileUploadService
*.upload
2 af-service.xml里面可以添加多个文件上传处理器
3 AfFileUploadService根据不同的名字,创建不同的处理器进行处理(1) 解出服务器(2) 从服务器找到相应的处理类(3) new出对象(4) 处理处理过程:- 上传开始前,调用 tmpFile = handler.uploadStarted() , 由Handler 决定临时文件的位置- 上传过程中,调用 handler.uploadProgress( fileSize) ,由 Handler决定最大文件大小- 上完完成后,调用 handler.uploadComplete() ,由 Handler 决定给客户端的返回数据

 

转载于:https://www.cnblogs.com/cqbstyx/p/10320374.html

你可能感兴趣的文章
spring MVC的第一次记录
查看>>
js获取 X-X-X N 天后 是 X年X月X日
查看>>
我的友情链接
查看>>
神奇的504 Bad Gateway Timeout
查看>>
mysql安装报错解决一例
查看>>
在服务器上排除问题的头五分钟
查看>>
安装 - FreeBSD + Nginx 环境搭建教程(推荐)
查看>>
学习cocos2d --- 场景创建
查看>>
小凡带你搭建本地的光盘yum源
查看>>
java 求最大公约数和最小公倍数
查看>>
vmware workstation的bridged NAT host-only区别与适用场景简介
查看>>
Linux基础知识
查看>>
Struts2中的OGNL详解
查看>>
隐藏/屏蔽服务器信息与web软件版本信息
查看>>
ifstat 网络流量统计工具
查看>>
VLC 2.2.6 Windows下搭建 rtsp流媒体服务器
查看>>
Django2 model操作数据库
查看>>
使用Azure Policy限制所有ASM资源
查看>>
在win7系统下使用TortoiseGit(乌龟git)简单操作Git@OSC
查看>>
强大的ghost.py 使用实例
查看>>