互联网轻量级框架整合之JavaEE基础II

编写本篇代码并实际执行之前请仔细阅读前一篇互联网轻量级框架整合之JavaEE基础I

Servlet

在Servlet容器中,Servlet是最基础的组件,也可以把JSP当做Servlet,JSP的存在意义只在于方便编写动态页面,使Java语言能和HTML相互结合,然后在前后端分离大势下,JSP的讨论已经意义不大;按照Servlet3.0以后的规范,组件都可以使用注解来配置,而不必使用web.xml配置,随着Spring Boot的流行,使用注解开发的方式成为主流

首先在pom文件中添加如下依赖

    <!-- https://mvnrepository.com/artifact/javax.servlet/javax.servlet-api -->
    <dependency>
      <groupId>javax.servlet</groupId>
      <artifactId>javax.servlet-api</artifactId>
      <version>4.0.1</version>
      <scope>provided</scope>
    </dependency>

新建路径src/mian/java/com/ssm/servlet,在该路径下新建java文件,并命名为MyServlet(Java基础关于命名规则此处不解)

package com.ssm.servlet;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;


// 使用@WebServlet将类标识为Servlet, Servlet容器会自动识别
@WebServlet(
        name="myServlet",
        urlPatterns="/my"    //Servlet拦截路径,可以使用正则
)
public class MyServlet extends HttpServlet {
    @Override
    public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException{
        response.getWriter().print("Hello Servlet");  //写入返回信息
    }

}

在编译器中直接执行,并访问路径/my,浏览器会展示如下内容
在这里插入图片描述

代码解析

首先代码中使用@WebServlet自定义了一个servlet,并命名为myServlet,该servlet会拦截/my这个路径下的动作,然后定义了一个MySeervlet类它扩展了HttpServlet这个基础类,将其doGet方法重写从而返回Hello Servlet字符串,基础类中的doGet方法源码如下

    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        String protocol = req.getProtocol();
        String msg = lStrings.getString("http.method_get_not_supported");
        if (protocol.endsWith("1.1")) {
            resp.sendError(405, msg);
        } else {
            resp.sendError(400, msg);
        }

    }

面向对象编程中的重写(override)指的是子类可以重写其父类中的非private方法,使得子类在调用该方法时会使用自己的实现而不是父类的实现
面向对象编程中的重载(Overload)指的是在同一个类中声明多个方法,它们拥有相同的名称,但是参数类型或数量不同

Servlet生命周期

Servlet在Java中是个接口,在它基础上实现了两个抽象类GenerticServlet和HttpServlet,两个抽象类中分别实现了若干方法
在这里插入图片描述

package com.ssm.servlet;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;


// 使用@WebServlet将类标识为Servlet, Servlet容器会自动识别
@WebServlet(
        name="myServlet",
        urlPatterns="/my"    //Servlet拦截路径,可以使用正则
)
public class MyServlet extends HttpServlet {

    @Override
    public void init(){
        System.out.println("init方法调用");
    }

    @Override
    public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException{
        System.out.println("doGet方法调用");
        response.getWriter().print("Hello Servlet");  //写入返回信息
    }

    @Override
    public void destroy(){
        System.out.println("destroy方法调用");
    }

}

代码解析

代码中新增了init()方法和destroy()方法,均是重写了原方法,但细看HttpServlet这个基础抽象类中并没有这两个方法的实现,发现HttpServlet是扩展了GenericServlet类,在这个类中实现了init()方法和Destroy()方法
在这里插入图片描述
上边代码在第一次执行的时候,会在控制台输出init方法调用doGet方法调用字样,刷新页面(再次请求)控制台只会输出doGet方法调用,表明在第一次请求时,Servlet容器会构建Servlet实例,然后进行初始化,接着调用服务类方法而响应请求;在第二次请求则是直接调用服务类方法响应请求不会再调用init方法进行初始化Servlet实例的动作,可见这个过程Servlet只有一个实例而并非多个,而该Servlet实例会在Servlet容器正常关闭或者Servlet实例超时的时候执行destroy()方法,从而销毁该Servlet实例

在这里插入图片描述
在这里插入图片描述

Servlet参数配置

package com.ssm.servlet;

import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebInitParam;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;


