Super detailed explanation of Servlet [the latest version in 2023]

Compilation software: IntelliJ IDEA 2019.2.4 x64
Operating system: win10 x64-bit Home Edition
Server software: apache-tomcat-8.5.27



1. What is a Servlet?

Servlet,英文全称为Server Applet,意为服务器端的一小程序. It runs on a web server that supports the Java Servlet specification. Among the many web applications deployed on the server, no matter it is a B/S architecture or a C/S architecture, their basic operation mode is shown in the following figure (taking Java programs as an example):
insert image description here

If the operation mode of the above-mentioned web application is compared to a restaurant that is in business, then the Servlet plays the role of the waiter in it . When the customer enters the restaurant to eat ( the client sends a request ), it is responsible for serving the menu to the customer and waiting for the customer to order. For the menu, the servlet will notify the cook ( web application ) to cook (handle the business), and the cook will ask the waiter to serve the dishes ( response ) to the guests.

总的来说,Servlet就是和客户端进行交互(处理请求和响应)

Servlets are commonly used to create web applications like e-commerce sites, social media applications, online banking sites, and the like. By using Servlets, developers can build web applications in a portable, flexible, efficient and reusable manner.


2. How to write the first servlet program?

step:

①Create an html page and create a hyperlink on it (plan to visit the HelloServlet in the background)

<a href="">访问HelloServlet</a>

②Create HelloServlet

  1. Create a new common class HelloServelet
  2. HelloServlet implements interface Servlet
  3. Implement all abstract methods in the interface

The code demonstration is as follows:

import javax.servlet.*;
import java.io.IOException;
import java.util.Enumeration;

public class HelloServelet implements Servlet {
    
    

   

    @Override
    public void init(ServletConfig servletConfig) throws ServletException {
    
    
	

    }


    @Override
    public ServletConfig getServletConfig() {
    
    
        return null;
    }

    /**
     * 主要功能:处理客户端的请求和响应
     * @param servletRequest  处理请求
     * @param servletResponse  处理响应
     * @throws ServletException
     * @throws IOException
     */
    @Override
    public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
    
    
        System.out.println("访问了HelloServlet类的service方法.......");


     
    }

    @Override
    public String getServletInfo() {
    
    
        return null;
    }

    @Override
    public void destroy() {
    
    
        
    }
}

  1. Set the access path for HelloServlet in web.xml

The code demonstration is as follows:

<!--  HelloServlet的访问路径:/hello  -->
<servlet>
    <!--   为Servlet起个名字     -->
    <servlet-name>abc</servlet-name>
    <!--   Servlet的全类名     -->
    <servlet-class>t1.HelloServelet</servlet-class>
</servlet>
<servlet-mapping>
    <!--  要和Servlet中的servlet-name的名字一致      -->
    <servlet-name>abc</servlet-name>
    <!--   设置访问路径,注意,必须是/开头     -->
    <url-pattern>/hello</url-pattern>
</servlet-mapping>

③Set the set access path to the hyperlink

<a href="hello">访问HelloServlet</a>

④Test HelloServlet

insert image description here
insert image description here

Notice:

  1. 网页必须直接在web下(不能放在WEB-INF下)
  2. web.xml中url-pattern的值必须以/开头
  3. The request path of the webpage, which cannot start with /
  4. Web pages cannot be opened in a static way

The request principle is as follows:

insert image description here

Servlet object management:

  • Servlet的实例对象由Servlet容器(tomcat)负责创建

  • Servlet的方法由容器在特定情况下调用

  • Servlet容器会在web应用卸载时(tomcat停止)销毁Servlet对象的实例


3. Servlet life cycle

There are five methods in the Servlet interface, three of which are related to the life cycle (init/service/destroy).

Request process:

  1. 默认情况下在第一次发出请求时,Servlet容器(tomcat服务器)会创建相应的servlet对象、进行初始化(执行init方法)、执行service方法
  2. 第二次以及以后的每一次请求发出,都直接执行service方法
  3. 在web应用被卸载(服务器被停止时)的时候,servlet对象会被销毁,销毁之前执行destroy方法

Can a servlet create its object when starting the server?

Can

Methods as below:

Add a tag inside the servlet tag of the current Servlet in web-xml

//设置自启动
<load-on-startup>l</1oad-on-startup>

