Spring-集成Web

一、引子

前面我们在Spring集成Junit中为读者引出了Spring善于集成其它框架的优势,而Spring项目不可能仅限于小范围的某个方法的测试,终究会落脚于Web项目上。于是,我们就从这里正式进入Spring集成Web的话题。由于笔者会从原生的Java Web开发过渡到Spring集成Web,从而体现出Spring集成的魅力,因此在阅读这篇文章之前,希望读者已经有关于Java Web的一些基础(可先浏览Java Web专栏),包括Servlet,Tomcat,JSP等。

这里笔者想多说几句,虽然现在主流的开发似乎都不再与Servlet,Tomcat,JSP之流直接接触了,但是理解一个技术,是要理解这个技术为什么产生,是解决了当时的什么问题,这样能帮助我们将不断迭代的技术连贯起来,因此我们就需要了解这门技术产生之前使用的是什么技术,这样会让我们更深入地理解现在使用的技术的优势。Servlet是Web应用的基石,虽不直接使用却是必要掌握的;Tomcat(这里泛指Web服务器)似乎在SpringBoot的兴起后而不再需要像此前一样关注,但是Web项目离不开Tomcat;JSP更是一门难用、逐渐被摒弃的语言,虽然JSP是过时的技术,但依旧不妨去学习到能看懂JSP代码的程度,这样你将更能理解什么是前后端分离。重要的是,当你慢慢熟悉技术的迭代发展,你会对一些似乎耳熟能详的词语感觉到豁然开朗而不是"看似"理解了这些概念。

二、仅用Spring框架如何实现?

(1)利用我们上一篇介绍的Spring注解开发,声明一个配置类:

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

@Configuration
@ComponentScan("com.bylearning")
public class SpringConfiguration {
}

(2)定义Dao层与Service层类,注解在类上添加注解,表明将此类交给Spring容器:

import org.springframework.stereotype.Repository;

@Repository
public class UserDao {

    public void save() {
        System.out.println("save successfully...");
    }
}

Service层注入Dao层对象属性

import com.bylearning.dao.UserDao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class UserService {

    @Autowired
    private UserDao userDao;

    public void saveUser() {
        userDao.save();
    }
}

Web层先延用在Java Web中使用的Servlet:

import com.bylearning.config.SpringConfiguration;
import com.bylearning.service.UserService;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@WebServlet("/demo")
public class DemoServlet extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) {
        ApplicationContext ioc = new AnnotationConfigApplicationContext(SpringConfiguration.class);
        UserService us = ioc.getBean(UserService.class);
        us.saveUser();
    }
}

配置Tomcat,启动项目,在浏览器地址栏中访问该Servlet便可在控制台中看到Dao层中打印的输出语句。至此便完成了原生的Spring 对于Web的开发。

三、在此基础上怎么改进?

我们注意到在DemoServlet类中,我们为了获取到容器中的Service层对象,利用配置类创建了一个IoC容器。我们不禁想到:难道每个Servlet中都要重复这一段代码吗,这不仅是代码的重复,可以想象更是性能的负担,我们不可能这么做。有经验的小伙伴可能会想到一个办法:提供一个静态方法来获取单例的IoC容器呗。例如这样:

import com.bylearning.config.SpringConfiguration;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class IoCUtil {
    
    public static ApplicationContext ioc;
    
    static {
        ioc = new AnnotationConfigApplicationContext(SpringConfiguration.class);
    }
    
    public static ApplicationContext getIoC() {
        return ioc;
    }
}

但是我们根据Java类加载顺序知道,静态代码块会在类第一次被加载的时候自动执行,这意味着创建容器的耗时操作将落在第一次被访问的Servlet时,这似乎也不太优雅。

解决办法:还记得我们在介绍Java Web阶段简单提及的三大组件之一——Listener(回顾)。监听器中其中有一个ServletContextListener就是监听ServletContext对象的创建与销毁。因此我们在启动Web项目时,会自动执行该监听器的contextInitialized()方法。我们把创建容器的逻辑放在这个方法里很优雅了。

监听类中创建IoC容器:

import com.bylearning.config.SpringConfiguration;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

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

@WebListener
public class ContextLoaderListener implements ServletContextListener {

    @Override
    public void contextInitialized(ServletContextEvent servletContextEvent) {
        System.out.println("listener init...");
        ApplicationContext ioc = new AnnotationConfigApplicationContext(SpringConfiguration.class);
        ServletContext servletContext = servletContextEvent.getServletContext();
        servletContext.setAttribute("ioc", ioc);
    }

    @Override
    public void contextDestroyed(ServletContextEvent servletContextEvent) {

    }

}

提供一个工具类:

import org.springframework.context.ApplicationContext;

import javax.servlet.ServletContext;

public class WebApplicationContextUtils {

    public static ApplicationContext getWebApplicationContext(ServletContext servletContext) {
        ApplicationContext ioc = (ApplicationContext) servletContext.getAttribute("ioc");
        return ioc;
    }
}

改造Servlet获取Service层对象:

