1.首先我们在IDEA里面新建一个工程:
我们进行创建之后如下,我们点击父工程pom.xml,发现多了一个moudle:
我们将Servlet-02里面的pom.xml进行必要的清除,设置一个干净的项目:
untitled2
org.example
1.0-SNAPSHOT
4.0.0
servlet-02
war
我们将该删的进行删除,即可发现一个干净的项目。
如果这个过程中出现错误,我们点击刷新即可。
对于我们要进行修改的web.xml,修改这个比较麻烦。
对于经常共用的东西,我们可以在外面设置一个东西: (note.md)
我们的公用的代码如下所示:
web.xml
```xml
```
这里面的点为esc键下面的键盘,···。
之后我们将main项目进行补全:
我们之后进行建包,同时建立HelloServlet类,然后进行在类里面编辑方法。
写完Servlet之后,立马进入web,xml里面进行注册:
hello
com.rgf.servlet.HelloServlet
hello
/hello
这样子正常的操作就完成了。
之后我们进行查看Tomcat,我们点击如下所示:
进入之后,我们选择我们所创建的包servlet-02,将此前的包进行删除,确保里面只有一个,这样子可以快速打包,避免一次打多个包:
我们点击运行之后如下所示:
我们出现这个画面即为成功。
由于我们没有写输出,所以这个为空白页面。
我们从HttpServlet,按住ctrl,点击鼠标左键,进入HttpServlet的源码界面,我们来进行分析:
我们依靠这三个方面来进行分析:主要通过Structure分析方法:
我们了解如下所示:
//this.getInitParameter() 初始化参数
//this.getServletConfig() Servlet配置
//this.getServletContext() Servlet上下文
// this指代自己,因为继承了HttpServlet所有父类的方法,就能使用父类方法this.。
在web.xml了解如下所示:
hello
com.rgf.servlet.HelloServlet
我们进行重点了解ServletContext,如下所示:
比如我们在淘宝登录的时候,登陆完之后的注册信息会带到很多页面,跳到其他页面也是登录上去的,这个不是自己做到的,是中间商做到的。
web容器在启动的时候,它会为每个web程序都创建一个对应的ServletContext对象,它代表了当前的web应用。
这个网站就是由这个对象来进行管理的:ServletContext
我在这个Servlet保存的数据可以在另外一个Servlet中拿到:
但是这种方法是比较不合适的。
如下所示:
我们利用ServletContext进行检验:
我们新建一个class,类名为GetServlet:(读取的类)
package com.rgf.servlet;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
public class GetServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
ServletContext context = this.getServletContext();
String username = (String) context.getAttribute("username");
resp.getWriter().print("rgf"+username);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
之后,我们将HelloServlet进行修改:(放置的类)
package com.rgf.servlet;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
public class GetServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
ServletContext context = this.getServletContext();
String username = (String) context.getAttribute("username");
resp.getWriter().print("rgf"+username);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
之后,我们新建了一个Servlet之后,我们在web.xml进行新建一个servlet:
getc
com.rgf.servlet.GetServlet
getc
/getc
点击运行之后,我们出现如下所示:
我们看到了null,之后我们进行完善:代码如下所示:
package com.rgf.servlet;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
public class GetServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//数据放上面
ServletContext context = this.getServletContext();
String username = (String) context.getAttribute("username");
//响应放下面
resp.setContentType("text/html");
resp.setCharacterEncoding("utf-8");
resp.getWriter().print("rgf"+username);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
我们在设置过程中我们可以看其他网页的设置进行设置:
之后我们重新启动后如下所示:
我们利用hello里面的set方法先要赋值,getc里面的get才能取到值,我们示例如下:
我们先存起来如下所示:
之后我们取出来如下所示:
我们打开这个GetServlet进入该类:在ServletContext,按住ctrl键,点击鼠标左键,进入源代码:
我们查看源代码,进行对源代码的分析如下所示:
里面的@Deprecated,该标签标记为已过时被废弃的或者不建议被使用:
获得自己的路径:
String getContextPath();
获得版本信息:
int getMajorVersion();
int getMinorVersion();
int getEffectiveMajorVersion();
int getEffectiveMinorVersion();
获得自己这个对象:(可以通过某一个字符串进行获取)
ServletContext getContext(String var1);
获取复杂的消息类型:
String getMimeType(String var1);
获取资源的路径:
Set getResourcePaths(String var1);
获取资源把它变成一个流:
InputStream getResourceAsStream(String var1);
获取一个RequestDispatcherr,通过请求转发:
RequestDispatcher getRequestDispatcher(String var1);
获取一个RequestDispatcher,通过名字转发:
RequestDispatcher getNamedDispatcher(String var1);
获得真实的地址:
String getRealPath(String var1);
获得服务的信息:
String getServerInfo();
获得初始化的参数:
String getInitParameter(String var1);
进行设置:(上面为获得,下面就是设置了)
void setAttribute(String var1, Object var2);
3.我们可以设置新的一个类:ServletDemo03:
在里面进行写如下代码:
context.getInitParameter("");
这个除了可以获取setInitParameter("");还可以获取如下所示:
我们可以在web.xml里面进行配置:
url
jdbc:mysql://localhost:3306/mybatis //jdbc的连接url
web.xml里面的初始化参数我们可以在ServletDemo03里面拿到:
我们的ServletDemo03里面的代码如下所示:
package com.rgf.servlet;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
public class ServletDemo03 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//数据放上面
ServletContext context = this.getServletContext();
String url = context.getInitParameter("url");
//响应放下面
resp.getWriter().print(url);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
之后我们在web.xml里面进行注册该类的信息:
gp
com.rgf.servlet.ServletDemo03
gp
/gp
综上所述,所以ServletContext除了数据共享还可以获取初始化参数:
(1)ServletDemo03代码编写:
package com.rgf.servlet;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
public class ServletDemo03 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//数据放上面
ServletContext context = this.getServletContext();
String url = context.getInitParameter("url");
//响应放下面
resp.getWriter().print(url);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
(2)web.xml代码进行设置:
gp
com.rgf.servlet.ServletDemo03
gp
/gp
我们进行运行之后如下所示:
我们设置一个新的类:ServletDemo04,我们编写该类的时候,会发现RequestDispatcher,我们进入该类的源码进行查看:
public interface RequestDispatcher {
String FORWARD_REQUEST_URI = "javax.servlet.forward.request_uri";
String FORWARD_CONTEXT_PATH = "javax.servlet.forward.context_path";
String FORWARD_MAPPING = "javax.servlet.forward.mapping";
String FORWARD_PATH_INFO = "javax.servlet.forward.path_info";
String FORWARD_SERVLET_PATH = "javax.servlet.forward.servlet_path";
String FORWARD_QUERY_STRING = "javax.servlet.forward.query_string";
String INCLUDE_REQUEST_URI = "javax.servlet.include.request_uri";
String INCLUDE_CONTEXT_PATH = "javax.servlet.include.context_path";
String INCLUDE_PATH_INFO = "javax.servlet.include.path_info";
String INCLUDE_MAPPING = "javax.servlet.include.mapping";
String INCLUDE_SERVLET_PATH = "javax.servlet.include.servlet_path";
String INCLUDE_QUERY_STRING = "javax.servlet.include.query_string";
String ERROR_EXCEPTION = "javax.servlet.error.exception";
String ERROR_EXCEPTION_TYPE = "javax.servlet.error.exception_type";
String ERROR_MESSAGE = "javax.servlet.error.message";
String ERROR_REQUEST_URI = "javax.servlet.error.request_uri";
String ERROR_SERVLET_NAME = "javax.servlet.error.servlet_name";
String ERROR_STATUS_CODE = "javax.servlet.error.status_code";
void forward(ServletRequest var1, ServletResponse var2) throws ServletException, IOException;
void include(ServletRequest var1, ServletResponse var2) throws ServletException, IOException;
}
我们发现该类的源码里面:只有forward和include两个方法,其他的都是一堆常量。
我们在ServletDemo04里面进行编写的代码如下所示:
package com.rgf.servlet;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
public class ServletDemo04 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//数据放上面
ServletContext context = this.getServletContext();
System.out.println("进入了ServletDemo04");
RequestDispatcher requestDispatcher = context.getRequestDispatcher("/gp"); //转发的请求路径
//我们上面只有请求路径,还没有转发
requestDispatcher.forward(req,resp); //调用forward方法实现请求转发
//需要传两个参数,就是从HttpServletRequest的rep请求处理,到HttpServletResponse的resp请求响应回去
String url = context.getInitParameter("url");
//响应放下面
resp.getWriter().print(url);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
之后我们在web.xml里面的代码如下所示:
sd4
com.rgf.servlet.ServletDemo04
sd4
/sd4
进行运行之后如下所示:
我们可以看到,jdbc:mysql://localhost:3306/mybatis,本是http://localhost:9571/servlet_02_war/gp里面的,但是http://localhost:9571/servlet_02_war/sd4加载的也是这个页面里面的内容。
我们可知Status Code里面为200,而不是重定向的300,这是转发实现的。
我们请求到web.xml里面的
Properties,这里需要用到这个,我们去那个类里面进行new一个对象。
我们在ServletDemo03里面进行编写如下代码:
Properties properties = new Properties();
我们进入Properties类里面查看源码,如下所示:
Properties里面继承了一些东西,它里面有一些自己的方法。
我们对这些方法进行分析:
(1)可以传递一个自定义参数,让他读取某一个,否则就是默认的
public Properties(Properties defaults) {
(2) 设置一些属性的值,就是put里面的return put(key, value);
public synchronized Object setProperty(String key, String value) {
(3)加载,可以加载一个字符流也可以加载字节流
return put(key, value);
(4)往磁盘写。
public void store(Writer writer, String comments)
(5)从XML里面去加载
public synchronized void loadFromXML(InputStream in)
(6)get一个属性
public String getProperty(String key) {
我们创建一个properties文件,可以在任何地方创建,只要没有超出main。
我们在里面输入如下所示:
我们进行了解我们在初学properties是如何进行读取的。
我们进行创建该类如下所示:
我们一般都采用流,即为load(inStream);我们直接读取db.properties的绝对地址即可。但是现在是web应用,没有办法去保证绝对地址,因为web服务要走服务器,我们需要去web里面去拿,所以我们要观察db.properties会生成在web里面的哪个地方。
首先我们通过Maven,clean一下:
出现如下所示即可完成:
我们发现在WEB-INF里面的classes类里面,com下面有db.properties。
classpath叫类路径。里面还有servlet文件。
我们进行做如下测试:
我们可以将 db.properties复制到main下面的文件命名为aa.properties,重新运行之后,看target里面是否有aa.properties。
我们重新运行之后如下所示:
我们发现里面没有aa.properties。
在Maven里面资源导出可能存在问题,Maven由于它的约定大于配置,我们之后可能遇到我们写的配置文件,无法被导出或者生效的问题,解决方案如下所示:在build下面加个resouces.我们将该代码放到当前项目的pom.xml里面:
src/main/resources
**/*.properties
**/*.xml
true
src/main/java
**/*.properties
**/*.xml
true
我们将该代码添加之后,重新运行之后,结果如下所示:
我们发现里面成功的出现了aa.properties。如果没有出现的话,我们可以再通过Maven里面的clean进行清除,然后再重新运行。即可进行查询。
Properties
在java目录下新建Properties
在resouces目录下新建Properties
发现:都被打包到了同一个路径下:classes,我们俗称这个路径为classpath;
我们了解到路径是怎么放的了,我们现在可以去读他了。
我们创建一个类为ServletDemo05,我们编写的代码如下所示:
package com.rgf.servlet;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;
public class ServletDemo05 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
InputStream is = this.getServletContext().getResourceAsStream("/WEB-INF/classes/db.properties");
//把资源变成一个流
//第一个/不能省略,代表当前web项目,不然无法找到,这是一个相对定位的感觉
Properties prop = new Properties();
prop.load(is); //文件的流就拿到了。
String user = prop.getProperty("username");//最好直接从db.properties文件里面直接复制。
String pwd = prop.getProperty("password");
resp.getWriter().print(user+":"+pwd);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
之后我们在那个web.xml里面进行配置如下所示:
sd5
com.rgf.servlet.ServletDemo05
sd5
/sd5
之后我们运行进行测试:
我们可以读取到resouces里面的db.properties。我们是否可以读取到我们在main下面的aa.properties。我们进行测试如下所示:
我们的aa.properties文件如下所示:
我们运行之后的界面如下所示:
我们可知我们可以进行读取到。
综上所述:我们的读取资源文件的思路如下所示:
需要一个文件流,只要能变成一个流,我们即可进行读取到。
Properties(文件内容为:)
username=root
password=123456
通过ServletContext读取配置文件。
ServletContext是一个对象,我们之后还会再学习一些对象,比如Response,Request,Cookie,Session这些对象,我们就是再学习一个一个的类,这个类有哪些方法,如何去使用等等。针对ServletContext的四个应用。我们会在后面通过Session或者Request的一些方法来取代Context的共享数据的作用,我们更多的是用Session或者Request的一些方法来实现共享数据。第二个获取初始化参数我们基本不使用这个。第三个请求转发我们使用Request。第四个读取资源文件的话我们更多的是用类加载器。