The code demonstration is as follows:

<!--   设置自启动,若有多个servlet都设了自启动,根据标签体中的值来判定启动优先级,值越小,优先级越高     -->
<!--     <load-on-startup></load-on-startup>中的标签体为非0的整数     -->
        <load-on-startup>1</load-on-startup>

Four. Servlet technical system

Three ways to create a Servlet:

① Implement the Servlet interface

Rewrite its five methods (only one service is the focus), and the other four must also be rewritten

Case: Create a HelloServlet class to implement the Servlet interface

The code demonstration is as follows:

import javax.servlet.*;
import java.io.IOException;
import java.util.Enumeration;

public class HelloServelet implements Servlet {
    
    

   

    @Override
    public void init(ServletConfig servletConfig) throws ServletException {
    
    
	
    }


    @Override
    public ServletConfig getServletConfig() {
    
    
        return null;
    }

    /**
     * 主要功能:处理客户端的请求和响应
     * @param servletRequest  处理请求
     * @param servletResponse  处理响应
     * @throws ServletException
     * @throws IOException
     */
    @Override
    public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
    
    
        System.out.println("访问了HelloServlet类的service方法.......");


     
    }

    @Override
    public String getServletInfo() {
    
    
        return null;
    }

    @Override
    public void destroy() {
    
    
        
    }
}

web-xml creates its access path:

<!--  HelloServlet的访问路径:/hello  -->
<servlet>
    <!--   为Servlet起个名字     -->
    <servlet-name>abc</servlet-name>
    <!--   Servlet的全类名     -->
    <servlet-class>t1.HelloServelet</servlet-class>
</servlet>
<servlet-mapping>
    <!--  要和Servlet中的servlet-name的名字一致      -->
    <servlet-name>abc</servlet-name>
    <!--   设置访问路径,注意,必须是/开头     -->
    <url-pattern>/hello</url-pattern>
</servlet-mapping>

insert image description here

insert image description here

②Inherit GenericServlet

step:

  1. create a class
  2. Inherit an abstract class (GenericServlet)
  3. Implement an abstract method in an abstract class
  4. Configure the access path of Servlet in web-xml

Notice:

The main function of GenericServlet is to implement the four methods other than service. Our own Servlet only needs to implement the service method . If you want to use the other four methods, you can use rewriting.

Case: Create MyFirstServlet class to inherit GenericServlet class

The code demonstration is as follows:

public class MyFirstServlet extends GenericServlet {
    
    

    @Override
    public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
    
    
        System.out.println("触发了继承GenericServlet类的子类MyFirstServlet类的service方法......");


    }
}

web-xm configures its access path:

<!-- 设置访问MyFirstServlet的路径:/myfirst   -->
    <servlet>
        <servlet-name>def</servlet-name>
        <servlet-class>t1.MyFirstServlet</servlet-class>
    </servlet>

    <servlet-mapping>
        <servlet-name>def</servlet-name>
        <url-pattern>/myfirst</url-pattern>
    </servlet-mapping>

insert image description here

insert image description here

③ Inherit HttpServlet

step:

  1. create a class

  2. Inherit an abstract class (HttpServlet)

  3. Override two methods doGet and doPost

  4. Configure the access path of the Servlet

Notice:

The main function of HttpServlet is to implement the service method, and then distribute the request (different request methods call different methods). The get request calls the doGet method , and the post request calls the doPost method .

Case: Create MyFirstServlet class to inherit GenericServlet class

The code demonstration is as follows:

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 SecondServlet extends HttpServlet {
    
    
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    
    
        System.out.println("访问了SecondServlet里的doPost方法");
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    
    
        System.out.println("访问了SecondServlet里的doGet方法");
    }
}

web-xm configures its access path:

<!-- 设置访问SecondServlet的路径:/second   -->
    <servlet>
        <servlet-name>SecondServlet</servlet-name>
        <servlet-class>t1.SecondServlet</servlet-class>
    </servlet>


    <servlet-mapping>
        <servlet-name>SecondServlet</servlet-name>
        <url-pattern>/second</url-pattern>
    </servlet-mapping>

insert image description here
insert image description here


Five. Two interfaces in the web project

5.1 Servletconfig interface

​A Servlet object corresponds to a unique ServletConfigi configuration object

