Servlet注解的使用,简化配置 以及,使用模板方法设计模式优化oa项目

这篇具有很好参考价值的文章主要介绍了Servlet注解的使用,简化配置 以及,使用模板方法设计模式优化oa项目。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

Servlet注解的使用,简化配置 以及,使用模板方法设计模式优化oa项目

Servlet注解的使用,简化配置 以及,使用模板方法设计模式优化oa项目

每博一文案

有句谚语说:“一怒之下踢石头,只有痛着脚趾头。”
比一件糟糕的事情更可拍的,是你用糟糕的态度去面对它。看过一个很有意思的故事:
有个男人清早洗漱的时候,把自己的手表放在了桌子上。他的儿子不小心把手表碰倒地上摔坏了,男人
气得儿子揍了一顿,还埋怨妻子没看好儿子,两个人吵了起来。
男人气急败坏地摔门出去,路上想起有一份重要文件忘记带了,他匆忙回家取。可没有人在家,
他只得打电话让妻子回来送钥匙。妻子赶回家时,不小心撞翻了路边的一个小吃摊,赔了一笔钱。
男人没等到妻子回家,因为迟到也遭受了罚款。
费斯汀格法则认为:“10%的生活,由发生在你身上的事情组成,而另外的90%,则取决于你做出的反应。”
这个故事中。摔坏手表就是其中10%,而后面的一系列的事情则是另外的90%,是由埋怨引起的。
面对人生得失时,一颗平常心,比一百种智慧更有力量。
人这一生,得与失,都是常态。不是此处得,彼处失,就是彼处得,此处失,得得失失,失失得得,才构成了“人间事”。
正如席慕容的那首诗《写给幸福》:“挫折会来,也会过去。热泪会流下来,也会收起。没有什么
可以让我气馁的,因为我有着长长的一生。”
别为昨日忧愁,别为琐事烦忧,因为真正的人间清醒,是努力活着。
余生,愿你所有快乐,无需假装;愿你此生尽兴,赤诚善良。
                                   ——————  《一禅心灵庙语》

@

目录
  • Servlet注解的使用,简化配置 以及,使用模板方法设计模式优化oa项目
    • 每博一文案
    • 1. web.xml 的缺点分析
    • 2. @WebServlet 注解
      • 2.1 @WebServlet注解当中常用的一些属性的说明
    • 3. 使用模板方法设计模式优化oa项目
    • 4. 总结:
    • 5. 最后:

1. web.xml 的缺点分析

分析 oa项目中的 web.xml文件 具体的可以移步至:🔜🔜🔜 使用“纯”Servlet做一个单表的CRUD操作_ChinaRainbowSea的博客-CSDN博客

  • 现在只是一个单标的CRUD,没有复杂的业务逻辑,很简单的一丢丢功能。web.xml文件中就有如此多的配置信息。如果采用这种方式,对于一个大的项目来说,这样的话 web.xml文件会非常庞大,有可能最终会达到几十兆。
  • web.xml文件中进行 servlet信息的配置,显然开发效率比较低,每一个都需要配置一下。
  • 而且在web.xml文件中的配置是很少被修改的,所以这种配置信息能不能直接写到java类当中呢?可以的。

Servlet3.0版本之后,推出了各种Servlet基于注解式开发。优点是什么?

  • 开发效率高,不需要编写大量的配置信息。直接在 java 类上使用注解进行标注。

  • web.xml文件体积变小了。

  • 并不是说注解有了之后,web.xml文件就不需要了:

    • 有一些需要变化的信息,还是要配置到web.xml文件中。一般都是 注解+配置文件 的开发模式。
    • 一些不会经常变化修改的配置建议使用注解。一些可能会被修改的建议写到配置文件中。

2. @WebServlet 注解

Servlet注解的使用,简化配置 以及,使用模板方法设计模式优化oa项目

注解对象的使用格式:

@注解名称(属性名=属性值, 属性名=属性值, 属性名=属性值....)
// 如果注解当中的属性赋值的类型是数组,格式如下
@注解名称(属性名={属性值1,属性值2,属性值3},属性名=属性值)
// 如果注解当中还有注解的赋值如下:
@注解名称(属性名=属性值,注解名称(属性名=属性值,属性名=属性值),属性名=属性值)

想要了解更多的注解信息的内容,大家可以移步至:🔜🔜🔜 Java “框架 = 注解 + 反射 + 设计模式” 之 注解详解_ChinaRainbowSea的博客-CSDN博客

如下是 @WebServlet 注解基于 Tomcat 10 的源码:


package jakarta.servlet.annotation;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;


