01-环境搭建 尚筹网

news2024/11/25 2:37:29

环境搭建

一、项目结构搭建

​ 模块关系

​ parent模块仅仅用来确定各个Maven依赖的版本

​ webui、component、entity模块继承自parent模块

​ util、reverse模块属于独立工程,不参与继承与聚合

​ 且webui依赖于component,component依赖于entity、util。
在这里插入图片描述
各个工程的打包方式:

<!--parent-->
    <groupId>org.example</groupId>
    <artifactId>crowdfunding01-admin-parent</artifactId>
    <version>1.0-SNAPSHOT</version>
<packaging>pom</packaging>

<!--webui-->
	<packaging>war</packaging>
<!--其他的模块都是默认打包方式(jar)-->

​ IDEA中创建多模块工程:

​ 先创建一个Empty Project(空工程),创建完成后一个个添加各个Maven模块

​ 由于webui模块,需要打成war包,因此需要有web工程的目录结构,可以通过在Modules中添 加,产生对应的结构:
在这里插入图片描述
​ 模块创建时应该选择好父模块

二、数据库构建与逆向

1、建表:

CREATE DATABASE project_rowd CHARACTER SET utf8;

USE project_rowd;
drop table if exists t_admin;				# 如果存在t_admin则删除存在的表
    CREATE TABLE t_admin (
    id INT NOT NULL auto_increment,			# 主键
    login_acct VARCHAR ( 255 ) NOT NULL,	# 登录账号
    user_pswd CHAR ( 32 ) NOT NULL,			# 登录密码
    user_name VARCHAR ( 255 ) NOT NULL,		# 昵称
    email VARCHAR ( 255 ) NOT NULL,			# 邮件地址
    create_time CHAR ( 19 ),				# 创建时间
    PRIMARY KEY ( id ) 						# 设置主键
);

​ 进行基于Maven的逆向工程(根据已存在的表,在项目中逆向生成对应的实体类、Mapper文件、Mapper接口)

2、在reverse模块中进行逆向:

1)、pom.xml中导入依赖

<!-- 控制Maven在构建过程中的相关配置 -->
<build>
    <plugins>
        <plugin>
            <groupId>org.mybatis.generator</groupId>
            <artifactId>mybatis-generator-maven-plugin</artifactId>
            <version>1.3.0</version>

            <dependencies>
                <!-- 逆向工程核心依赖 -->
                <dependency>
                    <groupId>org.mybatis.generator</groupId>
                    <artifactId>mybatis-generator-core</artifactId>
                    <version>1.3.2</version>
                </dependency>
                <dependency>
                    <groupId>com.mchange</groupId>
                    <artifactId>c3p0</artifactId>
                    <version>0.9.2</version>
                </dependency>
                <!--MySQL驱动-->
                <dependency>
                    <groupId>mysql</groupId>
                    <artifactId>mysql-connector-java</artifactId>
                    <version>8.0.15</version>
                </dependency>
            </dependencies>
        </plugin>
    </plugins>
</build>

2)、编写generatorConfig.xml文件

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE generatorConfiguration
        PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN"
        "http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd">

<generatorConfiguration>
    <context id="atguiguTables" targetRuntime="MyBatis3">
        <commentGenerator>
            <!-- 是否去除自动生成的注释 true:是 : false:否 -->
            <property name="suppressAllComments" value="true" />
        </commentGenerator>

        <!-- 数据库链接URL、用户名、密码 -->
        <jdbcConnection
                driverClass="com.mysql.cj.jdbc.Driver"
                connectionURL="jdbc:mysql://localhost:3306/project_rowd?serverTimezone=UTC"
                userId="root"
                password="root">
        </jdbcConnection>

        <!--
        默认false,把JDBC DECIMAL 和 NUMERIC 类型解析为 Integer
            true,把JDBC DECIMAL 和 NUMERIC 类型解析为java.math.BigDecimal
        -->
        <javaTypeResolver>
            <property name="forceBigDecimals" value="false" />
        </javaTypeResolver>

        <!--
        生成model模型,对应的包路径,以及文件存放路径(targetProject),targetProject可以指定具体的路径,如./src/main/java,
        也可以使用“MAVEN”来自动生成,这样生成的代码会在target/generatord-source目录下
        -->
        <!--<javaModelGenerator targetPackage="com.joey.mybaties.test.pojo" targetProject="MAVEN">-->
        <javaModelGenerator targetPackage="crowd.entity" targetProject=".\src\main\java">
            <!--是否让schema作为包的后缀-->
            <property name="enableSubPackages" value="false"/>
            <!-- 从数据库返回的值被清理前后的空格  -->
            <property name="trimStrings" value="true" />
        </javaModelGenerator>

        <!--对应的mapper.xml文件  -->
        <sqlMapGenerator targetPackage="mapper" targetProject=".\src\main\java">
            <!--是否让schema作为包的后缀-->
            <property name="enableSubPackages" value="false"/>
        </sqlMapGenerator>

        <!-- 对应的Mapper接口类文件 -->
        <javaClientGenerator type="XMLMAPPER" targetPackage="org.fall.mapper" targetProject=".\src\main\java">
            <!--是否让schema作为包的后缀-->
            <property name="enableSubPackages" value="false"/>
        </javaClientGenerator>

        <!-- 数据库表名与需要的实体类对应映射的指定 -->
        <table tableName="t_admin" domainObjectName="Admin"/>
    </context>
</generatorConfiguration>

​ 在IDEA中进行逆向工程的方法:
在这里插入图片描述
运行完后,应当对产生的所有文件各归各位(Mapper接口放入component的mapper包下;实体类放入entity模块的entity包;xxxMapper.xml放入webui的resources文件夹下**(xml放在web模块下方便寻找)**)

三、通过父工程管理依赖版本

在父工程通过dependencyManagement标签管理依赖版本,但是在子工程正式通过dependencies标签导入依赖前,这些依赖并不会生效