How to get Servletconfig object?

In the formal parameter position of the init method, Servletconfig is passed to the init method when the current Servlet is initialized

The main function:

  1. Get the Servlet name (the value of servlet-name in web.xml)

    insert image description here

       //获取Servlet名称
       String servletName = servletConfig.getServletName();
       System.out.println("servletName:"+servletName);
       
    
    
  2. Get the global context (ServletContext) object

    //获取全局上下文对象
    ServletContext servletContext = servletConfig.getServletContext();
    System.out.println("servletContext:"+servletContext);
    
  3. Get Servlet initialization parameters

    The prerequisite for obtaining Servlet initialization parameters is to have servlet initialization parameters

    How to set the initialization parameters of the servlet?

    Location: In the servlet tag of web.xml, set above sub-tag 1–>, otherwise an error will be reported

    The code demonstration is as follows:

     		<!--设置当前Servlet的初始化参数-->
    	   <init-param>
    	   <param-name>path</param-name>
    	   <param-value>classpath:springmvc.xml</param-value>
    	   </init-param>
    

    Get Servlet initialization parameters:

    	   //获取web-xml中的servlet标签内的初始化参数<param-name>为path的value值
    	   String path = servletConfig.getInitParameter("path");
    	   System.out.println("path:"+path);
    	   
    	   //获取HelloServelet内所有初始化参数的<param-name>【key】值
    	   Enumeration<String> initParameterNames = servletConfig.getInitParameterNames();
    	   while (initParameterNames.hasMoreElements()){
          
          
    	         System.out.println("initParameterNames.nextElement():"+initParameterNames.nextElement());
    	           
    	   }
    

Case: Implement the above functions in the HelloServelet class

The code demonstration is as follows:

import javax.servlet.*;
import java.io.IOException;
import java.util.Enumeration;

public class HelloServelet implements Servlet {
    
    

    public HelloServelet() {
    
    
        System.out.println("HelloServelet类的构造方法被执行了");
    }

    @Override
    public void init(ServletConfig servletConfig) throws ServletException {
    
    

        System.out.println("HelloServelet类的init方法被执行了");

        //1.获取的是当前Servlet名称(web.xml中配置servlet-name的值)
        String servletName = servletConfig.getServletName();
        System.out.println("servletName:"+servletName);

        //2.获取全局上下文ServletContext对象
        ServletContext servletContext = servletConfig.getServletContext();
        System.out.println("servletContext:"+servletContext);


        //3.获取Servlet初始化参数
        //获取web-xml中的servlet标签内的初始化参数<param-name>为path的value值
        String path = servletConfig.getInitParameter("path");
        System.out.println("path:"+path);

        //获取web-xml中的初始化参数<param-name>为aaa的value值
        String aaa = servletConfig.getInitParameter("aaa");
        System.out.println("aaa:"+aaa);


        //获取HelloServelet内所有初始化参数的<param-name>【key】值
        Enumeration<String> initParameterNames = servletConfig.getInitParameterNames();
        while (initParameterNames.hasMoreElements()){
    
    
            System.out.println("initParameterNames.nextElement():"+initParameterNames.nextElement());
        }

    }


    @Override
    public ServletConfig getServletConfig() {
    
    
        return null;
    }

    /**
     * 主要功能:处理客户端的请求和响应
     * @param servletRequest  处理请求
     * @param servletResponse  处理响应
     * @throws ServletException
     * @throws IOException
     */
    @Override
    public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
    
    
        System.out.println("访问了HelloServlet类的service方法.......");

    }

    @Override
    public String getServletInfo() {
    
    
        return null;
    }

    @Override
    public void destroy() {
    
    
        System.out.println("HelloServelet类的destroy方法被执行了");
    }
}

insert image description here

5.2 ServletContext interface

Notice:

  • A web project has only one ServletContext object, representing the current web application
  • All Servlets share the same ServletContext object, so the ServletContext object is also called the application object (Web application object)
  • The ServletContext object is created by Tomcat when the server is started, and destroyed when the project is unloaded (when the server is shut down).

How to get the ServletContext object?

  1. Get it through ServletConfig

    //使用servletConfig获取全局上下文ServletContext对象
    ServletContext servletContext = servletConfig.getServletContext();
    System.out.println("servletContext:"+servletContext);
    
  2. Get it through request

    //使用servletRequest获取servletcontext对象(全局上下文对象)
    ServletContext servletContext = servletRequest.getServletContext();
    System.out.println("servletContext:"+servletContext);
    

