JavaWeb

1、基本概念

静态网页无法与人工交互

动态网页可以人工交互

技术栈:Servlet、JSP、PHP

简介:在Java中,动态web资源开发的技术统称为JavaWeb.

2、web应用

web应用程序“可以提供浏览器访问的程序。

注意:网上可以访问的资源,都是储存在摸个计算机(服务器)上。通过URL(地址)去访问这个地址。

这个统一的web资源会被放置在同一个文件夹上,web应用程序–>Tomcat(服务器),将web应用部署在服务器上。

web应用程序编写完毕后,若想提供给外界访问:需要一个服务器来同意管理。

3、组成部分

包括(静态web,动态web):

  1. 网页前端:html javaScript CSS
  2. 技术栈:JSP Servlet
  3. java程序
  4. jar包
  5. 配置文件

3.1、静态web

静态网页存在的缺点:

1.web页面无法动态更新,所有用户看到的都是同一个页面

2.无法和数据库交互(数据无法持久化,用户无法交互)

3.伪动态(轮播图,点击特效)

Javascript[实际开发用的最多]

VBScript

3.2、动态web

  1. 客户端发送请求到服务端
  2. 服务端经过webServer 插件过滤请求
  3. webServer Plugin分别处理动态资源与静态资源
  4. 其中静态资源由webServer来处理请求
  5. 动态资源则由Servlet/JSP来处理,再发送给webServer,WebServer再处理请求,病发送响应给客户端

缺点:

1.加入服务器的动态web资源出现错误时,后台就需要修改,重新发布。----停机维护

优点:

1.动态更新,所有用户看到的不是同一个

2.人工交互

3.数据库交互

4、Web服务器

4.1、技术讲解

ASP:

  • ​ 微软:国内最早流行的是ASP

  • ​ 在HTML中嵌套VB脚本,ASP+COM

  • ​ 在ASP开发中,页面比较乱,维护成本高

  • ​ 在ASP中使用是C#

  • ​ IIS

PHP

  • PHP开发速度快,功能强大,跨平台,代码简单(WP,中国70%网站使用)
  • 无法承载大访问量的情况(局限性)

JSP/Servlet

B/S:浏览器和服务器

C/S:客户端和服务器

  • sun公司主推的B/S架构
  • 基于Java语言的
  • 可以承载三高问题(高并发,高可用,高高性能)
  • 语法像ASP,ASP–>JSP,加强市场强度

4.2、Web服务器

服务器是一种被动的操作,用来处理用户的一些请求和给用户一些响应信息。

4.2.1、IIS(暂时了解)

微软的:windows中自带的

4.2.2、Tomcat

对初学者来说,不错的选择;

可用尝试手写Tomcat;

下载Tomcat

1.解压或者安装

2.了解配置文件及目录结构

3.了解这个东西的作用

注意:同样适用于其他软件(包括Java以及其他)

rt.jar是Java的核心jar包

Tomcat

1、启动Tomcat

  • 选择Tomcat文件夹中bin目录下的startup.bat启动
  • 选择Tomcat文件夹中bin目录下的shutdown.bat启动

访问测试:http://localhost:8080/

可能遇到的问题:

​ 1.Java环境变量没有配置

​ 2.闪退问题:需要配置兼容性

​ 3.乱码问题:配置文件中设置

2、配置Tomcat

Tomcat—>conf—>server.xml(服务器核心配置文件)

server.xml用处:

1.可以配置启动的端口号

​ Tomcat的默认端口号:8080

​ MySQL:3306

​ HTTP:80

​ https:443

<Connector port="8081"             redirectPort="8443" protocol="HTTP/1.1" connectionTimeout="20000" URIEncoding="utf-8"/>

2.可以配置主机的名称

​ 默认主机名为:localhost->127.0.0.1

​ 默认网站应用存放的位置为:webapps

<Host name="localhost" unpackWARs="true" autoDeploy="true" appBase="webapps">

3、发布一个网站

3.1、猴版

将自己写的网站,放置到服务器(Tomcat)中指定的web应用的文件夹(webapps)下,就可以访问了。

步骤一、准备启动Tomcat

步骤二、打开服务器

步骤三、测试是否打开服务器

步骤四、成功打开服务器