<!--通过properties标签指定一些需要重用的版本号,方便在后面调用-->
<properties>
    <fall.spring.version>4.3.20.RELEASE</fall.spring.version>
    <fall.spring.security.version>4.2.10.RELEASE</fall.spring.security.version>
</properties>

<!--依赖管理-->
<dependencyManagement>
    <dependencies>

        <!-- Spring 依赖 -->
        <!-- https://mvnrepository.com/artifact/org.springframework/spring-orm -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-orm</artifactId>
            <version>${fall.spring.version}</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.springframework/spring-webmvc -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>${fall.spring.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-test</artifactId>
            <version>${fall.spring.version}</version>
        </dependency>
        <!-- Spring AOP -->
        <!-- https://mvnrepository.com/artifact/org.aspectj/aspectjweaver -->
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjweaver</artifactId>
            <version>1.9.2</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/cglib/cglib -->
        <dependency>
            <groupId>cglib</groupId>
            <artifactId>cglib</artifactId>
            <version>2.2</version>
        </dependency>

        <!-- 数据库依赖 -->
        <!-- MySQL 驱动 -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.15</version>
        </dependency>
        <!-- 数据源 -->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
            <version>1.1.17</version>
        </dependency>
        <!-- MyBatis -->
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.2.8</version>
        </dependency>
        <!-- MyBatis 与 Spring 整合 -->
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis-spring</artifactId>
            <version>1.2.2</version>
        </dependency>
        <!-- MyBatis 分页插件 -->
        <dependency>
            <groupId>com.github.pagehelper</groupId>
            <artifactId>pagehelper</artifactId>
            <version>4.0.0</version>
        </dependency>

        <!-- 日志 -->
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-api</artifactId>
            <version>1.7.7</version>
        </dependency>
        <dependency>
            <groupId>ch.qos.logback</groupId>
            <artifactId>logback-classic</artifactId>
            <version>1.2.3</version>
        </dependency>
        <!-- 其他日志框架的中间转换包 -->
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>jcl-over-slf4j</artifactId>
            <version>1.7.25</version>
        </dependency>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>jul-to-slf4j</artifactId>
            <version>1.7.25</version>
        </dependency>

        <!-- Spring 进行 JSON 数据转换依赖 -->
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-core</artifactId>
            <version>2.11.0</version>
        </dependency>
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
            <version>2.11.0</version>
        </dependency>

        <!-- JSTL 标签库 -->
        <dependency>
            <groupId>jstl</groupId>
            <artifactId>jstl</artifactId>
            <version>1.2</version>
        </dependency>

        <!-- junit 测试 -->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
            <scope>test</scope>
        </dependency>

        <!-- 引入 Servlet 容器中相关依赖 -->
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>servlet-api</artifactId>
            <version>2.5</version>
            <scope>provided</scope>
        </dependency>

        <!-- JSP 页面使用的依赖 -->
        <dependency>
            <groupId>javax.servlet.jsp</groupId>
            <artifactId>jsp-api</artifactId>
            <version>2.1.3-b06</version>
            <scope>provided</scope>
        </dependency>
        <!-- https://mvnrepository.com/artifact/com.google.code.gson/gson -->
        <dependency>
            <groupId>com.google.code.gson</groupId>
            <artifactId>gson</artifactId>
            <version>2.8.5</version>
        </dependency>

        <!-- SpringSecurity 对 Web 应用进行权限管理 -->
        <dependency>
            <groupId>org.springframework.security</groupId>
            <artifactId>spring-security-web</artifactId>
            <version>${fall.spring.security.version}</version>
        </dependency>
        <!-- SpringSecurity 配置 -->
        <dependency>
            <groupId>org.springframework.security</groupId>
            <artifactId>spring-security-config</artifactId>
            <version>${fall.spring.security.version}</version>
        </dependency>
        <!-- SpringSecurity 标签库 -->
        <dependency>
            <groupId>org.springframework.security</groupId>
            <artifactId>spring-security-taglibs</artifactId>
            <version>${fall.spring.security.version}</version>
        </dependency>

    </dependencies>
</dependencyManagement>

四、Spring整合MyBatis

1、配置Maven依赖

component模块的pom.xml配置一些必要的依赖

<dependencies>
    <!--依赖entity-->
    <dependency>
        <groupId>org.example</groupId>
        <artifactId>crowdfunding04-admin-entity</artifactId>
        <version>1.0-SNAPSHOT</version>
    </dependency>
    <!--依赖util-->
    <dependency>
        <groupId>org.example</groupId>
        <artifactId>crowdfunding05-common-util</artifactId>
        <version>1.0-SNAPSHOT</version>
    </dependency>

    <!-- Spring 依赖 -->
    <!-- https://mvnrepository.com/artifact/org.springframework/spring-orm -->
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-orm</artifactId>
        <exclusions>
            <exclusion>
                <artifactId>commons-logging</artifactId>
                <groupId>commons-logging</groupId>
            </exclusion>
        </exclusions>
    </dependency>
    <!-- https://mvnrepository.com/artifact/org.springframework/spring-webmvc -->
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-webmvc</artifactId>
    </dependency>
    <!-- Spring AOP -->
    <!-- https://mvnrepository.com/artifact/org.aspectj/aspectjweaver -->
    <dependency>
        <groupId>org.aspectj</groupId>
        <artifactId>aspectjweaver</artifactId>
    </dependency>
    <!-- https://mvnrepository.com/artifact/cglib/cglib -->
    <dependency>
        <groupId>cglib</groupId>
        <artifactId>cglib</artifactId>
    </dependency>

    <!-- 数据库依赖 -->
    <!-- MySQL 驱动 -->
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
    </dependency>
    <!-- 数据源 -->
    <dependency>
        <groupId>com.alibaba</groupId>
        <artifactId>druid</artifactId>
    </dependency>
    <!-- MyBatis -->
    <dependency>
        <groupId>org.mybatis</groupId>
        <artifactId>mybatis</artifactId>
    </dependency>
    <!-- MyBatis 与 Spring 整合 -->
    <dependency>
        <groupId>org.mybatis</groupId>
        <artifactId>mybatis-spring</artifactId>
    </dependency>
    <!-- MyBatis 分页插件 -->
    <dependency>
        <groupId>com.github.pagehelper</groupId>
        <artifactId>pagehelper</artifactId>
    </dependency>
    <!-- Spring 进行 JSON 数据转换依赖 -->
    <dependency>
        <groupId>com.fasterxml.jackson.core</groupId>
        <artifactId>jackson-core</artifactId>
    </dependency>
    <dependency>
        <groupId>com.fasterxml.jackson.core</groupId>
        <artifactId>jackson-databind</artifactId>
    </dependency>

    <!-- JSTL 标签库 -->
    <dependency>
        <groupId>jstl</groupId>
        <artifactId>jstl</artifactId>
    </dependency>
    <!-- https://mvnrepository.com/artifact/com.google.code.gson/gson -->
    <dependency>
        <groupId>com.google.code.gson</groupId>
        <artifactId>gson</artifactId>
    </dependency>

    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <scope>test</scope>
    </dependency>

    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-test</artifactId>
    </dependency>
</dependencies>

webui模块配置依赖于component,并引入一些scope为test的依赖(如junit)

<dependencies>
    <dependency>
        <groupId>org.example</groupId>
        <artifactId>crowdfunding03-admin-component</artifactId>
        <version>1.0-SNAPSHOT</version>
    </dependency>
    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-test</artifactId>
    </dependency>
</dependencies>

​ 2、创建各配置文件

​ ①resources/mybatis/mybatis-config.xml(Mybatis配置文件,可以省略)

    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0/EN"
            "http://mybatis.org/dtd/mybatis-3-config.dtd">
    <configuration>
        <!--Spring与MyBatis整合后,MyBatis的配置文件可有可不有-->
    </configuration>

​ ②resources/spring-persist-mybatis.xml(Spring配置文件,用于整合MyBatis)

    <!--引入properties文件-->
    <context:property-placeholder location="classpath:jdbc.properties"/>

    <!--数据源配置-->
    <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
        <property name="username" value="${jdbc.user}"/>
        <property name="password" value="${jdbc.password}"/>
        <property name="url" value="${jdbc.url}"/>
        <property name="driverClassName" value="${jdbc.driver}"/>
    </bean>

    <!--配置SqlSessionFactory(设置mybatis配置文件的路径、mapper.xml文件的路径、注入数据源)-->
    <bean class="org.mybatis.spring.SqlSessionFactoryBean" id="sqlSessionFactoryBean">
        <property name="configLocation" value="classpath:mybatis/mybatis-config.xml"/>
        <property name="mapperLocations" value="classpath:mybatis/mapper/*.xml"/>
        <property name="dataSource" ref="dataSource"/>
    </bean>

    <!--配置与mapper.xml对应的mapper接口的包路径-->
    <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
        <property name="basePackage" value="org.fall.mapper"/>
    </bean>

​ ③resources/jdbc.properties(存放数据库连接信息)

    jdbc.user=root
    jdbc.password=root
    jdbc.url=jdbc:mysql://localhost:3306/project_rowd?serverTimezone=UTC&useUnicode=true&characterEncoding=UTF-8
    jdbc.driver=com.mysql.cj.jdbc.Driver

2、测试整合是否成功

/**
 * RunWith与ContextConfiguration指定xml的作用与
 * ApplicationContext context = new ClassPathXmlApplicationContext("spring-persist-mybatis.xml");类似
 * 前者通过让测试在Spring容器环境下执行,使得DataSource可以被自动注入,后者导入Spring配置文件
 */
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {"classpath:spring-persist-mybatis.xml"})
public class TestConnection {
    @Autowired
    DataSource dataSource;