The main function:

  • Get the context path of the project (project name with "/")

    //1.获取项目的上下文路径(带/的项目名)
    String contextPath = servletContext.getContextPath();
    System.out.println("contextPath:"+contextPath);
    
  • Get the local real path mapped by the virtual path

    Purpose: Need to use when uploading or downloading files

    //2.获取虚拟路径所映射的本地真实路径(根据相对路径获得绝对路径)
    String realPath = servletContext.getRealPath("/upload");
    System.out.println("realPath:"+realPath);
    
  • Get the global initialization parameters of the WEB application

    The prerequisite for obtaining global initialization parameters is that you must have global initialization parameters, if not, you must set them

    How to set global initialization parameters?

    Location: On the root node of web.xml

    insert image description here

    The corresponding code on web.xml looks like this:

    <context-param>
        <param-name>context-key</param-name>
        <param-value>context-value</param-value>
    </context-param>
     <context-param>
         <param-name>ccc</param-name>
         <param-value>ddd</param-value>
     </context-param>
    
    //3.获取WEB应用程序的全局初始化参数
    //获取全局初始化参数中<param-name>【 key】为ccc的value值
    String ccc = servletContext.getInitParameter("ccc");
    System.out.println("ccc="+ccc);
    
    //获取全局初始化参数中<param-name>【 context-key】为ccc的value值
    String context_key = servletContext.getInitParameter("context-key");
    System.out.println("context_key="+context_key);
    
    //获取全局初始化参数中所有的<param-name>【 key】值
    Enumeration<String> initParameterNames = servletContext.getInitParameterNames();
    while (initParameterNames.hasMoreElements()){
          
          
        System.out.println("nextElement:"+initParameterNames.nextElement());
    }
    

  • Share data as domain objects★

    Domain objects: Objects that share data within a certain scope

    The domain scope used by ServletContext is the entire web project

    test:

    1. In a Servlet, set shared data in the ServletContext object

    2. Get the shared data in another Servlet

    method:

    servletcontext.setAttribute(string key,object obj);
    object msg servletcontext.getAttribute(string key);
    
    //移除指定的共享数据(指定key,删除对应的value)
    servletcontext.removeAttribute(Sstring key);
    

    Case: Try to use SecondServlet to delete the shared data test created by myFirstServlet, and customize the value of test

    The code demonstration is as follows:

    
     //MyFirstServle新增共享数据test并显示
    import javax.servlet.*;
    import java.io.IOException;
    
    public class MyFirstServlet extends GenericServlet {
          
          
    
        @Override
        public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
          
          
            System.out.println("触发了继承GenericServlet类的子类MyFirstServlet类的service方法......");
    
            //如何在servletContext作用域范围内添加共享数据
            ServletContext servletContext = servletRequest.getServletContext();
            servletContext.setAttribute("msg","这是MyFirstServlet设置的共享数据");
    
            //MyFirstServle新增共享数据test并显示
            servletContext.setAttribute("test","这是MyFirstServlet设置的test共享数据");
    
            System.out.println("test="+servletContext.getAttribute("test"));
        }
    }
    
    //SecondServlet尝试删除并显示MyFirstServlet设置的共享数据test
    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 SecondServlet extends HttpServlet {
          
          
        protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
          
          
            System.out.println("访问了SecondServlet里的doPost方法");
        }
    
        protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
          
          
            System.out.println("访问了SecondServlet里的doGet方法");
    
            //如何获取MyFirstServlet在servletContext作用域范围内设置的共享数据
            ServletContext servletContext = request.getServletContext();
            Object msg = servletContext.getAttribute("msg");
            System.out.println("msg="+msg);
    
    
            //删除MyFirstServlet设置的共享数据test
            servletContext.removeAttribute("test");
            System.out.println("SecondServlet已经删除了共享数据test");
    
            System.out.println("共享数据test="+servletContext.getAttribute("test"));
        }
    }
    

    insert image description here
    insert image description here
    insert image description here


6. Interface for processing requests and responses

6.1 HttpservletRequest interface

Introduction:

