SEO技术

SEO技术

Products

当前位置:首页 > SEO技术 >

如何设计一个会展门户网站的高效网站制作方案?

96SEO 2026-02-19 22:22 0


ava

新疆-乌鲁木齐、新疆-吐鲁番、广东-广州、广东-佛山、湖南-长沙、湖南-张家界、山西、上海、郑州等。

如何设计一个会展门户网站的高效网站制作方案?

老家河南嘞

自律狂人

没有伞的孩子、只能用力奔跑。

向着架构师的方向努力、做一个有始有终的人。

案例代码Github

VView视图层指工程中的html或jsp等页面作用是与用户进行交互展示数据

CController控制层指工程中的servlet作用是接收请求和响应浏览器。

用户通过视图层发送请求到服务器在服务器中请求被Controller接收Controller调用相应的Model层处理请求处理完毕将结果返回到ControllerController再根据请求处理的结果找到相应的View视图渲染数据后最终响应给浏览器

SpringMVC是Spring的一个后续产品是Spring的一个子项目

SpringMVC

注三层架构分为表述层或表示层、业务逻辑层、数据访问层表述层表示前台页面和后台servlet

1、Spring

2、基于原生的Servlet通过了功能强大的前端控制器DispatcherServlet对请求和响应进行统一处理

4、代码清新简洁大幅度提升开发效率

5、内部组件化程度高可插拔式组件即插即用想要什么功能配置相应组件即可

2、SpringMVC创建实例Hello

2022最新版超详细的Maven下载配置教程、IDEA中集成maven包含图解过程、以及导入项目时jar包下载不成功的问题解决

添加web模块

--dependencygroupIdorg.springframework/groupIdartifactIdspring-webmvc/artifactIdversion5.3.1/version/dependency!--

--dependencygroupIdch.qos.logback/groupIdartifactIdlogback-classic/artifactIdversion1.2.3/version/dependency!--

ServletAPI

--dependencygroupIdjavax.servlet/groupIdartifactIdjavax.servlet-api/artifactIdversion3.1.0/versionscopecompile/scope/dependency!--

Spring5和Thymeleaf整合包

--dependencygroupIdorg.thymeleaf/groupIdartifactIdthymeleaf-spring5/artifactIdversion3.0.12.RELEASE/version/dependency

/dependencies注由于

的传递性我们不必将所有需要的包全部配置依赖而是配置最顶端的依赖其他靠传递性导入。

2.3、配置web.xml

过程创建webapp包、然后点击项目结构、找到对应的模块、添加web.xml。

对应的web.xml路径要写对。

然后自动在项目中完成创建

注册SpringMVC的前端控制器DispatcherServlet

2.3.2

此配置作用下SpringMVC的配置文件默认位于WEB-INF下默认名称为-servlet.xml例如以下配置所对应SpringMVC的配置文件位于WEB-INF下文件名为springMVC-servlet.xml

springMVC

org.springframework.web.servlet.DispatcherServlet

springMVC

可通过init-param标签设置SpringMVC配置文件的位置和名称通过load-on-startup标签设置SpringMVC前端控制器DispatcherServlet的初始化时间

!--

配置SpringMVC的前端控制器对浏览器发送的请求统一进行处理

servletservlet-namespringMVC/servlet-nameservlet-classorg.springframework.web.servlet.DispatcherServlet/servlet-class!--

--init-param!--

--param-namecontextConfigLocation/param-name!--

使用classpath:表示从类路径查找配置文件例如maven工程中的src/main/resources

--param-valueclasspath:springMVC.xml/param-value/init-param!--作为框架的核心组件在启动过程中有大量的初始化操作要做而这些操作放在第一次请求时才执行会严重影响访问速度因此需要通过此标签将启动控制DispatcherServlet的初始化时间提前到服务器启动时--load-on-startup1/load-on-startup

/servlet

servlet-mappingservlet-namespringMVC/servlet-name!--设置springMVC的核心控制器所能处理的请求的请求路径/所匹配的请求可以是/login或.html或.js或.css方式的请求路径但是/不能匹配.jsp请求路径的请求--url-pattern//url-pattern

/servlet-mapping提示、默认扩展就是将外部的MVC文件引入所以需要创建外部的xml文件

/所匹配的请求可以是/login或.html或.js或.css方式的请求路径但是/不能匹配.jsp请求路径的请求因此就可以避免在访问jsp页面时该请求被DispatcherServlet处理从而找不到相应的页面

/则能够匹配所有请求例如在使用过滤器时若需要对所有请求进行过滤就需要使用/的写

2.4、创建请求控制器

由于前端控制器对浏览器发送的请求进行了统一的处理但是具体的请求有不同的处理过程因此需要创建处理具体请求的类即请求控制器

因为SpringMVC的控制器由一个POJO普通的Java类担任因此需要通过Controller注解将其标识

为一个控制层组件交给Spring的IoC容器管理此时SpringMVC才能够识别控制器的存在

/***

xmlnshttp://www.springframework.org/schema/beansxmlns:xsihttp://www.w3.org/2001/XMLSchema-instancexmlns:contexthttp://www.springframework.org/schema/contextxsi:schemaLocationhttp://www.springframework.org/schema/beans

http://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/context

http://www.springframework.org/schema/context/spring-context.xsd!--扫描组件--context:component-scan

base-packagecom.zyz.mvc.controller/context:component-scan!--

配置Thymeleaf视图解析器

idviewResolverclassorg.thymeleaf.spring5.view.ThymeleafViewResolverproperty

nameorder

classorg.thymeleaf.spring5.SpringTemplateEngineproperty

classorg.thymeleaf.spring5.templateresolver.SpringResourceTemplateResolver!--

视图前缀

valueUTF-8//bean/property/bean/property/bean/beans2.6、配置tomcat

具体过程请参考2022年最新最详细在IDEA中配置Tomcat含有详细图解过程、建立使用IEDA建立一个Web项目的案例

2.7、测试HelloSpringMVC

RequestMapping注解处理请求和控制器方法之间的映射关系*

RequestMapping注解的value属性可以通过请求地址匹配请求/表示的当前工程的上下文路径*

/)public

xmlns:thhttp://www.thymeleaf.org

headmeta

th:href{/target}访问目标页面target.html/a

/body

注意要首先引入http://www.thymeleaf.org

!DOCTYPE

xmlns:thhttp://www.thymeleaf.org

headmeta

th:href{/target}访问目标页面target.html/a

/body

xmlns:thhttp://www.thymeleaf.org

headmeta

org.springframework.stereotype.Controller;

import

org.springframework.web.bind.annotation.RequestMapping;

import

org.springframework.web.bind.annotation.RequestParam;/***

author

RequestMapping注解处理请求和控制器方法之间的映射关系*

RequestMapping注解的value属性可以通过请求地址匹配请求/表示的当前工程的上下文路径*

localhost:8080/springMVC/*/RequestMapping(value

/)public