    @Test
    public void test01() throws SQLException {
        //ApplicationContext context = new ClassPathXmlApplicationContext("spring-persist-mybatis.xml");
        //DataSource dataSource = context.getBean(DataSource.class);
        Connection connection = dataSource.getConnection();
        System.out.println(connection);
    }

可以打印出connection的数据,而不是报空指针异常,得出结论:整合成功。

五、配置日志系统

使用日志的原因:

​ 在实际开发中,如果在所有想查看的地方都通过System.out来打印,会给项目上线带来很多问题
​ System.out本质是一个IO操作,通常IO操作比较消耗性能。如果项目中过多的System.out,则可能对性能造成影响,而如果使用日志系统,就可以通过控制日 志级别,来批量控制打印信息

这里使用slf4j+logback代替Spring默认使用的commons-loggin日志包。

1、在component中增加依赖

<!-- 日志 -->
<dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>slf4j-api</artifactId>
</dependency>
<dependency>
    <groupId>ch.qos.logback</groupId>
    <artifactId>logback-classic</artifactId>
</dependency>
<!-- 其他日志框架的中间转换包 -->
<dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>jcl-over-slf4j</artifactId>
</dependency>
<dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>jul-to-slf4j</artifactId>
</dependency>

2、使用日志打印的方法

@Test
public void test03(){
    //获取Logger对象,这里传入的Class就是当前打印日志的类
    Logger logger = LoggerFactory.getLogger(TestConnection.class);
    //等级 DEBUG < INFO < WARN < ERROR
    logger.debug("I am DEBUG!!!");

    logger.info("I am INFO!!!");

    logger.warn("I am WARN!!!");

    logger.error("I am ERROR!!!");

}

六、配置声明式事务

​ 配置声明式事务的目的:希望指定的事务方法中,如果存在多个数据库操作,则要么一起提交,要么一起回滚(rollback),即:事务方法中多个数据库操作,只要有一个失败,则所有操作回滚。

1、声明式事务所依赖的包

(前面已经加入了Maven依赖,不需要多次操作了)

<!-- Spring AOP -->
<dependency>
    <groupId>org.aspectj</groupId>
    <artifactId>aspectjweaver</artifactId>
</dependency>

<dependency>
    <groupId>cglib</groupId>
    <artifactId>cglib</artifactId>
</dependency>

2、配置针对事务的Spring配置文件

spring-persist-tx.xml

​ 事务方法一般定义在service层

<!--将org.fall.service包中的组件扫描入容器,因为事务方法一般定义在service层-->
<context:component-scan base-package="org.fall.service"/>

<!--配置事务管理器-->
<bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
    <property name="dataSource" ref="dataSource"/>
</bean>

<!--配置AOP-->
<aop:config>
    <!--配置切入点表达式-->
    <!--public void org.fall.service.impl.adminServiceImpl(Admin admin)-->
    <aop:pointcut id="txPointcut" expression="execution(* *..*ServiceImpl.*(..))"/>