This interface is a sub-interface of the ServletRequest interface, which encapsulates the relevant information of the HTTP request (all the information in the request message is encapsulated inside)

The main function:

  1. Get request header information

    request.getHeader(String key);
    
    //获取请求头中客户端的产品信息
    String header = request.getHeader("User-Agent");
    System.out.println("客户端的产品信息如下");
    System.out.println("header:"+header);
    
    //获取请求头中请求来源
    String referer = request.getHeader("Referer");
    System.out.println("请求来源如下");
    System.out.println("referer:"+referer);
    
  2. Get the path information of the url

    request.getContextPath()//获取上下文路径
    request.getServerName()  //获取主机名
    request.getServerPort()  //获取端口号
    
    //获取url
    String contextPath = request.getContextPath();//获取上下文路径
    System.out.println("contextPath:"+contextPath);
    
    //获取主机名
    String serverName = request.getServerName();
    System.out.println("serverName:"+serverName);
    
    //获取端口号
    int serverPort = request.getServerPort();
    System.out.println("serverPort:"+serverPort);
    
  3. Get request parameters

    What are the request parameters?
    The request parameter is the data submitted by the browser to the server.

    How does the browser send data to the server?

    ① Attached to the url (consistent with the get request, the form of splicing is the binding of the request data), as shown below:

    http://localhost:8989/MyServlet/MyHttpServlet?userId=20&username=jack
    

    ② Submit via the form

    	  <form action="MyHttpServlet" method="post">
    	  	你喜欢的足球队<br /><br />
    	  	巴西<input type="checkbox" name="soccerTeam" value="Brazil" />
    	  	德国<input type="checkbox" name="soccerTeam" value="German" />
    	  	荷兰<input type="checkbox" name="soccerTeam" value="Holland" />
    	  	<input type="submit" value="提交" />
    	  </form>
    	  
    

    Use the HttpServletRequest object to get request parameters

    string request.getparameter(string key);
    string[] request.getparametervalues("hobby");
    
    //获取请求参数
    //根据表单的name值获取它的value值
    String username = request.getParameter("username");//获取表单中name为username的value值,下同
    System.out.println("username="+username);
    
    String password = request.getParameter("password");
    System.out.println("password="+password);
    
    String gender = request.getParameter("gender");
    System.out.println("gender="+gender);
    
    //如何根据一个name获取有多个并存的value值
    String[] hobbies = request.getParameterValues("hobby");
    System.out.println("hobbies:");
    for (String hobby : hobbies) {
          
          
        System.out.println(hobby);
    }
    
  4. Get request method

     request.getMethod()
    
    //获取请求方式
    String method = request.getMethod();
    System.out.println("请求方式:");
    System.out.println("method:"+method);	
    
  5. Forward and share data

    Forwarding is one of the main means of page jumping

    What is forwarding? As shown below

    insert image description here

    The application scenarios are as follows:

    a. Forward to the second servlet

    //HttpServletRequest对象reg转发客户端请求至register_error的servlet中
    req.getRequestDispatcher("register_error").forward(req,resp);
    

    b. Forward to a web page

    //HttpServletRequest对象reg转发客户端请求至网页register_error中
    req.getRequestDispatcher("regist_error.html").forward(req,resp);
    

    Steps for usage:

    a. Obtain the transponder object

    RequestDispatcher requestDispatcher=request.getRequestDispatcher(目标路径)

    b. Perform forwarding operation (request and response need to be passed)

    requestDispatcher.forward(request,response);
    

    Code for page jump:

    //跳转至root.html
    request.getRequestDispatcher("root.html").forward(request,response);
    

    Can Secondservlet get the request parameters in the request?

    Yes, because forwarding passes the request object

    request can share data as a domain object (request domain)

    ​The scope of data应用域(ServletContext):

    请求域(HttpServletRequest)​: The scope of data sharing is this request, when the response is over, the request is also over

    //添加共享数据
    setAttribute(string key,object value);
    //获取共享数据
    getAttribute(string key)
    //移除共享数据
    removeAttribute(string kev)
    

6.2 HttpservletResponse interface

Introduction:

  • This interface is a sub-interface of the ServletResponse interface, which encapsulates the relevant information of the server for the HTTP response. (Temporarily only server configuration information, no specific content related to the response body)
  • The Servlet container creates its implementation class object and passes it into the service(HttpServletRequest req, HttpServletResponse res) method.
  • The HttpServletResponse object refers to the HttpServletResponse implementation class object provided by the container.

