public class spring { // HTTP是一套应用层协议 请求响应模式 // web资源以服务的形式体现 // // 请求 :有客户端发起 服务端接收 // 响应:有服务端发起 客户端接收 // // Http格式: // 请求 // 1.请求行 (请求方法 (POST GET ) 资源URL 版本) // 2.请求头 (KEY VALUE格式 每个占一行 ) 直到遇到空行截止 // 3.POST才有,请求体(本次要提交的数据) // // 响应 // 1.响应行 (响应版本信息 响应结果 (状态码+状态描述) ) // 2.响应头: (KEY VALUE格式 每个占一行 ) 直到遇到空行截止 // 3.响应体(如果有的话):资源内容 // // 继承 HttpServer 写服务器 // text/html:是一种html格式的文本 // // web资源: // 1.内容格式 2.生成方式(动态 静态) url 内容长度 // // url:协议(http(s)://) 服务器地址(ip) 服务器端口号 带层次的文件路径 ?参数 // url网络中的所有文件都可以使用url命名 // // 端口(TCP端口) 本机:127.0.0.1:8080 当端口是标准端口是可以省略 // // 对于静态资源,有个目录,称为资源的根(如static) ,这个目录下的所有资源被视为静态资源 // 写的时候一般很少些全路径 // 1.写url是一般省略协议号 // 2.可以省略除路径之后的全部部分 (访问的是本机 ) // 3.路径分为相对路径和绝对路径(绝对路径从根开始,相对路径从当前目录开始 可以想象a标签的href html的相互引入等) // 4. ./相当于原地顿一下 // 静态资源的默认路径是static(我试过 仅限本项目) 要想访问HTML.html(在static的第一级目录下) 直接/HTML.html // 动态资源:@Controller 标注的类,简单认为就是放置动态资源 // @GetMapping 标注的方法,是一个动态资源,注解中写明动态资源的资源路径是什么 GetMapping代表这个资源支持GET方法 // 请求参数:?后面的 键值对 用&区分 ?key=value&keyy=valuee // // URL编码:路径中不能出现中文 中文需要经过字符编码 // 1.指定字符集(默认UTF8) 以xx编码要以xx解码 // url编码 将汉字->16进制 url解码 16进制->汉字 // // 如何编写一个动态资源 // // SSM Spring(Springboot)SpringMVC Mybatis // Spring (Springboot) 提供了LOC功能 // loc:控制反转 DI:依赖注入 loc是一种理念 di是这种思想的具体实现 // SringMVC 提供web开发能力 // Mybatis:提供了比直接使用JDBC更方便的数据库操作能力 // // 进入ssm开发阶段 使用大量注解进行标注 // 所谓注解 可以为方法 类 变量添加额外的信息 @ // @Controller :简单认为就是放置动态资源 // // 下面三个可以修饰书类和方法 我们先关注方法 // @RequestMapping(“资源路径”):是一个动态资源,注解中写明动态资源的资源路径是什么 代表这个资源支持HTTP所有方法 // @GetMapping(“资源路径”):是一个动态资源,注解中写明动态资源的资源路径是什么 代表这个资源支持GET方法 // @PostMapping(“资源路径”):是一个动态资源,注解中写明动态资源的资源路径是什么 代表这个资源支持POST方法 // // // @ResponseBody //响应体 这个注解修饰的方法表示该方法完整的返回了整个响应体的内容 // punlic String f(){ // //返回的格式默认是HTML格式 //背后有Spring处理 // return <h1>2<h2> // } // ************************************************************************************************************ // 调用资源操作( @Controller) vrey 重要**** 由Spring处理 // 1.利用反射机制 得到类的实例化 // 2.扫描该类的所有方法by 反射 找到被 @RequestMapping()修饰的所有方法 // 读取资源文件 最终得到Map Map<String,方法> key:资源 value:对应的某个方法 // 3.当有请求来时,一定可以找到对应的资源路径 根据map找到对应的方法 // 4.调用该方法 第二步实例出来的对象 // **************************************************************************************************************** // HTTP请求: // 请求方法:表达本次请求我们想要对这个资源做出神魔样的动作 // 最常见的:获取get 提交post // 还有其他的 // 在浏览器输入URl一定是GET // POST <form>表单可以 Method=post // javascript 发起HTTP请求(ajax) // 当输入的不符合url格式,浏览器会进行搜索(当做一个搜素词,而不是路径) // html标签也可以发http请求;<a> <script> <link> // 通过ajax发起post:(使用比较多) // js代码: // 实例化一个XMLHttpRequest 对象,简称XHR // var xhr=new XMLHttpRequest() // 调用对象的open()方法 设置请求的 1)方法 2)路径 // xhr.open('get','/demo') // get // (xhr.open('post','/demo') post) // 设置回调函数 当/demo 资源的响应返回时,应该干什莫 // //事件绑定机制 // xhr.οnlοad=function(){ //响应回来时 // console.log(xhr.status)//响应的状态 // } // // xhr.send() 发送请求 // // GET 类似于对web资源进行 SELECT // POST 类似于对web资源进行 INSERT // PUT 类似于对web资源进行 UPDATE // DEKETE 类似于对web资源进行 DELETE // 假设 访问某资源(/resource)得到的响应时R1 // 幂等性:无论何时,随时访问/resource得到的都是R1,不会改变 假设环境是没有变得 // 反之,就不具备幂等性 // 副作用:会不会当值资源变化 // GET具备幂等性,且无副作用 // POST不具备幂等性,有副作用 // PUT具备幂等性,有副作用 假设UPdate的结果返回表的最新数据 // DEKETE 不具备幂等性,有副作用 // // GET应该是幂等性,且无副作用,should 不是 must 所以在现实中因为否写原因违反规则是可以使用的 // 幂等性+无副作用的HTTP请求是可以被缓存的。 // 缓存:由于某些性能上的考虑,并不是每次请求都要服务器参与,而是将结果暂时性的保留一段时间 供下次使用 // GET请求不允许有请求体 Post允许有 理解select于insert // // 那我自己写一个http客户端,如果携带了请求体,会怎摸样? // 就要看具体实现: 对方可以胡略你的请求体 也可以不乎略 // // 理论和实践: 你叫我做事,我可以听,也可以不听 // // 现象:GET把数据携带URL中 POST放在请求体中 // 例如form中对于相同的数据<input name=“”> get name会放在url中 post会放在请求体中 都是相同的数据,存放的位置不同 // @RequestMapping(“资源路径”)和@ResponseBody可以同时作用于一个方法上 因为ResponseBody无路径 可以理解我要你的返回值和你做业务逻辑不冲突 // url长度一般不易太长(没要求) ,而请求体无限制 // GET在query string 中无论携带什么数据,总体上还是key=value 但post则更灵活(非form表单) // // var xhr=new XMLHttpRequest() // xhr.open('post','/demo') // // xhr.οnlοad=function(){ // // } // // xhr.setRequestHeader('Content-Type','text/peixinchen') //请求头中规定请求体的格式 // xhr.send("随便写,按照Content-Type的格式就行") 发送请求 // // 由于浏览器发送非GET请求不方便,有专门的工具发送HTTp请求 Apifox // // HTTP请求---资源路径 // 填写完整的URL 或者是绝对路径,(不会出现相对路径) 但是可以有 查询字符串(也就是参数)和文档片段 // // 请求头 key--value格式 key和value中不能有中文 // Name有标准的,不提没大家都知道 也有自定义的:只有自己知道,建议用自定义Name用X-开头 X-courseId:xxx // 标准的Header中有些请求是专用的,有些是通用的 // 专用:host 通用:Content-Type // // 文本类型: // multipart/form-data 主要用于form表单+上传文件 (后面会有) // application/x-www-form-urlencodeded form默认的格式 key-value格式 // application/json 马上要讲的json格式 // application/xml (不讲) XML(pom.xml) // text/plain 无格式文本 // // Http响应 // 响应行 =响应版本+状态码+状态描述(可省略) // 响应头 // 空行 // 响应体 // // Http响应--版本 Http/1.1 // // Http响应--状态 // 用来表达本次请求-响应的结果 // 1.成功 // 2xx // 200 成功 // 2.失败 // 客户端 4xx 400 缺少必要的参数 404 请求的路径对应的资源不存在 405 请求的方法对应的资源不支持 (getMapping 请求PostMapping) // 服务器 5xx 500 代码出现异常 // // 3.其他情况 // 流程继续 1xx c处于一定的流程中,还在继续 // 重定向 3xx 301 永久重定向 // // 在开发者工具勾选 保留日志 和 停用缓存 // // 重定向: // 我去书店买 石头记 第一次请求 // 老板说石头记改名了叫红楼梦 第一次响应 【重定向】 // 我向老板买 红楼梦 第二次请求 // 我拿到了红楼梦 第二次响应 也可以站外重定向 :老板说去XX店买 // // @GetMapping("/redirect-demo") // public String redirectDemo(){ // //这里是死规定 redirect:+资源url组成 // return “redirect:/”; // ‘/’是首页 站内重定向 站外是不再本项目中 // 或 return “redirect:www.baidu.com” 站外重定向 // } // // “/method-form.html” 绝对路径 // “method-form.html” 相对路径 相对于 /redirect-demo 所在的目录是 / // // 重定向还可以继续分类:永久重定向(301)和临时重定向 // 临时重定向可细分 重定向一定是两种请求响应 // POST 请求 /r1 // 重定向到/r2 // 问 /r2使用的post or get? // 之前没做处理 都可以 302 // http 1.1 做了明确规定 // 1.请求方法保留第一次的请求方法 POST+POST 307 // 2. 请求方法退化为GET POST+GET 303 // // 网络 保留日志 停用缓存 // 重定向和Http响应的关系 // 1.状态码:301 302 303 307 // 2.响应头中有Location 他的value写明让浏览器去再次请求的url // 3.一般重定向响应是没有响应体,即使写了也不保证客户端会去读取使用 // // ajax的请求 后续的控制全是代码完成 即使是重定向浏览器也不会自动跳转(该有的请求都有) 也不支持站外重定向 // 但form表单 重定向浏览器会自动跳转 // // location.assign():也会页面跳转, // 请求转发:forward // 我 买石头记 // 老板找了本红楼梦包装成石头记卖给我 // 我买到了石头记 // 只有一次请求响应 // return “forward:/method-form.html” // // SSM中静态资源放在 recoures/static/下 // 动态资源放在src/main/java 代码下 @Controller +@requestMapping // // content-type: MIME-type 标准 // 如果是文本类型,可以通过如下格式指定字符编码 // text/plain;charset=utf-8 // 解释:大类型 text 表示文本类型 // 小类型 plain(无格式) 表示没有任何具备格式的文本类型--纯文本 // charset=utf-8 文本的字符集采用utf-8 // // 最常见 类型 // 1.大文本类型 // text/plain 纯文本 // text/html HTML结构的文本 // text/css // text/javascript // // 2.应用类型 // application/javascript javaScript结构的应用 // application/json javascript Obiect Notation 比较便捷的携带 人类可识别的 结构化数据的 主要用于前后端分离 // application/x-www-form-urlencodeded form默认的格式 key-value格式 // // 3.多媒体 // image/jpeg png // // 4. form表单+上传文件 // multipart/form-data 大类型:多部分--正文中的内容是由多个部分组成的 小类型 form-data 每个部分是form提交数据 // 使用时修改form类型 <form enctype="multipart/form-data"> 主要和<input type="file name=..">进行配合 // // 1.JSON格式 (以字符串来体现) // js对象格式:大括号 // { name:value,name1:vale1 } // 其中name必须是字符串类型 value可以是任意类型 // JSON下,做了一些约束({}可以换做[] 代表数组) // 1.name必须是双引号包裹(js可以省略引号,也可以使用单引号) // 2.value类似不能是函数类型 只剩数据(去除了动作) 可以为null 但不会有undefined(默认为null) // 3.jsvascript和后端都很容易解析哦 // // json序列化:JSON.stringify(..) obj/array-->string // js下的数据(对象 数组)----------->JSON格式化的字符串 // <------------ JSON反序列化 JSON.parse(..) string-->obj/array // 后端:java 和js不同 没有官方提供的JSON提供的序列化 反序列化工具 借助第三方代码完成 目前使用最多 // 1.jackson SSM默认使用jackson(咱们不用处理 springmvc 内部处理) // 2.gson // 3.fastjson 阿里的 // // java中序列化 反序列话 // Person p=new Person(); // p.name="ysg"; // p.age="103; // p.teacher=true; // ObjectMapper om= new ObjectMapper(); // String s=om.writeValueAsString(p); // System.out.println(s); // // map 在数据格式方面和对象是等价的 // Map<String,Object> map=new HashMap<>(); // map.put("名字","走起来"); // map.put("age",103); // map.put("isTeacher",true); // map.put("弟子","走起来sd"); // ObjectMapper om= new ObjectMapper(); // String s=om.writeValueAsString(map); // System.out.println(s); // // 反序列化 : // String s="{\"name\":\"tony\",\"age\":18}"; / /转义“ // String s="{\"name\":\"tony\",\"age\":18}"; // ObjectMapper om=new ObjectMapper(); // Person p=om.readValue(s,Person.class); // //map // Map map=om.readValue(s,Map.class); // // 1.动态资源使用JSON: // 1.得必须被@RequestMapping 修饰 代表是动态资源 // 2.方法应该被@ResponBody 注解修饰 表示返回的内容填充到响应体中 // 3.方法返回值类型必须是 某个类 Map list 等集合 // @GetMaping("/json-of-json") // public Person json{ //map也行 list也行 // Person p=new Person(); // p.name="sss"; // p.age=2 // return p; //ssm内部会将对象序列化成JSON格式 // } // 2.从请求体中读取JSON格式得字符串,并直接在动态资源中使用 【相对用的较多 前后端分离】 // 注: @ResponseBody+String 返回值类型就不是 application/json ,而是text/html格式 // 形参被@RequestBody 修饰 表示从请求体中得到内容 // 形参的类型是: Map 对象 list // @PsotMapping("/read-person") // @ResponseBody // public String readPreson(@RequestBody Person person){ // return "OK"; // } // // 前后端数据交流用json // // 结论:前端完全把后端当作一个简单的存取数据的子系统,通过Ajax http +json 进行通信 根据数据修改DOM树 // Dom 添加孩子节点有两种方式 // 1.element.innerHTML+=HTML 字符串 // 2.child =document.createElement(..) // element.appendChild(child) // // var tbody document。query Selector(‘tbody’); // for(var m of ml){ // //m 是元素 // var html=‘<tr><td>${m.who}</td><td>${m.whom}</td><td>${m.what}</td></tr>' '为模板字符串 // tbody.iinnerHTML+=html //添加一个孩子 // } // // 前端向后端提交数据有两种方式 // 1.采用form // form的后续处理,建议使用 重定向 这样浏览器自动就会重定向到指定资源上 // 2.ajax+请求体;JSON的形式 // ajax的后续处理,建议返回还是json,方便js根据情况继续处理 // // // 要重定向的动态资源不要写@ResponBody // // // // // // // // // // 购买云服务器 腾讯云 阿里云 百度云 华为云 // 一年:40-120 1核1 2g 就行 // 安装OS的时候 选择CentOS 8.X都行 重装系统很容易 // // // // // // // <input type="file" name="ccc"> //一个按钮,可以点击选择一个文件 需要搭配 form的enctype="multipart/form-data"使用 // 这时请求体是由多部份(multipart)组成,每个部分之间靠边界(boundary)来分割 // boundary样子:-------------------------------------156443231255445641233212566123 //数字是随机的 // // 文件上传后进行文件的保存 利用输出流复制文件 一个一个字节读 或直接交给SpringMVC // @Controller // public class UploadController{ // @PostMapping("/upload.do") // @ResponseBody // public String upload(MultipartFile ccc) throws Exception { // ccc.transferTo(new File("我们要保存的路径")) //若这个路径不存在时会创建 具体复习文件那块 // return “OK”; // } // 继续回到 请求/响应头 // 请求头:Cookie 响应头 :Set-Cookie // 重点:cookie和session机制 // 前提:一开始设置的http协议是无状态的协议:当服务器处理的请求响应很多时,这些属于那个用户发起的,服务器不知道(只知道当前这次请求的具体内容) // 例子:某人(A)开了一家店,A及较特殊,神魔都记不住,只能记忆一个客户进来提出购买服务 然后服务结束的过程 // 当A接待的客户比较多时,A就不知道谁是谁 // 矛盾:HTTP协议本身的无状态+实际需求是需要通过不同请求直接维护状态的,所以引出了解决方案 :Cookie(Http 协议标准) session // Cookie:就是A发给每个客户的一个凭证,客户有保存这个凭证的责任,也有下次购买服务携带这个凭证的责任(相当于理发店的会员卡) // 发凭证:从服务器到客户端,所以肯定是在响应中的 cookie:凭证的意思 // Set-Cookie:设置凭证 // 携带凭证:从客户端到服务器,所以肯定是在请求中 // Cookie:携带凭证跟在后面 // @Controller // public class CookieController { // //专门用来发凭证(Cookie)的 // // GetMapping("/set-cookie") // public void setCookie(HttpServletRequest request ,HttpServletResponse response){ // Cookie cookie=new Cookie(name,“ygs”); // Cookie cookie=new Cookie(course,“java”); // Cookie cookie=new Cookie(today,"2022-8-17"); // // response.addCookie(cookie1); // // response.addCookie(cookie2); // // response.addCookie(cookie3); // // // response.setCharacterEncoding("utf-8"); // response.setContentType("text/plain"); // // //写响应内容 // response.getWriter().println("cookie 设置成功,请观察开发者工具的 网络面版 和 应用面板") // } // } // 之后客户端在发送请求就会携带之前的cookie(在请求头中 key-value) // // // 服务器有设置凭证的职责,具体在HTTp中的表现 // 在http响应中台添加Set-Cookie的响应头,value为 <key value>形式的数据 // // 客户端有保存cookie的职责 具体在HTTp中的表现 // 根据响应的set-cookie的value 将cookie信息保存到 内存or 文件 所以cookie的范围是浏览器范围(内存) // // 大部分cookie是各个版本的浏览器自己去保存的,不会在不同浏览器之间共享 // Cookies=设置的时候可以设置过期时间,过期后失效了 服务器行为 // 设置域 默认cookie是本域限制的 // 当时可以通过设置,可以让子域生效 // 设置生效路径,默认情况是本域所有资源可用,但可以设置 // // 客户端在发送请求时,都有携带本网站所有cookie的职责 (如果没有就不带) // Http请求中,添加cookie头,后续的value是cookie中的key value // // 服务器具体去利用cookie // Coolie[] cookie=request.getCookies(); // // 如果完全信任cookie,因为cookie保存在客户端(谁都可以看,谁都可以改),则碰到恶意用户 或 恶意程序修改了cookie(或伪造cookie)都有问题 // // 解决办法:拆开保存数据,把敏感数据保存到服务器内部,cookie中只携带不敏感信息---session就此而生(会话) // session是保存在服务器的,专属每次会话的一组数据,可以跨请求访问到 // 通常,session中保存的数据可以视为name(key)-value // 一般利用cookie设置session-id,这样,客户端和服务端之间任然使用cookie机制,只是cookie只传递id,大头数据全部保存在服务器 // // HttpSrevletRequest类下的 // HttpSession getSession(Boolean create); HttpSession session=request.getSession(flag); // 用户获取本次请求的session数据是根据 // 1.请求中的cookie是否有session-id? 判断是否有id // 2.如果有session-id,对应的房间是否存在? 判断id是否是假的 // 3.既有session-id,对应的房间也存在,返回这个房间 // 参数Boolean create的作用: // 1.如果能获取 HttpSession对象,则create为true/false都没有区别 // 2.如果没有获取到HttpSession对象,则 // create==true 创建一个新的房子 (HttpSession对象)并且返回 // create==false 不创建,返回null // // // // HttpSession session=request.getSession(true); // session.setAttrribute("name","value"); // session.getAttrribute("name"); // // HttpSrevletRequest类下有 // request.getSession() 等价于 request.getSession(true) // // // Cookie和Session在实际场景中最常见的应用--在线用户管理(如何再一次HTTP请求-响应中判断用户是否登录 以及登录用户是谁) // 和cookie session有关系的:用户登录 用户推出 获取等前登录用户的信息:当前用户保存在session中 // // 用户注册:为用户信息做持久化保存--在数据库维护一条信息 等登录是来证明你是你 // 常见的信息: 1.用户名+密码 2.手机号加手机验证码 3.qq 微信 支付宝 // 用户名+密码的方案: // 用户表 :uid (唯一标识符) 用户名(需要保持唯一性) 密码(暂时明文) // // Connection对象(mysql),线程不安全的,原则上与许一个Connection执行多条SQL 性能更好 // prepareStatement对象(mysql) 线程不安全,原则上可多次绑定参数,多次执行的 // ResultSet对象是一次性的 // // @RequestParam("username") String username 作为形参出现 获取get请求的以“username”为参数的值 // TODO:TODO的在该注释处有功能代码代编写 就一个高亮显示 // // HttpSession session =request.getSession(); // //由于之前没有session的 // //所以内部的工作是 // //1.创建一个随机的session-id // //2.为这个session-id分配一个HttpSession对象 Map<String,Object>结构 // //3.响应中设置Cookie (Set-Cookie),JSESSIONID=session-id // // 获取当前登录用户信息,判断用户是否在线 如果在线 当前用户是谁 // 实际要做的判断: // 请求响应中若没有session对象,就说明没有经力过登录,就是用户未登录 因为登陆了一定会保存session 并且session有值 // // session是保存在服务端 浏览器范围有效 // 我们可以在cookie中得到sessionid从而session(JSessIONID) // 当程序退出后,进程结束,上一个保存的session就没了 比如我打开QQ(用户上线) 进程开启 退出QQ(用户下线) 进程关闭 // cookie和session的作用域一样 // // HTTP是基于TCP的一种应用层协议 是一种不安全的协议 可以植入广告 木马 // 网络安全 核心是加密 // 明文数据 -》 密文 // 支持反向 // 密文数据 -》明文数据 // // 现代密码学:明明白白地告诉别人我在传输数据,你就是破解不了 // HTTPS:http的安全版本 也是应用层的 // // // . ____ _ __ _ _ // /\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \ // ( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \ // \\/ ___)| |_)| | | | | || (_| | ) ) ) ) // ' |____| .__|_| |_|_| |_\__, | / / / / // =========|_|==============|___/=/_/_/_/ // :: Spring Boot :: (v2.7.3) // // // spring是神魔? spring 框架 // 围绕spring框架构造的一套java生态下的事实标准的解决方案 // // 长用 spring Framework+ spring boot // ------------------------------------------------------------------------------------------------------------------- // loc 控制反转 DI:依赖注入 // // 对象依赖其他对象少 对象依赖其他对象多 // 直接new 需要的对象 商品经济出现: // 买方: 买方 买卖方 // // // 依赖:对象之间有关系 // ioc 容器:放的是对象 就是一个对象市场 里面放置带出售的对象 // 作为对象的买方:我们只在代码中声明我们依赖(买)那些类型的对象,最终对象是被Spring loc注入给我们(对象送货上门) // 作为对象的卖方: // 1.自己生产好,再去卖 // 2.将生产对象的配方(告诉spring使用什么方法去实例化对象)告诉loc容器 最终售卖的对象有ioc生产[使用更多] // // 新建项目:只勾选lombok(不勾不让过) // // bean:就是spring售卖的对象 // // spring落实起来 // 1.基于xml的配置做法【学习阶段更方便 时间很少使用 实践中很乱】 // 创建一个.xml格式的文件 // 在主方法中定义一个 loc容器 // //FileSystemXmlApplicationContext is ApplicationContext 接口的一个子类 // //ApplicationContext 代表ioc 容器的抽象 // FileSystemXmlApplicationContext context=new FileSystemXmlApplicationContext("xxx.xml的路径"); // //我们希望spring帮我们售卖person对象,并且生产过程也交给spring来完成 // //那么xxx.xml中写: // 在<beans>中添加 // <bean id="wodea" class="从java下的类的路径(不包含java)"> </bean> // //因为没写构造方法,默认调用无参,并将生产好的对象以wodea来买 // 作为纯粹的买家去买:Object obj=context.getBean("wodea"); // System.out.println(obj.getClass().getCanonicalName) //打印真实的对象类型 // 卖方可以指定在实例化时调用那个构造方法 // <bean id="money" class="xxx.money"> <constructor-arg value="1998"/> </bean> //1980为构造方法的参数 // // 产生依赖关系: // 即使卖方有是买方 // 1>.以构造方法参数的形式注入 // <bean id=“zoo” class="sdsa.zoo"> // //通过 ref 指定注入这个构造过程的需要用到的另一个对象 Monkey 对象的id value 是直接值 // <constructor-arg ref="monkey"/> </bean> // 2>.以setter方法参数的形式注入 // <bean id="monkey-hill" class="com.ygs.web1"> name是monkey,就会调用monkey属性的设置 按照java的规范 会调用 // <proprety name="monkey" ref="some-animal"/> MonkeyHill的setter方法 所以回去调用setMonkey方法,使用 // ref="some-animal" some-animal是之前的monkey的id 意为买一个 monkey // </bean> // // public class MonkeyHill{ // public MonkeyHill{ // } // public void setMonkey(Monkey monkey){ // } // } // // // <bean id="city1" class="com.ygs.web1.CityFactory" factory-method="create"> 使用Spring 调用CityFactory下的Create() 得到一个City对象 命名为city1 // // public class CityFactory{ // public static City create(){ // return new City(); // } // } // Universe对象: // 1.先通过构造方法注入的方式,实例化出一个universeFactory对象 // <bean id="universe-factory" class="com.peixincgen.ioc.universeFactory"> // <constructor-arg ref="monkey"/> </bean> // <constructor-arg ref="monkey2"/> </bean> // <constructor-arg ref="monkey3"/> </bean> // <constructor-arg ref="monkey4"/> </bean> // // // </bean> // 通过指定universeFactory的createUniverse方法实例工厂方法 自己new出universe // <bean id="universe" factory-bean="universe-factory" factory-method="createUniverse"> // 依赖注入要发生在买/卖方 // // 通过beans标签Spring可得到 map<String id,String className> 对象的名字与配方 // 然后全部bean实例化 通过反射机制 // 得到类似的结构: Map<id,obj> beanMap 在loc贩卖 // context.getbean(id) 得到特定的bean // // 37 2022-8-22-ioc视频中有反射机制去模拟spring处理 // // // java中的对象从语法上来讲是平等的,但由于作用不同,使用场景不同,使得对象出现了不同的分类 // 对象:属性 方法 // // 只关注属性 【数据对象】 (大部分类在中间) 只关注方法(过程)【过程对象】 // <-----------------------------------------------------------------------> // 进行用户登录的例子: // User 类 UserService // int uid 根据用户名+密码进行查询 返回登录成功 // String username // String password // 只关注属性 【数据对象】 只关注方法(过程)【过程对象】 // 更注重tiString() equals() 越容易以单例模式存在 // hashCode() Comparable/comparator的重写 因为没属性,定义一个或多个没区别,那就定义一个 // 素材的抽象: 工业厂房的抽象 // 水 糖 工业色素 瓶子 饮料 贴牌 1.糖+水+色素-》饮料 Comtroller // 2.饮料+贴牌 》可以包装的饮料 view // MVC:Moudle view Controller // 最原生主义下的MVC // view:用来处理展示相关流程的对象 【过程对象】 // controller:用来处理数据加工流程的对象【过程对象】 // model: // 1.数据对象 [理解方式1] // 2.获取数据对象的【过程对象】 [理解方式2 ] // // java视角下的各种不同类型的对象 // 【过程对象】: // controller/控制器 : // 主要HTTP资源相关的工作 // 1.读取用户参数 判断合法性 // 2.HTTP响应 :状态码 重定向 响应头 // Service/服务 // 1.从各种数据聚合的整理 变换结构等 // // 数据对象 // model、entity、dataobject // ------------------------------------------------------------------------------------------------------- // SSM: // controller/service/Mapper(Repoisotry 、DAO) // entity viewObject 过程对象才会交给spring去管理----spring管理对象默认是单例的 // ---------------------------------------------------------------------------------------------------------- // 2.基于注解: // 通过为要注册的类上面添加注解 + spring在启动过程中扫描包下的所有类来确定那些类要被spring管理 (根据有无注解) // 在beans标签中加<context:component-scan base-package="com.peixinchen.io2"/> // Component:组件 // 添加@ Component后 Spring启动扫描这里会将其进行管理起来(会被new) // @Component // public class A{ // } // 如何进行类的注册 // 被以下注解修饰即可 // @component 组件 // @Controller 控制器 // @Service 服务 // @Repository 仓库 从数据库 进行数据读取 // @Configuration 配置 // // 一般来说用上面那个标签修饰都行,更建议使用@Configuration修饰 // @Configuration // public class AppConfig{ // public AppConfig(){} // // @bean //由于这个类已经被注册到spring中+这个方法被@bean 修饰,所以会把”你好“注册到spring中 // public String peixinchen(){ // return “你好” // } // } // // 使用bean :全是注入的方式(前提是使用bean的类先被spring管理起来) // @Autowried // 1.构造方法注入 用@Autowried 不写也行 但建议都带上 // 2.setter方法注入 用@Autowried修饰setter方法 // 3.直接属性注入 用@Autowried修饰属性 // 如果用@Autowried修饰一个有参数的构造方法,则默认调用此构造方法 // 加上@Autowried 会被调用 也就是以这种方式得到我需要的零件 而不是将方法注入到spring // // 如果使用人家提供的main方法 默认是从main方法所在类的包下 例如com.ygs.web1 // public static void main(String[] args) { // SpringApplication.run(Web1Application.class, args); // 可以获取loc // ApplicationContext context=SpringApplication.run(Web1Application.class, args); Web1Application:main的类名 // com.ygs.web1包下的范围 // } // @conponent等也可以通过@Autowried注入 // // // 配置文件:软件的设置 // java中默认的配置文件格式:prorerties格式 // 基本构造:key:value sposad=abc //abc为字符串,且不用""扩 // key是分段的 // // 我们希望可以在我们的代码中去读取配置文件,这样我们的代码逻辑可以根据配置进行调整 // 方式1.springboot中已经注册好了一个叫做envirment的对象 咱可直接用这个对象 // 这个对象提供了类似于map一样的读取配置的能力 根据key得到value // Environment environment =context.getBean(Enviroment.class); // String value=environment.getProperty("spring.banner.image.location"); //得到application.properties下的spring.banner.image.location" // 方式2.springboot提供了@value的注解,可直接将配置项的值注入 +spring表达式(SpEl) // @bean // public DataSource(@Value("${spring.datasource.url}") String v1, //spring.datasource.url写在application.properties下 // Value("${spring.datasource.username}") String v2, // Value("${spring.datasource.password}") String v3,){ // // // } // // 方法三 // 合适配置项特别多的情况,将其封装为一个对象 // @component // @ConfigyrationProperties("bit.hjb.pxc") //设置以bit.hjb,pxc下的所有配置(添加) 在application.properties- // { // private String name; // private String name1; // //必须要有set方法 //bit.hjb.pxc.name=name // public void setName(name){ // name=name; // } // } // // spring提供了另一种配置文件的格式:YAML // 1.等价于;bit.hjb.age // 每层有缩进(两个空格) :后面有一个空格 // bit: // hjb: // age: 3 //后面没有‘;’ 上一种格式也没有 // // 日志:就是记录 (打印信息:时间 线程 类。。。) // 一般使用 slf4j org.slf4j // lombok使用前提:1.导入包 2.下载lombok插件 (我都有) // @Data:此注解包含以下注解:@ToString、@EqualsAndHashCode、@Getter、@Setter、@RequiredArgsConstructor // @Slf4j:lombok自动导入日志 // // 对象代理: // interface Flyable{ // void fly() // } // class bird implements Flyable{ ... // public void fly(){} // } // Flyable flyable=new Bird(); // 对象代理:中间人 ,调用flyable的 fly()方法,优先将调用给代理对象,然后代理去进行调用处理 然后再去调用bird的fly方法 // 比如 你向老师查一些东西,通常是想班长查的,班长去和班主任交流 // public class BirdProxy implements InvocationHandler{ // private final Bird bird=new Bird(); // @Override // public Obiect invoke(object proxy,Method,object[] args)throws Throwable{ // method.invoke(bird);//调用bird对象的fly方法 // return null; // } // // public class FlyableFactory{ // public static Flyable cerate(){ // Flyable instance=new Bird(); // return instance; // } // // public static Flyable createWithProxy(){ // // BirdProxy proxy=new BirdProxy(); // //经过一套流程,弄出来了可以被Flyable 接口指向的对象(代理对象) // Object o=Proxy.newProxyInstance( // Flyable.class.getClassLoader(), // new Class[]Flyable.class, // proxy); // return (Flyable)o; // } // } // 要是有对象代理 // Flyable flyable=FlyableFactory.createWithProxy(); // 调用createWithProxy()-->得到一个java官方提供的Proxy对象-->得到bird // 代理完全可以拿钱不办事(拟造一个假的给你) // 对象代理+ioc组合一起: // 作为对象的买方不用关心买到的是啥,只要能满足我的需求即可 也不知道买的是啥, // 通过@Bean 修饰的方法 会将返回值注册到ioc里 // 通过类名.class拿到 类名.class也可以拿到@component等的对象 // 2022-8-25 有东西 很难 mybites的原理 动态代理 有些人家分装的代理 不一定要知道人家咋做的,我知道他是干啥的就行 很急就不用看了 // // mybatis: // // 从创建项目中勾选:关系型数据库--》spring data jdbc :勾了之后就会自建一个datasource // 勾选:myBatis Framework // 勾选:MYSQL Driver // 勾选:lombok // 此datasource 默认使用HikariDataSource:自带线程池,性能较好 // // myBatis Framework:就是引入 MyBatis框架 方便使用sql操作 // MYSQL Driver 引入mysql-connector-java 提供JDBC访问的底层支持 // 需要配置配置文件:在application.yml中配置 // 配置数据库: // spring: // datasource: // url: aaaaaaaaaaaaaaaaaaaaaxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx // username: root // password: 123456 // // @Mapper //来自Mybatis的注解 意思是让 myBatis 为这个接口创建一个代理对象 // public interface UserMapper{ // @select("select语句") //传入select 返回结果 如果不是查询 则返回值要变 // List<User> selectUser(); // } // myBatis:1.动态拼接SQL 2.ORM:把表映射成类,把表中记录映射成一个对象 // // myBatis偏向于ORM,但对动态SQL支持力度还不错 // // 我们作为myBatis的用户,提供 // 1.接口,接口中写明了各种各样的方法 // 2.需要告诉myBatis接口中的这些方法应该: // 1.需要执行的是那条SQL // 2.参数化的SQL 如何匹配方法中的参数和SQL里的参数 // 3.查询出来的表结果,如何和方法的返回值结(一般是对象)一一映射 // 3.myBatis根据我们提供的,提供好一个对象代理,完成jdbc的整套流程 // 有两种方案:1).注解 2)XML方式 // 参数化SQL的解决: // 引入 @Param(org.apache.ibatis.annotations) // @select("select.......where username = #{u}") // List<User> selectUser(@Param("u") String username); 意思是:用username替换#{u} //会防止sql注入 // // 方法的返回值类型: 对象实际上就是一个有约束的map 属性名称 // 1.返回一条记录 User 等价于 Map<String,Obiect> // 2.返回一批 List<User> 等价于 List<Map<String,Obiect>> // // XML方式 // 在yml下配置: // mybatis: // # *代表从孩子层 // # **代表所有子孙 // # 找以 .xml结尾的文件 认为是mybatis 的XML 配置 // # classpath:可以简单理解从resources目录开始算起 // mapper-locations: classpath:mapper/**-mappeer.xml //例如有一个 yse-mapper.xml就可以被识别 // look 2022-8-25 .png // <mapper namespace="com.ygs1.web1.UserMapper" // <insert id="addUser"> // insert into users (username,password) values (#{username},#{password}) // </insert></mapper> // @Repository //可以不写 插入时 // @Mapper //写在接口上 // public interface UserMapper{ // int addUser (User user); //注解: // @Select("insert into users (username,password) values (#{username},#{password})") // int adduser2(User user); // // // // // // // 如果返回值和表中的值不一样 表中的值用别名 修改成一致 /* 动态sql: <insert id ="addUserBatch" userGenerateKey="true" keyProrerty="uid" KeyClounm="uid"> //自增uid insert into users (username,password) values <foreach collections="list" item="xxx" speparator=", "> (#{xxx.username},#{xxx.password}) </foreach> <insert/> int addUserBatch(@Param("list")) List<User> userlist);//使用(@Param("list"))要在sql userlist.属性 <delete id="deleteBatch"> detele from users where uid in ( <foreach collections="uidlist" item="xxx" speparator=", "> #{uid} </foreach>) </delete> //查出uidlist的所有用户 <select id="selectlist" resultType="com.peixinchen.mybatis.demo.User"> select uid,usemname,passwoawd from user,where uid in ( <foreach collections="uidlist" item="xxx" speparator=", "> #{uid} </foreach> ) */ /* AOP面向切面编程 OOP面向对象编程 AOP面向切面编程 和使用者相关的概念: 1.这个公共业务代码是什么,验证登录,统计耗时 2.这个业务和那些具体业务产生关系:验证登录 发布消息 3.发生关系的具体时机是什么:之前 之后 开启AOP 在pom.xml中: springframework-boot <artifactId>spring-boot-starter-parent-aop</artifactId> 从query—string(GET /POST)或请求体(application/x-www-form-urlencoded 的post请求) 换而言之,从form表单读取数据 使用@RequestParam,修饰的形参,几种形式: @RequestParam String xxx; 读取form表单中name为xxx的值 String xxx; 读取form表单中name为xxx的值 @RequestParam(value="yyy") String xxx; 读取form表单中name为yyy的值 必须传yyy否则400错误 @RequestParam(value="yyy",required=false) String xxx; 读取form表单中name为yyy的值 不必须传 int xxx; 读取form表单中name为xxx的值,转换成int 如果转换失败 也是400错误 直接定义一个请求参数对象来接受,springmvc回将请求对象构造对象@model public String getParamObject(SomeClass s) SomeClass是我们定义的对象 {} 一般除了重定向 (转发应该也有) 资源都使用@ResponseBody @RequestBody可以接受JSON格式 public String getJSON (@RequestBody SomeClass someClass ){} @GetMapping("/csdn/{username}") public String (@getPathVariable("username") String name ){} 或者 @GetMapping("/csdn/{username}/{abc}") 上传文件: public string (@RequestPart("文件名") MultipartFile xx){} @Value("{app.upload-dir-root}") :读取配置文件下的值 application.properties public string (@RequestPart("文件名") MultipartFile xx){ String uuid; File dest; dest=new File(uploadDirRoot,uuid); //uploadDirRoot路径 创建一个件 uploadDirRoot,uuid 路径+名字 xx.transferTo(dest); //文件拷贝 除此之外,请求参数可以有: 1.HttpSevletRequest 对象 等同于sevlet中的 request的用法 2.HttpSession 等价于先获取 HttpSevletRequest 然后调用 request.getSession() 一般不用 3.@RequestHeader 注解修饰的对象,获取请求头 } 动态资源的返回值分两类: 1.方法被@RequestBody修饰 这个方法返回值是完整的响应体的内容 返回String Content-type:text/html 返回其他对象: content-type:application/json 2.方法没有被@RequestBody修饰 这个方法返回值应该被当做ModelAndView的逻辑处理 一般是view-nmae 返回名字 名字对应到 classpath:templates/某个模板文件的名称 返回String&&"redirect:"后面根url 返回String&&"forward:"后面根url @RequestBody修饰类是整个类下的所有方法都是 @RequestBody @RestController= @RequestBody+@Controller 在类上使用@RequestMapping("/user") 所有的RequestMapping有统一的前缀/user */ }
02-05
311
10-22
968
06-12
870