@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface WebServlet {

    /**
     * @return name of the Servlet
     */
    String name() default "";

    /**
     * A convenience method, to allow extremely simple annotation of a class.
     *
     * @return array of URL patterns
     * @see #urlPatterns()
     */
    String[] value() default {};

    /**
     * @return array of URL patterns to which this Filter applies
     */
    String[] urlPatterns() default {};

    /**
     * @return load on startup ordering hint
     */
    int loadOnStartup() default -1;

    /**
     * @return array of initialization params for this Servlet
     */
    WebInitParam[] initParams() default {};

    /**
     * @return asynchronous operation supported by this Servlet
     */
    boolean asyncSupported() default false;

    /**
     * @return small icon for this Servlet, if present
     */
    String smallIcon() default "";

    /**
     * @return large icon for this Servlet, if present
     */
    String largeIcon() default "";

    /**
     * @return description of this Servlet, if present
     */
    String description() default "";

    /**
     * @return display name of this Servlet, if present
     */
    String displayName() default "";
}

2.1 @WebServlet注解当中常用的一些属性的说明

WebServlet 当中存在着不少的属性,这里我们只介绍一些常用的属性。其他的大家感兴趣的可以去学习。

  • name 属性的作用:用来指定 Servle t的名字。等同于web.xml 当中的 : 。如下图所示的

Servlet注解的使用,简化配置 以及,使用模板方法设计模式优化oa项目

/**
* @return name of the Servlet
*/
String name() default "";  // default 表示该属性的默认值为 "" 空字符串
  • urlPatterns 属性的作用:用来指定 Servlet 的映射路径 url 。可以指定多个字符串(多个url)。等同于web.xml 当中的 :。如下图所示的.

注意: 需要注意的是:urlPatterns 所赋值的字符串映射的url 路径要带 / 开始的

Servlet注解的使用,简化配置 以及,使用模板方法设计模式优化oa项目

/**
* @return array of URL patterns to which this Filter applies
*/
String[] urlPatterns() default {};  // 是一个字符串数组的类型,因为一个Servlet 可以有多个映射路径 url
// 注意 urlPatterns 属性值和 web.xml 当中的  <url-pattern> 带 "/" 开始

举例:

package com.RainbowSea.servlet;

import jakarta.servlet.ServletException;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;

import java.io.IOException;
import java.io.PrintWriter;

// 注意: urlPatterns 属性值以 "/" 开始
@WebServlet(name="Test",urlPatterns = {"/test","/test2","/test3"})
public class TestWebServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException,
            IOException {
        // 设置在浏览器端显示的格式类型,以及字符集编码
        response.setContentType("text/html;charSet=UTF-8");
        PrintWriter writer = response.getWriter();

        // 获取到本Servlet Name
        String name = getServletName();
        writer.println("注解当中的name 值也就是web.xml中的<servlet-name>的值: " + name + "<br>");

        // 获取到该类当中 web.xml 中的 url-pattern 的值
        // 如果有多个的话,获取到的是你使用的那一个(在浏览器地址栏上显示的那一个url)
        String servletPath = request.getServletPath();
        writer.println("该类注解当中的urlPatterns也就是web.xml 中的 url-pattern的值:" + servletPath + "<br>");


    }
}

Servlet注解的使用,简化配置 以及,使用模板方法设计模式优化oa项目

  • value 属性的作用: 和 urlPatterns 属性的作用是一样的:用来指定 Servlet 的映射路径 url 。可以指定多个字符串(多个url)。等同于web.xml 当中的 :
  • 可以使用模糊查询
@WebServlet("/dept/*")  // 可以使用模糊查询,* 任意字符串 ;表示只要是 /dept/xxx的任意都可以访问该Servlet

这里为什么要设置两个作用一样的属性值呢?

因为 是一个 Servlet 当中最常用,而且是必须要有的。如果注解当中只对一个的属性赋值,并且该属性名名为 value的话。那么这个 value 的属性名就可以省略不写。 这里再说一点就是如果一个注解当中属性类型为数组,但是该数组只赋一个值的话,可以省略数组的 {} 花括号。

举例:

package com.RainbowSea.servlet;

import jakarta.servlet.ServletException;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;

import java.io.IOException;
import java.io.PrintWriter;

// 注意: urlPatterns 属性值以 "/" 开始
//@WebServlet(value = {"/test"})
// 可以省略为如下方式: 注解当只对名为 value属性名赋值,可以省略 value 属性名,数组如果只有一个值,可以省略{}
@WebServlet("/test") // 同样url 映射路径是以 "/" 开始的
public class TestWebServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException,
            IOException {
        // 设置在浏览器端显示的格式类型,以及字符集编码
        response.setContentType("text/html;charSet=UTF-8");
        PrintWriter writer = response.getWriter();

        // 获取到该类当中 web.xml 中的 url-pattern 的值
        // 如果有多个的话,获取到的是你使用的那一个(在浏览器地址栏上显示的那一个url)
        String servletPath = request.getServletPath();
        writer.println("该类注解当中的urlPatterns也就是web.xml 中的 url-pattern的值:" + servletPath + "<br>");




    }
}