步骤五、进入webapps准备建立猴版网站

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-DYxjbgPy-1614861455676)(https://img.imgdb.cn/item/6040d0d8360785be54699746.png)]

步骤六、复制一份项目

步骤七、建立项目

步骤八、删除不必要文件

步骤九、配置文件

步骤十、配置成功

步骤十一、测试新建项目

步骤十二、意外惊喜

步骤十三、关闭服务器

3.2、网站应该有的结构

--webapps:Tomcat服务器的web目录-zhangtaoStudy:网站的目录名(项目的名称)- WEB-INF:放置网站程序的-classes:java程序-lib:web应用所依赖的jar包-web.xml- index.html:默认的首页-   static:其他文件夹-css-js-img........

4、HTTP

4.1、什么是HTTP

HTTP(超文本传输协议)是一个简单的请求-响应协议,他通常运行在TCP上。

  • ​ 文本:html,字符串,、、、
  • ​ 超文本:图片,音乐,视频,定位,地图…
  • ​ 默认端口:80
  • ​ HTTPS默认端口:443

4.2、两个时代

http1.0

​ HTTP/1.0:客户端可以与服务端连接后,只能获得一个web资源,断开后无法再连接

http2.0

​ HTTP/1.1:客户端可以与web服务器连接后,可以获得多个web资源。

4.3、HTTP请求

客户端—>发送请求(request)—>服务器

eg:baidu

Request URL: https://www.baidu.com/  请求地址
Request Method: GET     get方法/post方法
Status Code: 200 OK     状态码:200
Remote Address: 36.152.44.95:443
Referrer Policy: strict-origin-when-cross-origin
Accept:text/html
Accept-Encoding: gzip, deflate, br
Accept-Language: zh-CN,zh;q=0.9,en;
Cache-Control:max-age=0
Connection: keep-alive
1.请求行
  1. 请求行中的请求方式:GET
  2. 请求方式:GET,POST(重点),head,delete,put,tract…
  • ​ get:请求能够携带的参数比较少,大小有限制,会在浏览器的URL地址栏显示数据,不安全。但是比较高效率、
  • ​ post:请求能够携带的参数没有限制,大小没有限制,不会在浏览器的URL地址栏显示数据,安全。但是不高效
2.消息头
Accept       告诉浏览器,它所支持的数据类型
Accept-Encoding 支持哪种编码格式 GBK UTF-8 GB2312   ISO8859-1
Accept-Language 告诉浏览器,它的语言环境
Cache-Control   缓存控制
Connection  告诉浏览器,请求完成是断开还是保持连接
HOST:主机......

4.4、HTTP响应

服务器—>发送响应(response)—>客户端

baidu 响应

Cache-Control: private   缓存控制
Connection: keep-alive  连接:保持连接
Content-Encoding: gzip  编码
Content-Type: text/html;类型
charset=utf-8
1.响应体
Accept       告诉浏览器,它所支持的数据类型
Accept-Encoding 支持哪种编码格式 GBK UTF-8 GB2312   ISO8859-1
Accept-Language 告诉浏览器,它的语言环境
Cache-Control   缓存控制
Connection  告诉浏览器,请求完成是断开还是保持连接
HOST:主机......
Refresh:告诉客户端,多久刷新一次
Location:让网页重新定位
2.响应状态码

200:表示响应请求成功

3**:请求重定向(重新到新的位置上)

404:表示网页不存在,找不到资源

5**:服务器代码错误 500 502:网关错误

5、Maven

5.1、为什么需要学习Maven

​ 1.在Javaweb开发中,需要使用大量的jar包,我们手动导入。

​ 2.如何能够让一个东西自动帮我导入和配置这个jar包。

目前用来就是方便导入jar包

3.Maven 的高级之处在于,他会帮你导入这个jar包所依赖的其他jar包

5.2、Maven项目架构管理工具

Maven的核心思想:约定大于配置

有约束,不要去违反。

Maven会规定如何去编写Java代码,必须按照这个规范来。

5.3、maven配置

5.4、maven阿里云镜像

镜像作用:加速我们的下载

国内建议使用阿里云镜像:

 <mirror><!--This sends everything else to /public --><id>nexus-aliyun</id><mirrorOf>*</mirrorOf><name>Nexus aliyun</name><url>http://maven.aliyun.com/nexus/content/groups/public</url></mirror>

5.5、本地仓库

https://blog.csdn.net/CDW2328/article/details/90113194

建立一个本地仓库:localRepository

<localRepository>F:\Maven\apache-maven-3.6.3-bin\apache-maven-3.6.3\maven-repo</localRepository>

5.6、在IDEA中创建Maven项目

虚拟路径映射

5.7、pom.xml文件

pom.xml文件是Maven的核心配置文件。

maven由于他的约定大于配置,我们之后可能遇到我们写的配置文件,无法被导出或者生效的问题,解决方案:

<!--    在build中配置resources,来防止我们资源导出失败的问题--><build><resources><resource><directory>src/main/resources</directory><includes><include>**/*.properties</include><include>**/*.xml</include></includes><filtering>true</filtering></resource><resource><directory>src/main/java</directory><includes><include>**/*.properties</include><include>**/*.xml</include></includes><filtering>true</filtering></resource></resources></build>

项目打包方式:

  • jar:java 应用

  • war:Javaweb应用

    <?xml version="1.0" encoding="UTF-8"?><project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><groupId>org.example</groupId><artifactId>MavenDemo1</artifactId><version>1.0-SNAPSHOT</version><packaging>war</packaging><name>MavenDemo1 Maven Webapp</name><!-- FIXME change it to the project's website --><url>http://www.example.com</url><properties><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding><maven.compiler.source>1.7</maven.compiler.source><maven.compiler.target>1.7</maven.compiler.target></properties><dependencies><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.11</version><scope>test</scope></dependency></dependencies><build><finalName>MavenDemo1</finalName><pluginManagement><!-- lock down plugins versions to avoid using Maven defaults (may be moved to parent pom) --><plugins><plugin><artifactId>maven-clean-plugin</artifactId><version>3.1.0</version></plugin><!-- see http://maven.apache.org/ref/current/maven-core/default-bindings.html#Plugin_bindings_for_war_packaging --><plugin><artifactId>maven-resources-plugin</artifactId><version>3.0.2</version></plugin><plugin><artifactId>maven-compiler-plugin</artifactId><version>3.8.0</version></plugin><plugin><artifactId>maven-surefire-plugin</artifactId><version>2.22.1</version></plugin><plugin><artifactId>maven-war-plugin</artifactId><version>3.2.2</version></plugin><plugin><artifactId>maven-install-plugin</artifactId><version>2.5.2</version></plugin><plugin><artifactId>maven-deploy-plugin</artifactId><version>2.8.2</version></plugin></plugins></pluginManagement></build>
    </project>

5.8、Maven配置时候可能遇到的问题:

1.Maven由于约定大于配置,所以我们之后可能遇到我们写的配置文件无法被导出或生效的问题:

​ 解决方案: Maven资源导出配出

2.Tomcat闪退问题

3.IDEA中每次都重复配置Maven

​ 解决方案:在IDEA的全局配置中进行配置,设置中找到Maven进行默认配置

4.Maven项目中Tomcat无法配置

5.9、Maven使用过程中可能遇到的问题:

1、无法导入

​ (兼容性问题)—unable to import Maven

​ 大概原因:Maven版本问题和JDK的兼容性

​ 目前解决方法:将版本降低一个版本

2、Tomcat闪退问题

​ jdk以及jre问题

3、IDEA中每次都重复配置Maven

​ 全局配置以及项目配置

​ 在全局配置中,以后就不用再修改

​ https://blog.csdn.net/weixin_44494373/article/details/108932403?ops_request_misc=%25257B%252522request%25255Fid%252522%25253A%252522160925339716780261984035%252522%25252C%252522scm%252522%25253A%25252220140713.130102334.pc%25255Fall.%252522%25257D&request_id=160925339716780261984035&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2allfirst_rank_v2~rank_v29-5-108932403.pc_search_result_cache&utm_term=IDEA%E4%B8%ADMaven%E9%BB%98%E8%AE%A4%E9%85%8D%E7%BD%AE%E5%9C%A8%E5%93%AA%E9%87%8C

4、Maven项目中Tomcat无法配置

​ 没有artifact文件

​ https://blog.csdn.net/weixin_44494373/article/details/108932403?ops_request_misc=%25257B%252522request%25255Fid%252522%25253A%252522160925339716780261984035%252522%25252C%252522scm%252522%25253A%25252220140713.130102334.pc%25255Fall.%252522%25257D&request_id=160925339716780261984035&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2allfirst_rank_v2~rank_v29-5-108932403.pc_search_result_cache&utm_term=IDEA%E4%B8%ADMaven%E9%BB%98%E8%AE%A4%E9%85%8D%E7%BD%AE%E5%9C%A8%E5%93%AA%E9%87%8C

个人建议:多刷新几次

5、Maven默认web项目中web.xml版本过老

<!DOCTYPE web-app PUBLIC"-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN""http://java.sun.com/dtd/web-app_2_3.dtd" ><web-app><display-name>Archetype Created Web Application</display-name>
</web-app>
<!--版本过老-->

使用Tomcat的头文件版本:

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"       xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaeehttp://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"version="4.0"metadata-complete="true"></web-app>

个人建议:直接在文件中附加一个note.md在这个笔记里面添加所需要的文件(包括web.xml等等)

6、新建文件夹

  • 在src–>main的目录下面新建Java文件夹以及resource文件夹。
  • IDEA会自动配置文件夹类型,直接新建即可。

7、Maven仓库的使用

https://mvnrepository.com/

官方的Maven的jar包仓库

eg:搜索Servlet的jar

其中标签代表的是作用域的意思,删除掉。代表在任何地方都可以使用。

    <dependencies><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.11</version><!--作用域--><scope>test</scope></dependency></dependencies>

Servlet

Sun在API中提供了一个接口叫做Servlet,如果想要开发一个Servlet程序,只需要完成两个小步骤:

1.编写一个类,实现Servlet接口

2.把开发好的Java类部署到web服务器上

把实现Servlet接口的Java程序叫做Servlet

1、HelloServlet

Servlet接口SUN公司有两个默认的实现类:HttpServlet/GenericServlet

1.1、创建一个普通的Maven项目

删除SRC目录,之后直接建立模块。这个空的工程就是主工程Maven。

在这个Maven的pom.xml中导入依赖

<!--    导入依赖--><dependencies><!-- https://mvnrepository.com/artifact/javax.servlet/javax.servlet-api --><dependency><groupId>javax.servlet</groupId><artifactId>javax.servlet-api</artifactId><version>4.0.1</version><scope>provided</scope></dependency><!-- https://mvnrepository.com/artifact/javax.servlet.jsp/javax.servlet.jsp-api --><dependency><groupId>javax.servlet.jsp</groupId><artifactId>javax.servlet.jsp-api</artifactId><version>2.3.3</version><scope>provided</scope></dependency><!-- https://mvnrepository.com/artifact/taglibs/standard --><dependency><groupId>taglibs</groupId><artifactId>standard</artifactId><version>1.1.2</version></dependency><!-- https://mvnrepository.com/artifact/javax.servlet.jsp.jstl/jstl-api --><dependency><groupId>javax.servlet.jsp.jstl</groupId><artifactId>jstl-api</artifactId><version>1.2</version></dependency></dependencies>

1.2、关于Maven父子工程的理解:

父项目中会有

 <modules><module>Servlet01</module></modules>

子项目中会有

 <parent><artifactId>JavaWeb-Servlet</artifactId><groupId>org.example</groupId><version>1.0-SNAPSHOT</version></parent>

父项目中的Java子项目可以直接使用:

son extends father

1.3、Maven环境优化

  • ​ 修改web.xml为最新的
  • ​ 将Maven的结构 搭建完整

子模块的web.xml最好配置一下,保证最新(从Tomcat的web.xml中提取)

<?xml version="1.0" encoding="UTF-8"?><web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaeehttp://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"version="4.0"metadata-complete="true">
</web-app>

1.4、编写一个Servlet程序

  • ​ 编写一个普通类
  • ​ 实现Servlet接口,继承HttpServlet
public class HelloServlet extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {PrintWriter writer =resp.getWriter();//响应流}@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {super.doPost(req, resp);}
}
//由于get或者post只是请求实现的不同方式,可以相互调用,业务逻辑都一样。

1.5、编写Servlet的映射(未知)

为什么需要映射:我们写的是Java程序,但是要通过浏览器访问,而浏览器需要实现服务器进行访问,所以我们需要再web服务器中注册我们写的Servlet,还需要给他一个浏览器能够访问的路径

        <!--  注册Servlet  --><servlet><servlet-name>HelloServlet</servlet-name><servlet-class>com.zhangtao.Servlet.HelloServlet</servlet-class><!--注意,servlet-class只能在servlet-name的下面,不能在上面,具体未知--></servlet><!--  Servlet的请求路径 --><servlet-mapping><servlet-name>HelloServlet</servlet-name><url-pattern>/hello</url-pattern><!--同理,url-pattern也是只能放置在servlet-name的后面--></servlet-mapping>

1.6、配置Tomcat

​ 注意:配置项目发布的路径即可。

1.7、启动测试

(注意:idea部署Tomcat时没有war文件,可能时Maven导入了,但是Idea还没有导入,刷新几次 )

https://blog.csdn.net/chpllp/article/details/105123042?ops_request_misc=%25257B%252522request%25255Fid%252522%25253A%252522160913617116780302934424%252522%25252C%252522scm%252522%25253A%25252220140713.130102334.pc%25255Fall.%252522%25257D&request_id=160913617116780302934424&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2allfirst_rank_v2~rank_v29-2-105123042.pc_search_result_no_baidu_js&utm_term=idea%E9%85%8D%E7%BD%AEtomcat%20deployment%E6%B2%A1%E6%9C%89artifact%E9%80%89%E9%A1%B9

2、Mapping

<!--servlet请求路径-->
<servlet-mapping><servlet-name>HelloServlet</servlet-name><url-pattern>/hello</url-pattern></servlet-mapping>

问题:

  • 一个Servlet可以指定一个映射路径

    <url-pattern>/hello</url-pattern>
    
  • 那么一个Servlet可以指定多个映射路径?

    <url-pattern>/hello1</url-pattern>
    <url-pattern>/hello2</url-pattern>
    <url-pattern>/hello3</url-pattern>
    <url-pattern>/hello4</url-pattern>
    <url-pattern>/*</url-pattern>
    

    直接使用通配符,那么使用任何字符都是可以的。

    其中“/*”就是默认请求路径

  • 一个Servlet可以指定通用映射路径

  • 指定一些后缀或者前缀的等等。。。。

    <url-pattern>*.zhangtao</url-pattern>
    <url-pattern>zhangtao.*</url-pattern>
    

    可以使用前缀和后缀,这些都是可以使用的。

    不过“*”前面不能加映射路径。

  • 优先级问题

    指定了固有的映射路径优先级最高,如果找不到就会走默认的处理请求

    (实践测试)

4、ServletContext

web容器在启动的时候,他为每个web程序都创建一个对应的ServletContext对象,他代表了当前的web应用

4.1、作用:

4.1.1、共享数据:

在这个Servlet中保存的数据,可以在另外一个Servlet中可以看到。

注意

先存后取,先保存数据,再读取数据;

搭配web.xml使用

//ContextDemo保存数据
@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {//打桩测试System.out.println("hello");//获取当前ServletContext对象ServletContext context =this.getServletContext();String username ="zhangtao";//数据//将一个键值对保存在ServletContext中,键:username;值:usernamecontext.setAttribute("username",username);}//GetServlet读取数据@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {ServletContext context =this.getServletContext();//获得保存在ServletContext中的username,其中由于不知道类型,需要强制转换一下String username = (String) context.getAttribute("username");/*防止出现中文乱码现象,要设置格式以及字符集不过要先保存ServletContext,否则取不到信息*/resp.setContentType("text/html");resp.setCharacterEncoding("utf-8");resp.getWriter().print("姓名:"+username);}
ContextDemo<!--注册Servlet--><servlet><servlet-name>ContextDemo</servlet-name><servlet-class>com.zhangtao.context.ContextDemo</servlet-class></servlet><!--Servlet请求路径--><servlet-mapping><servlet-name>ContextDemo</servlet-name><url-pattern>/context</url-pattern></servlet-mapping>
GetServlet<servlet><servlet-name>GetServlet</servlet-name><servlet-class>com.zhangtao.context.GetServlet</servlet-class></servlet><servlet-mapping><servlet-name>GetServlet</servlet-name><url-pattern>/get</url-pattern></servlet-mapping>