xmlnshttp://www.springframework.org/schema/beansxmlns:xsihttp://www.w3.org/2001/XMLSchema-instancexmlns:contexthttp://www.springframework.org/schema/contextxsi:schemaLocationhttp://www.springframework.org/schema/beans

http://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/context

http://www.springframework.org/schema/context/spring-context.xsd!--扫描组件--context:component-scan

base-packagecom.zyz.mvc.controller/context:component-scan!--

配置Thymeleaf视图解析器

idviewResolverclassorg.thymeleaf.spring5.view.ThymeleafViewResolverproperty

nameorder

classorg.thymeleaf.spring5.SpringTemplateEngineproperty

classorg.thymeleaf.spring5.templateresolver.SpringResourceTemplateResolver!--

视图前缀

valueUTF-8//bean/property/bean/property/bean/beans2.9.3

index.html

xmlns:thhttp://www.thymeleaf.org

headmeta

th:href{/target}访问目标页面target.html/a

/body

xmlns:thhttp://www.thymeleaf.org

headmeta

xmlnshttp://xmlns.jcp.org/xml/ns/javaeexmlns:xsihttp://www.w3.org/2001/XMLSchema-instancexsi:schemaLocationhttp://xmlns.jcp.org/xml/ns/javaee

http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsdversion4.0!--

配置SpringMVC的前端控制器对浏览器发送的请求统一进行处理

--servletservlet-namespringMVC/servlet-nameservlet-classorg.springframework.web.servlet.DispatcherServlet/servlet-class!--

--init-param!--

--param-namecontextConfigLocation/param-name!--

使用classpath:表示从类路径查找配置文件例如maven工程中的src/main/resources

--param-valueclasspath:springMVC.xml/param-value/init-param!--作为框架的核心组件在启动过程中有大量的初始化操作要做而这些操作放在第一次请求时才执行会严重影响访问速度因此需要通过此标签将启动控制DispatcherServlet的初始化时间提前到服务器启动时--load-on-startup1/load-on-startup/servletservlet-mappingservlet-namespringMVC/servlet-name!--设置springMVC的核心控制器所能处理的请求的请求路径/所匹配的请求可以是/login或.html或.js或.css方式的请求路径但是/不能匹配.jsp请求路径的请求--url-pattern//url-pattern/servlet-mapping/web-app2.10

、如何让创建的模板包含xmlns:th“http://www.thymeleaf.org”

3、RequestMapping注解

从注解名称上我们可以看到RequestMapping注解的作用就是将请求和处理请求的控制器方法关联起来建立映射关系。

SpringMVC

接收到指定的请求就会来找到在映射关系中对应的控制器方法来处理这个请求。

RequestMapping标识一个类设置映射请求的请求路径的初始信息

RequestMapping标识一个方法设置映射请求请求路径的具体信息

3.2.1

比如A类和B类中都有一个list。

为了区分是在类上加上注解、那么访问的地址就变成/A/list。

/B/list。

很实用的一个功能

Controller

return*/RequestMapping(/test)public

String

th:href{/hello/test}访问目标页面target.html/a测试结果

3.2.2

return*/RequestMapping(/test)public

String

th:href{/test}访问目标页面target.html/a测试结果

RequestMapping注解的value属性通过请求的请求地址匹配请求映射

RequestMapping注解的value属性是一个字符串类型的数组表示该请求映射能够匹配多个请求地址所对应的请求

RequestMapping注解的value属性必须设置至少通过请求地址匹配请求映射

注value一般写一个匹配路径就行

th:href{/test}访问目标页面target.html/aa

th:href{/myTest}访问目标页面target.html/a3.4、RequestMapping注解的method属性

RequestMapping注解的method属性通过请求的请求方式get或post匹配请求映射

RequestMapping注解的method属性是一个RequestMethod类型的数组表示该请求映射能够匹配多种请求方式的请求

若当前请求的请求地址满足请求映射的value属性但是请求方式不满足method属性则浏览器报错405Request

method

}1、对于处理指定请求方式的控制器方法SpringMVC中提供RequestMapping的派生注解

但是目前浏览器只支持get和post若在form表单提交时为method设置了其他请求方式的字符

RequestMapping注解的params属性通过请求的请求参数匹配请求映射

RequestMapping注解的params属性是一个字符串类型的数组可以通过四种表达式设置请求参数和请求映射的匹配关系

1、“param”要求请求映射所匹配的请求必须携带param请求参数

“2、!param”要求请求映射所匹配的请求必须不能携带param请求参数

“paramvalue”要求请求映射所匹配的请求必须携带param请求参数且paramvalue

4、“param!value”要求请求映射所匹配的请求必须携带param请求参数但是param!value

3.5.1

th:action{/test(username张三,password1234)}

methodpostinput

th:action{/test(username张三,password1234)}

methodpostinput

{username,password!1234})public

String

}若当前请求满足RequestMapping注解的value和method属性但是不满足params属性此时页面回报错400

RequestMapping注解的headers属性通过请求的请求头信息匹配请求映射

RequestMapping注解的headers属性是一个字符串类型的数组可以通过四种表达式设置请求头信息和请求映射的匹配关系

“header”要求请求映射所匹配的请求必须携带header请求头信息

“!header”要求请求映射所匹配的请求必须不能携带header请求头信息

“headervalue”要求请求映射所匹配的请求必须携带header请求头信息且headervalue

“header!value”要求请求映射所匹配的请求必须携带header请求头信息且header!value

若当前请求满足RequestMapping注解的value和method属性但是不满足headers属性此时页面显示404错误即资源未找到

3.6.1

th:action{/test(username张三,password12345)}

methodpostinput

{username,password!1234},headers

String

th:href{/fgf/mytest}访问目标页面target.html/aController

public