// 使用@WebServlet将类标识为Servlet, Servlet容器会自动识别
@WebServlet(
        name="myServlet",
        urlPatterns="/my", //Servlet拦截路径,可以使用正则
        asyncSupported = true, //是否异步执行默认为false, 表示不使用异步线程运行Servlet,设置为true代表支持多线程异步
        loadOnStartup = 1, //启动顺序,如果小于或者等于0,则不在项目启动时加载,只会在第一次请求时才会初始化,如果大于0,则在项目启动时加载
        initParams = { //Servlet参数
                @WebInitParam(name = "init.param1", value = "init-value1"),
                @WebInitParam(name = "init.param2", value = "init.value2")
        }
)
public class MyServlet extends HttpServlet {

    @Override
    public void init(ServletConfig servletConfig){
        System.out.println("init方法调用");
        String param1 = servletConfig.getInitParameter("init.param1");
        String param2 = servletConfig.getInitParameter("init.param2");
        System.out.println(param1);
        System.out.println(param2);
    }

    @Override
    public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException{
        System.out.println("doGet方法调用");
        response.getWriter().print("Hello Servlet");  //写入返回信息
    }

    @Override
    public void destroy(){
        System.out.println("destroy方法调用");
    }

}

01-Apr-2024 14:22:34.934 信息 [main] org.apache.catalina.core.StandardService.startInternal 正在启动服务[Catalina]
01-Apr-2024 14:22:34.934 信息 [main] org.apache.catalina.core.StandardEngine.startInternal 正在启动 Servlet 引擎:[Apache Tomcat/9.0.87]
01-Apr-2024 14:22:34.953 信息 [main] org.apache.coyote.AbstractProtocol.start 开始协议处理句柄["http-nio-8080"]
01-Apr-2024 14:22:34.976 信息 [main] org.apache.catalina.startup.Catalina.start [94]毫秒后服务器启动
Connected to server
[2024-04-01 02:22:35,311] Artifact Chapterone:war: Artifact is being deployed, please wait...
init方法调用
init-value1
init.value2
[2024-04-01 02:22:35,907] Artifact Chapterone:war: Artifact is deployed successfully
[2024-04-01 02:22:35,908] Artifact Chapterone:war: Deploy took 597 milliseconds
01-Apr-2024 14:22:44.999 信息 [Catalina-utility-2] org.apache.catalina.startup.HostConfig.deployDirectory 把web 应用程序部署到目录 [D:\apache-tomcat-9.0.87\webapps\manager]
01-Apr-2024 14:22:45.067 信息 [Catalina-utility-2] org.apache.catalina.startup.HostConfig.deployDirectory Web应用程序目录[D:\apache-tomcat-9.0.87\webapps\manager]的部署已在[67]毫秒内完成

在控制台输出中可以看到,页面并没有请求/my路径的(并未请求定义的servlet)情况下,也输出了配置信息,表明虽为请求但项目启动就已经加载了该servlet

HttpServletRequest

package com.ssm.servlet;

import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;

@WebServlet(
        name = "reqServlet",
        urlPatterns = "/request/*"
)

public class RequestServlet extends HttpServlet {

    @Override
    public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException{
        //获取请求信息
        int prot = request.getServerPort();
        String url = request.getRequestURI().toString();
        String uri = request.getRequestURI();
        System.out.println("服务器端口:" + prot);
        System.out.println("url:" + url);
        System.out.println("uri:" + uri);

        //获取请求头
        String userAgent = request.getHeader("User-Agent");
        System.out.println("User-Agent:" + userAgent);

        //获取参数
        String param1 = request.getParameter("param1");
        String param2 = request.getParameter("param2");

        //获取上下文
        ServletContext application = request.getServletContext();

        //设置上下文属性
        application.setAttribute("application", "application-value");

        //设置请求属性
        request.setAttribute("param1", param1);
        request.setAttribute("param2", param2);

        //设置Session属性
        HttpSession session = request.getSession();
        // 设置Session超时时间单位s
        session.setMaxInactiveInterval(1800);
        session.setAttribute("session1", "session-value1");

        //跳转到JSP页面
        request.getRequestDispatcher("/request-result.jsp") //此时会传递请求和响应的上下文,但浏览器地址不会发生改变
                .forward(request,response);

    }

}

