目录
如果配置好xml和servlet的java类,就可以访问了,那么具体我们是怎么访问并且执行servlet的呢?
环境
到了这一步不需要任何的环境了
了解什么是servlet
我们来说说这个servlet是啥,和jsp有啥差别:知乎:servlet和jsp介绍以及区别、区别与联系
【前一个连接特别好,里面还包含了其他关于servlet的东西】
servlet是位于web服务器内部,运行在服务器的java程序,可以生成动态的web,传统java应用是从命令行启动,但是servlet是由web服务器进行加载的,而且servlet运行需要在web.xml中进行描述和注册,比如映射servlet的名字啊,配置servlet类啊,初始化servlet的参数之类的,这个我们会在下面详细说明。
jsp和servlet都可以做页面,但是jsp更接近表示层,servlet更多处理比较复杂,jsp难以写出的逻辑层的东西
我们访问tomcat任何一个资源其实都是在访问servlet,也就是说其实jsp也是被编译成了一个Servlet,然后进行访问的。
创建servlet
关于如何在web工程中创建一个servlet,有两种方法,推荐适用前一种
Servlet架构由javax.servlet和javax.servlet.http两个Java包组成。前面定义了所有的servlet类,后面定义了最常见的采用http通信的httpservlet的类。照理来说所有用户编写的类都需要实现javax.servlet.Servlet这个接口的五个方法
- init()方法 :初始化一个Servlet类实例,并将其加载到内存中。只能用一次(开始的时候
- service()方法 :Servlet成功初始化后该方法会被调用,用于处理用户请求
- destroy()方法 :终止Servlet服务,销毁一个Servlet实例。 用一次
- getServletConfig()方法 :获得ServletConfig对象,里面包含该Servlet的初始化信息,如初始化参数和ServletContext对象。
- getServletInfo()方法:返回一个String对象,该对象包含Servlet的信息,例如开发者、创建日期、描述信息等
但是我们一般继承httpservlet(其他的比如genericservlet也有类似特性),这个类帮我其他都实现了,我们只需要实现service方法!cool
我们来看看第一节课的helloworld用servlet咋写:
import javax.servlet.*;
import javax.servlet.http.*;
import java.io.*;
public class Helloworld extends HttpServlet
{
public void doGet(HttpServletRequest req, HttpServletResponse res) throws ServletException,IOException
{
res.setContentType("text/html;charset=GBK");
PrintWriter out=res.getWriter();
out.println("<html>");
out.println("<head><title>HelloWorld!</title></head>");
out.println("<body>");
out.println("<p>欢迎学习java Servlet</p>");
out.println("</body></html>");
}
public void doPost(HttpServletRequest req, HttpServletResponse res) throws ServletException,IOException
{ doGet(req,res);}
}
来看看我们是怎么从index.jsp变到helloworld.java的
<%@ page language="java" import="java.util.*" pageEncoding="ISO-8859-1"%>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<base href="<%=basePath%>">
<title>My JSP 'index.jsp' starting page</title>
<meta http-equiv="pragma" content="no-cache">
<meta http-equiv="cache-control" content="no-cache">
<meta http-equiv="expires" content="0">
<meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
<meta http-equiv="description" content="This is my page">
<!--
<link rel="stylesheet" type="text/css" href="styles.css">
-->
</head>
<body>
This is my JSP page. <br>
</body>
</html>
这个是index.jsp的代码 我们发现,其实helloworld就是把要显示的,前后输出<html> </html>还有中间的body部分,虽然说一个是html里面嵌套java一个是java里面嵌套html语法,这就好像纸包鸡和鸡包纸(什么鬼?)
而我们转眼看看helloworld.java 这里的dopost直接交给doget处理,就是说不论发来的html是get还是post方法,我们都是用同一个函数处理。
并且如果你实际操作看看,就会发现这个.java文件被编译成了一个helloworld.class字节文件
那么xml里面怎么配置呢
我们编译完需要放在指定位置并且在web.xml中进行配置
指定位置)
在web.xml中配置文件中,<servlet>和<servlet-mapping>标识用于对Servlet进行配置,这个配置信息可以分为两个部分
- 第一部分是配置Servlet的名称和对应的类
- 第二部分是配置Servlet的访问路径
<servlet>:对每个Servlet进行说明和定义。
<description>是对Servlet的描述信息,<display-name>是发布时Servlet的名称,这两项在配置是可省略。
<servlet-name>是这个Servlet的名称,这个名字可以任意命名,但是要和<servlet-mapping>节点中的<servlet-name>保持一致。
<servlet-class>是Servlet对应类的路径,在这里要注意,如果有Servlet带有包名,一定要把包路径写完整,否则Servlet容器就无法找到对应的Servlet类。
<init-param>用于对Servlet初始化参数进行设置(没有可省略,但是想下面那个工程就需要用到name和password)
(对这些初始化参数的访问可以在init()方法体中通过getInitParameter()方法进行获取)
<load-on-startup>用于指定容器载入Servlet时的优先顺序。如果Servlet没有设定<load-on-startup>载入优先级,则Servlet容器会在这个Servlet被访问时再进行初始化。
<servlet-mapping>:是对Servlet的访问路径进行映射。
<servlet-name>是这个Servlet的名称,要和<servlet >节点中的<servlet-name>保持一致。
<url-pattern>定义了Servlet的访问映射路径,这个路径就是在地址栏中输入的路径。
注意: <servlet>和<servlet-mapping>是成对出现,而且Servlet容器中有多少个servlet类就需要配置多少次。
如果配置好xml和servlet的java类,就可以访问了,那么具体我们是怎么访问并且执行servlet的呢?
Servlet的执行过程:
首先根据在地址栏输入的路径信息找到<servlet-mapping>中<url-pattern>对应的<servlet-name>,再对应找到<servlet>中该<servlet-name>对应的<servlet-class>类,从而实例化该servlet并执行。
比如:
在上面我们的helloworld.java的<url-pattern>为/servlet/HelloWorld(此路径为虚拟路径,通常的写法为/servlet/类名)所以在地址栏中输入http://127.0.0.1:8080/servlet/HelloWorld
<servlet>
<description> Servlet Example</description>
<display-name>Servlet</ </display-name>
<servlet-name>HelloWorld</servlet-name>
<servlet-class>HelloWorld</servlet-class>
<init-param>
<param-name>user</param-name>
<param-value>alex</param-value>
</init-param>
<init-param>
<param-name>address</param-name>
<param-value>http://www.hrbust.edu.cn</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>HelloWorld </servlet-name>
<url-pattern>/servlet/HelloWorld</url-pattern>
</servlet-mapping>
此图是servlet的生命周期
干点大的:用户登录的身份验证
程序模块:程序共分3个部分
- 用户登录页面login.html
- 登录页面验证码生成类CheckCodeServlet.class
- 用户身份验证类LoginServlet.class。
工程目录:
界面十分简单,可以看到唯一可以讲的就是这个from action在点击之后会发生两种动作,这里是html的知识点,总之会发生不同的动作点击之后,下面这个程序中from action是提示我们等等提交submit之后跳转的页面,和我们数据库中add是一样的写法,而且图片那调用了checkcodeservlet生成一个图片,如果点击图片,会在这个servlet(我们说了这个文件最后会变成一个servlet)的对象调用reload。我们接下来会讲到checkcodeservlet中我们是生成图片的同时往session中保存了验证码是什么,好在loginservlet中判断是否正确。
<!DOCTYPE html>
<HTML>
<HEAD>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<TITLE>用户登录</TITLE>
</HEAD>
<BODY bgColor=#ffffff leftMargin=0 text=#000000 topMargin=30>
<form action="servlet/LoginServlet" method="get">
姓名<input maxlength=10 name=name size=8><br>
密码<input type=password name=password size=8><br>
验证码<input name=code size=8><br>
<img src="servlet/CheckCodeServlet" onclick="self.location.reload();"/><br>
<input name=Submit type=submit value=提交>
<input name=Submit2 type=reset value=重置>
</form>
</BODY>
</HTML>
数据库中操作(部分)
<form action="addAction.jsp" method="Post">
添加:
<br />
电影名称: <input type="text" name="MovieName" />
<br />
电影类型: <input type="text" name="MovieType" />
<br />
电影描述: <input type="text" name="MovieDes" />
<br />
<input type="submit" value="提交" />
</form>
————————————————
版权声明:本文为CSDN博主「专业渡劫修仙」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/kuizhao8951/article/details/100896498
checkcodeservlet.java部分,如果不懂下面java servlet request和respone部分,可以看看这里
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.io.OutputStream;
import javax.imageio.ImageIO;
import javax.servlet.*;
import javax.servlet.http.*;
public class CheckCodeServlet extends HttpServlet{
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException,IOException{
resp.setContentType("image/jpeg");//使客户端浏览器区分不同种类的数据,告诉客户端这是图片//设置显示内容类型
OutputStream out=resp.getOutputStream();//取得输出流
try{
resp.setHeader("programa","no-cache");//HTTP消息头
resp.setHeader("Cache-Control","no-cache");//Cache-Control指定请求和响应遵循的缓存机制
resp.setDateHeader("Expires",0);
//开始制作code
BufferedImage image=new BufferedImage(50,18,BufferedImage.TYPE_INT_RGB);
Graphics g=image.getGraphics();
g.setColor(Color.LIGHT_GRAY);
g.fillRect(0,0,50,18);
g.setColor(Color.LIGHT_GRAY);
g.drawRect(0,0,50,18);
String str="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
String code="";
for(int i=0;i<4;i++)
{
int k=(int)(Math.random()*36);
char c=str.charAt(k);
code+=c;
}
//将code放入session:session机制采用的是在服务器端保持 HTTP 状态信息的方案
HttpSession session=req.getSession();
session.setAttribute("code",code);
g.setColor(Color.BLACK);
Font font=new Font("DIALOG",Font.ITALIC,15);
g.setFont(font);
g.drawString(code,3,15);
ImageIO.write(image,"JPEG",out);
out.flush();
out.close();
}finally{out.close();}
}
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException,IOException
{doGet(req,resp);}
}
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
public class LoginServlet extends HttpServlet
{protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException,IOException
{ resp.setContentType("text/html;charset=gbk");
PrintWriter out=resp.getWriter();
try{
//req.setCharacterEncoding("utf-8");
String myUserName=this.getInitParameter("name");
String myPassWord=this.getInitParameter("password");
HttpSession session=req.getSession();
String scode=(String)session.getAttribute("code");
String userName=req.getParameter("name");
String passWord=req.getParameter("password");
String code=req.getParameter("code");
out.println("<html><body>");
out.println("<br/>");
if(!code.toUpperCase().equals(scode)){out.println("验证码错误!");}
else if(userName.equals(myUserName)&&passWord.equals(myPassWord))
{out.println("登录成功!");}
else{
out.println(myUserName+" "+myPassWord+" "+userName+" "+passWord);
out.println("登录失,败!");}
}
finally{out.close();}
}
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException,IOException{
doGet(req,resp);}
}
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5"
xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
<display-name></display-name>
<servlet>
<description>This is the description of my J2EE component</description>
<display-name>This is the display name of my J2EE component</display-name>
<servlet-name>CheckCodeServlet</servlet-name>
<servlet-class>CheckCodeServlet</servlet-class>
</servlet>
<servlet>
<description>This is the description of my J2EE component</description>
<display-name>This is the display name of my J2EE component</display-name>
<servlet-name>LoginServlet</servlet-name>
<servlet-class>LoginServlet</servlet-class>
<init-param>
<param-name>name</param-name>
<param-value>cxq</param-value>
</init-param>
<init-param>
<param-name>password</param-name>
<param-value>1234</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>CheckCodeServlet</servlet-name>
<url-pattern>/servlet/CheckCodeServlet</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>LoginServlet</servlet-name>
<url-pattern>/servlet/LoginServlet</url-pattern>
</servlet-mapping>
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
</web-app>
其实这里有一个问题,就是客户端get请求的时候,我这边用户名req收到的是iso编码的,需要在html里面设置编码转换,但是我还不会。并且//req.setCharacterEncoding("utf-8");是不能改变编码的,接受的时候已经默认是iso进行解码之后了