{RequestMapping(/f?f/mytest)public

String

th:href{/fg54edrf/mytest}访问目标页面target.html/aController

public

{RequestMapping(/f*f/mytest)public

String

th:href{/fg54edrf/mytest}访问目标页面target.html/aController

public

{RequestMapping(/**/mytest)public

String

success;}}3.8、SpringMVC支持路径中的占位符重点

SpringMVC路径中的占位符常用于RESTful风格中、我就喜欢这样使用

原始方式/deleteUser?id1

SpringMVC路径中的占位符常用于RESTful风格中当请求路径中将某些数据通过路径的方式传输到服务器中就可以在相应的RequestMapping注解的value属性中通过占位符{xxx}表示传输的数据在通过PathVariable注解将占位符所表示的数据赋值给控制器方法的形参

3.8.1

th:href{/mytest/4/张三}访问目标页面target.html/aController

public

{RequestMapping(/mytest/{id}/{username})public

String

将HttpServletRequest作为控制器方法的形参此时HttpServletRequest类型的参数表示封装了当前请求的请求报文的对象

4.1.1

th:href{/testServletAPI(username张三,password123456)}测试/aController

public

{RequestMapping(/testServletAPI)public

String

request.getParameter(username);String

password

request.getParameter(password);System.out.println(username:username,password:password);return

param_test;}

在控制器方法的形参位置设置和请求参数同名的形参当浏览器发送请求匹配到请求映射时在DispatcherServlet中就会将请求参数赋值给相应的形参

4.2.1

th:href{/testServletAPI(username张三,password123456)}测试/aController

public

{RequestMapping(/testServletAPI)public

String

password){System.out.println(username:username,password:password);return

param_test;}

{RequestMapping(/testParam)public

String

hobby){System.out.println(username:username,password:password,hobby:hobby);return

param_test;}

{RequestMapping(/testParam)public

String

hobby){System.out.println(username:username,password:password,hobby:

param_test;}

若请求所传输的请求参数中有多个同名的请求参数此时可以在控制器方法的形参中设置字符串

若使用字符串类型的形参此参数的值为每个数据中间使用逗号拼接的结果

4.3、RequestParam

RequestParam是将请求参数和控制器方法的形参创建映射关系

若设置为true时则当前请求必须传输value所指定的请求参数若没有传输该请求参数且没有设置

String

false则当前请求不是必须传输value所指定的请求参数若没有传输则注解所标识的形参的值为

null

defaultValue不管required属性值为true或false当value所指定的请求参数没有传输或传输的值

为时则使用默认值为形参赋值

{RequestMapping(/testParam)public

String

testParam(RequestParam(user_name)

String

hobby){System.out.println(username:username,password:password,hobby:

param_test;}

默认是必须传值设置这个参数非必须RequestMapping(/testParam)public

String

hobby){System.out.println(username:username,password:password,hobby:

param_test;}默认是必须传值RequestMapping(/testParam)public

String

testParam(RequestParam(user_name)

String

hobby){System.out.println(username:username,password:password,hobby:

param_test;}4.3.4

{RequestMapping(/testParam)public

String

RequestHeader是将请求头信息和控制器方法的形参创建映射关系

RequestHeader注解一共有三个属性value、required、defaultValue用法同RequestParam

4.4.1

{RequestMapping(/testParam)public

String

Arrays.toString(hobby),Host:host);return

param_test;}

CookieValue是将cookie数据和控制器方法的形参创建映射关系

CookieValue注解一共有三个属性value、required、defaultValue用法同RequestParam

可以在控制器方法的形参位置设置一个实体类类型的形参此时若浏览器传输的请求参数的参数名和实体类中的属性名一致那么请求参数就会为此属性赋值

4.6.1

{RequestMapping(/myTestParam)public

String

user){System.out.println(user);return

解决获取请求参数的乱码问题可以使用SpringMVC提供的编码过滤器CharacterEncodingFilter但是必须在web.xml中进行注册

filterfilter-nameCharacterEncodingFilter/filter-namefilter-classorg.springframework.web.filter.CharacterEncodingFilter/filter-classinit-paramparam-nameencoding/param-nameparam-valueUTF-8/param-value/init-paraminit-paramparam-nameforceResponseEncoding/param-nameparam-valuetrue/param-value/init-param/filterfilter-mappingfilter-nameCharacterEncodingFilter/filter-nameurl-pattern/*/url-pattern/filter-mapping环境搭建改系列文章开始有介绍。

这部分代码所在磁盘位置F:\workspace\SpringMVC代码\springMVC-demo4

从源码角度分析控制器https://blog.csdn.net/weixin_43304253/article/details/128071577

5、域对象共享数据

5.1、使用ServletAPI向request域对象共享数据

设置request.setAttribute(“testRequestScope”,“Hello,ServletAPI”);。

取值通过key

5.1.1

RequestMapping(/testRequestScope)

public

request){request.setAttribute(testRequestScope,Hello,ServletAPI);return

success;

xmlns:thhttp://www.thymeleaf.org

headmeta

5.2、使用ModelAndView向request域对象共享数据

5.1.1

RequestMapping(/testModelAndView)

public

View主要用于设置视图实现页面跳转*/ModelAndView

mav

ModelAndView();//用来处理模型数据向请求域request共享数据mav.addObject(testRequestScope,

Hello,ModelAndView);//设置视图名称mav.setViewName(success);return

mav;}取值同1.1

model){model.addAttribute(testRequestScope,Hello,Model);return

success;

map){map.put(testRequestScope,Hello,Map);return

success;

modelMap){modelMap.addAttribute(testRequestScope,Hello,ModelMap);return

success;

{}通过反射查看调用的方法System.out.println(model.getClass().getName());

System.out.println(map.getClass().getName());

System.out.println(modelMap.getClass().getName());5.7、向session域共享数据

5.7.1

session){session.setAttribute(testSession,Hello

Session);return

th:text${session.testSession}/p5.7.2

测试结果

RequestMapping(/testApplication)

public

session.getServletContext();application.setAttribute(testApplication,Hello

Application);return

th:text${application.testApplication}/p5.8.2

测试结果

xmlns:thhttp://www.thymeleaf.org

headmeta

th:href{/testRequestScope}测试requestAPI/a

th:href{/testModelAndView}测试ModelAndView/a

th:href{/testModelMap}测试ModelMap/a

th:href{/testSession}测试Session/a

th:href{/testApplication}测试Application/a

/body

xmlns:thhttp://www.thymeleaf.org

headmeta

th:text${session.testSession}/p

th:text${application.testApplication}/p

/body

org.springframework.stereotype.Controller;

import

org.springframework.ui.ModelMap;

import

org.springframework.web.bind.annotation.RequestMapping;

import

org.springframework.web.servlet.ModelAndView;import

import

javax.servlet.http.HttpServletRequest;

import

javax.servlet.http.HttpSession;

import

javax.servlet.http.HttpSessionContext;

import

return*/RequestMapping(/testRequestScope)public

String

{request.setAttribute(testRequestScope,

success;}/***

return*/RequestMapping(/testModelAndView)public

ModelAndView

View主要用于设置视图实现页面跳转*/ModelAndView

mav

ModelAndView();//用来处理模型数据向请求域request共享数据mav.addObject(testRequestScope,

Hello,ModelAndView);//设置视图名称mav.setViewName(success);return

mav;}/***

return*/RequestMapping(/testModel)public

String

model){model.addAttribute(testRequestScope,Hello,Model);System.out.println(model.getClass().getName());return

success;}/***

return*/RequestMapping(/testMap)public

String

map){map.put(testRequestScope,Hello,Map);System.out.println(map.getClass().getName());return

success;}/***

return*/RequestMapping(/testModelMap)public

String

modelMap){modelMap.addAttribute(testRequestScope,Hello,ModelMap);System.out.println(modelMap.getClass().getName());return

success;}/***

return*/RequestMapping(/testSession)public

String

session){session.setAttribute(testSession,Hello

Session);return

return*/RequestMapping(/testApplication)public

String

session.getServletContext();application.setAttribute(testApplication,Hello

Application);return

SpringMVC种通过追踪源码查看是哪种类型的视图渲染器一般流程方法

1、返回视图打断点

SpringMVC中的视图是View接口视图的作用渲染数据将模型Model中的数据展示给用户

若使用的视图技术为Thymeleaf在SpringMVC的配置文件中配置了Thymeleaf的视图解析器由此视

通过Debug模式查看通过追踪源码查看是哪种类型的视图渲染器一般流程方法

6.1、ThymeleafView

当控制器方法中所设置的视图名称没有任何前缀时此时的视图名称会被SpringMVC配置文件中所配置

的视图解析器解析视图名称拼接视图前缀和视图后缀所得到的最终路径会通过转发的方式实现跳转

6.1.1

RequestMapping(/testThymeleafView)

public

SpringMVC中默认的转发视图是InternalResourceView

当控制器方法中所设置的视图名称以forward:为前缀时创建InternalResourceView视图此时的视

图名称不会被SpringMVC配置文件中所配置的视图解析器解析而是会将前缀forward:“去掉剩余部分作为最终路径通过转发的方式实现跳转

例如forward:/”“forward:/employee”

6.2.1

RequestMapping(“/testThymeleafView”)

public

SpringMVC中默认的重定向视图是RedirectView

当控制器方法中所设置的视图名称以redirect:为前缀时创建RedirectView视图此时的视图名称不

会被SpringMVC配置文件中所配置的视图解析器解析而是会将前缀redirect:“去掉剩余部分作为最

例如redirect:/”“redirect:/employee”

6.3.1

RequestMapping(/testThymeleafView)

public

当控制器方法中仅仅用来实现页面跳转即只需要设置视图名称时可以将处理器方法使用viewcontroller标签进行表示

!--

view-namesuccess/mvc:view-controller注

当SpringMVC中设置任何一个view-controller时其他控制器中的请求映射将全部失效此时需

要在SpringMVC的核心配置文件中设置开启mvc注解驱动的标签

6.4.1

view-nameindex/mvc:view-controller代替RequestMapping(/)public

String

index;}需要添加注解驱动、否则跳转连接无效!--开启mvc的注解驱动--mvc:annotation-driven/6.4.2