JSP页面代码,放在src/main/webapp路径下

<%--
  Created by IntelliJ IDEA.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
<%
    out.print("<h2>内置对象request</h2>");
    String param1 = (String) request.getAttribute("param1");
    String param2 = (String) request.getAttribute("param2");
    out.print("param1 =>" + param1 + "<br>");
    out.print("param1 =>" + param2 + "<br>");

    out.print("<h2>内置对象session</h2>");
    String sessionValue = (String) session.getAttribute("session1");
    out.print("session1 =>" + sessionValue + "<br>");

    out.print("<h2>内置对象application</h2>");
    String appValue = (String) application.getAttribute("application");
    out.print("application =>" + appValue + "<br>");
%>
</body>
</html>

在IDEA中执行代码,并使用连接/request/url?param1=value1&param2=value2请求服务
在这里插入图片描述
同时在控制台会输出如下内容

服务器端口:8080
url:/Chapterone_war/request/url
uri:/Chapterone_war/request/url
User-Agent:Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.0.0 Safari/537.36

代码解析

这段代码结合了JSP,涉及到了JSP中3个重要内置对象requestsessionapplication,在使用这些内置对象时非常重要的一个概念便是作用域,比如request请求对象的作用域仅当次用户请求有效;session的作用域是浏览器和服务器会话期间有效,它是服务器在浏览器通信期间为了保存会话数据开辟的内存空间,通过一个sessionId进行关联;application的作用域是Web项目在Servlet容器中存活期间有效;还有一个不常用的内置对象page,其作用域只对当前页面有效,使用率很低; 其他解释见注释即可

HttpServletResponse

HttpServletRequest和HttpServletResponse这两个类是在Servlet开发中最常用的两个类,HttpServletResponse也被称为响应对象,主要用于设置响应头和响应体,在前后端分离的场景下,页面主要通过AJAX(Asynchronous Javascript And XML)获取数据,移动端应用也类似,因此后端更多的响应类型会以JSON数据集为主,这时就需要通过HttpServletResponse设置响应类型和编码

package com.ssm.servlet;

import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.HashMap;
import java.util.Map;
import com.alibaba.fastjson2.JSON;

@WebServlet(
        name= "respServlet",
        urlPatterns = "/response/*"
)


public class RessponseServlet extends HttpServlet {

    @Override
    public void doGet(HttpServletRequest request, HttpServletResponse response)throws IOException{
        //获取参数
        String param1 = request.getParameter("param1");
        String param2 = request.getParameter("param2");
        //将参数写到Map数据结构中
        Map<String, String> resultMap = new HashMap<>();
        resultMap.put("param1", param1);
        resultMap.put("param2", param2);
        //转换为JSON数据集
        String json = JSON.toJSONString(resultMap);
        //设置响应信息为JSON类型
        response.setContentType("application/json");
        //设置响应信息编码为UTF-8
        response.setCharacterEncoding("UTF-8");
        //设置响应头
        response.setHeader("success", "true");
        //设置状态码
        response.setStatus(200);
        //获取输出对象
        PrintWriter out = response.getWriter();
        //输出信息
        out.println(json);
    }

}

执行代码并访问链接/response/my?param1=value1&param2=value2
在这里插入图片描述
在这里插入图片描述

HttpServletResponse进行跳转

package com.ssm.servlet;

import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;


@WebServlet(
        name= "respJSP",
        urlPatterns = "/resp/jsp/*"
)


public class RessponseJspServlet extends HttpServlet {

    @Override
    public void doGet(HttpServletRequest request, HttpServletResponse response)throws IOException{
        //获取参数
        String param1 = request.getParameter("param1");
        String param2 = request.getParameter("param2");
        String param3 = request.getParameter("param3");
        request.setAttribute("param1", param1);
        request.getSession().setAttribute("param2", param2);
        request.getServletContext().setAttribute("param3", param3);
        response.sendRedirect("/Chapterone_war/response-result.jsp"); //这里的跳转需要使用全路径



    }

}

<%--
  Created by IntelliJ IDEA.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