    <!--关联事务通知与切入点-->
    <aop:advisor advice-ref="txAdvice" pointcut-ref="txPointcut"/>
</aop:config>

<!--配置事务通知-->
<tx:advice id="txAdvice" transaction-manager="txManager">
    <tx:attributes>
        <!--name属性指定当前要配置的事务方法的方法名,符合名字的配置对应规则-->
        <!--查询方法通常设置为只读,便于数据库根据只读属性进行性能优化-->
        <tx:method name="get*" read-only="true"/>
        <tx:method name="query*" read-only="true"/>
        <tx:method name="find*" read-only="true"/>
        <tx:method name="count*" read-only="true"/>

        <!--涉及增删改查操作的方法的配置-->
        <!--propagation属性配置事务方法的传播行为-->
            <!--
                默认行为:REQUIRED,表示当前方法必须运行在事务中,如果没有事务,则开启事务,在自己的事务中运行。
                    如果已经有了已开启的事务,则在当前事务中运行。有可能和其他方法共用同一个事务
                建议设置:REQUIRES_NEW,表示当前方法必须运行在事务中,如果没有事务,则开启事务,在自己的事务中运行。
                    和 REQUIRED 的区别是就算现在已经有了已开启的事务,也一定要开启自己的事务,避免和其他方法共用同一个事务。
            -->
        <!--rollback-for:表示触发什么异常时,进行回滚;默认值:运行时异常,建议设置为运行时异常+编译期异常-->
        <tx:method name="save*" propagation="REQUIRES_NEW" rollback-for="java.lang.Exception"/>
        <tx:method name="update*" propagation="REQUIRES_NEW" rollback-for="java.lang.Exception"/>
        <tx:method name="remove*" propagation="REQUIRES_NEW" rollback-for="java.lang.Exception"/>
		<!--需要了解的是,如果方法名没有匹配的name,则该方法的事务不会生效-->
    </tx:attributes>
</tx:advice>

​ 配置完成后,在org.fall.service包下,进行数据库操作时,触发异常,即发生回滚,不会依然执行

七、表述层环境搭建

​ 首先需要确定已经导入了SpringMVC的依赖

<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-webmvc</artifactId>
</dependency>

1、配置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">

    <!--配置ContextLoaderListener,加载Spring配置文件-->
    <!--contextConfigLocation需要的内容-->
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:spring-persist-*.xml</param-value>
    </context-param>
    <!--将ContextLoaderListener加入容器-->
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>

