本篇文章將和大家介紹JavaWeb中常用到的小服務(wù)程序Servlet的內(nèi)容,下面將詳細介紹關(guān)于Servlet的簡要內(nèi)容、具體的原理以及用實例代碼展示實現(xiàn)過程。
Servlet
1 Servlet 簡介
Servlet就是Sun 公司開發(fā)動態(tài)web的一門技術(shù)
Sun在這些API中提供一個接口叫做:Servlet ,如果你向開發(fā)一個Servlet程序,只需要完成兩個小步驟
- 編寫一個類,實現(xiàn)Servlet接口
- 把開發(fā)好的Java類部署到web服務(wù)器中
把實現(xiàn)Servlet接口的Java程序叫做 Servlet
2 HelloServlet
構(gòu)建一個普通的Maven項目,刪除里面的src目錄。這個空的工程就是Maven主工程
關(guān)于Maven父子工程的理解:
父項目中會有
<modules>
<module>servlet-02</module>
</modules>
子項目中會有
<parent>
<artifactId>javaweb-02-servlet</artifactId>
<groupId>com.srx</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
父項目中的Java子項目可以直接使用
son extends father
Maven環(huán)境優(yōu)化
- 修改web.xmd為最新的
- 將maven的結(jié)構(gòu)搭建完整
編寫一個Servlet程序
編寫Servlet的映射
為什么需要映射,我們系的是java程序,但是要通過瀏覽器訪問,而瀏覽器需要連接web服務(wù)器,所以我們需要再web服務(wù)中注冊我們寫的Servlet 還需要給他一個瀏覽器 能夠訪問的路徑
<!-- 注冊servlet-->
<servlet>
<servlet-name>hello</servlet-name>
<servlet-class>com.srx.HellowServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>hello</servlet-name>
<url-pattern>hello</url-pattern>
</servlet-mapping>
配置Tomcat
注意:配置項目發(fā)布的路徑就可以了
啟動測試 歐克
3 Servlet 原理
servlet 是由web服務(wù)器調(diào)用,wev服務(wù)器在收到瀏覽器請求之后 會:
4 Mapping 問題
一個Servlet 可以指定一個映射路徑
一個Servlet 可以指定多個映射路徑
<servlet-mapping>
<servlet-name>hello</servlet-name>
<url-pattern>/hello</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>hello</servlet-name>
<url-pattern>/hello1</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>hello</servlet-name>
<url-pattern>/hello2</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>hello</servlet-name>
<url-pattern>/hello3</url-pattern>
</servlet-mapping>
一個Servlet 可以指定通用映射路徑
<servlet-mapping>
<servlet-name>hello</servlet-name>
<url-pattern>/hello/*</url-pattern>
</servlet-mapping>
默認請求路徑
<servlet-mapping>
<servlet-name>hello</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
指定一些后綴或者前綴等等…
<!-- 可以自定義后綴實現(xiàn)請求映射
注意點: *前面不能加項目映射路徑
-->
<servlet-mapping>
<servlet-name>hello</servlet-name>
<url-pattern>*.abc</url-pattern>
</servlet-mapping>
優(yōu)先級問題
指定了固有的映射路徑優(yōu)先級最高,如果找不到就會走默認的處理請求;
<!--404-->
<servlet>
<servlet-name>error</servlet-name>
<servlet-class>com.srx.Error</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>error</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
5 servletContext
web容器在啟動的時候,它會為每個web程序都創(chuàng)建一個對應(yīng)的ServletContext 對象,它代表了當(dāng)前web應(yīng)用。
1.共享數(shù)據(jù)
我在這個Servlet中保存的數(shù)據(jù),可以在另外一個servlet中拿到
存放數(shù)據(jù)的類
public class test extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//this.getInitParameter(); //初始化參數(shù)
//this.getServletContext(); // servlet 上下文
//this.getServletConfig(); servlet 配置
ServletContext servletContext = this.getServletContext();
String username="我愛學(xué)習(xí)";
//將一個數(shù)據(jù)保存在ServletContext中 名字為 uesrname 值為 username
servletContext.setAttribute("username",username);
System.out.println("hello");
}
}
輸出的類
public class show extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
ServletContext servletContext = this.getServletContext();
resp.setContentType("text/html");
resp.setCharacterEncoding("utf-8");
String username = (String) servletContext.getAttribute("username");
resp.getWriter().print("姓名:"+username);
}
}
配置的文件
<servlet>
<servlet-name>test</servlet-name>
<servlet-class>com.srx.test</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>test</servlet-name>
<url-pattern>/test</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>getc</servlet-name>
<servlet-class>com.srx.show</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>getc</servlet-name>
<url-pattern>/getc</url-pattern>
</servlet-mapping>
測試訪問結(jié)果
2.獲取初始化參數(shù)
<!-- 配置一些web的初始化參數(shù)-->
<context-param>
<param-name>url</param-name>
<param-value>JDBC:mysql//localhost:3306/mybatis</param-value>
</context-param>
測試類
public class context extends HttpServlet {
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
ServletContext Context = this.getServletContext();
String url = Context.getInitParameter("url");
resp.getWriter().print(url);
}
}
路徑
<servlet>
<servlet-name>url</servlet-name>
<servlet-class>com.srx.context</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>url</servlet-name>
<url-pattern>/url</url-pattern>
</servlet-mapping>
3.請求轉(zhuǎn)發(fā)
public class ServletDemo extends HttpServlet {
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("進入了這個方法");
ServletContext context = this.getServletContext();
// RequestDispatcher zf = context.getRequestDispatcher("zf"); //轉(zhuǎn)發(fā)的路徑
// zf.forward(req,resp); //調(diào)用forward 方法 實現(xiàn)轉(zhuǎn)發(fā)
//簡寫
context.getRequestDispatcher("/getc").forward(req,resp);
}
}
<servlet>
<servlet-name>zzz</servlet-name>
<servlet-class>com.srx.ServletDemo</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>zzz</servlet-name>
<url-pattern>/zzz</url-pattern>
</servlet-mapping>
4.讀取資源文件
properties
- 在java目錄中新建properties
- zairesource目錄下新建properties
發(fā)現(xiàn):都被打包到了同一個路徑下;classes 我們俗稱這個路徑為classpath;
思路: 需要一個文件流
public class ServletDemo1 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
InputStream is = this.getServletContext().getResourceAsStream("/WEB-INF/classes/db.properties");
Properties prop = new Properties();
prop.load(is);
String user = prop.getProperty("username");
String pwd = prop.getProperty("password");
resp.getWriter().print(user+":"+pwd);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req,resp);
}
}
映射
<servlet>
<servlet-name>bbb</servlet-name>
<servlet-class>com.srx.ServletDemo1</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>bbb</servlet-name>
<url-pattern>/bbb</url-pattern>
</servlet-mapping>
6、HttpServletResponse
web服務(wù)器接收到客戶端的http請求,針對這個請求,反別創(chuàng)建一個代表請求的HttpServletRequest對象,代表響應(yīng)的一個HttpServletResponse;
- 如果獲取客戶端請求過來的參數(shù) 找 httpServletRequest
- 如果要給客戶端響應(yīng)一些信息:找HttpServletResponse
1下載文件
向瀏覽器輸出信息
2 下載文件
- 要獲取下載文件的路徑
- 下載的文件名是啥
- 設(shè)置想辦法讓瀏覽器支持下載我們所需要的東西
- 獲取下載文件的輸入流
- 創(chuàng)建緩沖區(qū)
- 獲得OutputStream對象
- 將FileOutputStream流寫入到Buffer緩沖區(qū)
- 使用OutputStream將緩沖區(qū)中的數(shù)據(jù)輸出到客戶端。
案例
public class FileServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// - 要獲取下載文件的路徑
String realPath = "D:\軟件安裝路徑\javaweb-02-servlet\response\target\classes\111.png";
System.out.println("文件的下載路徑"+realPath);
// - 下載的文件名是啥
String substring = realPath.substring(realPath.lastIndexOf("\") + 1);
// - 設(shè)置想辦法讓瀏覽器支持下載我們所需要的東西
resp.setHeader("Content-Disposition","attachment;filename="+ URLEncoder.encode(substring,"utf-8"));
// - 獲取下載文件的輸入流
FileInputStream in = new FileInputStream(realPath);
// - 創(chuàng)建緩沖區(qū)
int len = 0;
byte[] buffer=new byte[1024];
// - 獲得OutputStream對象
ServletOutputStream outputStream = resp.getOutputStream();
// - 將FileOutputStream流寫入到Buffer緩沖區(qū) 使用OutputStream將緩沖區(qū)中的數(shù)據(jù)輸出到客戶端
while ((len=in.read(buffer))>0){
outputStream.write(buffer,0,len);
}
in.close();
out.close();
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
3 隨機刷新的驗證碼圖片
public class ImgServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//使瀏覽器2秒刷新一次;
resp.setHeader("refresh","0.5");
//在內(nèi)存中創(chuàng)建一個圖片
BufferedImage image = new BufferedImage(80,20,BufferedImage.TYPE_INT_RGB);
//得到圖片
Graphics2D g = (Graphics2D) image.getGraphics(); //筆
//設(shè)置圖片的背景顏色
g.setColor(Color.white);
g.fillRect(0,0,80,20);
//給圖片寫數(shù)據(jù)
g.setColor(Color.BLUE);
g.setFont(new Font(null,Font.BOLD,20));
g.drawString(makeNum(),0,20);
//告訴瀏覽器 請求圖片的方式打開
resp.setContentType("image/jpeg");
//網(wǎng)站存在緩存,不讓瀏覽器緩存
resp.setDateHeader("expires",-1);
resp.setHeader("Cache-Control","no-cache");
resp.setHeader("Pragma","no-cache");
//把圖片寫給瀏覽器
ImageIO.write(image,"jpg", resp.getOutputStream());
}
private String makeNum() {
Random random = new Random();
String num=random.nextInt(9999999)+"";
StringBuffer sb = new StringBuffer();
for (int i = 0; i <7-num.length(); i++) {
sb.append("0");
}
num =sb.toString()+num;
return num;
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
4 重定向
b一個web資源收到客戶端a請求后,b他回通知a客戶端去訪問另一個web資源c,這個過程叫重定向
常見場景:
用戶登錄
void sendRedirect(String var1) throws IOException;
測試:
public class RedirectServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// //具體實現(xiàn)
// resp.setHeader("Location","/rr/img");
// resp.setStatus(302);
//重定向
resp.sendRedirect("/rr/img");
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
面試題:請你聊一聊重定向和轉(zhuǎn)發(fā)的區(qū)別?
相同點:
- 頁面都會實現(xiàn)跳轉(zhuǎn)
不同點:
- 請求轉(zhuǎn)發(fā)的時候 url不會產(chǎn)生變化
- 重定向時候,url地址欄回發(fā)生變化
總結(jié)
以上就是關(guān)于 JavaWeb 中的小服務(wù)程序 Servlet 的詳細內(nèi)容,想要了解更多相關(guān) JavaWeb 中 Servlet 的其他內(nèi)容請搜索W3Cschool以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持我們!