测试访问结果:姓名:zhangtao

4.1.2、获取初始化参数

1.设置初始化参数

 <!--配置一些web应用初始化参数--><context-param><param-name>URL</param-name><param-value>jdbc:mysql://localhost:3306/mybaits</param-value></context-param>

2.提取参数

    @Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {//获取当前ServletContext对象ServletContext context =this.getServletContext();//获取初始化参数String url = context.getInitParameter("URL");resp.getWriter().print(url);}

4.1.3、请求转发

 @Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {//获取当前ServletContext对象ServletContext context =this.getServletContext();/*请求转发,转发的请求路径”/contextdemo2“*/RequestDispatcher requestDispatcher =             context.getRequestDispatcher("/contextdemo2");/*转发调用forward()实现请求转发,两者可以合并*/requestDispatcher.forward(req,resp);//RequestDispatcher requestDispatcher = context.getRequestDispatcher("/contextdemo2").forward(req,resp);}
/*
其中,getRequestDispatcher()代表的意思是请求转发的意思。
而forward()是转发的方法。
*/
<servlet><servlet-name>ContextDemo2</servlet-name><servlet-class>com.zhangtao.context.ContextDemo2</servlet-class></servlet><servlet-mapping><servlet-name>ContextDemo2</servlet-name><url-pattern>/contextdemo2</url-pattern></servlet-mapping><!--配置一些web应用初始化参数--><context-param><param-name>URL</param-name><param-value>jdbc:mysql://localhost:3306/mybaits</param-value></context-param><!--请求转发--><servlet><servlet-name>ContextDemo3</servlet-name><servlet-class>com.zhangtao.context.ContextDemo3</servlet-class></servlet><servlet-mapping><servlet-name>ContextDemo3</servlet-name><url-pattern>/contextdemo3</url-pattern></servlet-mapping>
<!--ContextDemo2在获取初始化参数-->

请求转发与重定向区别:(重点)

4.1.4、读取资源文件

读取properties文件

username=zhangtao
password=123456
  • 在java 目录下新建properties
  • 在resources目录下新建properties

发现:都被打包到同一个路径下:classes。我们称这个路径为classpath;

建议:其中db.properties文件必须在main文件夹下面的sources文件夹下面main–>sources

思路:需要一个文件流去读取存放在properties文件中的信息

也可以在maven的pom.xml文件中,在build中配置resources,来防止资源导出失败的问题

<!--    在build中配置resources,来防止我们资源导出失败的问题--><build><resources><resource><directory>src/main/resources</directory><includes><include>**/*.properties</include><include>**/*.xml</include></includes><filtering>true</filtering></resource><resource><directory>src/main/java</directory><includes><include>**/*.properties</include><include>**/*.xml</include></includes><filtering>true</filtering></resource></resources></build>
  @Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {//获取当前ServletContext对象ServletContext context =this.getServletContext();//读取properties文件InputStream is = context.getResourceAsStream("/WEB-INF/classes/db.properties");//其中“/”代表的是当前web应用,//新建properties文件Properties prop = new Properties();//加载文件prop.load(is);//设置信息//由于不知道类型,所以强转类型,如果换成String也是可以,不过考虑其他因素(内存)Object age = prop.setProperty("age", "23");String information =(String) prop.setProperty("information", "电信1701");//读取信息String username = prop.getProperty("username");String password = prop.getProperty("password");String age1 = prop.getProperty("age");String information1 = prop.getProperty("information");//转到网页前端//设置格式resp.setContentType("text/html");resp.setCharacterEncoding("utf-8");resp.getWriter().println(username);resp.getWriter().println(password);resp.getWriter().println(age1);            resp.getWriter().println(information1);}

注意:

properties的文件路径是运行过的文件之后储存的位置。

其中,Context-1.0-SNAPSHOT是打包之后的项目,路径就储存在这个里面。

其中“/WEB-INF”,前面的“/”代表的意思是当前的web应用

这些都是底层的一些运用。

5、HttpServletResponse

web 服务器接收到客户端发送过来的请求,针对这个请求,分别创建了:

  • 代表请求的HttpServletRequest;
  • 代表响应的HttpServletResponse。
  • 如果要获取客户端请求过来的参数:找HttpServletRequest。
  • 如果要给客户端响应一些信息:找HttpServletResponse。

5.1、简单分类

5.1.1、负责向浏览器发送数据的方法

getWriter()
getOutputStream()

5.1.2、负责向浏览器发送响应头的方法

void setCharacterEncoding(String var1);
void setContentLength(int var1);
void setContentLengthLong(long var1);
void setContentType(String var1);
void setDateHeader(String var1, long var2);
void addDateHeader(String var1, long var2);
void setHeader(String var1, String var2);
void addHeader(String var1, String var2);
void setIntHeader(String var1, int var2);
void addIntHeader(String var1, int var2);

5.1.3、响应的状态码

 int SC_CONTINUE = 100;int SC_SWITCHING_PROTOCOLS = 101;int SC_OK = 200;int SC_CREATED = 201;int SC_ACCEPTED = 202;int SC_NON_AUTHORITATIVE_INFORMATION = 203;int SC_NO_CONTENT = 204;int SC_RESET_CONTENT = 205;int SC_PARTIAL_CONTENT = 206;int SC_MULTIPLE_CHOICES = 300;int SC_MOVED_PERMANENTLY = 301;int SC_MOVED_TEMPORARILY = 302;int SC_FOUND = 302;int SC_SEE_OTHER = 303;int SC_NOT_MODIFIED = 304;int SC_USE_PROXY = 305;int SC_TEMPORARY_REDIRECT = 307;int SC_BAD_REQUEST = 400;int SC_UNAUTHORIZED = 401;int SC_PAYMENT_REQUIRED = 402;int SC_FORBIDDEN = 403;int SC_NOT_FOUND = 404;int SC_METHOD_NOT_ALLOWED = 405;int SC_NOT_ACCEPTABLE = 406;int SC_PROXY_AUTHENTICATION_REQUIRED = 407;int SC_REQUEST_TIMEOUT = 408;int SC_CONFLICT = 409;int SC_GONE = 410;int SC_LENGTH_REQUIRED = 411;int SC_PRECONDITION_FAILED = 412;int SC_REQUEST_ENTITY_TOO_LARGE = 413;int SC_REQUEST_URI_TOO_LONG = 414;int SC_UNSUPPORTED_MEDIA_TYPE = 415;int SC_REQUESTED_RANGE_NOT_SATISFIABLE = 416;int SC_EXPECTATION_FAILED = 417;int SC_INTERNAL_SERVER_ERROR = 500;int SC_NOT_IMPLEMENTED = 501;int SC_BAD_GATEWAY = 502;int SC_SERVICE_UNAVAILABLE = 503;int SC_GATEWAY_TIMEOUT = 504;int SC_HTTP_VERSION_NOT_SUPPORTED = 505;

200:请求响应成功

5.2、HttpServletResponse常见应用

5.2.1、向浏览器输出信息

5.2.2、下载文件

  • 要获取下载文件的路径
  • 下载的文件名是啥?
  • 想办法让浏览器能够支持(Content-Disposition)下载我们所需要的东西
  • 获取下载文件的输入流
  • 创建缓冲器
  • 获取OutputStream对象
  • 将FileOutputStream流写入到buffer缓冲区
  • 使用OutputStream将缓冲区中的数据输入到客户端
package com.zhangtao;import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.FileInputStream;
import java.io.IOException;
import java.net.URLEncoder;public class FileServlet extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {//要获取下载文件的路径//String realPath = this.getServletContext().getRealPath("/1.png");String realPath ="F:\\IDEA\\JavaWeb-Servlet2\\HttpResponse\\target\\classes\\1.png";System.out.println(realPath);//下载的文件名是啥?String fileName = realPath.substring(realPath.lastIndexOf("//") + 1);/*** 1.截取字符串substring()* 2.截取“/”后面的字符,其中lastIndexOf()是截取最后一个*///想办法让浏览器能够支持(Content-Disposition)下载我们所需要的东西//resp.setHeader("Content-Disposition","attachment;filename="+fileName);resp.setHeader("Content-Disposition","attachment;filename="+ URLEncoder.encode(fileName,"UTF-8"));//其中URLEncoder.encode(fileName,"UTF-8")就是转码/*** 如果是中文的话,那么URLEncoder.encode()就使用,否则有可能乱码*///获取下载文件的输入流FileInputStream in = new FileInputStream(realPath);//创建缓冲器int len =0;byte[] buffer = new byte[1024];//获取OutputStream对象ServletOutputStream out = resp.getOutputStream();//将FileOutputStream流写入到buffer缓冲区,使用OutputStream将缓冲区中的数据输入到客户端while((len=in.read(buffer))>0){out.write(buffer,0,len);}in.close();out.close();}@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {doGet(req, resp);}
}

5.2.3、验证码功能

验证码怎么来的?后端实现,需要用到Java的图片类,生产一个图片。

package com.zhangtao;import javax.imageio.ImageIO;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.Random;public class ImageServlet extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {//如何让浏览器5秒自动刷新一次resp.setHeader("refresh","5");//在内存中创建一个图片BufferedImage image = new BufferedImage(80,20,BufferedImage.TYPE_INT_RGB);//得到图片Graphics2D graphics = (Graphics2D) image.getGraphics();//设置图片的背景颜色graphics.setColor(Color.white);graphics.fillRect(0,0,80,30);//给图片写数据graphics.setColor(Color.BLUE);graphics.setFont(new Font(null,Font.BOLD,20));graphics.drawString(makeNum(),0,20);//告诉浏览器,这个请求用图片的方式打开resp.setContentType("image/jpeg");//网站存在缓存,不让浏览器缓存resp.setDateHeader("exprise",-1);resp.setHeader("Cache-Control","no-cache");//不要缓存控制,具体可以参考之前的HTTP章节resp.setHeader("Pragma","no-cache");//把图片写给浏览器ImageIO.write(image, "jpg", resp.getOutputStream());}//生成随机数private String makeNum(){Random random = new Random();String num = random.nextInt(999999)+"";//6位数的随机数StringBuffer stringBuffer = new StringBuffer();for(int i= 0;i<7-num.length();i++){stringBuffer.append("0");}num = stringBuffer.toString()+num;return num;}@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {doGet(req, resp);}
}

5.2.4、重定向

一个web资源收到客户端请求后,他会通知客户

去顾问另一个web资源-----这个过程就是重定向。

常见场景:

用户登录—登录成功跳转到另外的页面。

public void sendRedirect(String location) throws IOException;

测试:

@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {resp.sendRedirect("/HttpResponse/image");//其中如果想要跳转到某个页面,一定要加上项目的名称//也是重定向resp.setHeader("loaction","HttpResponse/image");resp.setStatus(302);/*不过HttpServletResponse.SC_MOVED_TEMPORARILY代表的也是302直接使用常量比较规范*/}

6、HttpServletRequest

HttpServletRequest代表了客户端的请求,用户的通过Http协议访问服务器,HTTP请求中的所有信息会被封装到HttpServletRequest,通过这个HttpServletRequest的方法我们可以获得客户端的所有信息。

1.获取前端传递的参数

getParameter(String name)    //获取单个前端传递的参数
getParameterValues(String[] names)  //获取多个前端传递的参数

前端请求页面

<html>
<body>
<h2>Hello World!</h2>
<%--注意,这里的action指代的是提交的路径,提交到相关的页面进行处理,而且需要寻找到处理页面的路径--%>
<%--注意,${pageContext.request.contextPath}代表的是当前的项目--%>
<form action="${pageContext.request.contextPath}/request" method="get"><%--  寻找到当前项目下的login  --%>姓名:<input type="text" name="username" value="请输入姓名" minlength="5"/><br>密码:<input type="password" name="password" value="请输入密码" maxlength="20" minlength="8"/><br>爱好:<input type="checkbox" name="hobbies">写代码<input type="checkbox" name="hobbies">弹琴<input type="checkbox" name="hobbies">看书<input type="checkbox" name="hobbies">听音乐<br><input type="submit"/>
</form>
</body>
</html>

后端Java程序

//Java程序
public class RequestDemo extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {System.out.println("进入这个请求当中");//处理请求String username = req.getParameter("username");String password = req.getParameter("password");String[] hobbies = req.getParameterValues("hobbies");System.out.println("姓名:"+username);System.out.println("密码:"+password);System.out.println(Arrays.toString(hobbies));//将hobbies数组进行打印//作出回应,进入处理页面resp.sendRedirect("/HttpResponse/sucess.jsp");}

后端配置----绑定Servlet

<web-app><servlet><servlet-name>RequestDemo</servlet-name><servlet-class>com.zhangtao.Servlet.RequestDemo</servlet-class></servlet><servlet-mapping><servlet-name>RequestDemo</servlet-name><url-pattern>/request</url-pattern></servlet-mapping>
</web-app>

前端处理页面

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head><title>成功处理请求</title>
</head>
<body><h2>请求成功处理</h2>
</body>
</html>

2.请求转发

//Java程序
public class RequestDemo extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {System.out.println("进入这个请求当中");//处理请求String username = req.getParameter("username");String password = req.getParameter("password");String[] hobbies = req.getParameterValues("hobbies");System.out.println("姓名:"+username);System.out.println("密码:"+password);System.out.println(Arrays.toString(hobbies));//将hobbies数组进行打印//通过请求转发req.getRequestDispatcher(req.getContextPath()+"/sucess.jsp").forward(req,resp);req.setCharacterEncoding("utf-8");/***在请求转发的时候,会出现404现象这个时候往往是把项目名也输入进去请求转发不需要项目名,而“/”代表的是当前的web应用*/}

请求转发与重定向的区别:

相同点:

​ 页面都会实现跳转

不同点:

  • 请求转发的时候,url不会发生变化:307
  • 重定向的时候,URL地址栏会发生变化:302
  • 请求转发不需要项目名,重定向需要项目名

7、Cookie、Session

Cookie:

Session:会话

一个网站怎么证明你来过?

客户端 服务端

1.服务端给客户端一个信件,客户端下次访问服务端带上信件即可;(信件----cookies)

2.服务器登记你来过,下次你来的时候我来匹配你;session

7.1、会话

会话:用户打开一个浏览器,点击了很多的链接,访问多个web资源,关闭浏览器,这个过程就是会话。

**有状态会话:**客户端再次访问服务器,我们知道这个客户端来过,我们称这个过程为有状态过程。

7.2、保存会话的两种技术

Cookie

客户端技术(响应,请求)

Session

服务端技术;利用这个技术,可以保存用户的会话信息,我们可以将信息或者数据保存在Session中。

常见例子:网站登录之后,你下次就不用再登录,可以直接进去。

7.3、Cookie

1.从请求中拿到信息

2.服务器响应给客户端cookie

Cookie[] cookie = req.getCookies();//获得Cookie
cookie.getName();//获得cookie中的key
cookie.getValue();//获得cookie中的value
new Cookie("lastLoginTime",System.currentTimeMillis()+"");
cookie.setMaxAge(24*60*60);//设置cookie的有效期
resp.addCookie(cookie);//服务端返回一个响应给客户端一个cookie

cookie:一般会保存在本地的用户目录下的APPdata;

细节问题:

一个网站cookie是否存在上限?

  • 一个Cookie只能保存一个信息;
  • 一个web站点可以给浏览器发送多个Cookie,最多存放20个Cookie;
  • Cookie大小有限制4kb;
  • 300个Cookie浏览器上限;

删除Cookie方式:

  • 不设置有效期,关闭浏览器,自动失效;
  • 设置有效期时间为0;

编码

URLEncoder.encoder("","UTF-8")

解码

URLDecoder.decoder("","UTF-8");

7.4、Session(重点)

什么是Session?

  • 服务器会给每一个用户(浏览器)创建一个Session;
  • 一个Session独占一个浏览器,只要浏览器没有关闭,这个Session就会一直存在;
  • 用户登录之后,整个网站都可以访问到–>保存用户的信息,保存购物车的信息等…

1、Session共享数据

之前Servlet共享数据是servletContext,但是如果数据过多的话,会引起服务器卡顿现象。

使用Session比较好

//ServletDedmo1
package com.Servlet.Session;import javax.servlet.ServletException;
import javax.servlet.http.*;
import java.io.IOException;public class SessionDemo extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {//解决乱码问题req.setCharacterEncoding("UTF-8");resp.setCharacterEncoding("UTF-8");resp.setContentType("text/html; charset=UTF-8");//得到SessionHttpSession session = req.getSession();//往Session中存东西session.setAttribute("username1","张韬");//也可以通过其他类来存取键值对session.setAttribute("username2",new Person(1,"张韬"));//获取Session的IDString id = session.getId();//判断Session是不是新创建的if(session.isNew()){resp.getWriter().write("session创建成功:"+id);}else{resp.getWriter().write("session已经存在了ID::"+id);}//Session创建的时候做了什么事情Cookie cookie = new Cookie("JSESSIONID", id);resp.addCookie(cookie);}@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {doGet(req, resp);}
}
//ServletDemo2
package com.Servlet.Session;import javax.servlet.ServletException;
import javax.servlet.http.*;
import java.io.IOException;public class SessionDemo2 extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {//解决乱码问题req.setCharacterEncoding("UTF-8");resp.setCharacterEncoding("UTF-8");resp.setContentType("text/html; charset=UTF-8");//得到SessionHttpSession session = req.getSession();//获取Session中的数据String username1 = (String)session.getAttribute("username1");System.out.println(username1);//获取Session中存储的数据(通过其他类新建的键值对)Person person = (Person)session.getAttribute("username2");System.out.println(person.toString());/*** 这里之前是同时向Session中存储两个数据,不知道为何之前会报错500以及404问题* 有待之后再进行验证*/}@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {doGet(req, resp);}
}
//Person
package com.Servlet.Session;public class Person {private int age;private String username;public Person() {}public Person(int age, String username) {this.age = age;this.username = username;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}public String getUsername() {return username;}public void setUsername(String username) {this.username = username;}//为了调试方便,都会加上一个toString()@Overridepublic String toString() {return "Person{" +"age=" + age +", username='" + username + '\'' +'}';}
}

2、Session消除、注销

//ServletDemo3
package com.Servlet.Session;import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;public class SessionDemo3 extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {//获得sessionHttpSession session = req.getSession();//消除Session中的数据session.removeAttribute("username");//手动注销sessionsession.invalidate();/*** 注销就是相当于关闭这个请求*/}@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {doGet(req, resp);}
}

注意:Session注销就是相当于关闭这个请求,原因:之前的SessionID被注销掉了,所以没有办法使用。

所以如果想要使用的话,那么就只能进行另一次请求。

会话自动过期,使用web.xml

   <!--设置Session的时效--><session-config><!--15分钟后,session就会自动失效,单位为分钟--><session-timeout>15</session-timeout></session-config>

注意:这个session-config在里面也是可以配置cookie的,所以还需要进行操作。

3、Session和Cookie的区别

  • Cookie是把用户的数据写给用户的浏览器,保存地址是浏览器(可以保存多个);
  • Session把用户的数据写到用户独占的Session中,保存地址是服务器端(保存重要的信息,减少服务器资源的浪费);
  • Session对象由服务器创建;

注意:还是有待测试;

3.1、详情图对比

Cookie详情

Session详情

ServletContext

注意:如果是两个人或者是多个人一起使用同一个资源的话,那么Session就不再适用(可能会占有很多的空间),这个时候使用ServletContext比较好。这个在之后也被成为applicationContext。

使用场景:
  • 保存一个登陆用户的信息
  • 购物车信息
  • 在整个网站中经常会使用的数据,我们将它保存在Session中;

JavaWeb---Tomcat---Servlet相关推荐

  1. JavaWeb+Tomcat+Servlet使用<c:foreach>标签时,jsp等网页文件获取不到request域中的数据

    自己也是刚学习就遇到了这个问题,上网找了两天,弄清楚了就分享出来 我的各个文件都没有报错,而且 jdk 和 jstl 的版本,web.xml 的版本都没什么问题,而且也能获取数据库中的数据,但是使用 ...

  2. JavaWeb:tomcat服务器安装总结及Http协议

    JavaWeb:tomcat服务器安装总结 目录 JavaWeb:tomcat服务器安装总结 一:服务器端概述: 二:Tomcat下载: 三:安装: 四:HTTP问题: 五:深入了解tomcat服务器 ...

  3. javaweb(07) Servlet详解

    javaweb(07) Servlet详解 什么是Servlet 简介 从广义上来讲,Servlet规范是Sun公司制定的一套技术标准,包含与web应用相关的一系列接口,是web应用实现方式的宏观解决 ...

  4. 基于javaweb+JSP+Servlet简单购物车

    基于javaweb+JSP+Servlet简单购物车 开发工具:eclipse/idea/myeclipse/sts等均可配置运行 适用 课程设计,大作业,毕业设计,项目练习,学习演示等 public ...

  5. 基于javaweb+JSP+Servlet电影票售票管理系统

    基于javaweb+JSP+Servlet电影票售票管理系统 开发工具:eclipse/idea/myeclipse/sts等均可配置运行 适用 课程设计,大作业,毕业设计,项目练习,学习演示等 } ...

  6. 基于javaweb+JSP+Servlet在线商城鲜花花卉商城(前台、后台)

    基于javaweb+JSP+Servlet在线商城鲜花花卉商城(前台.后台) 开发工具:eclipse/idea/myeclipse/sts等均可配置运行 适用 课程设计,大作业,毕业设计,项目练习, ...

  7. 基于javaweb+JSP+Servlet在线商城购物商城服装商城(前台、后台)

    基于javaweb+JSP+Servlet在线商城购物商城服装商城(前台.后台) 开发工具:eclipse/idea/myeclipse/sts等均可配置运行 适用 课程设计,大作业,毕业设计,项目练 ...

  8. 基于javaweb+JSP+Servlet学生成绩管理系统(管理员、教师、学生)

    基于javaweb+JSP+Servlet学生成绩管理系统(管理员.教师.学生) 开发工具:eclipse/idea/myeclipse/sts等均可配置运行 适用 课程设计,大作业,毕业设计,项目练 ...

  9. 基于javaweb+JSP+Servlet学生在线选课系统(管理员、教师、学生)

    基于javaweb+JSP+Servlet学生在线选课系统(管理员.教师.学生) 开发工具:eclipse/idea/myeclipse/sts等均可配置运行 适用 课程设计,大作业,毕业设计,项目练 ...

  10. 基于javaweb+JSP+Servlet网上书店图书商城(前台、后台)

    基于javaweb+JSP+Servlet网上书店图书商城(前台.后台) 开发工具:eclipse/idea/myeclipse/sts等均可配置运行 适用 课程设计,大作业,毕业设计,项目练习,学习 ...

最新文章

  1. t-SNE(t-distributed stochastic neighbor embedding)
  2. 地壳中元素含量排名记忆口诀_【中考化学】初中化学记忆性知识点03-生活中的化学-生活常识...
  3. python中如何调用或修改元组中的元素_python 元组的使用方法
  4. 云重磅 | 没有硬件,苹果发布多款“云服务”;阿里云发布基于公共云的虚拟GPU服务;中国移动首发5G套餐...
  5. B-Tree及其建立过程
  6. mongoDB 3.0以前版本 - 入门指南、示例
  7. git学习(四)比较文件差异diff
  8. 转帖:Three Ways to Inject Your Code into Another Process
  9. 深度学习样本标完后图片增强标签内容不变
  10. 人生成功的十大说话技巧
  11. VIM 快捷键汇总(持续更新)
  12. 3D打印是什么?如何工作的?
  13. windows11 截屏键无法使用 Print screen
  14. 【H5钢琴示例代码】
  15. 三菱触摸屏怎么改时间_三菱触摸屏时钟设置步骤
  16. 总结学过的技术,实现加密注册,登录及过期不能访问,微信朋友圈功能,文章比较长,但是比较详细。
  17. 【转载】WPS通过设置密码的方式对Excel文件加密
  18. 清理工作区git clean -fd
  19. 外报分析中国房价上涨三原因 指开发商行为怪异
  20. 护肤品买了这么多还是不见好转,钱都去哪里了?

热门文章

  1. 嫌画笔长得不好看,今天教你如何隐藏Python画笔!
  2. [转]ISE ChipScope使用
  3. 用C++编写一个模拟战争的游戏
  4. 通过ROS控制真实机械臂(7)---三次样条插补
  5. 微信小程序1,常用组件 view、swiper、swiper-item、 scroll-view、 icon、progress、text、rich-text、button、input、image
  6. Java不适合做爬虫?试试这个工具!
  7. 内迁,沿海地理优势在劳动密集型产业中已不存在。中西部人将有望更多地在家乡工作。深圳只会是记忆。...
  8. 精彩的2009已经悄然离开,充满期待的2010年正向我走来。
  9. MotionBuilder-动作整合-Story(一)
  10. Gwt第三方组件、框架介绍