    <!--配置CharacterEncodingFilter,解决乱码问题-->
    <!--如果web.xml中存在多个Filter,则此Filter必须作为过滤器链的第一个Filter-->
    <filter>
        <filter-name>characterEncodingFilter</filter-name>
        <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
        <!-- 指定字符集编码 -->
        <init-param>
            <param-name>encoding</param-name>
            <param-value>UTF-8</param-value>
        </init-param>
        <!--强制请求进行编码-->
        <init-param>
            <param-name>forceRequestEncoding</param-name>
            <param-value>true</param-value>
        </init-param>
        <!--强制响应进行编码-->
        <init-param>
            <param-name>forceResponseEncoding</param-name>
            <param-value>true</param-value>
        </init-param>
    </filter>
    <!--设置过滤器过滤的请求的路径(/*表示全部请求)-->
    <filter-mapping>
        <filter-name>characterEncodingFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

    <!--配置DispatcherServlet(即配置SpringMVC的前端控制器)-->
    <servlet>
        <servlet-name>dispatcherServlet</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <!--指定SpringMVC配置文件-->
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath:spring-web-mvc.xml</param-value>
        </init-param>

        <!--使DispatcherServlet在Web应用启动时就创建对象并初始化-->
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>dispatcherServlet</servlet-name>
        <!--根据请求的扩展名决定是否交给SpringMVC来处理-->
        <!--
			请求的扩展名应与预计的响应体格式相同
			要求json数据则后缀.json;	要求页面则后缀.html
		-->
        <url-pattern>*.html</url-pattern>
        <url-pattern>*.json</url-pattern>
    </servlet-mapping>
</web-app>

2、配置SpringMVC配置文件

<!--配置包扫描,这里将controller层放在mvc包下,因此配置扫描mvc-->
<context:component-scan base-package="org.fall.mvc"/>

<!--配置视图解析器-->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
    <property name="prefix" value="/WEB-INF/"/>
    <property name="suffix" value=".jsp"/>
</bean>

<!--启动注解驱动-->
<mvc:annotation-driven/>

3、测试SSM整合是否成功

Controller控制器代码:

@Controller
public class TestHandler {

    @Autowired
    AdminService adminService;

    @RequestMapping("/test/ssm.html")
    public String testSSM(Model model){
        //Admin admin = adminService.queryAdmin(1);
        List<Admin> admins = adminService.getAll();
        model.addAttribute("admins", admins);
        return "target";
    }
}

​ **前端代码:**index.jsp

<%-- 一、无base标签:--%>
    <a href="${pageContext.request.contextPath}/test/ssm.html">测试页面</a>

<%-- 二、有base标签:--%>
<head>
    <base href="http://${pageContext.request.serverName}:${pageContext.request.serverPort}${pageContext.request.contextPath}/">
</head>
<body>
    <a href="test/ssm.html">测试页面</a>
</body>

Base标签的要求:

​ base 标签必须写在 head 标签内部
base 标签必须在所有“带具体路径”的标签的前面
​ serverName 部分 EL 表达式和 serverPort 部分 EL 表达式之间必须写“:”
serverPort 部分 EL 表达式和 contextPath 部分 EL 表达式之间绝对不能写“/”
​ 原因:contextPath 部分 EL 表达式本身就是“/”开头,如果多写一个“/”会干扰 Cookie 的工作机制
serverPort 部分 EL 表达式后面必须写“/”

八、SpringMVC环境下的Ajax请求

​ 检查依赖的包:

<!-- Spring 进行 JSON 数据转换依赖 -->
<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-core</artifactId>
</dependency>
<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
</dependency>

​ 加入jQuery:
在这里插入图片描述
​ 测试Ajax(基于jQuery):

​ jQuery代码:

<script src="jquery/jquery-3.4.1.js" type="text/javascript"></script>
<script type="text/javascript">
    $(function () {

        //btn1
        //此方式可以在浏览器看到发送的请求体是Form Data(表单数据)
        $("#btn1").click(function () {
            $.ajax({
                url: "send/array/one.html",         //请求目标资源地址
                type: "post",                       //请求方式
                data: arrayStr,                     //发送的请求参数
                dataType: "text",                   //表示如何对待服务器返回的数据
                success: function (response) {
                    alert(response);
                },
                error: function (response) {
                    alert(response);
                }

            });
        });

        //btn2
        //此方式可以在浏览器看到发送的请求体是Request Payload(请求负载)
        $("#btn2").click(function () {
            //准备要发送的数据
            var array=[5,8,12];
            //必须先将目标转换成JSON字符串
            var arrayStr = JSON.stringify(array);
            $.ajax({
                url: "send/array/two.html",         
                type: "post",                       
                data: arrayStr,                     
                dataType: "text",                   
                contentType: "application/json;charset=UTF-8",  //告诉服务器端当前请求的请求体是JSON格式
                success: function (response) {
                    alert(response);
                },
                error: function (response) {
                    alert(response);
                }

            });
        });

        //btn3
        //传输复杂对象
        $("#btn3").click(function () {
            var student = {
                "name":"Fall",
                "id":21,
                "address":{
                    "province":"浙江",
                    "city":"宁波"
                },
                "subjects":[
                    {
                        "subjectName":"Java",
                        "score":96
                    },
                    {
                        "subjectName":"Data Struct",
                        "score":93
                    }
                ],
                "map":{
                    "key1":"value1",
                    "key2":"value2"
                }
            };   //student end
            var studentStr = JSON.stringify(student);
            $.ajax({
                url: "send/compose/object.html",         
                type: "post",                       
                data: studentStr,                     
                dataType: "text",                   
                contentType: "application/json;charset=UTF-8",  
                success: function (response) {
                    alert(response);				//在浏览器控制台打印返回的信息
                },
                error: function (response) {
                    alert(response);
                }
            });

        });     //btn3

        //btn4
        //使用ResultEntity,统一返回的格式
        $("#btn4").click(function () {
            var student = {
				//...与前面相同
            };   
            var studentStr = JSON.stringify(student);
            $.ajax({
                url: "send/compose/object.json",    //此时是json,表示返回的数据是json格式的
                type: "post",                       
                data: studentStr,                    
                dataType: "json",                   //此时服务端返回的数据是json格式
                contentType: "application/json;charset=UTF-8",  
                success: function (response) {
                    console.log(response);			//在浏览器控制台打印返回的信息
                },
                error: function (response) {
                    console.log(response);
                }
            });

        });
        //btn4
    });
</script>

​ 对应的四个按钮:

<button id="btn1">Test Ajax One</button>
<br/><br/>
<button id="btn2">Test Ajax Two</button>
<br/><br/>
<button id="btn3">Test Compose Object</button>
<br/><br/>
<button id="btn4">Test ResultEntity</button>

​ 对应的控制层的四个方法:

    //通过@RequestParam接收数组
    @ResponseBody
    @RequestMapping("/send/array/one.html")
    public String testAjax01(@RequestParam("array") Integer[] array){
        for(Integer num : array){
            System.out.println("num:"+num);
        }
        return "success";
    }

    //通过@RequestBody接收数组
    @ResponseBody
    @RequestMapping("/send/array/two.html")
    public String testAjax02(@RequestBody Integer[] array){
        for(Integer num : array){
            System.out.println("num:"+num);
        }
        return "success";
    }

    //通过@RequestBody接收复杂对象
    @ResponseBody
    @RequestMapping("/send/compose/object.html")
    public String testSendComposeObject(@RequestBody Student student){
        System.out.println(student);
        return "success";
    }

    //通过一个工具类(ResultEntity<T>)统一返回数据的格式
    @ResponseBody
    @RequestMapping("/send/compose/object.json")
    public ResultEntity<Student> testResultEntity(@RequestBody Student student){
        return ResultEntity.successWithData(student);
    }

如果希望通过@RequestBody接收前端发来的JSON数据,则前端发来的数据需要进行以下几步:

  1. 准备好要发送的数据(需要是JSON对象或JSON数组)
  2. 通过JSON.stringify()方法,转换成JSON字符串
  3. 将JSON字符串直接赋值给data属性
  4. 必须设置contentType: “application/json;charset=UTF-8”

此时后端在加入了json依赖,并开启mvc注解驱动,就可以使用RequestBody接收JSON数据。

统一后端返回数据格式

通过工具类,实现统一后端返回的数据格式

​ 工具类代码:

public class ResultEntity<T> {
	//设置两个常量
    public static final String SUCCESS = "SUCCESS";
    public static final String FAILED = "FAILED";

    //请求错误时,返回的错误信息,对应SUCCESS与FAILED
    private String message;

    //要返回的数据
    private T data;

    //封装当前请求的处理结果是成功还是失败
    private String result;

    //请求处理成功并且不向前端返回数据时,使用的静态方法
    //第一个<Type>表示声明一个泛型Type,第二个和return中的<Type>表示使用该泛型
    public static <Type> ResultEntity<Type> successWithoutData(){
        return new ResultEntity<Type>(null,null,SUCCESS);
    }
    
	//请求处理成功并且向前端返回数据时,使用的静态方法
    public static <Type> ResultEntity<Type> successWithData(Type data){
        return new ResultEntity<Type>(null,data,SUCCESS);
    }
    
	//请求处理失败,需要返回错误信息时,使用的静态方法
    public static <Type> ResultEntity<Type> failed(String message){
        return new ResultEntity<>(message,null,FAILED);
    }
    
    /** Getter,Setter,constructor and toString **/
}

​ 工具类中静态方法的泛型Type,代表了在前端请求后,后端返回的数据的类型;只是因为静态方法中不能调用非静态的属性,因此需要重新声明一个泛型,名 字为Type(其他也可以)。

​ 即想要返回一个Student对象时,就通过方法

@RequestMapping(...)
@ResponseBody
public ResultEntity<Student> getStudent(){
    //...例如进行数据库查询操作等
    return ResultEntity.successWithData(student);
}

九、异常处理

目标:统一管理项目中的异常。