开启后、正常跳转

资源是一种看待服务器的方式即将服务器看作是由很多离散的资源组成。

每个资源是服务器上一个可命名的抽象概念。

因为资源是一个抽象的概念所以它不仅仅能代表服务器文件系统中的一个文件、数据库中的一张表等等具体的东西可以将资源设计的要多抽象有多抽象只要想象力允许而且客户端应用开发者能够理解。

与面向对象设计类似资源是以名词为核心来组织的首先关注的是名词。

一个资源可以由一个或多个URI来标识。

URI既是资源的名称也是资源在Web上的地址。

对某个资源感兴趣的客户端应用可以通过资源的URI与其进行交互。

资源的表述是一段对于资源在某个特定时刻的状态的描述。

可以在客户端-服务器端之间转移换。

资源的表述可以有多种格式例如HTML/XML/JSON/纯文本/图片/视频/音频等等。

资源的表述格式可以通过协商机制来确定。

请求-响应方向的表述通常使用不同的格式。

c状态转移

状态转移说的是在客户端和服务器端之间转移transfer代表资源状态的表述。

通过转移和操作资源的表述来间接实现操作资源的目的。

HTTP

协议里面四个表示操作方式的动词GET、POST、PUT、DELETE。

它们分别对应四种基本操作GET

地址使用统一的风格设计从前到后各个单词使用斜杠分开不使用问号键值对方式携带请求参数而是将要发送给服务器的数据作为

URL

由于浏览器只支持发送get和post方式的请求那么该如何发送put和delete请求呢

SpringMVC

method的值因此请求参数method的值才是最终的请求方式

在web.xml中注册HiddenHttpMethodFilter

filterfilter-nameHiddenHttpMethodFilter/filter-namefilter-classorg.springframework.web.filter.HiddenHttpMethodFilter/filter-class

/filter

filter-mappingfilter-nameHiddenHttpMethodFilter/filter-nameurl-pattern/*/url-pattern

/filter-mapping目前为止SpringMVC中提供了两个过滤器CharacterEncodingFilter和

在web.xml中注册时必须先注册CharacterEncodingFilter再注册HiddenHttpMethodFilter

request.setCharacterEncoding(encoding)

方法设置字

request.setCharacterEncoding(encoding)

paramValue

request.getParameter(this.methodParam);

7.4、实际代码案例

org.springframework.stereotype.Controller;

import

org.springframework.web.bind.annotation.RequestMapping;

import

org.springframework.web.bind.annotation.RequestMethod;/***

author

使用RESULT模拟用户资源的增删改查*/***查询所有用户信息*