<%
    out.print("<h2>内置对象request</h2>");
    String param1 = (String) request.getAttribute("param1");
    out.print("param1=>" + param1 + "<br>");

    out.print("<h2>内置对象session</h2>");
    String param2 = (String) session.getAttribute("param2");
    out.print("param2=>" + param2 + "<br>");

    out.print("<h2>内置对象application</h2>");
    String param3 = (String) application.getAttribute("param3");
    out.print("param3=>" + param3 + "<br>");

%>
</body>
</html>

重新执行并访问页面/resp/jsp/my?param1=value1&param2=value2&param3=value3如下结果
在这里插入图片描述

可以看到param1的值为null,也就是并没有获取到,因为HttpServletResponse的跳转并不传递请求上下文,所以不能读取Servlet中HttpServletRequest设置的属性,只能查看Session的属性和ServletContext的属性

过滤器

过滤器Filter其作用是在Servlet执行的过程前后执行一些逻辑,例如可以控制对Servlet的访问权限,在Servlet规范中,需要使用注解@WebFilter标识过滤器,同时需要实现Filter接口,该接口代码如下

package javax.servlet;

import java.io.IOException;

public interface Filter {
	//初始化方法,在项目启动时先于Servlet的init方法执行
    default void init(FilterConfig filterConfig) throws ServletException {
    }
	//过滤逻辑,filterChain参数是放行标准
    void doFilter(ServletRequest var1, ServletResponse var2, FilterChain var3) throws IOException, ServletException;
	//过滤器超时或者Servlet容器正常关闭时候会调用,且是在Servlet的destroy方法之后执行
    default void destroy() {
    }
}
package com.ssm.servlet;

import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.annotation.WebInitParam;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

@WebFilter(
        filterName = "servletFilter",
        //请求拦截的范围
        urlPatterns = {"/request/*", "/response/*"},
        //需要拦截的Servlet,需要提供Servlet名称
        servletNames = {"reqServlet", "respServlet"},
        //初始化参数
        initParams = {
                @WebInitParam(name="init_param1", value = "init-value-1"),
                @WebInitParam(name="init_param2", value = "init-value-2")
        }
)

public class ServletFilter implements Filter {
    //初始化
    @Override
    public void init(FilterConfig filterConfig) throws ServletException{
        String initParam1 = filterConfig.getInitParameter("init_para1");
        String initParam2 = filterConfig.getInitParameter("init_para2");
        System.out.println("Filter初始化参数:param1=>" + initParam1);
        System.out.println("Filter初始化参数:param2=>" + initParam2);

    }

    /**
     *
     * @param req 请求对象
     * @param resp 响应对象
     * @param filterChain 过滤器责任链
     * @throws IOException
     * @throws ServletException
     */
    @Override
    public void doFilter(ServletRequest req, ServletResponse resp, FilterChain filterChain) throws IOException, ServletException{
        //强制转换
        HttpServletRequest request = (HttpServletRequest) req;
        HttpServletResponse response = (HttpServletResponse) resp;
        request.setCharacterEncoding("UTF-8");
        //获取参数
        String param1 = request.getParameter("param1");
        if(param1 == null || param1.trim().equals("")){
            response.setCharacterEncoding("UTF-8");
            response.setContentType("text/html");
            response.getWriter().println("没有参数:param1, 拦截请求");
            //在过滤器中结束请求,不再转发到Servlet
            return;
        }
        filterChain.doFilter(req,resp);
    }

    @Override
    public void destroy(){
        System.out.println("Filter销毁方法");
    }
}

  • 过滤器中doFilter是核心,在此代码中首先从请求中获取参数param1,如果为空,则拦截请求并提示信息,并返回,如果不为空则执行filterChain.doFilter(req, resp);放行该请求

在编译器中关闭Tomcat服务,如图所示可以看到过滤器的init()、destroy()方法和其他servlet中相关方法的执行顺序
在这里插入图片描述

监听器

在Servlet的规范中存在多种监听,例如监听Servlet上下文属性的ServletContextAttributeListener、监听请求的ServletRequestListener和监听Session属性操作的HttpSessionAttributeListener等

package com.ssm.servlet;

import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.annotation.WebListener;

@WebListener
public class WebContextListener implements ServletContextListener {
    /**
     * Servlet上下文初始化后的逻辑
     * @param sce
     */
    public void contextInitialized(ServletContextEvent sce)  {
        System.out.println("Servlet上下文初始化后的逻辑");
    }