  • 抛出异常
  • 返回给前端异常信息
    • 普通请求:在返回的页面上显示异常信息
    • Ajax请求:返回JSON格式的数据

观察浏览器的开发者工具中,发现可以根据客户端发送的请求类型,区别是普通请求还是Ajax请求。

在这里插入图片描述
根据这一特点,编写一个工具类,其中一个静态方法用来判断请求是否是JSON请求

public class CrowdUtil {

    /**
     * @param request
     * @return true==json请求 ; false==普通页面请求
     */
    public static boolean judgeRequestType(HttpServletRequest request){
        String accept = request.getHeader("Accept");
        String header = request.getHeader("X-Requested-With");
        return (accept != null && accept.contains("application/json"))
                ||
                (header != null && header.equals("XMLHttpRequest"));
    }
}

异常映射实现的方式

一、通过XML配置实现

在mvc的配置文件中将SimpleMappingExceptionResolver加入容器,在exceptionMappings中配置异常与错误页面的映射

但是此时并未实现区别JSON请求与普通请求的要求。

<!--基于XML的异常映射-->
<bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver" id="simpleMappingExceptionResolver">
    <property name="exceptionMappings">
        <props>
            <prop key="java.lang.Exception">system-error</prop>
        </props>
    </property>
</bean>

二、通过注解实现

这里通过使用前面编写的工具类的判断方法,实现对不同请求类型进行不同处理。

//注解标明该类是基于注解的异常处理器类
@ControllerAdvice
public class CrowdExceptionResolver {

    //处理空指针异常
    @ExceptionHandler(value = {NullPointerException.class})
    public ModelAndView resolveNullPointerException(NullPointerException exception,
            HttpServletRequest request, HttpServletResponse response
    ) throws IOException {
        return commonCode(exception,request,response,"system-error");
    }

    //处理数学异常,这里如果内部操作相同,跳转页面也相同,其实可以放在上面一个方法中,此处只是为了演示
    @ExceptionHandler(value = {ArithmeticException.class})
    public ModelAndView resolveArithmeticException(ArithmeticException exception,
            HttpServletRequest request,HttpServletResponse response) throws IOException {
        return commonCode(exception,request,response,"system-error");

    }
    
    //整理出的不同异常的可重用代码
    private ModelAndView commonCode(
            //触发的异常,此处借助多态
            Exception exception,
            //客户器端的请求
            HttpServletRequest request,
            //服务端的响应
            HttpServletResponse response,
            //指定普通页面请求时,去的错误页面
            String viewName
    ) throws IOException {
        boolean judgeRequestType = CrowdUtil.judgeRequestType(request);
        if (judgeRequestType){
            //if判断-是json请求
            ResultEntity<Object> failed = ResultEntity.failed(exception.getMessage());
            //创建Gson对象
            Gson gson = new Gson();
            //将ResultEntity对象转换成json格式
            String json = gson.toJson(failed);
            //通过原生servlet的response传回异常内容
            response.getWriter().write(json);
            //此时只需要返回null(因为是通过json格式返回数据)
            return null;
        } else {
            //if判断-是普通页面请求
            //创建ModelAndView对象
            ModelAndView modelAndView = new ModelAndView();
            //设置触发异常跳转的页面(会自动被视图解析器加上前后缀)
            modelAndView.setViewName(viewName);
            //将异常信息加入
            modelAndView.addObject(CrowdConstant.ATTR_NAME_EXCEPTION, exception);
            //返回设置完成的ModelAndView
            return modelAndView;
        }
    }

}

十、以常量管理常用的属性

对于经常使用到且存在复用的属性名,可以单独设置一个常量类。这样的好处是可以减少因拼写导致的错误。

//常量类
public class CrowdConstant {

    public static final String ATTR_NAME_EXCEPTION = "exception";
    public static final String MESSAGE_LOGIN_FAILED = "登录失败!请确认账号密码是否正确";

}

十一、前端页面引入

引入登录页面

1、引入需要的静态资源
在这里插入图片描述
2、将登录页面的代码复制入创建的admin-login.jsp文件,并进行适当的修改(还未完全修改)

​ 主要是修改了编码方式为统一的UTF-8;添加了base标签;提前设置form表单的action和method;设置了账号密码的name属性。

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <meta name="description" content="">
    <meta name="keys" content="">
    <meta name="author" content="">
    <base href="http://${pageContext.request.serverName}:${pageContext.request.serverPort}${pageContext.request.contextPath}/">
    <link rel="stylesheet" href="bootstrap/css/bootstrap.css">
    <link rel="stylesheet" href="css/font-awesome.min.css">
    <link rel="stylesheet" href="css/login.css">
</head>
<body>
<nav class="navbar navbar-inverse navbar-fixed-top" role="navigation">
    <div class="container">
        <div class="navbar-header">
            <div><a class="navbar-brand" href="index.html" style="font-size:32px;">尚筹网-创意产品众筹平台</a></div>
        </div>
    </div>
</nav>

<div class="container">