/user,method

getAllUser(){System.out.println(查询所有用户信息);return

success;}/***

getUserById(){System.out.println(根据ID查询用户信息);return

success;}/***

password){System.out.println(添加用户信息username,password);return

success;}/***

password){System.out.println(修改用户信息username,password);return

success;}}

xmlns:thhttp://www.thymeleaf.org

headmeta

8、SpringMVC创建JSP页面的详细过程配置模板实现页面跳转配置Tomcat

8.1、创建Maven项目

packagingwar/packaging依赖、可自行添加需要jar包依赖

dependencies!--

--dependencygroupIdorg.springframework/groupIdartifactIdspring-webmvc/artifactIdversion5.3.1/version/dependency!--

--dependencygroupIdch.qos.logback/groupIdartifactIdlogback-classic/artifactIdversion1.2.3/version/dependency!--

ServletAPI

--dependencygroupIdjavax.servlet/groupIdartifactIdjavax.servlet-api/artifactIdversion3.1.0/versionscopecompile/scope/dependency!--

Spring5和Thymeleaf整合包

--dependencygroupIdorg.thymeleaf/groupIdartifactIdthymeleaf-spring5/artifactIdversion3.0.12.RELEASE/version/dependencydependencygroupIdorg.projectlombok/groupIdartifactIdlombok/artifactIdversionRELEASE/versionscopecompile/scope/dependencydependencygroupIdorg.projectlombok/groupIdartifactIdlombok/artifactIdversionRELEASE/versionscopecompile/scope/dependencydependencygroupIdorg.projectlombok/groupIdartifactIdlombok/artifactIdversionRELEASE/versionscopecompile/scope/dependencydependencygroupIdorg.projectlombok/groupIdartifactIdlombok/artifactIdversionRELEASE/versionscopecompile/scope/dependencydependencygroupIdorg.projectlombok/groupIdartifactIdlombok/artifactIdversionRELEASE/versionscopecompile/scope/dependency/dependencies8.4、选择项目结构

8.5、创建web.xml

xmlnshttp://xmlns.jcp.org/xml/ns/javaeexmlns:xsihttp://www.w3.org/2001/XMLSchema-instancexsi:schemaLocationhttp://xmlns.jcp.org/xml/ns/javaee

http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsdversion4.0!--配置过滤器编码--filterfilter-nameCharacterEncodingFilter/filter-namefilter-classorg.springframework.web.filter.CharacterEncodingFilter/filter-classinit-paramparam-nameencoding/param-nameparam-valueUTF-8/param-value/init-paraminit-paramparam-nameforceResponseEncoding/param-nameparam-valuetrue/param-value/init-param/filterfilter-mappingfilter-nameCharacterEncodingFilter/filter-nameurl-pattern/*/url-pattern/filter-mapping!--

配置SpringMVC的前端控制器对浏览器发送的请求统一进行处理

--servletservlet-namespringMVC/servlet-nameservlet-classorg.springframework.web.servlet.DispatcherServlet/servlet-class!--

--init-param!--

--param-namecontextConfigLocation/param-name!--

使用classpath:表示从类路径查找配置文件例如maven工程中的src/main/resources

--param-valueclasspath:springMVC.xml/param-value/init-param!--作为框架的核心组件在启动过程中有大量的初始化操作要做而这些操作放在第一次请求时才执行会严重影响访问速度因此需要通过此标签将启动控制DispatcherServlet的初始化时间提前到服务器启动时--load-on-startup1/load-on-startup/servletservlet-mappingservlet-namespringMVC/servlet-name!--设置springMVC的核心控制器所能处理的请求的请求路径/所匹配的请求可以是/login或.html或.js或.css方式的请求路径但是/不能匹配.jsp请求路径的请求--url-pattern//url-pattern/servlet-mapping

/web-app8.8、配置模板解析器

xmlnshttp://www.springframework.org/schema/beansxmlns:xsihttp://www.w3.org/2001/XMLSchema-instancexmlns:contexthttp://www.springframework.org/schema/contextxsi:schemaLocationhttp://www.springframework.org/schema/beans

http://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/context

http://www.springframework.org/schema/context/spring-context.xsd!--扫描组件--context:component-scan

base-packagecom.zyz.mvc.controller/context:component-scanbean

classorg.springframework.web.servlet.view.InternalResourceViewResolverproperty

nameprefix

value/WEB-INF/templates//propertyproperty

namesuffix

value.jsp/property/bean/beans8.9、配置包templates

8.10、创建index.jsp

contentTypetext/html;charsetUTF-8

languagejava

org.springframework.stereotype.Controller;

import