Servlet注解的使用,简化配置 以及,使用模板方法设计模式优化oa项目

  • initParams 属性作用:表示的是 Servlet对象的配置信息对象的信息,一个Servlet 就有一个 Servlet 配置对象的信息,封装在了 标签当中的 标签当中设置。如下图所示

Servlet注解的使用,简化配置 以及,使用模板方法设计模式优化oa项目

注意: initPatams属性的类型是 WebInitParam这个注解 数组。

/**
* @return array of initialization params for this Servlet
*/
WebInitParam[] initParams() default {};

如下是 @WebInitParam的源码:

该@WebInitParam 注解当中的 name 表示:

XXX的值,而 value 表示 :

XXX/param-value> 的值。

Servlet注解的使用,简化配置 以及,使用模板方法设计模式优化oa项目

/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package jakarta.servlet.annotation;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface WebInitParam {

    /**
     * @return name of the initialization parameter
     */
    String name();

    /**
     * @return value of the initialization parameter
     */
    String value();

    /**
     * @return description of the initialization parameter
     */
    String description() default "";
}

举例:

package com.RainbowSea.servlet;

import jakarta.servlet.ServletException;
import jakarta.servlet.annotation.WebInitParam;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;

import java.io.IOException;
import java.io.PrintWriter;

// 注意: urlPatterns 属性值以 "/" 开始
//@WebServlet(value = {"/test"})
// 可以省略为如下方式: 注解当只对名为 value属性名赋值,可以省略 value 属性名,数组如果只有一个值,可以省略{}
@WebServlet(value = "/test", initParams = {@WebInitParam(name = "user", value = "root"),
        @WebInitParam(name = "password", value = "11235813")}) // 同样url 映射路径是以 "/" 开始的
public class TestWebServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException,
            IOException {
        // 设置在浏览器端显示的格式类型,以及字符集编码
        response.setContentType("text/html;charSet=UTF-8");
        PrintWriter writer = response.getWriter();

        // 获取到该类当中 web.xml 中的 url-pattern 的值
        // 如果有多个的话,获取到的是你使用的那一个(在浏览器地址栏上显示的那一个url)
        String servletPath = request.getServletPath();
        writer.println("该类注解当中的urlPatterns也就是web.xml 中的 url-pattern的值:" + servletPath + "<br>");


        // 获取到初始化参数,对应的一个Servlet 标签当中的 <init-param> 标签当中设置
        String username = getInitParameter("user"); // 根据对应的配置的 name 获取到对应的 value 值
        writer.println("该类注解当中initParams的值也就是本Servlet当中的 配置对象的为 user的值: " + username + "<br>");

        String password = getInitParameter("password");
        writer.println("该类注解当中initParams的值也就是本Servlet当中的 配置对象的为 password的值: " + password + "<br>");


    }
}

Servlet注解的使用,简化配置 以及,使用模板方法设计模式优化oa项目

  • loadOnStartUp属性的作用:用来指定在服务器启动阶段是否加载该Servlet的构造器(默认是加载Servlet 是不会立即就调用其中的构造器的,而是访问的时候才会调用该Servlet的构造器)。等同于:整数值 其中数值越小,优先被调用执行。
/**
* @return load on startup ordering hint
 */
int loadOnStartup() default -1;

举例:

package com.RainbowSea.servlet;

import jakarta.servlet.ServletException;
import jakarta.servlet.annotation.WebInitParam;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;

import java.io.IOException;
import java.io.PrintWriter;


@WebServlet(value = "/test",loadOnStartup = 1) 
public class TestWebServlet extends HttpServlet {
    
    public TestWebServlet() n{
        System.out.println("TestWebServlet 的构造器执行");
    }
}

Servlet注解的使用,简化配置 以及,使用模板方法设计模式优化oa项目

3. 使用模板方法设计模式优化oa项目

注意:建议: 如果你阅读到这里时,非常感谢您的大力支持,如果还要继续阅读的话,建议先移步至:🔜🔜🔜 使用“纯”Servlet做一个单表的CRUD操作_ChinaRainbowSea的博客-CSDN博客 博客,方便后续的内容上的理解阅读。

上面的@WebServlet 注解解决了配置文件的问题。但是现在的oa项目仍然存在一个比较臃肿的问题。

  • 一个单标的CRUD,就写了6个Servlet。如果一个复杂的业务系统,这种开发方式,显然会导致类爆炸。(类的数量太大。)

Servlet注解的使用,简化配置 以及,使用模板方法设计模式优化oa项目

  • 怎么解决这个类爆炸问题?可以使用模板方法设计模式(定义一个操作中的算法的骨架,而将一些步骤延迟到子类中,使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。"父类定义骨架,子类实现某些细节。")。具体的模板方法设计模式,大家可以移步至:🔜🔜🔜 23种设计模式之 : 模板方法设计模式_ChinaRainbowSea的博客-CSDN博客