import com.bylearning.WebApplicationContextUtils;
import com.bylearning.service.UserService;
import org.springframework.context.ApplicationContext;

import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@WebServlet("/demo")
public class DemoServlet extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) {
        ApplicationContext ioc = WebApplicationContextUtils.getWebApplicationContext(getServletContext());
        UserService us = ioc.getBean(UserService.class);
        us.saveUser();
    }
}
四、Spring为我们做好了——Spring集成Web

如此典型的优化动作,Spring作为一个优秀的框架,当然为我们做好了。于是我们要开始介绍Spring集成Web。

1、引入依赖

<!-- https://mvnrepository.com/artifact/org.springframework/spring-web -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-web</artifactId>
            <version>5.3.1</version>
        </dependency>

2、使用spring-web依赖中提供的工具类。我们此时删除import,重新引入时发现了两个工具类供我们选择,一个是我们在上一步中自己实现的,下一个是spring-web提供的。我们选择下面那一个。

3、在web.xml里配置监听类。不用我们自己在定义监听类了,只需要在web.xml里配置好,并将Spring配置文件作为全局参数配置好。前面我们特意设计将我们自定义的监听类与spring-web提供的监听类名称一致。

    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>
            classpath:applicationContext.xml
        </param-value>
    </context-param>

    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>

4、Spring配置文件。进行包扫描即可

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">

    <!--扫描控制层组件-->
    <context:component-scan base-package="com.bylearning"/>

</beans>
五、总结

至此,我们便完成了Spring集成Web的介绍,我们可以看到我们只需要完成监听器的配置与初始参数的配置,接着就可以利用工具类获取到IoC容器了。接下来,我们将为读者继续介绍SpringMVC的内容。

读者在阅读第三、四节时可能会有一个疑问:这里为什么是用一个Servlet来充当Web层呢,这和当下流行的Controller是什么关系呢?因为我们是从原生的Java Web开发过渡而来,因此采用在Java Web开发中常用的继承HttpServlet接口来承接客户端请求,下面我们将为读者介绍SpringMVC的内容,这将与大家熟知的Controller联系起来,请读者继续阅读SpringMVC-基本概念。

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

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

相关文章

【Spark实践6】特征转换FeatureTransformers实践Scala版--补充算子

本节介绍了用于处理特征的算法&#xff0c;大致可以分为以下几组&#xff1a; 提取&#xff08;Extraction&#xff09;&#xff1a;从“原始”数据中提取特征。转换&#xff08;Transformation&#xff09;&#xff1a;缩放、转换或修改特征。选择&#xff08;Selection&…

前端常见标签

<li> (List Item)&#xff1a;定义列表中的一个项目&#xff08;项&#xff09; <ul> (Unordered List)&#xff1a;定义无序列表 <ol> (Ordered List)&#xff1a;定义有序列表 <a> (Anchor Tag)&#xff1a;定义超链接 <ul><li>苹…

关于华为应用市场上架,申请权限未告知目的被驳回问题的简单处理方式

关于华为应用市场上架过程中出现的【您的应用在运行时&#xff0c;未同步告知权限申请的使用目的&#xff0c;向用户索取&#xff08;存储、拍照&#xff09;等权限&#xff0c;不符合华为应用市场审核标准。】 使用方式&#xff1a; 1、引入 import permision from "/m…

paddle环境安装

一、paddle环境安装 如pytorch环境安装一样&#xff0c;首先在base环境下创建一个新的环境来安装paddlepaddle框架。首先创建一个新的环境名叫paddle。执行如下命令。 conda create -n paddle python3.8创建好了名叫paddle这个环境以后&#xff0c;进入到这个环境中&#xff…

【Java 数据结构】排序

排序算法 1. 排序的概念及引用1.1 排序的概念1.2 常见的排序算法 2. 常见排序算法的实现2.1 插入排序2.1.1 直接插入排序2.1.2 希尔排序( 缩小增量排序 ) 2.2 选择排序2.2.1 直接选择排序2.2.2 堆排序 2.3 交换排序2.3.1冒泡排序2.3.2 快速排序2.3.3 快速排序非递归 2.4 归并排…

【Linux C | 网络编程】netstat 命令图文详解 | 查看网络连接、查看路由表、查看统计数据

&#x1f601;博客主页&#x1f601;&#xff1a;&#x1f680;https://blog.csdn.net/wkd_007&#x1f680; &#x1f911;博客内容&#x1f911;&#xff1a;&#x1f36d;嵌入式开发、Linux、C语言、C、数据结构、音视频&#x1f36d; &#x1f923;本文内容&#x1f923;&a…

rust gui开发框架选择

作为一个系统编程强大语言&#xff0c;怎么能少得了图形界面的开发 实际上写这篇前我也不知道&#xff0c;于是我问了ai大模型&#xff0c;文心3.5和chatgpt4.0 答案实际上不能满意&#xff0c;最后我做了下筛选 参考博文&#xff1a; rust开发环境配置&#xff1a;链接 一、…

如何选择最适合的服务器