org.springframework.web.bind.annotation.RequestMapping;/***

author

{RequestMapping(/success)public

String

contentTypetext/html;charsetUTF-8

languagejava

contentTypetext/html;charsetUTF-8

languagejava

href${pageContext.request.contextPath}/successsuccess.jsp/a

/body

idviewResolverclassorg.thymeleaf.spring5.view.ThymeleafViewResolverproperty

nameorder

classorg.thymeleaf.spring5.SpringTemplateEngineproperty

classorg.thymeleaf.spring5.templateresolver.SpringResourceTemplateResolver!--

视图前缀

valueUTF-8//bean/property/bean/property/bean这篇的主要目的是锻炼使用Result风格的接口开发。

数据是假数据并未真正连接到数据库、页面使用BootStrap大致构建一下不至于那么丑

项目地址F:\workspace\SpringMVC代码\SpringMVC-rest

项目的搭建过程、如何配置Tomcat过程略、改专栏系列之前有些。

此处不做赘述

9、RESTful案例。

SpringMVCthymeleafBootStrapRestFul实现员工信息的增删改查

9.1、项目结构

xmlnshttp://xmlns.jcp.org/xml/ns/javaeexmlns:xsihttp://www.w3.org/2001/XMLSchema-instancexsi:schemaLocationhttp://xmlns.jcp.org/xml/ns/javaee

http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsdversion4.0!--配置过滤器编码--filterfilter-nameCharacterEncodingFilter/filter-namefilter-classorg.springframework.web.filter.CharacterEncodingFilter/filter-classinit-paramparam-nameencoding/param-nameparam-valueUTF-8/param-value/init-paraminit-paramparam-nameforceResponseEncoding/param-nameparam-valuetrue/param-value/init-param/filterfilter-mappingfilter-nameCharacterEncodingFilter/filter-nameurl-pattern/*/url-pattern/filter-mappingfilterfilter-nameHiddenHttpMethodFilter/filter-namefilter-classorg.springframework.web.filter.HiddenHttpMethodFilter/filter-class/filterfilter-mappingfilter-nameHiddenHttpMethodFilter/filter-nameurl-pattern/*/url-pattern/filter-mapping!--

配置SpringMVC的前端控制器对浏览器发送的请求统一进行处理

--servletservlet-namespringMVC/servlet-nameservlet-classorg.springframework.web.servlet.DispatcherServlet/servlet-class!--

--init-param!--

--param-namecontextConfigLocation/param-name!--

使用classpath:表示从类路径查找配置文件例如maven工程中的src/main/resources

--param-valueclasspath:springMVC.xml/param-value/init-param!--作为框架的核心组件在启动过程中有大量的初始化操作要做而这些操作放在第一次请求时才执行会严重影响访问速度因此需要通过此标签将启动控制DispatcherServlet的初始化时间提前到服务器启动时--load-on-startup1/load-on-startup/servletservlet-mappingservlet-namespringMVC/servlet-name!--设置springMVC的核心控制器所能处理的请求的请求路径/所匹配的请求可以是/login或.html或.js或.css方式的请求路径但是/不能匹配.jsp请求路径的请求--url-pattern//url-pattern/servlet-mapping/web-app9.2.2

springMVC.xml文件

xmlnshttp://www.springframework.org/schema/beansxmlns:xsihttp://www.w3.org/2001/XMLSchema-instancexmlns:contexthttp://www.springframework.org/schema/contextxmlns:mvchttp://www.springframework.org/schema/mvcxsi:schemaLocationhttp://www.springframework.org/schema/beans

http://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/context

http://www.springframework.org/schema/context/spring-context.xsd

http://www.springframework.org/schema/mvc

https://www.springframework.org/schema/mvc/spring-mvc.xsd!--扫描组件--context:component-scan

base-packagecom.zyz.mvc/context:component-scan!--

配置Thymeleaf视图解析器

idviewResolverclassorg.thymeleaf.spring5.view.ThymeleafViewResolverproperty

nameorder

classorg.thymeleaf.spring5.SpringTemplateEngineproperty

classorg.thymeleaf.spring5.templateresolver.SpringResourceTemplateResolver!--

视图前缀

valueUTF-8//bean/property/bean/property/bean!--配置视图控制器--mvc:view-controller

path/

view-nameindex/mvc:view-controllermvc:view-controller

path/addEmployee

view-nameemployee_add/mvc:view-controller!--开放对静态资源的访问--mvc:default-servlet-handler/!--开启mvc的注解驱动--mvc:annotation-driven//beans9.2.3

package

org.springframework.beans.factory.annotation.Autowired;

import

org.springframework.stereotype.Controller;

import

org.springframework.web.bind.annotation.PathVariable;

import

org.springframework.web.bind.annotation.RequestMapping;

import

org.springframework.web.bind.annotation.RequestMethod;import

author

employeeDao.getAll();model.addAttribute(employeeList,employeeList);return

employee_list;}/***

deleteEmployee(PathVariable(id)

Integer

){employeeDao.delete(id);return

添加用户信息*

employee){employeeDao.save(employee);return

跳转修改员工信息*

toUpdateEmployee(PathVariable(id)

Integer

employeeDao.get(id);model.addAttribute(employee,employee);return

修改用户信息*

employee){employeeDao.save(employee);return

EmployeeDao.java

org.springframework.stereotype.Repository;import

import

{employee.setId(initId);}employees.put(employee.getId(),

employee);}public

xmlns:thhttp://www.thymeleaf.org

headmeta

charsetUTF-8title员工信息/titlestyle

typetext/cssa

hrefhttps://cdn.staticfile.org/twitter-bootstrap/3.3.7/css/bootstrap.min.css

relstylesheet

classpage-headerh1small员工信息----------显示所有员工信息/small/h1/div/div/divdiv

classrow

th:href{/addEmployee}添加员工/a/divdiv

classcol-md-4

table-stripedtheadtrth编号/thth姓名/thth邮箱/thth性别/thth

colspan2操作/th/tr/thead!--查询用户处理--tbodytr

th:eachemployee

th:text${employee.lastName}/tdtd

th:text${employee.email}/tdtddiv

th:switch${employee.gender}span

th:case1男/spanspan

clickdeleteEmployeeth:href{/employee/${employee.id}}删除/aa

classbtn

th:href{/employee/${employee.id}}修改/a/td/tr/tbody/table/div/div/divform

iddeleteForm

th:src{/static/js/vue.js}/script

script

document.getElementById(deleteForm);deleteForm.action

event.target.href;deleteForm.submit();event.preventDefault();}}})

/script/body

xmlns:thhttp://www.thymeleaf.org

headmeta

hrefhttps://cdn.staticfile.org/twitter-bootstrap/3.3.7/css/bootstrap.min.css

relstylesheet

classpage-headerh1small添加员工/small/h1/div/div/divform

th:action{/employee}

classform-grouplabel姓名/labelinput

typetext

classform-grouplabel邮箱/labelinput

typetext

xmlns:thhttp://www.thymeleaf.org

headmeta

hrefhttps://cdn.staticfile.org/twitter-bootstrap/3.3.7/css/bootstrap.min.css

relstylesheet

classpage-headerh1small修改信息/small/h1/div/div/divform

th:action{/employee}

classform-grouplabel姓名/labelinput

typetext

th:value${employee.lastName}/divdiv

classform-grouplabel邮箱/labelinput

typetext

th:value${employee.email}/divdiv

classform-grouplabel

th:field${employee.gender}男input

typeradio

th:field${employee.gender}女/divinput

typesubmit

xmlns:thhttp://www.thymeleaf.org

headmeta

HttpMessageConverter报文信息转换器将请求报文转换为Java对象或将Java对象转换为响应报文

HttpMessageConverter提供了两个注解和两个类型RequestBodyResponseBodyRequestEntity

ResponseEntity

RequestBody可以获取请求体需要在控制器方法设置一个形参使用RequestBody进行标识当前请求的请求体就会为当前注解所标识的形参赋值

form

{System.out.println(requestBody);return

success;}测试结果

RequestEntity封装请求报文的一种类型需要在控制器方法的形参中设置该类型的形参当前请求的请求报文就会赋值给该形参可以通过getHeaders()获取请求头信息通过getBody()获取请求体信息

form

testRequestEntity(RequestEntityString

requestEntity)

requestEntity.getHeaders());System.out.println(请求体

requestEntity.getBody());return

success;}测试结果

ResponseBody用于标识一个控制器方法可以将该方法的返回值直接作为响应报文的响应体响应到浏览器

th:href{/testResponse}测试response/a/***

测试response*

IOException*/RequestMapping(/testResponse)public

