96SEO 2026-02-20 01:14 14
Request是请求对象Response是响应对象。

这两个对象在我们使用Servlet的时候有看到
此时我们就需要思考一个问题request和response这两个参数的作用是什么?
浏览器会发送HTTP请求到后台服务器[Tomcat]HTTP的请求中会包含很多请求数据[请求行请求头请求体]后台服务器[Tomcat]会对HTTP请求中的数据进行解析并把解析结果存入到一个对象中所存入的对象即为request对象所以我们可以从request对象中获取请求的相关参数获取到数据后就可以继续后续的业务比如获取用户名和密码就可以实现登录操作的相关业务
业务处理完后后台就需要给前端返回业务处理的结果即响应数据把响应数据封装到response对象中后台服务器[Tomcat]会解析response对象,按照[响应行响应头响应体]格式拼接结果浏览器最终解析结果把内容展示在浏览器给用户浏览
对于上述所讲的内容我们通过一个案例来初步体验下request和response对象的使用。
request.getParameter(name);//url?namezhangsan//使用response对象
设置响应数据response.setHeader(content-type,text/html;charsetutf-8);response.getWriter().write(h1name,欢迎您/h1);}Overrideprotected
}启动成功后就可以通过浏览器来访问并且根据传入参数的不同就可以在页面上展示不同的内容:
在这节中我们主要认识了下request对象和reponse对象:
request对象是用来封装请求数据的对象response对象是用来封装响应数据的对象
目前我们只知道这两个对象是用来干什么的那么它们具体是如何实现的就需要我们继续深入的学习。
接下来就先从Request对象来学习,主要学习下面这些内容:
在学习这节内容之前我们先思考一个问题前面在介绍Request和Reponse对象的时候比较细心的同学可能已经发现
当我们的Servlet类实现的是Servlet接口的时候service方法中的参数是ServletRequest和ServletResponse当我们的Servlet类继承的是HttpServlet类的时候doGet和doPost方法中的参数就变成HttpServletRequest和HttpServletReponse
ServletRequest和HttpServletRequest的关系是什么?request对象是有谁来创建的?request提供了哪些API,这些API从哪里查?
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-YIMpho4w-1692455387623)(assets/1628740441008.png)]
从上图中可以看出ServletRequest和HttpServletRequest都是Java提供的所以我们可以打开JavaEE提供的API文档[参考:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-pwmtLLi3-1692455387623)(assets/1628741839475.png)]
所以ServletRequest和HttpServletRequest是继承关系并且两个都是接口接口是无法创建对象这个时候就引发了下面这个问题:
这个时候我们就需要用到Request继承体系中的RequestFacade:
该类实现了HttpServletRequest接口也间接实现了ServletRequest接口。
Servlet类中的service方法、doGet方法或者是doPost方法最终都是由Web服务器[Tomcat]来调用的所以Tomcat提供了方法参数接口的具体实现类并完成了对象的创建要想了解RequestFacade中都提供了哪些方法我们可以直接查看JavaEE的API文档中关于ServletRequest和HttpServletRequest的接口文档因为RequestFacade实现了其接口就需要重写接口中的方法
对于上述结论要想验证可以编写一个Servlet在方法中把request对象打印下就能看到最终的对象是不是RequestFacade,代码如下:
{System.out.println(request);}Overrideprotected
}启动服务器运行访问http://localhost:8080/request-demo/demo2,得到运行结果:
Request的继承体系为ServletRequest–HttpServletRequest–RequestFacadeTomcat需要解析请求数据封装为request对象,并且创建request对象传递到service方法使用request对象可以查阅JavaEE
API文档的HttpServletRequest接口中方法说明
HTTP请求数据总共分为三部分内容分别是请求行、请求头、请求体对于这三部分内容的数据分别该如何获取首先我们先来学习请求行数据如何获取?
请求行包含三块内容分别是请求方式、请求资源路径、HTTP协议及版本
对于这三部分内容request对象都提供了对应的API方法来获取具体如下:
getContextPath()获取URL(统一资源定位符):
http://localhost:8080/request-demo/req1
getQueryString()介绍完上述方法后咱们通过代码把上述方法都使用下:
req.getMethod();System.out.println(method);//GET//
getContextPath()获取虚拟目录(项目访问路径)/request-demoString
req.getContextPath();System.out.println(contextPath);//
获取URL(统一资源定位符)http://localhost:8080/request-demo/req1StringBuffer
req.getRequestURL();System.out.println(url.toString());//
req.getRequestURI();System.out.println(uri);//
req.getQueryString();System.out.println(queryString);}Overrideprotected
}启动服务器访问http://localhost:8080/request-demo/req1?usernamezhangsanpasswrod123获取的结果如下:
name)接下来在代码中如果想要获取客户端浏览器的版本信息则可以使用
req.getHeader(user-agent);System.out.println(agent);}Overrideprotected
重新启动服务器后http://localhost:8080/request-demo/req1?usernamezhangsanpasswrod123获取的结果如下:
浏览器在发送GET请求的时候是没有请求体的所以需要把请求方式变更为POST请求体中的数据格式如下:
对于请求体中的数据Request对象提供了如下两种方式来获取其中的数据分别是:
获取字节输入流如果前端发送的是字节数据比如传递的是文件数据则使用该方法
该方法可以获取字节获取字符输入流如果前端发送的是纯文本数据则使用该方法
getReader()接下来大家需要思考要想获取到请求体的内容该如何实现?
1.准备一个页面在页面中添加form表单,用来发送post请求
3.在doPost方法中使用request的getReader()或者getInputStream()来获取
在项目的webapp目录下添加一个html页面名称为req.html
action:form表单提交的请求地址method:请求方式指定为post
}调用getReader()或者getInputStream()方法因为目前前端传递的是纯文本数据所以我们采用getReader()方法来获取
br.readLine();System.out.println(line);}
BufferedReader流是通过request对象来获取的当请求完成后request对象就会被销毁request对象被销毁后BufferedReader流就会自动关闭所以此处就不需要手动关闭流了。
启动服务器通过浏览器访问http://localhost:8080/request-demo/req.html
HTTP请求数据中包含了请求行、请求头和请求体针对这三部分内容Request对象都提供了对应的API方法来获取对应的值:
getMethod()获取请求方式getContextPath()获取项目访问路径getRequestURL()获取请求URLgetRequestURI()获取请求URIgetQueryString()获取GET请求方式的请求参数
浏览器发送的POST请求才有请求体如果是纯文本数据:getReader()如果是字节数据如文件数据:getInputStream()
getReader();有了上述的知识储备我们来实现一个案例需求:
此处大家需要注意的是GET请求和POST请求接收参数的方式不一样具体实现的代码如下:
req.getQueryString();System.out.println(result);}Overrideprotected
br.readLine();System.out.println(result);}
当然也可以在doGet中调用doPost,在doPost中完成参数的获取和打印,另外需要注意的是doGet和doPost方法都必须存在不能删除任意一个。
GET请求和POST请求获取请求参数的方式不一样在获取请求参数这块该如何实现呢?
GET请求方式和POST请求方式区别主要在于获取请求参数的方式不一样是否可以提供一种统一获取请求参数的方式从而统一doGet和doPost方法内的代码?
if(POST.equals(method)){BufferedReader
reader.readLine();}//将请求参数进行打印控制台System.out.println(params);}Overrideprotected
}使用request的getMethod()来获取请求方式根据请求方式的不同分别获取请求参数值这样就可以解决上述问题但是以后每个Servlet都需要这样写代码实现起来比较麻烦这种方案我们不采用
request对象已经将上述获取请求参数的方法进行了封装并且request提供的方法实现的功能更强大以后只需要调用request提供的方法即可在request的方法中都实现了哪些操作?
注意:因为参数的值可能是一个也可能有多个所以Map的值的类型为String数组。
/html2.在Servlet代码中获取页面传递GET请求的参数值
{//GET请求逻辑System.out.println(get....);//1.
lisiSystem.out.print(key:);//获取值String[]
);}System.out.println();}}Overrideprotected
{//GET请求逻辑//...System.out.println(------------);String[]
req.getParameterValues(hobby);for
{System.out.println(hobby);}}Overrideprotected
req.getParameter(username);String
req.getParameter(password);System.out.println(username);System.out.println(password);}Overrideprotected
3.1将req.html页面form表单的提交方式改成post
{//采用request提供的获取请求参数的通用方式来获取请求参数//编写其他的业务代码...}Overrideprotected
使用通用方式获取请求参数后屏蔽了GET和POST的请求方式代码的不同则代码可以定义如下格式:
由于格式固定所以我们可以使用IDEA提供的模板来制作一个Servlet的模板这样我们后期在创建Servlet的时候就会更高效具体如何实现:
request.getParameter(username);System.out.println(username);}Overrideprotected
5把req.html页面的请求方式改成post,再次发送请求和中文参数
通过上面的案例会发现不管是GET还是POST请求在发送的请求参数中如果有中文在后台接收的时候都会出现中文乱码的问题。
具体该如何解决呢
POST的请求参数是通过request的getReader()来获取流中的数据TOMCAT在获取流的时候采用的编码是ISO-8859-1ISO-8859-1编码是不支持中文的所以会出现乱码
页面设置的编码格式为UTF-8把TOMCAT在获取流数据之前的编码设置为UTF-8通过request.setCharacterEncoding(“UTF-8”)设置编码,UTF-8也可以写成小写
getReader()//设置字符输入流的编码设置的字符集要和页面保持一致request.setCharacterEncoding(UTF-8);//2.
request.getParameter(username);System.out.println(username);}Overrideprotected
至此POST请求中文乱码的问题就已经解决但是这种方案不适用于GET请求这个原因是什么呢咱们下面再分析。
刚才提到一个问题是POST请求的中文乱码解决方案为什么不适用GET请求
GET请求获取请求参数的方式是request.getQueryString()POST请求获取请求参数的方式是request.getReader()request.setCharacterEncoding(“utf-8”)是设置request处理流的编码getQueryString方法并没有通过流的方式获取数据
所以GET请求不能用设置编码的方式来解决中文乱码问题那问题又来了如何解决GET请求的中文乱码呢?
(1)浏览器通过HTTP协议发送请求和数据给后台服务器Tomcat)
(3)在进行URL编码的时候会采用页面meta标签指定的UTF-8的方式进行编码张三编码后的结果为%E5%BC%A0%E4%B8%89
(4)后台服务器(Tomcat)接收到%E5%BC%A0%E4%B8%89后会默认按照ISO-8859-1进行URL解码
(5)由于前后编码与解码采用的格式不一样就会导致后台获取到的数据为乱码。
如果把req.html页面的meta标签的charset属性改成ISO-8859-1,后台不做操作能解决中文乱码问题么?
答案是否定的因为ISO-8859-1本身是不支持中文展示的所以改了标签的charset属性后会导致页面上的中文内容都无法正常展示。
分析完上面的问题后我们会发现其中有两个我们不熟悉的内容就是URL编码和URL解码什么是URL编码什么又是URL解码呢?
使用http://www.mytju.com/classcode/tools/encode_utf8.asp输入张三
就可以获取张和三分别对应的10进制然后在使用计算器选择程序员模式计算出对应的二进制数据结果:
在计算的十六进制结果中每两位前面加一个%,就可以获取到%E5%BC%A0%E4%B8%89。
但是对于上面的计算过程如果没有工具纯手工计算的话相对来说还是比较复杂的我们也不需要进行手动计算在Java中已经为我们提供了编码和解码的API工具类可以让我们更快速的进行编码和解码:
java.net.URLEncoder.encode(需要被编码的内容,字符集(UTF-8))解码:
java.net.URLDecoder.decode(需要被解码的内容,字符集(UTF-8))接下来咱们对张三来进行编码和解码
utf-8);System.out.println(encode);
浏览器把中文参数按照UTF-8进行URL编码Tomcat对获取到的内容进行了ISO-8859-1的URL解码在控制台就会出现类上å¼
在进行编码和解码的时候不管使用的是哪个字符集他们对应的%E5%BC%A0%E4%B8%89是一致的
三转换成字节在把字节转换成张三在转换的过程中是它们的编码一致就可以解决中文乱码问题。
utf-8);System.out.println(encode);//2.
ISO-8859-1);System.out.println(decode);
decode.getBytes(ISO-8859-1);for
其实打印出来的是十进制数据我们只需要使用计算机换算下就能得到他们的对应关系如下图:
至此对于GET请求中文乱码的解决方案我们就已经分析完了最后在代码中去实现下:
解决乱码POSTgetReader()//request.setCharacterEncoding(UTF-8);//设置字符输入流的编码//2.
request.getParameter(username);System.out.println(解决乱码前username);//3.
乱码原因tomcat进行URL解码默认的字符集ISO-8859-1/*
username.getBytes(StandardCharsets.ISO_8859_1);//3.2
StandardCharsets.UTF_8);*/username
String(username.getBytes(StandardCharsets.ISO_8859_1),StandardCharsets.UTF_8);System.out.println(解决乱码后username);}Overrideprotected
把request.setCharacterEncoding(UTF-8)代码注释掉后会发现GET请求参数乱码解决方案同时也可也把POST请求参数乱码的问题也解决了只不过对于POST请求参数一般都会比较多采用这种方式解决乱码起来比较麻烦所以对于POST请求还是建议使用设置编码的方式进行。
另外需要说明一点的是Tomcat8.0之后已将GET请求乱码问题解决设置默认的解码方式为UTF-8
POST请求和GET请求的参数中如果有中文后台接收数据就会出现中文乱码问题
request.setCharacterEncoding(UTF-8);
注意:设置的字符集要和页面保持一致通用方式GET/POST需要先解码再编码
String(username.getBytes(ISO-8859-1),UTF-8);URL编码实现方式:
URLEncoder.encode(str,UTF-8);解码:
URLDecoder.decode(s,ISO-8859-1);2.5
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-qpkNbRmN-1692455387638)(assets/1628851404283.png)]
req.getRequestDispatcher(资源B路径).forward(req,resp);具体如何来使用我们先来看下需求:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-U1hsTCX4-1692455387638)(assets/1628854783523.png)]
1.创建一个RequestDemo5类接收/req5的请求在doGet方法中打印demo5
2.创建一个RequestDemo6类接收/req6的请求在doGet方法中打印demo6
req.getRequestDispatcher(“/req6”).forward(req,resp)进行请求转发
{System.out.println(demo5...);}Overrideprotected
{System.out.println(demo6...);}Overrideprotected
}(3)在RequestDemo5的doGet方法中进行请求转发
{System.out.println(demo5...);//请求转发request.getRequestDispatcher(/req6).forward(request,response);}Overrideprotected
访问http://localhost:8080/request-demo/req5,就可以在控制台看到如下内容:
此处主要解决的问题是把请求从/req5转发到/req6的时候如何传递数据给/req6。
存储数据到request域[范围,数据是存储在request对象]中
1.在RequestDemo5的doGet方法中转发请求之前将数据存入request域对象中
2.在RequestDemo6的doGet方法从request域对象中获取数据并将数据打印到控制台
{System.out.println(demo5...);//存储数据request.setAttribute(msg,hello);//请求转发request.getRequestDispatcher(/req6).forward(request,response);}Overrideprotected
{System.out.println(demo6...);//获取数据Object
request.getAttribute(msg);System.out.println(msg);}Overrideprotected
访问http://localhost:8080/request-demo/req5,就可以在控制台看到如下内容:
虽然后台从/req5转发到/req6,但是浏览器的地址一直是/req5,未发生变化
Request:使用request对象来获取请求数据Response:使用response对象来设置响应数据
Reponse的继承体系和Request的继承体系也非常相似:
介绍完Response的相关体系结构后接下来对于Response我们需要学习如下内容:
Response设置响应数据的功能介绍Response完成重定向Response响应字符数据Response响应字节数据
HTTP响应数据总共分为三部分内容分别是响应行、响应头、响应体对于这三部分内容的数据respone对象都提供了哪些方法来进行设置?
getOutputStream();介绍完这些方法后后面我们会通过案例把这些方法都用一用首先先来完成下重定向的功能开发。
Response重定向(redirect):一种资源跳转方式。
(2)资源A现在无法处理该请求就会给浏览器响应一个302的状态码location的一个访问资源B的路径
(3)浏览器接收到响应状态码为302就会重新发送请求到location对应的访问地址去访问资源B
(4)资源B接收到请求后进行处理并最终给浏览器响应结果这整个过程就叫重定向
resp.setHeader(location,资源B的访问路径);具体如何来使用我们先来看下需求:
1.创建一个ResponseDemo1类接收/resp1的请求在doGet方法中打印resp1....
2.创建一个ResponseDemo2类接收/resp2的请求在doGet方法中打印resp2....
response.setHeader(“Location”,“/request-demo/resp2”)
{System.out.println(resp1....);}Overrideprotected
{System.out.println(resp2....);}Overrideprotected
}(3)在ResponseDemo1的doGet方法中给前端响应数据
{System.out.println(resp1....);//重定向//1.设置响应状态码
302response.setStatus(302);//2.
Locationresponse.setHeader(Location,/request-demo/resp2);}Overrideprotected
访问http://localhost:8080/request-demo/resp1,就可以在控制台看到如下内容:
说明/resp1和/resp2都被访问到了。
到这重定向就已经完成了。
虽然功能已经实现但是从设置重定向的两行代码来看会发现除了重定向的地址不一样其他的内容都是一模一样所以request对象给我们提供了简化的编写方式为:
resposne.sendRedirect(/request-demo/resp2)所以第3步中的代码就可以简化为
{System.out.println(resp1....);//重定向resposne.sendRedirect(/request-demo/resp2)}Overrideprotected
当进行重定向访问的时候由于是由浏览器发送的两次请求所以地址会发生变化
因为第一次响应结果中包含了浏览器下次要跳转的路径所以这个路径是可以任意位置资源。
因为浏览器发送了两次请求是两个不同的request对象就无法通过request对象进行共享数据
介绍完请求重定向和请求转发以后接下来需要把这两个放在一块对比下:
问题1转发的时候路径上没有加/request-demo而重定向加了那么到底什么时候需要加什么时候不需要加呢?
对于重定向来说路径最终是由浏览器来发送请求就需要添加虚拟目录。
action路径req.getRequestDispatcher(“路径”)resp.sendRedirect(“路径”)
4.重定向是由浏览器进行跳转需要加问题2在重定向的代码中/request-demo是固定编码的如果后期通过Tomcat插件配置了项目的访问路径那么所有需要重定向的地方都需要重新修改该如何优化?
答案也比较简单我们可以在代码中动态去获取项目访问的虚拟目录具体如何获取我们可以借助前面咱们所学习的request对象中的getContextPath()方法修改后的代码如下:
{System.out.println(resp1....);//简化方式完成重定向//动态获取虚拟目录String
request.getContextPath();response.sendRedirect(contextPath/resp2);}Overrideprotected
}重新启动访问测试功能依然能够实现此时就可以动态获取项目访问的虚拟路径从而降低代码的耦合度。
{response.setContentType(text/html;charsetutf-8);//1.
response.getWriter();writer.write(aaa);}Overrideprotected
//content-type告诉浏览器返回的数据类型是HTML类型数据这样浏览器才会解析HTML标签
response.setHeader(content-type,text/html);
writer.write(h1aaa/h1);注意:一次请求响应结束后response对象就会被销毁掉所以不要手动关闭流。
返回一个中文的字符串你好需要注意设置响应数据的编码为utf-8
response.setContentType(text/html;charsetutf-8);
通过Response对象获取字节输出流ServletOutputStream
FileInputStream(d://a.jpg);//2.
获取response字节输出流ServletOutputStream
response.getOutputStream();//3.
-1){os.write(buff,0,len);}fis.close();}Overrideprotected
}上述代码中对于流的copy的代码还是比较复杂的所以我们可以使用别人提供好的方法来简化代码的开发具体的步骤是:
dependencygroupIdcommons-io/groupIdartifactIdcommons-io/artifactIdversion2.6/version
FileInputStream(d://a.jpg);//2.
获取response字节输出流ServletOutputStream
response.getOutputStream();//3.
完成流的copyIOUtils.copy(fis,os);fis.close();}Overrideprotected
接下来我们通过两个比较常见的案例一个是注册一个是登录来对今天学习的内容进行一个实战演练首先来实现用户登录。
用户在登录页面输入用户名和密码提交请求给LoginServlet在LoginServlet中接收请求和数据[用户名和密码]在LoginServlt中通过Mybatis实现调用UserMapper来根据用户名和密码查询数据库表将查询的结果封装到User对象中进行返回在LoginServlet中判断返回的User对象是否为null如果为nul说明根据用户名和密码没有查询到用户则登录失败返回登录失败数据给前端如果不为null,则说明用户存在并且密码正确则登录成功返回登录成功数据给前端
MyBatis环境\tb_user.sql中的sql语句执行下:
MyBatis环境\User.java拷贝到com.i***ima.pojo
dependencygroupIdorg.mybatis/groupIdartifactIdmybatis/artifactIdversion3.5.5/version
/dependencydependencygroupIdmysql/groupIdartifactIdmysql-connector-java/artifactIdversion5.1.34/version
/dependency创建mybatis-config.xml核心配置文件UserMapper.xml映射文件,UserMapper接口
MyBatis环境\mybatis-config.xml拷贝到resources目录下
3.0//ENhttp://mybatis.org/dtd/mybatis-3-config.dtd
configuration!--起别名--typeAliasespackage
namecom.i***ima.pojo//typeAliasesenvironments
iddevelopmenttransactionManager
valuecom.mysql.jdbc.Driver/!--useSSL:关闭SSL安全连接
性能更高useServerPrepStmts:开启预编译功能amp;
valuejdbc:mysql:///db1?useSSLfalseamp;useServerPrepStmtstrue/property
value1234//dataSource/environment/environmentsmappers!--扫描mapper--package
namecom.i***ima.mapper//mappers
在com.i***ima.mapper包下创建UserMapper接口
MyBatis环境\UserMapper.xml拷贝到resources目录下
注意在resources下创建UserMapper.xml的目录时要使用/分割
在UserMapper接口中提供一个根据用户名和密码查询用户对象的方法
Param注解的作用:用于传递参数,是方法的参数可以与SQL中的字段名相对应。
charsetUTF-8titlelogin/titlelink
action/request-demo/loginServlet
hrefregister.html没有账号点击注册/a/div/form
request.getParameter(username);String
request.getParameter(password);//2.
Resources.getResourceAsStream(resource);SqlSessionFactory
SqlSessionFactoryBuilder().build(inputStream);//2.2
sqlSessionFactory.openSession();//2.3
sqlSession.getMapper(UserMapper.class);//2.4
释放资源sqlSession.close();//获取字符输出流并设置content
typeresponse.setContentType(text/html;charsetutf-8);PrintWriter
登陆失败writer.write(登陆失败);}}Overrideprotected
用户在注册页面输入用户名和密码提交请求给RegisterServlet在RegisterServlet中接收请求和数据[用户名和密码]在RegisterServlet中通过Mybatis实现调用UserMapper来根据用户名查询数据库表将查询的结果封装到User对象中进行返回在RegisterServlet中判断返回的User对象是否为null如果为nul说明根据用户名可用则调用UserMapper来实现添加用户如果不为null,则说明用户不可以返回用户名已存在数据给前端
编写UserMapper提供根据用户名查询用户数据方法和添加用户方法
values(null,#{username},#{password}))
charsetUTF-8title欢迎注册/titlelink
classreg-contenth1欢迎注册/h1span已有帐号/span
action/request-demo/registerServlet
none用户名不太受欢迎/span/td/trtrtd密码/tdtd
request.getParameter(username);String
request.getParameter(password);//封装用户对象User
User();user.setUsername(username);user.setPassword(password);//2.
Resources.getResourceAsStream(resource);SqlSessionFactory
SqlSessionFactoryBuilder().build(inputStream);//2.2
sqlSessionFactory.openSession();//2.3
sqlSession.getMapper(UserMapper.class);//2.4
userMapper.selectByUsername(username);//3.
用户名不存在添加用户userMapper.add(user);//
用户名存在给出提示信息response.setContentType(text/html;charsetutf-8);response.getWriter().write(用户名已存在);}}Overrideprotected
上面两个功能已经实现但是在写Servlet的时候因为需要使用Mybatis来完成数据库的操作所以对于Mybatis的基础操作就出现了些重复代码如下
Resources.getResourceAsStream(resource);
SqlSessionFactoryBuilder().build(inputStream);有了这些重复代码就会造成一些问题:
重复代码不利于后期的维护SqlSessionFactory工厂类进行重复创建
就相当于每次买手机都需要重新创建一个手机生产工厂来给你制造一个手机一样资源消耗非常大但性能却非常低。
所以这么做是不允许的。
代码重复可以抽取工具类对指定代码只需要执行一次可以使用静态代码块
Resources.getResourceAsStream(resource);sqlSessionFactory
SqlSessionFactoryBuilder().build(inputStream);}
}工具类抽取以后以后在对Mybatis的SqlSession进行操作的时候就可以直接使用
SqlSessionFactoryUtils.getSqlSessionFactory();这样就可以很好的解决上面所说的代码重复和重复创建工厂导致性能低的问题了。
作为专业的SEO优化服务提供商,我们致力于通过科学、系统的搜索引擎优化策略,帮助企业在百度、Google等搜索引擎中获得更高的排名和流量。我们的服务涵盖网站结构优化、内容优化、技术SEO和链接建设等多个维度。
| 服务项目 | 基础套餐 | 标准套餐 | 高级定制 |
|---|---|---|---|
| 关键词优化数量 | 10-20个核心词 | 30-50个核心词+长尾词 | 80-150个全方位覆盖 |
| 内容优化 | 基础页面优化 | 全站内容优化+每月5篇原创 | 个性化内容策略+每月15篇原创 |
| 技术SEO | 基本技术检查 | 全面技术优化+移动适配 | 深度技术重构+性能优化 |
| 外链建设 | 每月5-10条 | 每月20-30条高质量外链 | 每月50+条多渠道外链 |
| 数据报告 | 月度基础报告 | 双周详细报告+分析 | 每周深度报告+策略调整 |
| 效果保障 | 3-6个月见效 | 2-4个月见效 | 1-3个月快速见效 |
我们的SEO优化服务遵循科学严谨的流程,确保每一步都基于数据分析和行业最佳实践:
全面检测网站技术问题、内容质量、竞争对手情况,制定个性化优化方案。
基于用户搜索意图和商业目标,制定全面的关键词矩阵和布局策略。
解决网站技术问题,优化网站结构,提升页面速度和移动端体验。
创作高质量原创内容,优化现有页面,建立内容更新机制。
获取高质量外部链接,建立品牌在线影响力,提升网站权威度。
持续监控排名、流量和转化数据,根据效果调整优化策略。
基于我们服务的客户数据统计,平均优化效果如下:
我们坚信,真正的SEO优化不仅仅是追求排名,而是通过提供优质内容、优化用户体验、建立网站权威,最终实现可持续的业务增长。我们的目标是与客户建立长期合作关系,共同成长。
Demand feedback