6-Servlet入门

Servlet入门

1. Web服务器介绍

  • Web服务器是基于B/S结构,通过http协议进行数据交互(收发)

报文实例

请求:
GET  /mytest  HTTP/1.1  
Host: www.cnblogs.com 
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.0; zh-CN; rv:1.8.1) Gecko/20061010 Firefox/2.0  
.......

响应:
HTTP/1.1 200 OK
Content-Type:text/html;charset=utf-8
 
<html>
    <body>
       Hello http!
</body>
</html>
  • 简单selvet实现

http包下

public class MyRequest {
    private String method;
    private String url;
    
    public MyRequest(InputStream is){
        try {
            BufferedReader br = new BufferedReader(new InputStreamReader(is));// 01 获取请求报文
            String readHeader = br.readLine();                                // 02 获取请求报文的第一句
            String[] methodAndUrl = readHeader.split(" ");  
            // GET  /mytest  HTTP/1.1   03 以空格为条件将方法 地址放入数组
            this.method = methodAndUrl[0];  //04 取得请求报文方法
            this.url = methodAndUrl[1];     //05 取得请求报文地址
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public String getMethod() {                 //为了外部取该方法中定义的私有属性method
        return method;
    }
    
    public String getUrl() {                     //为了外部取该方法中定义的私有属性url
        return url;
    }
}
public class MyResponse {
    private OutputStream writer;

    public static String respHeader =   "HTTP/1.1 200 OK\n" +
                                        "Content-Type:text/html;charset=utf-8\n" +
                                        "\n";   //06 响应报文头部内容
    public MyResponse(OutputStream os){
        this.writer = os;            //07
    }
    
    public OutputStream getWriter() {
        return writer;                         //07 获取到的输出流对象提供给其它类
    }
}

servlet包下

public abstract class MyServlet {                             //08 定义  规则抽象类   为类对应的方法定义规则

    public void doService(MyRequest req, MyResponse resp){
        if("GET".equals(req.getMethod())){                   //09  直接抽象类判断完后  不用每个方法在重复写进行判断
            doGet(req,resp);
        }else{
            doPost(req,resp);
        }
    };

    public abstract void doGet(MyRequest req, MyResponse resp);   //10  定义的请求 报文的"请求方法" 的抽象方法
    public abstract void doPost(MyRequest req, MyResponse resp);  //10  定义的请求 报文的"请求方法" 的抽象方法

}
//实现登录功能
public class LoginServlet extends MyServlet {
    @Override
    public void doGet(MyRequest req, MyResponse resp) {
        OutputStream out = resp.getWriter();             //11 获得到响应的输出流对象
        try {
            out.write(resp.respHeader.getBytes());       //12 写入响应报文 头部
            out.write("login ok!!!!".getBytes());        //13 接着写响应的页面代码内容
            out.flush();                                 //刷新 关闭
            out.close();                                 //接下来建立对应的properties文件
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void doPost(MyRequest req, MyResponse resp) {
    }
}

//实现 吟首诗
public class QueryServlet extends MyServlet{
    @Override
    public void doGet(MyRequest req, MyResponse resp) {
        OutputStream out = resp.getWriter();
        try {
            out.write(resp.respHeader.getBytes());
            out.write("<h1>我的标题</h1><br/><p>床前明月光</p>".getBytes());
            out.flush();
            out.close();

        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void doPost(MyRequest req, MyResponse resp) {

    }
}

properties文件

servlet.one.url=/login
servlet.one.class=com.javasm.servlet.LoginServlet


servlet.three.url=/query
servlet.three.class=com.javasm.servlet.QueryServlet

server包下

public class MyServer {

    public static Map<String, MyServlet> myMapping = new HashMap<String, MyServlet>();
    //14 定义Servlet容器  通过请求 找到指定的servlet
    private static Properties prop = new Properties();
    //15 初始化properties对象


    public static void myInit(){
        try {
            prop.load(MyServer.class.getResourceAsStream("/MyMapping.properties"));   //16 获取properties位置 并加载
            Set keys = prop.keySet();                                            //17 获取properties所有Key
            for (Object key: keys){
                if(key.toString().endsWith(".url")){
                    //18 将properties里的地址  对应方法  通过键值对放入myMapping里
                    String url = prop.getProperty(key.toString());
                    String classNameKey = key.toString().replace("url","class");
                    String className = prop.getProperty(classNameKey);
                    MyServlet ms = (MyServlet)Class.forName(className).newInstance();
                    myMapping.put(url,ms);
                }
            }
        } catch (IOException | ClassNotFoundException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        }
    }

    public static void serverStart(){
        try {
            ServerSocket s = new ServerSocket(8011);      //18 开一个指定的监听的端口8011
            System.out.println("服务器开启 监听8011端口 等待访问");
            while (true){                                       // 就是让他一直开着
                Socket soc = s.accept();                        
                //19 拿到Socket对象  多线程开就是一个端口等待请求 多线程开启
                MyProcess newThread = new MyProcess(soc);       //20 请求线程
                newThread.start();                              //25 开启线程

            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) {
        MyServer.myInit();
        MyServer.serverStart();
    }

}
public class MyProcess extends Thread{
    Socket soc;                           //定义 Socket对象
    public MyProcess(Socket soc){
        this.soc = soc;
    }

    @Override
    public void run() {
        try{
            MyRequest req = new MyRequest(soc.getInputStream());       //21 拿到请求报文
            MyResponse resp = new MyResponse(soc.getOutputStream());   //22 拿到响应报文
            MyServlet ms = MyServer.myMapping.get(req.getUrl());       //23 通过拿到的对象的网址拿到myMapping对应的方法
            if(ms!=null){                                              //24 判断下如果是空的告诉用户没有该方法
                ms.doService(req,resp);
            }else{
                OutputStream out = resp.getWriter();
                out.write(resp.respHeader.getBytes());
                out.write("404 not  Found!!!".getBytes());
                out.flush();
                out.close();
            }
        }catch (Exception e){
            e.printStackTrace();
        }
    }
}

2. Tomcat下载和使用

2.1 Tomcat介绍

下载地址:http://tomcat.apache.org/;

安装:下载到的是一个压缩包,解压缩即可(路径中不要有中文);

2.2 Tomcat目录结构
名称作用
/bin存放Windows或Linux平台上用于启动和停止Tomcat的脚本文件
/conf存放Tomcat服务器的各种配置文件,其中最重要的是server.xml
/lib存放Tomcat服务器所需的各种JAR文件 //自己创建
/logs存放Tomcat运行中产生的日志文件
/webapps存放Tomcat发布的Web应用
/workTomcat把由JSP生成的Servlet放于此目录下
  • 启动和停止Tomcat服务器

可通过apache解压目录中的startup.bat/shutdown.bat来启动或停止tomcat

在浏览器地址栏中输入:http://127.0.0.1:端口号或者http://localhost:端口号,页面进入到Tomcat启动成功界面

Tomcat默认端口号为-8080

  • 可以在conf中的server.xml中修改tomcat端口号
<Connector port="8080" protocol="HTTP/1.1 " 
connectionTimeout="20000" redirectPort="8443 " 	
/>
2.3 Tomcat在idea中配置
1.创建空项目
2.配置tomcat
  右上角 edit configurations defaults 配置模板 选择tomcat真实目录
  点加号 用此模板添加一份
3.新建模块 选javaEE  勾选 web application

4.如果默认没创建好项目与tomcat的关联 手动添加artifacts   web application war exploded
5.tomcat中加载项目 artifact 改项目名

//
2.4 其他web服务器
  • Jetty 更轻量级,更灵活,被一些框架集成,免费
  • JBoss JBoss支持JavaEE标准,能够作为JavaEE应用服务器使用,Servlet容器只是其

中一部分,免费

  • Weblogic 市场上最好的J2EE工具之一,功能大而全,收费

3. Servlet

3.1 servlet介绍
  • Servlet是JavaEE规范中的Web开发组件;

  • Servlet运行在服务器端,需要Servlet容器的支持,例如Tomcat(运行在tomcat中);

  • 可以通过浏览器访问Servlet,Servlet可以生成动态页面返回给浏览器

在这里插入图片描述

3.2 编写servlet
public class TestServlet extends HttpServlet {//继承httpservlet 重写doGet doPost方法
	  protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		  //处理代码
	}
	  protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		  doGet(request, response);
	}
}


Web.xml中配置
    <servlet>
        <servlet-name> TestServlet </servlet-name>                               //name---TestServlet
        <servlet-class>com.javasm.servlet. TestServlet </servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name> TestServlet </servlet-name>                               //name---TestServlet
        <url-pattern>/TestServlet </url-pattern>
	</servlet-mapping>
配置中servlet-name相同作为同一组配置 
servlet-class配置完整包名类名
url-pattern配置开放的访问路径 该路径为虚拟的路径
3.3 Servlet实现方式
  • 实现Servlet的三种方式:一个实现,两个继承
  1. 实现Servlet接口
  2. 继承GenericServlet抽象类 重写service()方法
  3. 继承HttpServlet抽象类 HttpServlet继承于GenericServlet 重写doGet(),doPost()方法 //最常用
3.4 Servlet生命周期

在这里插入图片描述

3.5 Servlet其他配置参数
  • servlet中配置初始化参数,可在servlet中直接读取
配置中:
<servlet>
        <servlet-name>HelloServlet</servlet-name>
        <servlet-class>com.javasm.servlet.HelloServlet</servlet-class>
        <init-param>
            <param-name>testParam</param-name>
            <param-value>Hello Servlet</param-value>
        </init-param>
</servlet>

代码中:
String initParam = getInitParameter("testParam");      
//在代码中直接将上面存储的"testParam"的值读取了
//不过只能在 "HelloServlet" Servlet里读取得到
  • 配置servlet全局参数,与servlet标签同级,所有servlet都可以读取
配置中:    //配置服务器全局参数用
 <context-param>
        <param-name>contextParam</param-name>
        <param-value>Hello Servlet</param-value>
 </context-param>

代码中:
String contextParam = getServletContext().getInitParameter("contextParam");
//这个全局都可以得到
  • 配置servlet启动顺序load-on-startup
<servlet>
        <servlet-name>HelloServlet</servlet-name>
        <servlet-class>com.javasm.servlet.HelloServlet</servlet-class>
        <load-on-startup>1</load-on-startup>
</servlet>

注意:如果配置了load-on-startup,servlet实例会在项目启动时就加载,并且按照load-on-startup中配置的顺序加载,如果不加load-on-startup,实例会在有请求访问到该servlet时实例化

3.6 Servlet中处理乱码

Servlet运行在web容器(tomcat)中,tomcat默认对传递的数据使用iso-8859-1进行编码,传递中文无法正常显示。

请求乱码:
如果数据在传递时是正常中文,但是在servlet中取出是乱码,需要在请求对象中设置编码格式,对请求数据进行重新编码。
request.setCharacterEncoding("UTF-8");
响应乱码:
如果数据在servlet中是正常中文,到页面中显示乱码,则需要在响应对象中设置响应头,让页面指定以何种编码格式解析响应数据。
response.setContentType("text/html;charset=UTF-8");
public class LoginServlet extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doPost(req, resp);
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("运行了");
        //获取请求的参数 getParameter
        //设置请求参数编码格式setCharacterEncoding 需要在获取之前设置
        //设置响应编码格式resp.setContentType("text/html;charset=utf-8");
        // 实际上设置在响应头中 先设置响应头 再获取输出流

        req.setCharacterEncoding("utf-8");              //将请求格式调整为utf-8格式
        String uname = req.getParameter("uname");
        String upwd = req.getParameter("upwd");

        System.out.println(uname+" ___ "+upwd);
        resp.setContentType("text/html;charset=utf-8");   //将响应后的格式调整为utf-8格式
        PrintWriter out = resp.getWriter();
        out.print("<h1>hello !!! "+uname+"</h1>");
        out.flush();
        out.close();
    }
}


 

注意:如果浏览器中样式没有起效果 将web文件夹 右键

在这里插入图片描述

@WebServlet("/login")    //注解: 直接写请求地址   //javax包下   不用大量在web.xml写大量的配置方法;了
public class LoginServlet extends HttpServlet {

}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
/* * Copyright (c) 2000 David Flanagan. All rights reserved. * This code is from the book Java Examples in a Nutshell, 2nd Edition. * It is provided AS-IS, WITHOUT ANY WARRANTY either expressed or implied. * You may study, use, and modify it for any non-commercial purpose. * You may distribute it non-commercially as long as you retain this notice. * For a commercial use license, or to purchase the book (recommended), * visit http://www.davidflanagan.com/javaexamples2. */ package com.hexiang.examples.servlet; import javax.servlet.*; import javax.servlet.http.*; import java.sql.*; import java.io.*; /** * This class demonstrates how JDBC can be used within a servlet. It uses * initialization parameters (which come from the web.xml configuration file) * to create a single JDBC database connection, which is shared by all clients * of the servlet. ***/ public class Query extends HttpServlet { private static final long serialVersionUID = -5616899811848789885L; Connection db; // This is the shared JDBC database connection public void init() throws ServletException { // Read initialization parameters from the web.xml file ServletConfig config = getServletConfig(); String driverClassName = config.getInitParameter("driverClassName"); String url = config.getInitParameter("url"); String username = config.getInitParameter("username"); String password = config.getInitParameter("password"); // Use those init params to establish a connection to the database // If anything goes wrong, log it, wrap the exception and re-throw it try { Class.forName(driverClassName); db = DriverManager.getConnection(url, username, password); } catch (Exception e) { log("Can't create DB connection", e); throw new ServletException("Query: can't initialize: " + e.getMessage(), e); } } /** Close the database connection when the servlet is unloaded */ public void destroy() { try { db.close(); } // Try to close the connection catch (SQLException e) {} // Ignore errors; at least we tried! } public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { response.setContentType("text/html"); // We're outputting HTML PrintWriter out = response.getWriter(); // Where to output it to // Output document header and a form for entering SQL queries // When the form is submitted, this servlet is reloaded out.println("<head><title>DB Query</title></head>\n" + "<body bgcolor=white><h1>DB Query</h1>\n" + "<form><b>Query: </b><input name='q'>" + "<input type=submit></form>"); // See if a query was specified in this request. String query = request.getParameter("q"); if (query != null) { // display the query text as a page heading out.println("<h1>" + query + "</h1>"); // Now try to execute the query and display the results in a table Statement statement = null; // An object to execute the query try { // Create a statement to use statement = db.createStatement(); // Use it to execute the specified query, and get result set ResultSet results = statement.executeQuery(query); // Ask for extra information about the results ResultSetMetaData metadata = results.getMetaData(); // How many columns are there in the results? int numcols = metadata.getColumnCount(); // Begin a table, and output a header row of column names out.println("<table border=2><tr>"); for(int i = 0; i < numcols; i++) out.print("<th>" + metadata.getColumnLabel(i+1) + "</th>"); out.println("</tr>"); // Now loop through the "rows" of the result set while(results.next()) { // For each row, display the the values for each column out.print("<tr>"); for(int i = 0; i < numcols; i++) out.print("<td>" + results.getObject(i+1) + "</td>"); out.println("</tr>"); } out.println("</table>"); // end the table } catch (SQLException e) { // If anything goes wrong (usually a SQL error) display the // error to the user so they can correct it. out.println("SQL Error: " + e.getMessage()); } finally { // Whatever happens, always close the Statement object try { statement.close(); } catch(Exception e) {} } } // Now, display the number of hits on this page by invoking the // Counter servlet and including its output in this page. // This is done with a RequestDispatcher object. RequestDispatcher dispatcher = request.getRequestDispatcher("/servlet/counter"); if (dispatcher != null) { out.println("<br>Page hits:"); // Add a request attribute that tells the servlet what to count. // Use the attribute name defined by the Counter servlet, and // use the name of this class as a unique counter name. request.setAttribute(Counter.ATTRIBUTE_NAME,Query.class.getName()); // Tell the dispatcher to invoke its servlet and include the output dispatcher.include(request, response); } // Finally, end the HTML output out.println("</body>"); } }

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值