    /**
     * Servlet上下文销毁后的逻辑
     * @param sce
     */
    public void contextDestroyed(ServletContextEvent sce)  {
        System.out.println("Servlet上下文销毁后的逻辑");
        // 关闭数据库连接池
    }
}

在这里插入图片描述
在这里插入图片描述

启动项目可以看到contextInitialized方法在过滤器的init方法之前执行,正常关闭Servlet容器,则ContextDestroyed方法在过滤器的destroy方法之后执行

Servlet容器初始化器

Servlet容器初始化器ServletContainerInitializer允许将一些第三方的类加载到Servlet容器中,加载哪些类通过注解@HandlesTypes来指定

package com.ssm.servlet;

public interface OuterService {
    void sayHello(String servlet容器初始化器);
}

package com.ssm.servlet;

public class OuterServiceImpl implements OuterService{
    @Override
    public void sayHello(String ss) {
        // TODO 自动生成的方法存根
        System.out.println(ss);
    }
}

package com.ssm.servlet;


import javax.servlet.ServletContainerInitializer;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.annotation.HandlesTypes;
import java.lang.reflect.Constructor;
import java.util.Objects;
import java.util.Set;

//配置需要加载的类,连同类的实现或者子类加载进来
@HandlesTypes(value = {OuterService.class})
public class WebContainInitializer implements ServletContainerInitializer {
    /**
     *
     * @param set 加载类集合
     * @param servletContext Servlet上下文
     * @throws ServletException
     */
    @Override
    public void onStartup(Set<Class<?>> set, ServletContext servletContext) throws ServletException {
        for(Class clazz:set){
            try {
                Class[] itfs = clazz.getInterfaces();
                for(Class itf:itfs){
                    if(OuterService.class.equals(itf)){ //符合当前配置的类
                        //获取构造方法数组
                        Constructor<?>[] constructors = Class.forName(clazz.getName()).getConstructors();
                        //通过反射创建对象
                        Object service = constructors[0].newInstance();
                        //强制转换
                        OuterService outerService = (OuterService) service;
                        //执行服务方法
                        outerService.sayHello("Servlet容器初始化器");
                        //将服务对象放入上下文
                        servletContext.setAttribute("outerService",outerService);
                        break;
                    }
                }
            }catch (Exception e){
                e.printStackTrace();
            }

        }
    }
}

Servlet初始化器标注了@HandlesTypes,并且指定了加载类型为OuterService,同时初始化器实现了ServletContainerInitializer的onStartup方法,该方法会在Servlet上下文构建时执行,它有两个参数,set是一个@HandlesTypes所指定类型的集合,该集合包含所指定类型的实现类或子类,另一个是servletContext,它是Servlet的上下文

然后在项目结构中如图所示新建文件及内容
在这里插入图片描述
文件名 javax.servlet.ServletContainerInitializer文件内容javax.servlet.ServletContainerInitializer, 实际上就是指向刚才写好的初始化类,然后启动项目
在这里插入图片描述
在所有监听器、过滤器和Servlet初始化之前,控制台输出Servlet容器初始化器

使用Cookie

package com.ssm.servlet;


import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import javax.servlet.http.Cookie;

@WebServlet(
        name = "cookieServlet",
        urlPatterns = "/cookie/*"
)
public class CookieServlet extends HttpServlet {

    public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException{
        response.setContentType("text/html");
        response.setCharacterEncoding("UTF-8");
        String action = request.getParameter("action");
        if("write".equalsIgnoreCase(action)){
            //写入cookie
            response.getWriter().println("<h1>写入cookie</h1>");
            this.writeCookie(request, response);
        }else if("show".equalsIgnoreCase(action)){
            //显示cookie
            this.showCookie(request, response);
        }else{
            response.getWriter().println("<h1>404</h1>");
        }
    }


    private void writeCookie(HttpServletRequest request, HttpServletResponse response) throws IOException{
        for(int i=1; i<10; i++){
            Cookie cookie = new Cookie("cookie"+i, "cookie"+i);
            response.addCookie(cookie);
        }
        response.getWriter().println("<h1>写入cookie成功</h1>");
    }
    