许多朋友想做一些网站&#xff0c;应用&#xff0c;游戏&#xff0c;小程序等等&#xff0c;都需要接触一个基础&#xff0c;就是服务器。服务器相当于一台24小时不关机的联网电脑&#xff0c;浏览网页或者应用相当于用户在访问这台电脑里的文件。那么如何选择最适合自己的服务…

[C++]类和对象(中)

一:类的六个默认成员函数 如果一个类中什么成员都没有&#xff0c;简称为空类。空类中并不是什么都没有&#xff0c;任何类在什么都不写时&#xff0c;编译器会自动生成以下6个默认成员函数。默认成员函数&#xff1a;用户没有显式实现&#xff0c;编译器会生成的成员函数称为…

Android Studio非UI线程修改控件——定时器软件

目录 一、UI界面设计 1、UI样式 2、XML代码 二、功能编写 1、定义 2、实现方法 3、功能实现 一、UI界面设计 1、UI样式 2、XML代码 <?xml version"1.0" encoding"utf-8"?> <RelativeLayout xmlns:android"http://schemas.android…

Interpolator:在Android中方便使用一些常见的CubicBezier贝塞尔曲线动画效果

说明 方便在Android中使用Interpolator一些常见的CubicBezier贝塞尔曲线动画效果。 示意图如下 import android.view.animation.Interpolator import androidx.core.view.animation.PathInterpolatorCompat/*** 参考* android https://yisibl.github.io/cubic-bezier* 实现常…

【AI数字人-论文】Geneface论文

文章目录 前言pipelineaudio-to-motionMotion domain adaptation可视化 Motion-to-imageHead-NeRFTorso-NeRF 结果对比 前言 语音驱动的说话人视频合成旨在根据一段输入的语音&#xff0c;合成对应的目标人脸说话视频。高质量的说话人视频需要满足两个目标&#xff1a; &#…

算法基础,一维,二维前缀和差分详解

目录 1.前缀和 1.一维前缀和 例题&#xff1a;【模板】前缀和 2.二维前缀和 例题&#xff1a;【模板】二维前缀和 2.差分 1.一维差分 1.性质&#xff1a;d[i]的前缀和等于a[i] 2.性质&#xff1a;后缀区间修改 例题&#xff1a;【模板】差分 2.二维差分 例题&#x…

[.NET] 查询当前已安装所有 Win32 与 UWP 应用

为了获取当前设备用户已安装的所有应用程序, 一般来讲有两种方案. 一种是通过查询 “shell:AppsFolder” 目录下所有项, 一种是从开始菜单中获取所有快捷方式, 然后加上查询所有已安装的 UWP 应用, 最后得到总列表. 如需代码参考, 请看 github.com/SlimeNull/WindowsAppsQuery …

Opencv(C++)学习 之RV1126平台的OPENCV交叉编译

本文特点&#xff1a;网上已经有了很多opencv移植RV1106的文章&#xff0c;本文主要记录基于cmake-gui编译&#xff0c;碰到的报错&#xff0c;及解决报错问题的方法&#xff0c;同时简单总结一些配置项相关的知识。 一、环境&#xff1a; ubuntu18 x64 RV1126交叉编译工具链 …

用HTML5 + JavaScript实现下雪效果

用HTML5 JavaScript实现下雪效果 下面是用HTML5 JavaScript实现下雪效果示例&#xff0c;展示了如何使用 HTML5 的 <canvas> 元素以及 JavaScript 来创建下雪效果。效果如下&#xff1a; 源码如下&#xff1a; <!DOCTYPE html> <html lang"en">…

逸学区块链【solidity】真随机数

参考Get a Random Number | Chainlink Documentation 但是很贵&#xff0c;价格 Gas Price&#xff1a;当前gas价格&#xff0c;根据网络状况而波动。Callback gas &#xff1a;返回您所请求的随机值时&#xff0c;回调请求消耗的gas 量。验证gas &#xff1a;量gas 用于验证…

应用层协议 ——— HTTP协议

应用层协议 ——— HTTP协议 HTTP简介认识URL二、登录信息三、服务器地址四、服务器端口号五、带层次的文件路径六、查询字符串七、片段标识符urlencode和urldecodeHTTP协议格式HTTP请求协议格式HTTP的方法HTTP的状态码HTTP常见的HeaderHTTPS VS HTTP对称加密 VS 非对称加密 HT…

Unity | YooAssetV2.1.0 + HybridCLR热更新

目录 一、项目更改 二、使用YooAsset热更 1.资源配置 2.资源构建 3.将两个文件夹下的资源上传CDN服务器 4.修改代码 5.运行效果 本文记录利用YooAssetHybridCLR来进行资源和dll的更新。YooAsset使用的是新版V2.1.0。相比于旧版&#xff0c;dll(原生文件)和资源要建两个p…

zabbix添加主机

zabbix添加主机 查看ip地址 [rootershi ~]# yum -y install net-tools [rootershi ~]# ifconfig eth0 |grep netmask |cut -d " " -f 10 192.168.88.20被监控主机安装zabbix-agent [root20 ~]# mount /dev/cdrom /mnt [root20 ~]# yum -y install wget [root20 ~]…
最新文章