void

testResponse(HttpServletResponse

response)

{response.getWriter().print(hello,Resopnse);}测试结果

10.4、SpringMVC处理json

dependencygroupIdcom.fasterxml.jackson.core/groupIdartifactIdjackson-databind/artifactIdversion2.12.1/version

/dependency●

在SpringMVC的核心配置文件中开启mvc的注解驱动此时在HandlerAdaptor中会自动装配一个消息转换器MappingJackson2HttpMessageConverter可以将响应到浏览器的Java对象转换为Json格式的字符串

将Java对象直接作为控制器方法的返回值返回就会自动转换为Json格式的字符串

/***

RequestMapping(/testResponseUser)

ResponseBody

ArrayList();list.add(user1);list.add(user2);return

list;}测试结果

th:href{/testAxios}SpringMVC处理axios/a

/divscript

th:src{/static/js/vue.js}/script

script

th:src{/static/js/axios.min.js}/script

script

Vue({el:#app,methods:{testAxios:function

(event){axios({method:post,url:event.target.href,params:{username:张三,password:123456}}).then(function

(res){alert(res.data)})event.preventDefault();}}})

/script控制器方法

password){System.out.println(姓名username,密码password);return

hello,axios;

我终于深刻理解RestController和Controller两者的使用场景

RestController注解是springMVC提供的一个复合注解标识在控制器的类上就相当于为类添加了Controller注解并且为其中的每个方法添加了ResponseBody注解

10.7、ResponseEntity

ResponseEntity用于控制器方法的返回值类型该控制器方法的返回值就是响应到浏览器的响应报文

该文对纯小白不友好

IOException*/RequestMapping(/testDown)public

ResponseEntitybyte[]

{//获取ServletContext对象ServletContext

servletContext

session.getServletContext();//获取服务器中文件的真实路径String

realPath

servletContext.getRealPath(/static/img/1.jpg);//创建输入流InputStream

new

FileInputStream(realPath);//创建字节数组byte[]

bytes

byte[is.available()];//将流读到字节数组中is.read(bytes);//创建HttpHeaders对象设置响应头信息MultiValueMapString,

String

HttpHeaders();//设置要下载方式以及下载文件的名字headers.add(Content-Disposition,

attachment;filename1.jpg);//设置响应状态码HttpStatus

statusCode

HttpStatus.OK;//创建ResponseEntity对象ResponseEntitybyte[]

responseEntity

statusCode);//关闭输入流is.close();return

responseEntity;}测试结果

文件上传要求form表单的请求方式必须为post并且添加属性enctype“multipart/form-data”

SpringMVC中将上传的文件封装到MultipartFile对象中通过此对象可以获取文件相关信息

添加依赖

dependencygroupIdcommons-fileupload/groupIdartifactIdcommons-fileupload/artifactIdversion1.3.1/version

/dependency●

!--必须通过文件解析器的解析才能将文件转换为MultipartFile对象--

bean

classorg.springframework.web.multipart.commons.CommonsMultipartResolver/bean●

控制器方法

photo.getOriginalFilename();//处理文件重名问题String

hzName

fileName.substring(fileName.lastIndexOf(.));fileName

hzName;//获取服务器中photo目录的路径ServletContext

servletContext

session.getServletContext();String

photoPath

servletContext.getRealPath(photo);System.out.println(photoPath);File

file

File(photoPath);if(!file.exists()){file.mkdir();}String

finalPath

fileName;//实现上传功能photo.transferTo(new

success;