The main function:

a. Output the response data to the client through the output stream

Printwriter writer=response.getwriter();
writer.write("<h1>success</h1>");

b. You can set the garbled characters of the response (the way to add the response header)

response.addHeader("Content-Type","text/html;charset=utf-8");
简写:response.setContentType("text/html;charset=utf-8");

c. Redirection
One of the main means of page jump

What are redirects? As shown below:

insert image description here

The application scenarios are as follows:

①Redirect to another Servlet

response.sendRedirect("second");

② Redirect to the page

response.sendRedirect("admin.html");

When the request parameters sent to the firstservlet request, can the secondservlet get it?

Unable to fetch; because the second request was sent (the request parameters in the first request have nothing to do with the second request)

Can redirects share data using the requested domain?

Can't

The difference between forwarding and redirection

Forward redirect
browser perception Can't feel it perceived
URL in the URL bar constant will change
number of requests one request two requests
Request shared data in the domain can visit not accessible
Initiator request response
WEB-INF can visit not accessible
target resource resources on this server Resources from other servers

ps:

The resources under WEB-INF have a feature: the client cannot access them, but the server can access them, and you can put resources that you do not want the client to directly access under WEB-INF


7. Processing of request and response garbled characters

7.1 Request garbled characters

get请求: tomcat8 has been processed

Notice:

If your Tomcat version is 7 or below, you need to modify the tomcat configuration file . Modify the Connector tag in the server.xml file and add the URIEncoding="utf-8" attribute, as shown in the following figure:
insert image description here
insert image description here

post请求: Chinese garbled characters

solution:

Before getting the request parameters in the code, set the charset

code show as below:

request.setcharacterEncoding("utf-8");

Case: The form submits data to FirstServlet in post mode, demonstrating the post garbled problem

The code demonstration is as follows:

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 FirstServlet extends HttpServlet {
    
    
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    
    
        //请求
        //post方法的中文乱码问题
//        request.setCharacterEncoding("utf-8");
        String username = request.getParameter("username");
        System.out.println("username="+username);
        String password = request.getParameter("password");
        System.out.println("password="+password);
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    
    
        System.out.println("触发了FirstServlet的doGet方法.......");

       /* //设置请求域的共享数据
        //注意,设置的共享数据需要放在使用请求转发的代码之前,不然另一个servlet无法获取之前设的请求域共享数据
        request.setAttribute("requestMsg","这是requestMsg共享的数据");

        request.setAttribute("msg","这是msg");


        //实现转发跳转至secondservlet
//        request.getRequestDispatcher("second").forward(request,response);

        //实现重定向至secondservlet
        response.sendRedirect("second");
*/
    }
}

insert image description here

insert image description here

After adding the character set, modify it as follows:

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 FirstServlet extends HttpServlet {
    
    
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    
    
        //请求
        //post方法的中文乱码问题
        request.setCharacterEncoding("utf-8");
        String username = request.getParameter("username");
        System.out.println("username="+username);
        String password = request.getParameter("password");
        System.out.println("password="+password);
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    
    
        System.out.println("触发了FirstServlet的doGet方法.......");

       /* //设置请求域的共享数据
        //注意,设置的共享数据需要放在使用请求转发的代码之前,不然另一个servlet无法获取之前设的请求域共享数据
        request.setAttribute("requestMsg","这是requestMsg共享的数据");

        request.setAttribute("msg","这是msg");


        //实现转发跳转至secondservlet
//        request.getRequestDispatcher("second").forward(request,response);

        //实现重定向至secondservlet
        response.sendRedirect("second");
*/
    }
}

insert image description here

7.2 Garbled response

Classification:

① Get the output stream and write data directly

It is written as follows:

response.addHeader("Content-Type","text/html;charset=utf-8);
//简写
response.setContentType("text/html;charset=utf-8");

Do not believe? Please see the demo below:

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.PrintWriter;

public class ResponseServlet extends HttpServlet {
    
    
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    
    
        doGet(request,response);
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    
    

        //添加响应头以规避中文乱码
//        response.setContentType("text/html;charset=utf-8");

        //输出响应数据流给客户端
        PrintWriter writer = response.getWriter();



        writer.print("<html>");
        writer.print("<head>");
        writer.print("</head>");
        writer.print("<body>");
        writer.print("<h1>success 成功</h1>");
        writer.print("</body>");


        writer.print("</html>");

    }
}