怎么解决类爆炸问题?

  • 以前的设计是一个请求一个 Servlet类。1000个请求对应1000个Servlet类。导致类爆炸。
  • 可以这样做:一个请求对应一个方法。一个业务对应一个Servlet类。比如:处理部门相关业务的对应一个DeptServlet。处理用户相关业务的对应一个UserServlet。处理银行卡卡片业务对应一个CardServlet

思想:

模板方法:父类定义骨架,子类实现某些细节。而这里我们将骨架定义为一个核心的方法也就是这里重写的父类中的 protected void service(HttpServletRequest request, HttpServletResponse response)的方法,需要注意的是:重写的 service 就没有 405 错误的提示了。

这里我们使用@WebServlet 注解的方式,进行一个 url 映射路径的配置。

该核心方法思路是: 通过浏览器地址栏上访问的不同的 url ,对应不同的功能访问。我们就可以使用request.getServletPath()获取到浏览器地址栏上的 url 的字符串,再根据获取到的不同的 url 字符串进行一个功能上的匹配equals 对应不同的功能,我们使用方法将该功能实现。

可以为 value 属性值设置为 模糊查询

@WebServlet("/dept/*") // 可以使用模糊查询,* 任意字符串,表示/dept/xxx的任意都可以访问该Servlet

具体代码如下:

package com.RainbowSea.oa;

import com.RainbowSea.DBUtil.DBUtil;
import jakarta.servlet.ServletException;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;

import java.io.IOException;
import java.io.PrintWriter;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;


/**
 * 采用模板方法设计模式,重新设计一个 OA 系统
 */

//@WebServlet(value = {"/dept/list","/dept/save","/dept/edit","/dept/detail","/dept/delete","/dept/modify"}

//@WebServlet({"/dept/list", "/dept/save", "/dept/edit", "/dept/detail", "/dept/delete", "/dept/modify"})
@WebServlet("/dept/*") // 可以使用模糊查询,* 任意字符串,表示/dept/xxx的任意都可以访问该Servlet
public class DeptServlet extends HttpServlet {

    // 模板方法
    // 重写其中的 servlet 方法(并没有重写其中的doGet()方法,405错误没有了)

    @Override
    protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException,
            IOException {

        // 获取到该对应请求地址栏上的 url ,也就是一个servet对应当中的 url 映射路径
        // 这里是对应浏览器地址栏上的 url
        String servletPath = request.getServletPath();  // 返回的 url 的开头是带了 "/" 的

        if ("/dept/list".equals(servletPath)) {
            doList(request, response);
        } else if ("/dept/save".equals(servletPath)) {
            doSave(request, response);
        } else if ("/dept/edit".equals(servletPath)) {
            doEdit(request, response);
        } else if ("/dept/detail".equals(servletPath)) {
            doDetail(request, response);
        } else if ("/dept/delete".equals(servletPath)) {
            doDel(request, response);
        } else if ("/dept/modify".equals(servletPath)) {
            doModify(request, response);
        }

    }