    <form action="admin/login/login.html" method="post" class="form-signin" role="form">
        <h2 class="form-signin-heading"><i class="glyphicon glyphicon-log-in"></i> 用户登录</h2>
        <div class="form-group has-success has-feedback">
            <input type="text" name="login-user" class="form-control" id="inputSuccess4" placeholder="请输入登录账号" autofocus>
            <span class="glyphicon glyphicon-user form-control-feedback"></span>
        </div>
        <div class="form-group has-success has-feedback">
            <input type="text" name="login-pwd" class="form-control" id="inputSuccess4" placeholder="请输入登录密码" style="margin-top:10px;">
            <span class="glyphicon glyphicon-lock form-control-feedback"></span>
        </div>
        <div class="checkbox" style="text-align:right;"><a href="reg.html">我要注册</a></div>
        <button type="submit" class="btn btn-lg btn-success btn-block">登录</button>
    </form>
</div>
<script src="jquery/jquery-2.1.1.min.js"></script>
<script src="bootstrap/js/bootstrap.min.js"></script>
</body>
</html>

遇到的奇怪的问题

在mvc配置文件中通过view-controller,使通过path指定的路径,访问登录页面(因为只需要单纯的访问而不需要附带数据等操作,因此使用此方法相比handler方法转发更加方便)

<!--通过view-controller 来设置一些直接的页面跳转-->
<mvc:view-controller path="/admin/login/page.html" view-name="admin-login"/>

但是最后测试下来,发现访问时会发生404错误

​ 我使用的默认是Edge Beta浏览器,当使用Edge浏览器时,可以通过链接访问登录页面,也可以直接使用 localhost:8888/admin/login/page.html访问登录页面;但是当使用了chrome浏览器,使用地址栏输入…page.html时,发生奇怪的事情:报404错误,且之后edge也不能访问登录页面。最后尝试了很久,觉得应该是Tomcat缓存的问题,但尝试了多种清理缓存的方法,还是没有效果,最后去掉了IDEA中对tomcat的一个勾选

在这里插入图片描述
这样可以算是“暂时”解决了问题。


尝试使用layer弹层组件

​ 1、网上下载layer.js(此处是3.3.1版本)

​ 2、引入与测试使用layer组件

​ 注意:layer组件依赖于jquery,因此layer的引入必须在jquery之后,否则会出错。

<script src="jquery/jquery-3.4.1.js" type="text/javascript"></script>
<script src="layer/layer.js" type="text/javascript"></script>
<script>
    $("#btn5").click(function () {
        layer.msg("test layer");
    });
</script>
<body>
 	<button id="btn5">Test layer</button>
</body>

修饰错误页面

借助登录页面的样式,给错误页面换壳

使错误页面可以显示错误信息,并且提供了返回上一层的按钮。

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<!DOCTYPE html>
<html lang="zh-CN">
<head>
	<%-- 前面与登录页面相同 --%>
    <script src="jquery/jquery-3.4.1.js" type="text/javascript"></script>
    <script type="text/javascript">
        $(function () {
            $("button").click(function () {
				//用js的方法,完成回退的目的
                window.history.back();
            });
        });
    </script>
</head>
<body>
<nav class="navbar navbar-inverse navbar-fixed-top" role="navigation">
	<%-- 与登录页面同 --%>
</nav>
    
<div class="container">
    <h1 style="text-align: center;">请求出现了错误QAQ</h1>
    <h2 style="text-align: center;">错误消息:${requestScope.exception.message}</h2>
    <br/><br/>
    <button style="width:150px;margin: 0 auto;" class="btn btn-lg btn-success btn-block">返回上一步</button>
</div>
    