insert image description here
insert image description here
The code as a whole remains unchanged, only one sentence of code is added as follows:

		//添加响应头以规避中文乱码
        response.setContentType("text/html;charset=utf-8");

        //输出响应数据流给客户端
        PrintWriter writer = response.getWriter();

insert image description here

②Forward

③Redirection


8. Case: login and registration function of connection database version

Case: To realize the login and registration function, it needs to be compared with the database

8.1 Registration function

step:

① Build the environment

  1. Import the jar package (database driver package, database connection pool, DBUtils) and put it in the lib directory under WEB-INF
    insert image description here

  2. Create] DBCTools and BaseDao
    insert image description here

  3. The configuration file of the database connection pool (put it in the src directory)
    insert image description here

  4. Create users table in MySQL

  5. Create an entity class (User)

② Write the registration function

  1. Create a registration page
  2. createUsersDAOlmpl
  3. Create a Registe'rServlet

Part of the code is provided here:

package DAO;

import bean.users;

import java.sql.SQLException;

public class UsersDAOlmpl extends BaseDAOImpl implements UsersDAO {
    
    

    @Override
    public users findUserByUsername(String username) {
    
    
        String sql="select * from users where username=?";
        try {
    
    
            return getBean(users.class, sql, username);
        } catch (Exception e) {
    
    
           throw new RuntimeException(e);
        }
    }

    @Override
    public boolean addUser(users user) {
    
    
        String sql="insert into users values(null,?,?,?)";
        try {
    
    
            int len = update(sql, user.getUsername(), user.getPassword(), user.getEmail());
            if (len>0){
    
    
                return true;
            }
            return false;
        } catch (SQLException e) {
    
    
            throw new RuntimeException(e);
        }

    }
}

package DAO;

import bean.users;

public interface UsersDAO {
    
    

    //注册
    //根据用户名来查找相应的用户信息
    users findUserByUsername(String username); //登录

    //添加用户
    boolean addUser(users user);



}

8.2 Login function

step:

  1. Create a login page
  2. createUsersDAOlmpl
  3. Create LoginServlet

8.3 Realize the effect

①Test registration function

insert image description here
insert image description here
insert image description here
insert image description here
insert image description here
insert image description here

②Test login function

insert image description here

insert image description here


Nine. Use Beanutils to optimize code

Introduction:

Beanutils is a Java library that provides a set of utility classes for working with JavaBeans. JavaBeans are Java classes that follow certain conventions, such as having a default constructor and getter and setter methods for their properties. Beanutils provides methods for copying properties between JavaBeans, converting property values ​​to strings, and performing other common JavaBeans-related tasks. It is part of the Apache Commons project and is widely used in Java applications.

Function:

Automatically map the data in the map collection to javaBean

Conditions of Use:

The key value in the Map collection must be consistent with the attribute name in the javaBean, otherwise the inconsistent key value will not be mapped

Steps for usage:

  1. import jar package

    ① Copy the following three jar packages, and then paste them to the local dynamic web project to be applied under Web/WEB-INF/lib ②
    insert image description here
    insert image description here
    Select the three jar packages just now in the lib directory, right-click to open –> Add as Library - -> Select the corresponding parameters in Create Library
    insert image description here
    insert image description here

  2. Just use Beanutils to call the method directly

The case is as follows: use Beanutils to optimize the registration function in the case of the login and registration function of the connection database version above

The code demonstration is as follows:

import DAO.UsersDAOlmpl;
import bean.users;
import org.apache.commons.beanutils.BeanUtils;

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.lang.reflect.InvocationTargetException;
import java.util.Map;

public class RegistServlet extends HttpServlet {
    
    

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

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    
    
        //处理注册业务
      /*  String username = req.getParameter("username");
        String password = req.getParameter("password");
        String email = req.getParameter("email");
        //数据库中user表的uid字段是自增长列
        users user=new users(null,username,password,email);*/