    private void doList(HttpServletRequest request, HttpServletResponse response) throws IOException {

        // 设置前端浏览器显示的格式类型,以及编码
        response.setContentType("text/html;charSet=UTF-8");
        PrintWriter writer = response.getWriter();
        Connection connection = null;
        PreparedStatement preparedStatement = null;
        ResultSet resultSet = null;

        // 获取到该webapp的项目根路径:也就是在Tomcat 当中设置的访问的项目路径
        String contextPath = request.getContextPath();


        int i = 0;

        writer.println("     <!DOCTYPE html>");
        writer.println("<html lang='en'>");

        writer.println("<head>");
        writer.println("    <meta charset='UTF-8'>");
        writer.println("   <title>部门列表页面</title>");
        writer.println("</head>");

        writer.println("    <script type = 'text/javascript' >");
        writer.println("            function del(dno) {");
        // 弹出确认框,用户点击确定,返回true,点击取消返回false
        writer.println("        var ok = window.confirm('亲,删了不可恢复哦!');");
        writer.println("        if (ok) {");
        // 发送请求进行删除数据的操作
        // 在js代码当中如何发送请求给服务
        // document.location.href='请求路径
        // document.location = '请求路径'")
        // window.location.href = '请求路径
        // window.location = '请求路径'
        // 注意是根据所传的部门编号删除数据的
        writer.println("             document.location.href = '" + contextPath + "/dept/delete?deptno=' + dno");
        writer.println("          }");
        writer.println("       }");
        writer.println("</script >");

        writer.println("<body>");
        writer.println("    <h1 align='center'>部门列表</h1>");
        writer.println("   <table border='1px' align='center' width='50%'>");
        writer.println("      <tr>");
        writer.println("          <th>序号</th>");
        writer.println("         <th>部门编号</th>");
        writer.println("         <th>部门名称</th>");
        writer.println("     </tr>");

        try {
            // 连接数据库,查询所有部门:
            // 1. 注册驱动,获取连接
            connection = DBUtil.getConnection();
            // 2. 获取操作数据库对象,预编译sql语句
            String sql = "select depton as det,dname,loc from dept"; // 在mysql中测试一下是否正确
            preparedStatement = connection.prepareStatement(sql);

            // 3. 执行sql语句
            resultSet = preparedStatement.executeQuery();

            // 4. 处理查询结果集
            while (resultSet.next()) {
                String det = resultSet.getString("det");  // 有别名要使用别名
                String dname = resultSet.getString("dname");
                String loc = resultSet.getString("loc");

                writer.print("			<tr>");
                writer.print("				<td>" + (++i) + "</td>");
                writer.print("				<td>" + det + "</td>");
                writer.print("				<td>" + dname + "</td>");
                writer.print("				<td>");
                writer.print("					<a href='javascript:void(0)' onclick= 'del(" + det + ")'>删除</a>");
                // 将部门编号传过去,用户数据库查询修改
                writer.print("					<a href='" + contextPath + "/dept/edit?deptno=" + det + "'>修改</a>");
                //注意这里的是前端的资源,需要加项目名,但是这里的项目名我们通过 getContestPath()方法动态获取
                // 并且将部门名传过去,再从数据库当中查找出来对应的部门的详细信息:注意: ?(间隔) Http传输协议
                writer.print("					<a href='" + contextPath + "/dept/detail?deptno=" + det + "'>详情</a>");
                writer.print("				</td>");
                writer.print("			</tr>");
            }
        } catch (SQLException e) {
            throw new RuntimeException(e);
        } finally {

            // 5. 关闭资源
            DBUtil.close(connection, preparedStatement, resultSet);
        }

        writer.println("</table>");
        writer.println("<hr>");
        // 前端的资源路径访问需要加项目名
        writer.println("<a href='" + contextPath + "/add.html'>新增部门</a>");
        writer.println("</body>");
        writer.println("</html>");

    }


    private void doSave(HttpServletRequest request, HttpServletResponse response) throws IOException {
         /*
        思路:
         获取到前端的提交的数据,注意 编码设置post 请求
         连接数据库: 进行添加数据
         添加成功: 返回部门列表页面
         添加失败: 返回失败的页面
         */

        request.setCharacterEncoding("UTF-8");

        // 获取到前端的数据,建议 name 使用复制
        String deptno = request.getParameter("deptno");
        String dname = request.getParameter("dname");
        String loc = request.getParameter("loc");

        // 连接数据库,添加数据
        Connection connection = null;
        PreparedStatement preparedStatement = null;
        // 影响数据库的行数
        int count = 0;

        try {
            // 1. 注册驱动,连接数据库
            connection = DBUtil.getConnection();

            // 2. 获取操作数据库对象,预编译sql语句,Sql测试
            String sql = "insert into dept(depton,dname,loc) values(?,?,?)";
            preparedStatement = connection.prepareStatement(sql);

            // 3. 填充占位符, 真正执行sql语句,
            // 注意: 占位符的填充是从 1 开始的,基本上数据库相关的起始下标索引都是从 1下标开始的
            preparedStatement.setString(1, deptno);
            preparedStatement.setString(2, dname);
            preparedStatement.setString(3, loc);

            // 返回影响数据库的行数
            count = preparedStatement.executeUpdate();

            // 5.释放资源
        } catch (SQLException e) {
            throw new RuntimeException(e);
        } finally {
            DBUtil.close(connection, preparedStatement, null);
        }

        // 保存成功,返回部门列表页面
        if (count == 1) {
            // 这里应该使用,重定向
            // 这里用的转发,是服务器内部的,不要加项目名
            //request.getRequestDispatcher("/dept/list/").forward(request, response);

            // 重定向
            response.sendRedirect(request.getContextPath() + "/dept/list/");
        } else {
            // 保存失败
            // web当中的 html资源,这里的 "/" 表示 web 目录
            //request.getRequestDispatcher("/error.html").forward(request, response);

            response.sendRedirect(request.getContextPath() + "/error.html");
        }
    }