    private void showCookie(HttpServletRequest request, HttpServletResponse response) throws IOException{
        Cookie[] cookies = request.getCookies();
        if(cookies != null){
            for(Cookie cookie : cookies){
                response.getWriter().println("<h1>"+cookie.getName()+"</h1>");
                response.getWriter().println("<h1>"+cookie.getValue()+"</h1>");
            }
        }else {
            response.getWriter().println("<h1>没有cookie</h1>");
        }
    }
}

在这里插入图片描述

提交表单

<%--
  Created by IntelliJ IDEA.
  User: Administrator
  Date: 2024/4/1
  Time: 20:46
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Test Post Request</title>
</head>
<body>
<form action="./postServlet" method="post">
    角色名称:<input id="role_id" type="text" name="roleName"><br>
    角色描述:<input id="desc_id" type="text" name="roleDesc"><br>
    <input type="submit" value="提交">
</form>
</body>
</html>

package com.ssm.servlet;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.io.PrintWriter;

@WebServlet(
        name="postServlet",
        urlPatterns = "/postServlet"
)

public class PostServlet extends HttpServlet {
    @Override
    public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        String roleName = request.getParameter("roleName"); //input标签里的name值 不是id
        String desc = request.getParameter("roleDesc");//input标签里的name值 不是id
        response.setContentType("text/html");
        response.setCharacterEncoding("UTF-8");
        PrintWriter out = response.getWriter();
        out.println("提交的表单参数【roleName】为:"+roleName);
        out.println("提交的表单参数【desc】为:"+desc);

    }
}

使用web.xml

除了使用Servlet.3.0规范给出的各种注解之外,还可以使用web.xml配置Servlet、监听器和过滤器等的内容,将之前写的代码里的注解标识全部去掉,这样Servlet容器就无法识别它了,然后再在web.xml里配置一遍
在这里插入图片描述