{System.out.println(FirstInterceptor---:preHandle);/***

如果返回false、视图页面不出效果由源码得知、走到一般返回了。

没有到视图解析那一步*/return

true;}/***

{System.out.println(FirstInterceptor---:postHandle);}/***

视图渲染后执行*

afterCompletion(HttpServletRequest

request,

{System.out.println(FirstInterceptor---:afterCompletion);}

}在SpringMVC中进行配置

/*拦截当前目录下的请求。

/**拦截所有的请求。

这里的exclude-mapping表示排除拦截

!--

以上配置方式可以通过ref或bean标签设置拦截器通过mvc:mapping设置需要拦截的请求通过mvc:exclude-mapping设置需要排除的请求即不需要拦截的请求

--!--配置拦截器--mvc:interceptorsmvc:interceptormvc:mapping

path//ref

beanfirstInterceptor/ref/mvc:interceptor/mvc:interceptors12.2、拦截器的三个抽象方法

preHandle控制器方法执行之前执行preHandle()其boolean类型的返回值表示是否拦截或放行返回true为放行即调用控制器方法返回false表示拦截即不调用控制器方法

postHandle控制器方法执行之后执行postHandle()

afterComplation处理完视图和模型数据渲染视图完毕之后执行afterComplation()

若每个拦截器的preHandle()都返回true此时多个拦截器的执行顺序和拦截器在SpringMVC的配置文件的配置顺序有关preHandle()会按照配置的顺序执行而postHandle()和afterComplation()会按照配置的反序执行

若某个拦截器的preHandle()返回了falsepreHandle()返回false和它之前的拦截器的preHandle()都会执行postHandle()都不执行返回false的拦截器之前的拦截器的afterComplation()会执行

配置文件中配置拦截器、可以通过普通的bean也可以通过注解形式

mvc:interceptors

SpringMVC提供了一个处理控制器方法执行过程中所出现的异常的接口HandlerExceptionResolver

HandlerExceptionResolver接口的实现类有DefaultHandlerExceptionResolver和SimpleMappingExceptionResolver

SpringMVC提供了自定义的异常处理器SimpleMappingExceptionResolver使用方式

1、编写一个方法里边运算异常。

2、调用该异常方法会自动抛出异常信息到指定页面

bean

classorg.springframework.web.servlet.handler.SimpleMappingExceptionResolverproperty

nameexceptionMappingsprops!--properties的键表示处理器方法执行过程中出现的异常properties的值表示若出现指定异常时设置一个新的视图名称跳转到指定页面--prop

keyjava.lang.ArithmeticExceptionerror/prop/props/property!--exceptionAttribute属性设置一个属性名将出现的异常信息在请求域中进行共享--property

valueex/property

//ControllerAdvice将当前类标识为异常处理的组件

ControllerAdvice

{//ExceptionHandler用于设置所标识方法处理的异常ExceptionHandler(ArithmeticException.class)//ex表示当前请求处理中出现的异常对象public

String

handleArithmeticException(Exception

ex,



SEO优化服务概述

作为专业的SEO优化服务提供商,我们致力于通过科学、系统的搜索引擎优化策略,帮助企业在百度、Google等搜索引擎中获得更高的排名和流量。我们的服务涵盖网站结构优化、内容优化、技术SEO和链接建设等多个维度。

百度官方合作伙伴 白帽SEO技术 数据驱动优化 效果长期稳定

SEO优化核心服务

网站技术SEO

  • 网站结构优化 - 提升网站爬虫可访问性
  • 页面速度优化 - 缩短加载时间,提高用户体验
  • 移动端适配 - 确保移动设备友好性
  • HTTPS安全协议 - 提升网站安全性与信任度
  • 结构化数据标记 - 增强搜索结果显示效果

内容优化服务

  • 关键词研究与布局 - 精准定位目标关键词
  • 高质量内容创作 - 原创、专业、有价值的内容
  • Meta标签优化 - 提升点击率和相关性
  • 内容更新策略 - 保持网站内容新鲜度
  • 多媒体内容优化 - 图片、视频SEO优化

外链建设策略

  • 高质量外链获取 - 权威网站链接建设
  • 品牌提及监控 - 追踪品牌在线曝光
  • 行业目录提交 - 提升网站基础权威
  • 社交媒体整合 - 增强内容传播力
  • 链接质量分析 - 避免低质量链接风险

SEO服务方案对比

服务项目 基础套餐 标准套餐 高级定制
关键词优化数量 10-20个核心词 30-50个核心词+长尾词 80-150个全方位覆盖
内容优化 基础页面优化 全站内容优化+每月5篇原创 个性化内容策略+每月15篇原创
技术SEO 基本技术检查 全面技术优化+移动适配 深度技术重构+性能优化
外链建设 每月5-10条 每月20-30条高质量外链 每月50+条多渠道外链
数据报告 月度基础报告 双周详细报告+分析 每周深度报告+策略调整
效果保障 3-6个月见效 2-4个月见效 1-3个月快速见效

SEO优化实施流程

我们的SEO优化服务遵循科学严谨的流程,确保每一步都基于数据分析和行业最佳实践:

1

网站诊断分析

全面检测网站技术问题、内容质量、竞争对手情况,制定个性化优化方案。

2

关键词策略制定

基于用户搜索意图和商业目标,制定全面的关键词矩阵和布局策略。

3

技术优化实施

解决网站技术问题,优化网站结构,提升页面速度和移动端体验。

4

内容优化建设

创作高质量原创内容,优化现有页面,建立内容更新机制。

5

外链建设推广

获取高质量外部链接,建立品牌在线影响力,提升网站权威度。

6

数据监控调整

持续监控排名、流量和转化数据,根据效果调整优化策略。

SEO优化常见问题

SEO优化一般需要多长时间才能看到效果?
SEO是一个渐进的过程,通常需要3-6个月才能看到明显效果。具体时间取决于网站现状、竞争程度和优化强度。我们的标准套餐一般在2-4个月内开始显现效果,高级定制方案可能在1-3个月内就能看到初步成果。
你们使用白帽SEO技术还是黑帽技术?
我们始终坚持使用白帽SEO技术,遵循搜索引擎的官方指南。我们的优化策略注重长期效果和可持续性,绝不使用任何可能导致网站被惩罚的违规手段。作为百度官方合作伙伴,我们承诺提供安全、合规的SEO服务。
SEO优化后效果能持续多久?
通过我们的白帽SEO策略获得的排名和流量具有长期稳定性。一旦网站达到理想排名,只需适当的维护和更新,效果可以持续数年。我们提供优化后维护服务,确保您的网站长期保持竞争优势。
你们提供SEO优化效果保障吗?
我们提供基于数据的SEO效果承诺。根据服务套餐不同,我们承诺在约定时间内将核心关键词优化到指定排名位置,或实现约定的自然流量增长目标。所有承诺都会在服务合同中明确约定,并提供详细的KPI衡量标准。

SEO优化效果数据

基于我们服务的客户数据统计,平均优化效果如下:

+85%
自然搜索流量提升
+120%
关键词排名数量
+60%
网站转化率提升
3-6月
平均见效周期

行业案例 - 制造业

  • 优化前:日均自然流量120,核心词无排名
  • 优化6个月后:日均自然流量950,15个核心词首页排名
  • 效果提升:流量增长692%,询盘量增加320%

行业案例 - 电商

  • 优化前:月均自然订单50单,转化率1.2%
  • 优化4个月后:月均自然订单210单,转化率2.8%
  • 效果提升:订单增长320%,转化率提升133%

行业案例 - 教育

  • 优化前:月均咨询量35个,主要依赖付费广告
  • 优化5个月后:月均咨询量180个,自然流量占比65%
  • 效果提升:咨询量增长414%,营销成本降低57%

为什么选择我们的SEO服务

专业团队

  • 10年以上SEO经验专家带队
  • 百度、Google认证工程师
  • 内容创作、技术开发、数据分析多领域团队
  • 持续培训保持技术领先

数据驱动

  • 自主研发SEO分析工具
  • 实时排名监控系统
  • 竞争对手深度分析
  • 效果可视化报告

透明合作

  • 清晰的服务内容和价格
  • 定期进展汇报和沟通
  • 效果数据实时可查
  • 灵活的合同条款

我们的SEO服务理念

我们坚信,真正的SEO优化不仅仅是追求排名,而是通过提供优质内容、优化用户体验、建立网站权威,最终实现可持续的业务增长。我们的目标是与客户建立长期合作关系,共同成长。

提交需求或反馈

Demand feedback