    private void doEdit(HttpServletRequest request, HttpServletResponse response) throws IOException {
        response.setContentType("text/html;charSet=UTF-8");
        PrintWriter writer = response.getWriter();

        writer.println("     <!DOCTYPE html>");
        writer.println("<html lang='en'>");

        writer.println("<head>");
        writer.println("    <meta charset='UTF-8'>");
        writer.println("   <title>部门列表页面</title>");
        writer.println("</head>");
        writer.println("<body>");
        writer.println("    <h1>修改部门</h1>");


        writer.println("   <form action='" + request.getContextPath() + "/dept/modify' method='post'>");



        /*
        思路:
        获取到提交的过来的 部门编号
        根据部门编号修改信息,注意:部门编号是唯一的不要被修改了
        连接数据库,查询到相关信息显示到浏览器页面当中,方便用户修改
         */

        String deptno = request.getParameter("deptno");

        // 连接数据库
        Connection connection = null;
        PreparedStatement preparedStatement = null;
        ResultSet resultSet = null;

        try {
            // 1. 注册驱动,连接数据库
            connection = DBUtil.getConnection();

            // 2. 获取到操作数据库对象,预编译SQL语句,sql测试
            String sql = "select dname,loc from dept where depton = ?";

            preparedStatement = connection.prepareStatement(sql);

            // 3. 填充占位符,真正执行sql语句
            preparedStatement.setString(1, deptno);
            resultSet = preparedStatement.executeQuery();

            // 4. 处理查询结果集
            while (resultSet.next()) {
                String dname = resultSet.getString("dname");  // 查询使用的别名,要用别名
                String loc = resultSet.getString("loc");

                // <!-- readonly 表示只读,不可修改的作用
                writer.println("      部门编号: <input type='text' name='deptno' value='" + deptno + "' readonly /><br>");
                writer.println("     部门名称: <input type='text' name='dname' value=" + dname + " /><br>");
                writer.println("    部门位置: <input type='text' name='loc' value=" + loc + " /><br>");

            }
        } catch (SQLException e) {
            throw new RuntimeException(e);
        } finally {
            // 5.释放资源,最后使用的优先关闭(因为如果是关闭优先使用的话,再最后面使用的可能需要前面的资源,才能执行)
            DBUtil.close(connection, preparedStatement, resultSet);
        }

        writer.println(" <input type='submit' value='修改' />");
        writer.println(" </form>");
        writer.println("</body>");
        writer.println("</html>");
    }


    private void doDetail(HttpServletRequest request, HttpServletResponse response) throws IOException {
        // 设置前端浏览器格式类型和字符集编码
        response.setContentType("text/html;charSet=UTF-8");
        PrintWriter writer = response.getWriter();
        Connection connection = null;
        PreparedStatement preparedStatement = null;
        ResultSet resultSet = null;
        //中文思路(思路来源于:你要做什么?目标:查看部门详细信息。)
        // 第一步:获取部门编号
        // 第二步:根据部门编号查询数据库,获取该部门编号对应的部门信息。
        // 第三步:将部门信息响应到浏览器上。(显示一个详情。)


        // 1.
        // http://127.0.0.1:8080/servlet09/dept/detail?deptno=40
        String deptno = request.getParameter("deptno");  // 注意是我们前端提交的数据,建议复制name

        try {
            // 2. 连接数据库,根据部门编号查询数据库
            // 1.注册驱动,连接数据库
            connection = DBUtil.getConnection();

            // 2. 预编译SQL语句,sql要测试
            String sql = "select dname,loc from dept where depton = ?";  // ? 占位符
            preparedStatement = connection.prepareStatement(sql);

            // 3. 填充占位符,真正执行sql语句
            preparedStatement.setString(1, deptno);
            resultSet = preparedStatement.executeQuery();

            // 4. 处理查询结果集
            while (resultSet.next()) {
                String dname = resultSet.getString("dname");
                String loc = resultSet.getString("loc");


                // 注意将 “双引号转换为单引号,因为在Java当中不可以嵌套多个双引号,除非是字符串的拼接
                // 所以使用 '单引号
                writer.println("    <body>");
                writer.println("  <h1>部门详情</h1>");
                writer.println("              部门编号: " + deptno + " <br>");
                writer.println("          部门名称: " + dname + "<br>");
                writer.println("     部门位置: " + loc + "<br>");
                writer.println("  <input type='button' value='后退' onclick='window.history.back()'  />");

            }
        } catch (SQLException e) {
            throw new RuntimeException(e);
        } finally {
            // 5. 释放资源
            DBUtil.close(connection, preparedStatement, resultSet);
        }


        writer.println("</body>");
        writer.println("</html>");
    }