        //使用BeanUtils,减少代码冗余,这样即使注册表单中有300个name属性值,我也不用一个个手动输入,然后再一一添加进user对象里,那样代码量太大
        Map<String, String[]> parameterMap = req.getParameterMap();//map集合中的key值是表单中的name属性值
        users user=new users();

        try {
    
    
            BeanUtils.populate(user,parameterMap);
        } catch (IllegalAccessException e) {
    
    
            e.printStackTrace();
        } catch (InvocationTargetException e) {
    
    
            e.printStackTrace();
        }


        UsersDAOlmpl dao=new UsersDAOlmpl();
        users userByUsername = dao.findUserByUsername(user.getUsername());

        if (userByUsername==null){
    
    
            dao.addUser(user);
            req.getRequestDispatcher("regist_success.html").forward(req,resp);
        }else {
    
    
            req.getRequestDispatcher("regist_error.html").forward(req,resp);
        }
    }
}


10. The path problem of the web project★

10.1 url (commonly used)

Interpretation:

Uniform resource locator (find a resource from the entire network environment), such as http://localhost:9999/day06_servlet_war_exploded/login.html

相对路径: relative to ur1 as a reference
绝对路径 : url is the absolute path (starting from the ip address)

The locations involved in the path are:

  • Hyperlinks, forms, links, img, scripts in web pages...

  • Forward

  • redirect

  • web.xml

Notice:

In the web project, add / before the path, using an absolute path

建议使用绝对路径,因为绝对路径一旦写死,不管该资源上有多少个上级目录,依然可以找到,若用相对路径,则要时刻注意该资源的上级目录的变化

What does / mean?

  1. server resolution

    从当前项目下开始找  例如http://localhost:9999/day06_servlet_war_exploded/
    

    ①web.xml

    For example:

     <!--  设置访问loginservlet的路径  /login  -->
    <servlet>
        <servlet-name>loginServlet</servlet-name>
        <servlet-class>t1.LoginServlet</servlet-class>
    </servlet>
    
    <servlet-mapping>
        <servlet-name>loginServlet</servlet-name>
        <url-pattern>/login</url-pattern>
    </servlet-mapping>
    
    

    The above example sets the access path of LoginServlet to access login directly from the project

     <!--  设置访问loginservlet的路径  /abc/login  -->
    <servlet>
        <servlet-name>loginServlet</servlet-name>
        <servlet-class>t1.LoginServlet</servlet-class>
    </servlet>
    
    <servlet-mapping>
        <servlet-name>loginServlet</servlet-name>
    	<url-pattern>/abc/login</url-pattern>
    </servlet-mapping>
    

    The above example sets the access path of Loginservlet to find abc first under the project, and then find login under abc to find LoginServlet

    ② Forward
    For example:

    //建议使用绝对路径
    request.getRequestDispatcher("/second").forward(request,response);
    //http://localhost:9999/day06_servlet_war_exploded/second
    
    
  2. browser analysis

    从当前服务器下去找  例如:在 http://localhost:9999/ 下去找
    

    ①All paths in the webpage (hyperlink, form, link, img, script...)

    ②Redirection

    The code example is as follows:

    response.sendRedirect("second");//不加/,默认前面是./second
    //重定向是在浏览器里解析,它是从当前服务器下去找,即http://localhost:9999/second去找,绝对找不到,遂报404
    
    /*
    
    解决方案:在second前面加上/day06_servlet_war_exploded/,这样就是在当前项目下去找second,一定能找到
    即从http://localhost:9999/day06_servlet_war_exploded/second去找
    
    但是这样写有一个弊端,若修改了上下文路径,代码里也得改,比较麻烦,扩展性不是很好
    
    推荐这样写,即动态的获取上下文路径+/second
    response.sendRedirect(request.getContextPath()+"/second");
    
    */
    
    
    

Summarize:

路径前加/,就是使用绝对路径 /的含义,由服务器解析就是当前项目下,由浏览器解析就是当前服务器下,网页内和重定向路径的/由浏览器解析。转发和web.ml中的/由服务器解析

10.2 uri (rarely used)

Interpretation:

Uniform Resource Identifier (find a resource from the current project)

For example

/day06_servlet_war_exploded/login.html

Find login.html under the war package named day06_servlet_war_exploded (web project deployed on the server)


Guess you like

Origin blog.csdn.net/siaok/article/details/130111639
Recommended