类似如下方式(猴烦猴烦的)

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
         version="4.0">
    <!--配置监听-->
    <listener>
        <listener-class>com.ssm.servlet.WebContextListener</listener-class>
    </listener>
    <!--配置过滤器-->
    <filter>
        <!--过滤器名称-->
        <filter-name>servletFilter</filter-name>
        <filter-class>com.ssm.servlet.ServletFilter</filter-class>
        <init-param>
            <param-name>init_param1</param-name>
            <param-value>init-value-1</param-value>
        </init-param>
        <init-param>
            <param-name>init_param2</param-name>
            <param-value>init-value-2</param-value>
        </init-param>
    </filter>
    <filter-mapping>
        <filter-name>servletFilter</filter-name>
        <url-pattern>/response/*,/request/*</url-pattern>
    </filter-mapping>
    <servlet>
        <servlet-name>myServlet</servlet-name>
        <servlet-class>com.ssm.servlet.MyServlet</servlet-class>
        <init-param>
            <param-name>init.param1</param-name>
            <param-value>init-value-1</param-value>
        </init-param>
        <init-param>
            <param-name>init.param2</param-name>
            <param-value>init-value-2</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>myServlet</servlet-name>
        <url-pattern>/my</url-pattern>
    </servlet-mapping>
    <servlet>
        <servlet-name>CookieServlet</servlet-name>
        <servlet-class>com.ssm.servlet.CookieServlet</servlet-class>
        <init-param>
            <param-name>init.param1</param-name>
            <param-value>init-value-1</param-value>
        </init-param>
        <init-param>
            <param-name>init.param2</param-name>
            <param-value>init-value-2</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>CookieServlet</servlet-name>
        <url-pattern>/cookie/*</url-pattern>
    </servlet-mapping>
    <session-config>
        <session-timeout>30</session-timeout>
    </session-config>
    <welcome-file-list>
        <welcome-file>index.jsp</welcome-file>
    </welcome-file-list>
    <error-page>
        <error-code>404</error-code>
        <location>/WEB-INF/jsp/404.jsp</location>
    </error-page>
    <error-page>
        <error-code>500</error-code>
        <location>/WEB-INF/jsp/500.jsp</location>
    </error-page>


</web-app>

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/517888.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【数据结构(一)】初识数据结构

❣博主主页: 33的博客❣ ▶文章专栏分类: Java从入门到精通◀ &#x1f69a;我的代码仓库: 33的代码仓库&#x1f69a; &#x1faf5;&#x1faf5;&#x1faf5;关注我带你学更多数据结构知识 目录 1.前言2.集合架构3.时间和空间复杂度3.1算法效率3.2时间复杂度3.2.1大O的渐进…

Docker 安装 | 部署MySQL 8.x 初始设置

1、准备工作 如果不想看前面的废话请直接右边目录跳到 运行容器 处 默认你已经有 docker 环境。 Windows 推荐 Docker Desktop &#xff08;下载地址&#xff09;并基于 WSL2 运行 Docker 环境 mac 推荐 Orbstack &#xff08;下载地址&#xff09;&#xff08;这个很节省资源&…

Codeforces Round 836 (Div. 2) D. Range = √Sum

题目 思路&#xff1a; #include <bits/stdc.h> using namespace std; #define int long long #define pb push_back #define fi first #define se second #define lson p << 1 #define rson p << 1 | 1 const int maxn 1e6 5, inf 1e18, maxm 4e4 5; c…

Codeforces Round 837 C. Hossam and Trainees 【欧拉筛加速大数素因子分解】

C. Hossam and Trainees 题意 给定一个长度为 n n n 的正整数数组 a a a&#xff0c;问是否能找到两个不同的位置 i , j ( i ≠ j ) i,j(i \neq j) i,j(ij)&#xff0c;使得 a i a_i ai​&#xff0c; a j a_j aj​ 不互质&#xff0c;即 g c d ( a i , a j ) > 1 gc…

算法设计与分析实验报告java实现(排序算法、三壶谜题、交替放置的碟子、带锁的门)

一、 实验目的 1&#xff0e;加深学生对算法设计方法的基本思想、基本步骤、基本方法的理解与掌握&#xff1b; 2&#xff0e;提高学生利用课堂所学知识解决实际问题的能力&#xff1b; 3&#xff0e;提高学生综合应用所学知识解决实际问题的能力。 二、实验任务 1、排序算法…

数据挖掘中的PCA和KMeans:Airbnb房源案例研究

目录 一、PCA简介 二、数据集概览 三、数据预处理步骤 四、PCA申请 五、KMeans 聚类 六、PCA成分分析 七、逆变换 八、质心分析 九、结论 十、深入探究 10.1 第 1 步&#xff1a;确定 PCA 组件的最佳数量 10.2 第 2 步&#xff1a;使用 9 个组件重做 PCA 10.3 解释 PCA 加载和特…

小林coding图解计算机网络|TCP篇06|如何理解TCP面向字节流协议、为什么UDP是面向报文的协议、如何解决TCP的粘包问题?

小林coding网站通道&#xff1a;入口 本篇文章摘抄应付面试的重点内容&#xff0c;详细内容还请移步&#xff1a;小林coding网站通道 文章目录 如何理解UDP 是面向报文的协议如何理解字节流如何解决粘包固定长度的消息 特殊字符作为边界自定义消息结构 如何理解UDP 是面向报文的…

Linux系统中的高级动态链接器技术

Linux系统中的高级动态链接器技术是当今软件开发中不可或缺的一部分。其中&#xff0c;ELF格式&#xff08;Executable and Linkable Format&#xff09;和动态链接库&#xff08;Dynamic Linking Library&#xff09;是两个核心概念。本文将详细介绍Linux系统中的这些技术&…

【数据结构】顺序表的实现——动态分配

&#x1f388;个人主页&#xff1a;豌豆射手^ &#x1f389;欢迎 &#x1f44d;点赞✍评论⭐收藏 &#x1f917;收录专栏&#xff1a;数据结构 &#x1f91d;希望本文对您有所裨益&#xff0c;如有不足之处&#xff0c;欢迎在评论区提出指正&#xff0c;让我们共同学习、交流进…

从C到C++过渡知识 中(为什么C++支持函数重载,而C不支持函数重载)

感谢大家的阅读&#xff0c;这篇文章我们接着了解C对于C的一些优化。 函数重载 了解C这个特殊用法之前&#xff0c;我们先考虑一个问题&#xff0c;如何交换两个整数。相信大家一定信手捏来&#xff0c;实参传地址而非变量&#xff0c;于是可以写出如下函数。 void Swap(int*…

轻薄本没有独立显卡如何运行stable diffusion

众所周知&#xff0c;Stable Diffusion WebUI 使用 GPU 模式运行。 一&#xff1a;检查自己显卡 打开任务管理器或者winR 输入dxdiag 查看自己显卡状态 很明显一般轻薄本只会带有集显&#xff0c;不能满足stable diffusion要求所以我们可以使用cup来运行stable diffusion 在…

计算机服务器中了halo勒索病毒怎么办,halo勒索病毒解密流程步骤

随着网络技术的不断应用&#xff0c;企业的生产运营得到了快速发展&#xff0c;越来越多的企业开始利用服务器数据库存储企业的重要信息文件&#xff0c;数据库为企业的生产运营提供了极大便利&#xff0c;但网络技术的不断发展也为企业的数据安全带来严重威胁。近日&#xff0…

用于推荐系统的自监督超图Transformer 笔记

1 Title Self-Supervised Hypergraph Transformer for Recommender Systems&#xff08;Lianghao Xia, Chao Huang, Chuxu Zhang&#xff09;【KDD 2022】 2 Conclusion User behavior data in many practical recommendation scenarios is often noisy and exhibits skewed d…

模糊控制对应关系

一. 基本的一些对应关系 1.论域&#xff1a;X&#xff0c;一般来说取得变量∀x∈X 2.隶属函数&#xff1a;μ( x ) 3.误差&#xff1a;e 4.误差变化率&#xff1a;c&#xff0c;这是对误差求导得到的 5.模糊集常用的量&#xff1a; PL/PB&#xff08;Positive Large/Posi…

Leetcode_2两数相加

文章目录 前言一、两数相加1.1 问题描述1.2 解法一&#xff1a;分别将链表转为数字&#xff0c;然后相加1.3 代码实现1.4 解法二&#xff1a;分别将对应位置数字相加1.5 代码实现 二、使用步骤1.引入库2.读入数据 前言 链表是一种物理内存非连续存储&#xff0c;非顺序的线性数…

C++相关概念和易错语法(3)(类的声明和定义、空指针分析、this指针)

1.类的声明和定义 注意类的声明和定义分离的时候&#xff0c;在定义处要使用域作用限定符&#xff0c;否则函数声明链接时的定位不到函数的定义。 这些成员变量、函数的作用于这个类域&#xff0c;将功能集成在一起&#xff0c;这体现出封装的思想。 在区分类的定义和声明时&…

ModuleNotFoundError: No module named ‘einops‘解决办法

安装对应的库就好 pip install einops -i https://pypi.tuna.tsinghua.edu.cn/simple 拓展——在python中einops模块有什么作用 einops 是一个 Python 库&#xff0c;它提供了一种简洁、易读的方式来操作多维数组&#xff08;通常是 NumPy 数组或 PyTorch 张量&#xff09;。e…

易宝OA ExecuteSqlForDataSet SQL注入漏洞复现

0x01 产品简介 易宝OA系统是一种专门为企业和机构的日常办公工作提供服务的综合性软件平台,具有信息管理、 流程管理 、知识管理(档案和业务管理)、协同办公等多种功能。 0x02 漏洞概述 易宝OA ExecuteSqlForDataSet接口处存在SQL注入漏洞,未经身份认证的攻击者可以通过…

海外媒体发稿:6个高效的旅游业媒体宣发策略为你带来爆炸性增长-华媒舍

随着旅游业的不断发展&#xff0c;媒体宣发策略变得愈发重要。如何让旅游业在众多竞争对手中脱颖而出&#xff0c;成为每个企业所思考的问题。本文将介绍6个高效的旅游业媒体宣发策略&#xff0c;帮助你实现爆炸性增长。 策略一&#xff1a;社交媒体营销 社交媒体已成为当今社…

【文献分享】机器学习 + 分子动力学 + 第一性原理 + 热力学性质 + 微观结构

分享一篇关于机器学习 分子动力学 第一性原理 热学性质&#xff08;密度、比热容、导热率和粘度&#xff09; 微观结构的文章。 感谢论文的原作者&#xff01; 关键词&#xff1a; 1. Deep potential 2. Machine learning 3. Molecular dynamics 4. Microscopic structu…