    private void doDel(HttpServletRequest request, HttpServletResponse response) throws IOException {
        response.setContentType("text/html;charSet=UTF-8");
        PrintWriter writer = response.getWriter();
        request.setCharacterEncoding("UTF-8");

        // 思路:
        /*
        根据部门编号删除信息,
        删除成功,跳转回原来的部门列表页面
        删除失败,跳转删除失败的页面
         */

        Connection connection = null;
        PreparedStatement preparedStatement = null;

        // 记录删除数据库的行数
        int count = 0;

        // 获取到前端提交的数据
        String deptno = request.getParameter("deptno");


        // 连接数据库进行删除操作

        try {
            // 1.注册驱动,连接数据库
            connection = DBUtil.getConnection();

            // 开启事务(取消自动提交机制),实现可回滚
            connection.setAutoCommit(false);

            // 2. 预编译sql语句,sql测试
            String sql = "delete from dept where depton = ?"; // ? 占位符
            preparedStatement = connection.prepareStatement(sql);

            // 3. 填充占位符,真正的执行sql语句
            preparedStatement.setString(1, deptno);
            // 返回影响数据库的行数
            count = preparedStatement.executeUpdate();
            connection.commit();  // 手动提交数据
        } catch (SQLException e) {
            // 遇到异常回滚
            if (connection != null) {
                try {
                    // 事务的回滚
                    connection.rollback();
                } catch (SQLException ex) {
                    throw new RuntimeException(ex);
                }
            }
            throw new RuntimeException(e);
        } finally {
            // 4. 释放资源
            // 因为这里是删除数据,没有查询操作,所以 没有 ResultSet 可以传null
            DBUtil.close(connection, preparedStatement, null);
        }

        if (count == 1) {
            // 删除成功
            // 仍然跳转到部门列表页面
            // 部门列表页面的显示需要执行另外一个Servlet,怎么办,可以使用跳转,不过这里最后是使用重定向
            // 注意:转发是在服务器间的,所以不要加“项目名” 而是 / + web.xml 映射的路径即可
            //request.getRequestDispatcher("/dept/list/").forward(request,response);

            // 优化:使用重定向机制 注意: 重定向是自发到前端的地址栏上的,前端所以需要指明项目名
            // 注意: request.getContextPath() 返回的根路径是,包含了 "/" 的
            response.sendRedirect(request.getContextPath() + "/dept/list/");
        } else {
            // 删除失败
            // web当中的 html资源,这里的 "/" 表示 web 目录
            //request.getRequestDispatcher("/error.html/").forward(request, response);

            // 优化,使用重定向
            response.sendRedirect(request.getContextPath() + "/error.html/");
        }
    }


    private void doModify(HttpServletRequest request, HttpServletResponse response) throws IOException {
         /*
        思路:
        获取到提交的数据信息,
        根据提交的信息,连接数据库修改
        修改成功,跳转到部门列表页面,
        修改失败:跳转到失败的页面
         */

        request.setCharacterEncoding("UTF-8");  // 设置获取的的信息的编码集
        Connection connection = null;
        PreparedStatement preparedStatement = null;
        // 影响数据库的行数
        int count = 0;


        String deptno = request.getParameter("deptno");
        String dname = request.getParameter("dname");
        String loc = request.getParameter("loc");


        try {
            // 1. 注册驱动,连接数据库
            connection = DBUtil.getConnection();

            // 2. 获取到操作数据库的对象,预编译sql语句,sql测试
            String sql = "update dept set dname = ?,loc = ? where depton = ?";
            preparedStatement = connection.prepareStatement(sql);

            // 3. 填充占位符,真正执行sql语句
            // 从下标 1开始
            preparedStatement.setString(1, dname);
            preparedStatement.setString(2, loc);
            preparedStatement.setString(3, deptno);

            count = preparedStatement.executeUpdate();
        } catch (SQLException e) {
            throw new RuntimeException(e);
        } finally {
            // 4. 释放资源,最后使用的优先被释放
            DBUtil.close(connection, preparedStatement, null);
        }

        if (count == 1) {
            // 更新成功
            // 跳转到部门列表页面(部门列表表面是通过java程序动态生成的,所以还需要再次执行另一个Servlet)
            // 转发是服务器内部的操作,“/” 不要加项目名
            // request.getRequestDispatcher("/dept/list/").forward(request,response);

            // 优化使用重定向,自发前端(需要指明项目名)
            response.sendRedirect(request.getContextPath() + "/dept/list/");

        } else {
            // 更新失败
            // request.getRequestDispatcher("/error.html").forward(request,response);

            // 优化重定向
            // request.getContextPath()  获取的根路径是,带了 "/" 的
            response.sendRedirect(request.getContextPath() + "/error.html");
        }
    }
}

4. 总结:

  1. @WebServlet 注解,提高开发效率高,不需要编写大量的配置信息。直接在 java 类上使用注解进行标注。web.xml文件体积变小了。
  2. @WebServlet 注解当中的valueurlPatterns 的作用都是一样的,表示 映射的url路径,注意 : 设置赋值的 url 要以 / 开始。不要忘记了,不要漏掉了。
  3. @WebServlet 常用的属性的作用和使用。
  4. 模板方法的核心思想:父类定义骨架,子类实现某些细节。也可以一个方法为骨架,多个方法实现某些细节。
  5. 注解可以使用模糊查询