    <script src="bootstrap/js/bootstrap.min.js"></script>
</body>
</html>

最后此阶段完成时的项目目录结构图如下:

在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Cont. TF-IDF (BigData Data Mining)

Cont. 举例 例1 词频 (TF) 是一词语出现的次数除以该文件的总词语数。 假如一篇文件的总词语数是100个&#xff0c;而词语“母牛”出现了3次&#xff0c;那么“母牛”一词在该文件中的词频就是3/1000.03。 一个计算文件频率 (IDF) 的方法是文件集里包含的文件总数除以测定有多…

一些关于单链表的操作

思维导图&#xff1a; 一&#xff0c; 链表 1.1节点的结构 链表是啥样的啊&#xff1f;顾名思义链表就是一种用链子链接起来的表。那这种表是怎么样的啊&#xff1f; 这样的呗&#xff1a; 现在&#xff0c;我们知道了链表的形状了。那我们该如何用编程语言来形成这一种形状…

mysql 安装全过程(linux上二进制包安装)

介绍 mysql 是一种RDBMS 关系型数据库管理系统 Relational Database Management System 关系型数据库将数据保存在不同的表中&#xff0c;而不是放在一个大仓库内&#xff0c;增加了速度&#xff0c;提高了灵活性。 . mysql版本 5.7.x 和 8.0.x 是目前主流。2个…

RT-Thread 在线软件包改为本地软件包的方法

问题描述 RT-Thread 的软件包&#xff0c;使用时&#xff0c;需要手动通过 ENV 工具 更新到 本地的 packages 目录&#xff0c;并且 packages 目录默认不参与 Git 工程管理&#xff0c;软件包多了&#xff0c;并且偶尔需要更改软件包本身的一些代码&#xff0c;这就造成了软件项…

Spring 依赖注入源码

文章目录 依赖注入原始依赖注入方式注解方式寻找注入点注入点进行注入 从BeanFactory中找注入对象总结 依赖注入 具体代码是在AbstractAutowireCapableBeanFactory类的populateBean()方法&#xff0c;此方法中主要做的事情如下&#xff1a; 实例化之后&#xff0c;调用Instan…

【Java校招面试】基础知识(二)——Spring Framework AOP

目录 前言一、Spring Framewwork基础知识二、Spring AOP基础概念1. 切面&#xff08;Aspect&#xff09;2. 织入&#xff08;Weaving&#xff09;3. 增强&#xff08;Advice&#xff09;4. 动态代理 三、JDK动态代理1. 基本用法2. 原理分析 四、CGLib动态代理1. 基本用法2. 原理…

【五一创作】使用Resnet残差网络对图像进行分类(猫十二分类,模型定义、训练、保存、预测)(二)

使用Resnet残差网络对图像进行分类 &#xff08;猫十二分类&#xff0c;模型定义、训练、保存、预测&#xff09;(二&#xff09; 目录 &#xff08;6&#xff09;、数据集划分 &#xff08;7&#xff09;、训练集增强 &#xff08;8&#xff09;、装载数据集 &#xff08…

山东专升本计算机第十一章-新一代信息技术

新一代信息技术 物联网 概念 物联网就是物物相连的互联网&#xff0c;其核心和基础仍然是互联网 计算机&#xff0c;互联网之后信息产业发展的第三次浪潮 推入人类进入智能时代&#xff0c;又称物联时代 三大特征 全面感知 可靠传递 智能处理 • 物联网的最核心 技术架…

阿里云g8i服务器ECS通用型服务器CPU处理器性能测评

阿里云服务器ECS通用型实例规格族g8i采用2.7 GHz主频的Intel Xeon(Sapphire Rapids) Platinum 8475B处理器&#xff0c;3.2 GHz睿频&#xff0c;g8i实例采用阿里云全新CIPU架构&#xff0c;可提供稳定的算力输出、更强劲的I/O引擎以及芯片级的安全加固。阿里云百科分享阿里云服…

JavaScript 入门(1)

script 标签 <scrtipt> 标签可以插入到HTML中的任何位置在很老的代码中需使用type属性&#xff0c;但是现在的代码中不需要 <script type"text/javascript"><!-- ... //--></script>外部脚本 通过src 属性将脚本添加到HTML中 <script …

Maven的全面讲解及如何安装使用

Maven是一种流行的Java项目管理工具&#xff0c;可用于构建、测试、打包和部署Java应用程序。本文将介绍Maven的概念、安装配置、使用方法、生命周期以及IDEA集成Maven的方法。 Maven的概念 Maven是一种基于项目对象模型&#xff08;POM&#xff09;的构建工具。POM是一个XML…

【C++】位运算类题目总结

文章目录 一. 位运算符脑图二. 相关题目1. 统计二进制数中0的个数2. 数组中只出现一次的数字3. 数组中只出现一次的数字 II4. 不用加减乘除做加法 一. 位运算符脑图 二. 相关题目 1. 统计二进制数中0的个数 解题思路&#xff1a;x & (x-1)&#xff1b;它的作用是每次循环…

系统集成项目管理工程师 笔记(第18章:项目风险管理)

文章目录 18.1.2 风险的分类 54318.1.3 风险的性质 544项目风险管理6个过程&#xff08;风险管理、识别风险、实施定性风险分析、实施定量风险分析、规划风险应对、控制风险&#xff09;组织和干系人的风险态度影响因素18.3.3 规划风险管理的输出 550风险识别的原则18.4.2 识别…

针对Vue前后端分离项目的渗透思路

引言 在目前的开发环境下&#xff0c;越来越多的厂商选择 Vue.js 来实现前端功能的编写&#xff0c;且成熟的前端框架已经可以实现后端代码实现的功能&#xff0c;导致后端目前只负责提供 Api 接口和文档&#xff0c;方便前端的同时去调用。本文主要介绍如何针对这类前后端分离…

如何利用几何坐标变换后纠正技术实现倾斜摄影三维模型数据拼接?

如何利用几何坐标变换后纠正技术实现倾斜摄影三维模型数据拼接&#xff1f; 倾斜摄影三维模型数据拼接是指将多个倾斜摄影数据集合并为一个完整的三维模型。在这个过程中&#xff0c;由于不同数据集之间的相对位置和姿态不同&#xff0c;需要进行几何坐标变换以实现数据拼接。…

借用AI工具为视频添加中文字幕,消除语言障碍,母语环境最快速地学习

由于chatgpt的启动&#xff0c;感觉语言已经完全不会成为学习的障碍&#xff0c;突发奇想&#xff0c;在我们查看youtube视频的时候&#xff0c;有没有方便的工具能够将其字幕翻译为中文。这样能够极大提高在youtube学习的效率&#xff0c;于是顺手问了一下ChatGPT&#xff0c;…

Nginx—在linux的ubuntu系统上的安装使用

前言: 有关Nginx的基础知识和使用都在这里Nginx简介和快速入门_北岭山脚鼠鼠的博客-CSDN博客 常用命令: cd /usr/local/nginx/sbin/ ./nginx 启动 ./nginx -s stop 停止 ./nginx -s quit 安全退出 ./nginx -s reload 重新加载配置文件(常用) //在修改配置文件之后使用 p…

教你部署chatgpt商业版源码,支持卡密开通国内使用

教你部署chatgpt商业版源码&#xff0c;支持卡密开通国内使用 当今&#xff0c;人工智能技术在各个领域的应用越来越广泛&#xff0c;其中自然语言处理是非常重要的一环。OpenAI 的 GPT 模型是自然语言处理领域的一项重要技术&#xff0c;它可以根据已有的文本数据&#xff0c;…

Java 怎样实现代理模式,有什么优缺点

一、介绍 代理模式是一种常见的设计模式&#xff0c;它可以为其他对象提供一种代理以控制对这个对象的访问。代理对象具有与被代理对象相同的接口&#xff0c;客户端无需知道代理对象和被代理对象的区别。代理模式可以应用于各种不同的场景&#xff0c;例如远程代理、虚拟代理…

Ubantu docker学习笔记(九)容器监控 自带的监控+sysdig+scope+cAdvisor+prometheus

文章目录 一、Docker命令监控二、Sysdig2.1介绍2.2 基本操作2.2.1 切换视图2.2.2 查看标签含义2.2.3 排序2.2.4 查看内部进程2.2.5 查找2.2.6 暂停2.2.7 上一级2.2.8 退出 三、Weave Scope3.1介绍3.2基本操作3.2.1 显示容器3.2.2 选择容器3.2.3 按照CPU使用情况排序3.2.4 控制容…