@WebServlet("/dept/*")  // 可以使用模糊查询,* 任意字符串

5. 最后:

限于自身水平,其中存在的错误,希望大家,给予指教,韩信点兵——多多益善,谢谢大家,江湖再见,后会有期!!!

Servlet注解的使用,简化配置 以及,使用模板方法设计模式优化oa项目文章来源地址https://www.toymoban.com/news/detail-410288.html

到了这里,关于Servlet注解的使用,简化配置 以及,使用模板方法设计模式优化oa项目的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Spring Boot学习随笔- 集成JSP模板(配置视图解析器)、整合Mybatis(@MapperScan注解的使用)

    学习视频:【编程不良人】2021年SpringBoot最新最全教程 在main创建webapp,然后创建index.jsp进行测试,在访问之前需要进行一个设置,否则springboot是找不到jsp页面的 修改jsp无需重启应用 数据库访问框架:hibernate、jpa、mybatis【主流】 SpringBoot(微框架) = Spring(工厂) + SpringMV

    2024年02月05日
    浏览(52)
  • Spring Cache的介绍以及使用方法、常用注解

    Spring Cache是一个框架,实现了基于注解的缓存功能,只需要简单地加一个注解,就能实现缓存功能. Spring Cache提供了一层抽象,底层可以切换不同的cache实现。具体就是通过CacheManager接口来统一不同的缓存技术。 CacheManager是Spring提供的各种缓存技术抽象接口。 针对不同的缓存

    2024年02月16日
    浏览(39)
  • freemarker模板引擎详解以及使用方法

    哈喽!大家好,我是旷世奇才李先生 文章持续更新,可以微信搜索【小奇JAVA面试】第一时间阅读,回复【资料】更有我为大家准备的福利哟,回复【项目】获取我为大家准备的项目 相关阅读 面试官:Zookeeper是什么,它有什么特性与使用场景? 面试官:Redis如何实现持久化的

    2024年02月09日
    浏览(43)
  • springboot 集成 Swagger2 配置以及常用注解的说明和使用 ( 超详细)

    一、注解的使用 和 说明 结构化说明如下: @Api:用在请求的类上,表示对类的说明      tags=\\\"说明该类的作用,可以在UI界面上看到的注解\\\"    (也就是给类取别名)     value=\\\"该参数没什么意义,在UI界面上也看到,所以不需要配置\\\"    @ApiOperation:用在请求的方法上,说

    2024年02月03日
    浏览(47)
  • 【设计模式】模板方法模式

    模板方法模式:定义一个操作中的算法骨架(父类),而将一些步骤延迟到子类中。 模板方法使得子类可以不改变一个算法的结构来重定义该算法的 实现一些操作时,整体步骤很固定,但是呢。就是其中一小部分需要改变,这时候可以使用模板方法模式,将容易变的部分抽

    2024年02月08日
    浏览(47)
  • 设计模式---模板方法模式

            所谓模板方法模式,就是提供一种方法的模板来实现一种规范,其他人可以利用这个模板定义自己的逻辑。         在Java编程中的应用,主要就是通过接口或者抽象类来实现的,抽象类中可以把逻辑函数声明为final类型,表示不能被重写,即不能改变逻辑。在接口中

    2024年04月24日
    浏览(45)
  • 设计模式—模板方法模式

    定义一个操作的流程框架,而将流程中一些步骤延迟到子类中实现。使得子类在不改变流程结构的情况下,重新定义流程中的特定步骤。 主要角色: 抽象类: 负责给出操作流程的轮廓或框架,由模板方法和若干基本方法组成。   1、抽象方法:由抽象类声明,在具体子类中实

    2024年02月10日
    浏览(51)
  • 设计模式——模板方法模式

    模板方法模式(Template Method Pattern)是一种行为型设计模式,它在抽象类中定义了一个算法的框架,并将一些步骤延迟到子类中实现。这种模式使得子类可以在不改变算法结构的情况下重写算法中的某些特定步骤。 抽象模板类(Abstract Template Class): 定义一个操作中的算法骨架

    2024年01月17日
    浏览(48)
  • 设计模式(7)模板方法模式

    一、定义: 定义一个操作中的算法骨架,而将算法的一些步骤延迟到子类中,使得子类可以不改变该算法结构的情况下重定义该算法的某些特定步骤。它是一种类行为型模式。

    2024年02月12日
    浏览(44)
  • 设计模式(13):模板方法模式

    实现一个功能时,整体步骤很固定,但是,某些部分易变。易变部分可以抽象出来,供子类实现。 非常繁琐,各个框架,类库中都有它的影子,比如常见的有: 数据库访问的封装 Junit单元测试 servlet中关于doGet/doPost方法调用 spring框架中各种Template shire中权限认证和授权都用到

    2024年04月16日
    浏览(48)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包