SSM(Spring+SpringMVC+Mybatis)是目前较为主流的企业级架构方案,不知道大家有没有留意,在我们看招聘信息的时候,经常会看到这一点,需要具备SSH框架的技能;而且在大部分教学课堂中,也会把SSH作为最核心的教学内容。

但是,我们在实际应用中发现,SpringMVC可以完全替代Struts,配合注解的方式,编程非常快捷,而且通过restful风格定义url,让地址看起来非常优雅。

另外,MyBatis也可以替换Hibernate,正因为MyBatis的半自动特点,我们程序猿可以完全掌控SQL,这会让有数据库经验的程序猿能开发出高效率的SQL语句,而且XML配置管理起来也非常方便。

好了,如果你也认同我的看法,那么下面我们一起来做整合吧!话不多说,来一起看看详细的介绍:

在写代码之前我们先了解一下这三个框架分别是干什么的?

相信大以前也看过不少这些概念,我这就用大白话来讲,如果之前有了解过可以跳过这一大段,直接看代码!

  1. SpringMVC:它用于web层,相当于controller(等价于传统的servlet和struts的action),用来处理用户请求。举个例子,用户在地址栏输入http://网站域名/login,那么springmvc就会拦截到这个请求,并且调用controller层中相应的方法,(中间可能包含验证用户名和密码的业务逻辑,以及查询数据库操作,但这些都不是springmvc的职责),最终把结果返回给用户,并且返回相应的页面(当然也可以只反馈josn/xml等格式数据)。springmvc就是做前面和后面过程的活,与用户打交道!!
  2. Spring:太强大了,以至于我无法用一个词或一句话来概括它。但与我们平时开发接触最多的估计就是IOC容器,它可以装载bean(也就是我们java中的类,当然也包括service dao里面的),有了这个机制,我们就不用在每次使用这个类的时候为它初始化,很少看到关键字new。另外spring的aop,事务管理等等都是我们经常用到的。
  3. MyBatis:如果你问我它跟鼎鼎大名的Hibernate有什么区别?我只想说,他更符合我的需求。第一,它能自由控制sql,这会让有数据库经验的人(当然不是说我啦~捂脸~)编写的代码能搞提升数据库访问的效率。第二,它可以使用xml的方式来组织管理我们的sql,因为一般程序出错很多情况下是sql出错,别人接手代码后能快速找到出错地方,甚至可以优化原来写的sql。

SSM框架整合配置

好了,前面bb那么多,下面我们真正开始敲代码了~

首先我们打开IED,我这里用的是eclipse(你们应该也是用的这个,对吗?),创建一个动态web项目,建立好相应的目录结构(重点!)

(打了马赛克是因为这里还用不到,你们不要那么污好不好?)

我说一下每个目录都有什么用吧(第一次画表格,我发现markdown的表格语法很不友好呀~)

这个目录结构同时也遵循maven的目录规范~

 

文件名作用
src根目录,没什么好说的,下面有main和test。
main主要目录,可以放java代码和一些资源文件。
java存放我们的java代码,这个文件夹要使用Build Path -> Use as Source Folder,这样看包结构会方便很多,新建的包就相当于在这里新建文件夹咯。
resources存放资源文件,譬如各种的spring,mybatis,log配置文件。
mapper存放dao中每个方法对应的sql,在这里配置,无需写daoImpl。
spring这里当然是存放spring相关的配置文件,有dao service web三层。
sql其实这个可以没有,但是为了项目完整性还是加上吧。
webapp这个貌似是最熟悉的目录了,用来存放我们前端的静态资源,如jsp js css。
resources这里的资源是指项目的静态资源,如js css images等。
WEB-INF很重要的一个目录,外部浏览器无法访问,只有羡慕内部才能访问,可以把jsp放在这里,另外就是web.xml了。你可能有疑问了,为什么上面java中的resources里面的配置文件不妨在这里,那么是不是会被外部窃取到?你想太多了,部署时候基本上只有webapp里的会直接输出到根目录,其他都会放入WEB-INF里面,项目内部依然可以使用classpath:XXX来访问,好像IDE里可以设置部署输出目录,这里扯远了~
test这里是测试分支。
java测试java代码,应遵循包名相同的原则,这个文件夹同样要使用Build Path -> Use as Source Folder,这样看包结构会方便很多。

 

resources 没什么好说的,好像也很少用到,但这个是maven的规范。

我先新建好几个必要的包,并为大家讲解一下每个包的作用,顺便理清一下后台的思路~

 

包名名称作用
dao数据访问层(接口)与数据打交道,可以是数据库操作,也可以是文件读写操作,甚至是redis缓存操作,总之与数据操作有关的都放在这里,也有人叫做dal或者数据持久层都差不多意思。为什么没有daoImpl,因为我们用的是mybatis,所以可以直接在配置文件中实现接口的每个方法。
entity实体类一般与数据库的表相对应,封装dao层取出来的数据为一个对象,也就是我们常说的pojo,一般只在dao层与service层之间传输。
dto数据传输层刚学框架的人可能不明白这个有什么用,其实就是用于service层与web层之间传输,为什么不直接用entity(pojo)?其实在实际开发中发现,很多时间一个entity并不能满足我们的业务需求,可能呈现给用户的信息十分之多,这时候就有了dto,也相当于vo,记住一定不要把这个混杂在entity里面,答应我好吗?
service业务逻辑(接口)写我们的业务逻辑,也有人叫bll,在设计业务接口时候应该站在“使用者”的角度。额,不要问我为什么这里没显示!IDE调皮我也拿它没办法~
serviceImpl业务逻辑(实现)实现我们业务接口,一般事务控制是写在这里,没什么好说的。
web控制器springmvc就是在这里发挥作用的,一般人叫做controller控制器,相当于struts中的action。

 

还有最后一步基础工作,导入我们相应的jar包,我使用的是maven来管理我们的jar,所以只需要在poom.xml中加入相应的依赖就好了,如果不使用maven的可以自己去官网下载相应的jar,放到项目WEB-INF/lib目录下。关于maven的学习大家可以看慕课网的视频教程,这里就不展开了。我把项目用到的jar都写在下面,版本都不是最新的,大家有经验的话可以自己调整版本号。另外,所有jar都会与项目一起打包放到我的github上,喜欢的给个star吧~

poom.xml

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

125

126

127

128

129

130

131

132

133

134

135

136

137

138

139

140

141

142

143

144

145

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemalocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">

 <modelversion>4.0.0</modelversion>

 <groupid>com.soecode.ssm</groupid>

 ssm</artifactid>

 <packaging>war</packaging>

 <version>0.0.1-SNAPSHOT</version>

 <name>ssm Maven Webapp</name>

 <url>http://github.com/liyifeng1994/ssm</url>

 <dependencies>

 <!-- 单元测试 -->

 <dependency>

 <groupid>junit</groupid>

 junit</artifactid>

 <version>4.11</version>

 </dependency>

  

 <!-- 1.日志 -->

 <!-- 实现slf4j接口并整合 -->

 <dependency>

 <groupid>ch.qos.logback</groupid>

 logback-classic</artifactid>

 <version>1.1.1</version>

 </dependency>

  

 <!-- 2.数据库 -->

 <dependency>

 <groupid>mysql</groupid>

 mysql-connector-java</artifactid>

 <version>5.1.37</version>

 <scope>runtime</scope>

 </dependency>

 <dependency>

 <groupid>c3p0</groupid>

 c3p0</artifactid>

 <version>0.9.1.2</version>

 </dependency>

  

 <!-- DAO: MyBatis -->

 <dependency>

 <groupid>org.mybatis</groupid>

 mybatis</artifactid>

 <version>3.3.0</version>

 </dependency>

 <dependency>

 <groupid>org.mybatis</groupid>

 mybatis-spring</artifactid>

 <version>1.2.3</version>

 </dependency>

  

 <!-- 3.Servlet web -->

 <dependency>

 <groupid>taglibs</groupid>

 standard</artifactid>

 <version>1.1.2</version>

 </dependency>

 <dependency>

 <groupid>jstl</groupid>

 jstl</artifactid>

 <version>1.2</version>

 </dependency>

 <dependency>

 <groupid>com.fasterxml.jackson.core</groupid>

 jackson-databind</artifactid>

 <version>2.5.4</version>

 </dependency>

 <dependency>

 <groupid>javax.servlet</groupid>

 javax.servlet-api</artifactid>

 <version>3.1.0</version>

 </dependency>

  

 <!-- 4.Spring -->

 <!-- 1)Spring核心 -->

 <dependency>

 <groupid>org.springframework</groupid>

 spring-core</artifactid>

 <version>4.1.7.RELEASE</version>

 </dependency>

 <dependency>

 <groupid>org.springframework</groupid>

 spring-beans</artifactid>

 <version>4.1.7.RELEASE</version>

 </dependency>

 <dependency>

 <groupid>org.springframework</groupid>

 spring-context</artifactid>

 <version>4.1.7.RELEASE</version>

 </dependency>

 <!-- 2)Spring DAO层 -->

 <dependency>

 <groupid>org.springframework</groupid>

 spring-jdbc</artifactid>

 <version>4.1.7.RELEASE</version>

 </dependency>

 <dependency>

 <groupid>org.springframework</groupid>

 spring-tx</artifactid>

 <version>4.1.7.RELEASE</version>

 </dependency>

 <!-- 3)Spring web -->

 <dependency>

 <groupid>org.springframework</groupid>

 spring-web</artifactid>

 <version>4.1.7.RELEASE</version>

 </dependency>

 <dependency>

 <groupid>org.springframework</groupid>

 spring-webmvc</artifactid>

 <version>4.1.7.RELEASE</version>

 </dependency>

 <!-- 4)Spring test -->

 <dependency>

 <groupid>org.springframework</groupid>

 spring-test</artifactid>

 <version>4.1.7.RELEASE</version>

 </dependency>

  

 <!-- redis客户端:Jedis -->

 <dependency>

 <groupid>redis.clients</groupid>

 jedis</artifactid>

 <version>2.7.3</version>

 </dependency>

 <dependency>

 <groupid>com.dyuproject.protostuff</groupid>

 <artifactid>protostuff-core</artifactid>

 <version>1.0.8</version>

 </dependency>

 <dependency>

 <groupid>com.dyuproject.protostuff</groupid>

 <artifactid>protostuff-runtime</artifactid>

 <version>1.0.8</version>

 </dependency>

  

 <!-- Map工具类 -->

 <dependency>

 <groupid>commons-collections</groupid>

 <artifactid>commons-collections</artifactid>

 <version>3.2</version>

 </dependency>

 </dependencies>

 <build>

 <finalname>ssm</finalname>

 </build>

</project>

 

下面真的要开始进行编码工作了,坚持到这里辛苦大家了~

第一步:我们先在spring文件夹里新建spring-dao.xml文件,因为spring的配置太多,我们这里分三层,分别是dao service web。

1、读入数据库连接相关参数(可选)

2、配置数据连接池 

     配置连接属性,可以不读配置项文件直接在这里写死

     配置c3p0,只配了几个常用的

3、配置SqlSessionFactory对象(mybatis)

4、扫描dao层接口,动态实现dao接口,也就是说不需要daoImpl,sql和参数都写在xml文件上

spring-dao.xml

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

<?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

 http://www.springframework.org/schema/context/spring-context.xsd">

 <!-- 配置整合mybatis过程 -->

 <!-- 1.配置数据库相关参数properties的属性:${url} -->

 <context:property-placeholder location="classpath:jdbc.properties" />

 

 <!-- 2.数据库连接池 -->

 <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">

 <!-- 配置连接池属性 -->

 <property name="driverClass" value="${jdbc.driver}" />

 <property name="jdbcUrl" value="${jdbc.url}" />

 <property name="user" value="${jdbc.username}" />

 <property name="password" value="${jdbc.password}" />

 

 <!-- c3p0连接池的私有属性 -->

 <property name="maxPoolSize" value="30" />

 <property name="minPoolSize" value="10" />

 <!-- 关闭连接后不自动commit -->

 <property name="autoCommitOnClose" value="false" />

 <!-- 获取连接超时时间 -->

 <property name="checkoutTimeout" value="10000" />

 <!-- 当获取连接失败重试次数 -->

 <property name="acquireRetryAttempts" value="2" />

 </bean>

 

 <!-- 3.配置SqlSessionFactory对象 -->

 <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">

 <!-- 注入数据库连接池 -->

 <property name="dataSource" ref="dataSource" />

 <!-- 配置MyBaties全局配置文件:mybatis-config.xml -->

 <property name="configLocation" value="classpath:mybatis-config.xml" />

 <!-- 扫描entity包 使用别名 -->

 <property name="typeAliasesPackage" value="com.soecode.lyf.entity" />

 <!-- 扫描sql配置文件:mapper需要的xml文件 -->

 <property name="mapperLocations" value="classpath:mapper/*.xml" />

 </bean>

 

 <!-- 4.配置扫描Dao接口包,动态实现Dao接口,注入到spring容器中 -->

 <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">

 <!-- 注入sqlSessionFactory -->

 <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory" />

 <!-- 给出需要扫描Dao接口包 -->

 <property name="basePackage" value="com.soecode.lyf.dao" />

 </bean>

</beans>

因为数据库配置相关参数是读取配置文件,所以在resources文件夹里新建一个jdbc.properties文件,存放我们4个最常见的数据库连接属性,这是我本地的,大家记得修改呀~还有喜欢传到github上“大头虾们”记得删掉密码,不然别人就很容易得到你服务器的数据库配置信息,然后干一些羞羞的事情,你懂的!!

jdbc.properties

?

1

2

3

4

jdbc.driver=com.mysql.jdbc.Driver

jdbc.url=jdbc:mysql://localhost:3307/ssm?useUnicode=true&characterEncoding=utf8

jdbc.username=root

jdbc.password=

友情提示:配置文件中的jdbc.username,如果写成username,可能会与系统环境中的username变量冲突,所以到时候真正连接数据库的时候,用户名就被替换成系统中的用户名(有得可能是administrator),那肯定是连接不成功的,这里有个小坑,我被坑了一晚上!!

因为这里用到了mybatis,所以需要配置mybatis核心文件,在recources文件夹里新建mybatis-config.xml文件。

  • 使用自增主键
  • 使用列别名
  • 开启驼峰命名转换 create_time -> createTime

mybatis-config.xml

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

<?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>

 <!-- 配置全局属性 -->

 <settings>

 <!-- 使用jdbc的getGeneratedKeys获取数据库自增主键值 -->

 <setting name="useGeneratedKeys" value="true" />

 

 <!-- 使用列别名替换列名 默认:true -->

 <setting name="useColumnLabel" value="true" />

 

 <!-- 开启驼峰命名转换:Table{create_time} -> Entity{createTime} -->

 <setting name="mapUnderscoreToCamelCase" value="true" />

 </settings>

</configuration>

第二步:刚弄好dao层,接下来到service层了。在spring文件夹里新建spring-service.xml文件。

  • 扫描service包所有注解 @Service
  • 配置事务管理器,把事务管理交由spring来完成
  • 配置基于注解的声明式事务,可以直接在方法上@Transaction

spring-service.xml

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

<?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"

 xmlns:tx="http://www.springframework.org/schema/tx"

 xsi:schemaLocation="http://www.springframework.org/schema/beans

 http://www.springframework.org/schema/beans/spring-beans.xsd

 http://www.springframework.org/schema/context

 http://www.springframework.org/schema/context/spring-context.xsd

 http://www.springframework.org/schema/tx

 http://www.springframework.org/schema/tx/spring-tx.xsd">

 <!-- 扫描service包下所有使用注解的类型 -->

 <context:component-scan base-package="com.soecode.lyf.service" />

 

 <!-- 配置事务管理器 -->

 <bean id="transactionManager"

 class="org.springframework.jdbc.datasource.DataSourceTransactionManager">

 <!-- 注入数据库连接池 -->

 <property name="dataSource" ref="dataSource" />

 </bean>

 

 <!-- 配置基于注解的声明式事务 -->

 <tx:annotation-driven transaction-manager="transactionManager" />

</beans>

第三步:配置web层,在spring文件夹里新建spring-web.xml文件。

  • 开启SpringMVC注解模式,可以使用@RequestMapping,@PathVariable,@ResponseBody等
  • 对静态资源处理,如js,css,jpg等
  • 配置jsp 显示ViewResolver,例如在controller中某个方法返回一个string类型的”login”,实际上会返回”/WEB-INF/login.jsp”
  • 扫描web层 @Controller

spring-web.xml

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

<?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"

 xmlns:mvc="http://www.springframework.org/schema/mvc"

 xsi:schemaLocation="http://www.springframework.org/schema/beans

 http://www.springframework.org/schema/beans/spring-beans.xsd

 http://www.springframework.org/schema/context

 http://www.springframework.org/schema/context/spring-context.xsd

 http://www.springframework.org/schema/mvc

 http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd">

 <!-- 配置SpringMVC -->

 <!-- 1.开启SpringMVC注解模式 -->

 <!-- 简化配置:

 (1)自动注册DefaultAnootationHandlerMapping,AnotationMethodHandlerAdapter

 (2)提供一些列:数据绑定,数字和日期的format @NumberFormat, @DateTimeFormat, xml,json默认读写支持

 -->

 <mvc:annotation-driven />

 

 <!-- 2.静态资源默认servlet配置

 (1)加入对静态资源的处理:js,gif,png

 (2)允许使用"/"做整体映射

 -->

 <mvc:default-servlet-handler/>

 

 <!-- 3.配置jsp 显示ViewResolver -->

 <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">

 <property name="viewClass" value="org.springframework.web.servlet.view.JstlView" />

 <property name="prefix" value="/WEB-INF/jsp/" />

 <property name="suffix" value=".jsp" />

 </bean>

 

 <!-- 4.扫描web相关的bean -->

 <context:component-scan base-package="com.soecode.lyf.web" />

</beans>

第四步:最后就是修改web.xml文件了,它在webapp的WEB-INF下。

web.xml

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

<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_3_1.xsd"

 version="3.1" metadata-complete="true">

 <!-- 如果是用mvn命令生成的xml,需要修改servlet版本为3.1 -->

 <!-- 配置DispatcherServlet -->

 <servlet>

 <servlet-name>seckill-dispatcher</servlet-name>

 <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>

 <!-- 配置springMVC需要加载的配置文件

 spring-dao.xml,spring-service.xml,spring-web.xml

 Mybatis - > spring -> springmvc

 -->

 <init-param>

 <param-name>contextConfigLocation</param-name>

 <param-value>classpath:spring/spring-*.xml</param-value>

 </init-param>

 </servlet>

 <servlet-mapping>

 <servlet-name>seckill-dispatcher</servlet-name>

 <!-- 默认匹配所有的请求 -->

 <url-pattern>/</url-pattern>

 </servlet-mapping>

</web-app>

我们在项目中经常会使用到日志,所以这里还有配置日志xml,在resources文件夹里新建logback.xml文件,所给出的日志输出格式也是最基本的控制台s呼出,大家有兴趣查看logback官方文档。

logback.xml

?

1

2

3

4

5

6

7

8

9

10

11

12

13

<?xml version="1.0" encoding="UTF-8"?>

<configuration debug="true">

 <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">

 <!-- encoders are by default assigned the type ch.qos.logback.classic.encoder.PatternLayoutEncoder -->

 <encoder>

 <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>

 </encoder>

 </appender>

 

 <root level="debug">

 <appender-ref ref="STDOUT" />

 </root>

</configuration>

到目前为止,我们一共写了7个配置文件,我们一起来看下最终的配置文件结构图。

SSM框架应用实例(图书管理系统)

一开始想就这样结束教程,但是发现其实很多人都还不会把这个SSM框架用起来,特别是mybatis部分。那我现在就以最常见的“图书管理系统”中【查询图书】和【预约图书】业务来做一个demo吧!

首先新建数据库名为ssm,再创建两张表:图书表book和预约图书表appointment,并且为book表初始化一些数据,sql如下。

schema.sql

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

-- 创建图书表

CREATE TABLE `book` (

 `book_id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '图书ID',

 `name` varchar(100) NOT NULL COMMENT '图书名称',

 `number` int(11) NOT NULL COMMENT '馆藏数量',

 PRIMARY KEY (`book_id`)

) ENGINE=InnoDB AUTO_INCREMENT=1000 DEFAULT CHARSET=utf8 COMMENT='图书表'

 

-- 初始化图书数据

INSERT INTO `book` (`book_id`, `name`, `number`)

VALUES

 (1000, 'Java程序设计', 10),

 (1001, '数据结构', 10),

 (1002, '设计模式', 10),

 (1003, '编译原理', 10)

 

-- 创建预约图书表

CREATE TABLE `appointment` (

 `book_id` bigint(20) NOT NULL COMMENT '图书ID',

 `student_id` bigint(20) NOT NULL COMMENT '学号',

 `appoint_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '预约时间' ,

 PRIMARY KEY (`book_id`, `student_id`),

 INDEX `idx_appoint_time` (`appoint_time`)

) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='预约图书表'

在entity包中添加两个对应的实体,图书实体Book.java和预约图书实体Appointment.java。

Book.java

?

1

2

3

4

5

6

7

8

9

10

11

12

13

package com.soecode.lyf.entity;

 

public class Book {

 

 private long bookId;// 图书ID

 

 private String name;// 图书名称

 

 private int number;// 馆藏数量

 

 // 省略构造方法,getter和setter方法,toString方法

 

}

Appointment.java

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

package com.soecode.lyf.entity;

 

import java.util.Date;

 

/**

 * 预约图书实体

 */

public class Appointment {

 

 private long bookId;// 图书ID

 

 private long studentId;// 学号

 

 private Date appointTime;// 预约时间

 

 // 多对一的复合属性

 private Book book;// 图书实体

 

 // 省略构造方法,getter和setter方法,toString方法

 

}

在dao包新建接口BookDao.java和Appointment.java

BookDao.java

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

package com.soecode.lyf.dao;

 

import java.util.List;

 

import com.soecode.lyf.entity.Book;

 

public interface BookDao {

 

 /**

 * 通过ID查询单本图书

 *

 * @param id

 * @return

 */

 Book queryById(long id);

 

 /**

 * 查询所有图书

 *

 * @param offset 查询起始位置

 * @param limit 查询条数

 * @return

 */

 List<Book> queryAll(@Param("offset") int offset, @Param("limit") int limit);

 

 /**

 * 减少馆藏数量

 *

 * @param bookId

 * @return 如果影响行数等于>1,表示更新的记录行数

 */

 int reduceNumber(long bookId);

}

AppointmentDao.java

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

package com.soecode.lyf.dao;

 

import org.apache.ibatis.annotations.Param;

 

import com.soecode.lyf.entity.Appointment;

 

public interface AppointmentDao {

 

 /**

 * 插入预约图书记录

 *

 * @param bookId

 * @param studentId

 * @return 插入的行数

 */

 int insertAppointment(@Param("bookId") long bookId, @Param("studentId") long studentId);

 

 /**

 * 通过主键查询预约图书记录,并且携带图书实体

 *

 * @param bookId

 * @param studentId

 * @return

 */

 Appointment queryByKeyWithBook(@Param("bookId") long bookId, @Param("studentId") long studentId);

 

}

提示:这里为什么要给方法的参数添加@Param注解呢?是因为该方法有两个或以上的参数,一定要加,不然mybatis识别不了。上面的BookDao接口的queryById方法和reduceNumber方法只有一个参数book_id,所以可以不用加 @Param注解,当然加了也无所谓~

注意:这里不需要实现dao接口不用编写daoImpl, mybatis会给我们动态实现,但是我们需要编写相应的mapper。 
在mapper目录里新建两个文件BookDao.xml和AppointmentDao.xml,分别对应上面两个dao接口,代码如下。

BookDao.xml

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE mapper

 PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"

 "http://mybatis.org/dtd/mybatis-3-mapper.dtd">

<mapper namespace="com.soecode.lyf.dao.BookDao">

 <!-- 目的:为dao接口方法提供sql语句配置 -->

 <select id="queryById" resultType="Book" parameterType="long">

 <!-- 具体的sql -->

 SELECT

 book_id,

 name,

 number

 FROM

 book

 WHERE

 book_id = #{bookId}

 </select>

 

 <select id="queryAll" resultType="Book">

 SELECT

 book_id,

 name,

 number

 FROM

 book

 ORDER BY

 book_id

 LIMIT #{offset}, #{limit}

 </select>

 

 <update id="reduceNumber">

 UPDATE book

 SET number = number - 1

 WHERE

 book_id = #{bookId}

 AND number > 0

 </update>

</mapper>

AppointmentDao.xml

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE mapper

 PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"

 "http://mybatis.org/dtd/mybatis-3-mapper.dtd">

<mapper namespace="com.soecode.lyf.dao.AppointmentDao">

 <insert id="insertAppointment">

 <!-- ignore 主键冲突,报错 -->

 INSERT ignore INTO appointment (book_id, student_id)

 VALUES (#{bookId}, #{studentId})

 </insert>

 

 <select id="queryByKeyWithBook" resultType="Appointment">

 <!-- 如何告诉MyBatis把结果映射到Appointment同时映射book属性 -->

 <!-- 可以自由控制SQL -->

 SELECT

 a.book_id,

 a.student_id,

 a.appoint_time,

 b.book_id "book.book_id",

 b.`name` "book.name",

 b.number "book.number"

 FROM

 appointment a

 INNER JOIN book b ON a.book_id = b.book_id

 WHERE

 a.book_id = #{bookId}

 AND a.student_id = #{studentId}

 </select>

</mapper>

mapper总结:namespace是该xml对应的接口全名,select和update中的id对应方法名,resultType是返回值类型,parameterType是参数类型(这个其实可选),最后#{...}中填写的是方法的参数,看懂了是不是很简单!!我也这么觉得~ 还有一个小技巧要交给大家,就是在返回Appointment对象包含了一个属性名为book的Book对象,那么可以使用"book.属性名"的方式来取值,看上面queryByKeyWithBook方法的sql。

dao层写完了,接下来test对应的package写我们测试方法吧。 

因为我们之后会写很多测试方法,在测试前需要让程序读入spring-dao和mybatis等配置文件,所以我这里就抽离出来一个BaseTest类,只要是测试方法就继承它,这样那些繁琐的重复的代码就不用写那么多了~

BaseTest.java

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

package com.soecode.lyf;

 

import org.junit.runner.RunWith;

import org.springframework.test.context.ContextConfiguration;

import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

 

/**

 * 配置spring和junit整合,junit启动时加载springIOC容器 spring-test,junit

 */

@RunWith(SpringJUnit4ClassRunner.class)

// 告诉junit spring配置文件

@ContextConfiguration({ "classpath:spring/spring-dao.xml", "classpath:spring/spring-service.xml" })

public class BaseTest {

 

}

因为spring-service在service层的测试中会时候到,这里也一起引入算了!

新建BookDaoTest.java和AppointmentDaoTest.java两个dao测试文件。

BookDaoTest.java

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

package com.soecode.lyf.dao;

 

import java.util.List;

 

import org.junit.Test;

import org.springframework.beans.factory.annotation.Autowired;

 

import com.soecode.lyf.BaseTest;

import com.soecode.lyf.entity.Book;

 

public class BookDaoTest extends BaseTest {

 

 @Autowired

 private BookDao bookDao;

 

 @Test

 public void testQueryById() throws Exception {

 long bookId = 1000;

 Book book = bookDao.queryById(bookId);

 System.out.println(book);

 }

 

 @Test

 public void testQueryAll() throws Exception {

 List<Book> books = bookDao.queryAll(0, 4);

 for (Book book : books) {

 System.out.println(book);

 }

 }

 

 @Test

 public void testReduceNumber() throws Exception {

 long bookId = 1000;

 int update = bookDao.reduceNumber(bookId);

 System.out.println("update=" + update);

 }

 

}

BookDaoTest测试结果

testQueryById

testQueryById

testQueryAll 

testReduceNumber 

AppointmentDaoTest.java

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

package com.soecode.lyf.dao;

 

import org.junit.Test;

import org.springframework.beans.factory.annotation.Autowired;

 

import com.soecode.lyf.BaseTest;

import com.soecode.lyf.entity.Appointment;

 

public class AppointmentDaoTest extends BaseTest {

 

 @Autowired

 private AppointmentDao appointmentDao;

 

 @Test

 public void testInsertAppointment() throws Exception {

 long bookId = 1000;

 long studentId = 12345678910L;

 int insert = appointmentDao.insertAppointment(bookId, studentId);

 System.out.println("insert=" + insert);

 }

 

 @Test

 public void testQueryByKeyWithBook() throws Exception {

 long bookId = 1000;

 long studentId = 12345678910L;

 Appointment appointment = appointmentDao.queryByKeyWithBook(bookId, studentId);

 System.out.println(appointment);

 System.out.println(appointment.getBook());

 }

 

}

AppointmentDaoTest测试结果

testInsertAppointment 

testQueryByKeyWithBook 

嗯,到这里一切到很顺利~那么我们继续service层的编码吧~可能下面开始信息里比较大,大家要做好心理准备~

首先,在写我们的控制器之前,我们先定义几个预约图书操作返回码的数据字典,也就是我们要返回给客户端的信息。我们这类使用枚举类,没听过的小伙伴要好好恶补一下了(我也是最近才学到的= =)

预约业务操作返回码说明

 

返回码说明
1预约成功
0库存不足
-1重复预约
-2系统异常

 

新建一个包叫enums,在里面新建一个枚举类AppointStateEnum.java,用来定义预约业务的数据字典,没听懂没关系,我们直接看代码吧~是不是感觉有模有样了!

AppointStateEnum.java

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

package com.soecode.lyf.enums;

 

/**

 * 使用枚举表述常量数据字典

 */

public enum AppointStateEnum {

 

 SUCCESS(1, "预约成功"), NO_NUMBER(0, "库存不足"), REPEAT_APPOINT(-1, "重复预约"), INNER_ERROR(-2, "系统异常");

 

 private int state;

 

 private String stateInfo;

 

 private AppointStateEnum(int state, String stateInfo) {

 this.state = state;

 this.stateInfo = stateInfo;

 }

 

 public int getState() {

 return state;

 }

 

 public String getStateInfo() {

 return stateInfo;

 }

 

 public static AppointStateEnum stateOf(int index) {

 for (AppointStateEnum state : values()) {

 if (state.getState() == index) {

 return state;

 }

 }

 return null;

 }

 

}

接下来,在dto包下新建AppointExecution.java用来存储我们执行预约操作的返回结果。

AppointExecution.java

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

package com.soecode.lyf.dto;

 

import com.soecode.lyf.entity.Appointment;

import com.soecode.lyf.enums.AppointStateEnum;

 

/**

 * 封装预约执行后结果

 */

public class AppointExecution {

 

 // 图书ID

 private long bookId;

 

 // 秒杀预约结果状态

 private int state;

 

 // 状态标识

 private String stateInfo;

 

 // 预约成功对象

 private Appointment appointment;

 

 public AppointExecution() {

 }

 

 // 预约失败的构造器

 public AppointExecution(long bookId, AppointStateEnum stateEnum) {

 this.bookId = bookId;

 this.state = stateEnum.getState();

 this.stateInfo = stateEnum.getStateInfo();

 }

 

 // 预约成功的构造器

 public AppointExecution(long bookId, AppointStateEnum stateEnum, Appointment appointment) {

 this.bookId = bookId;

 this.state = stateEnum.getState();

 this.stateInfo = stateEnum.getStateInfo();

 this.appointment = appointment;

 }

 

 // 省略getter和setter方法,toString方法

 

}

接着,在exception包下新建三个文件 

  • NoNumberException.java
  • RepeatAppointException.java
  • AppointException.java

预约业务异常类(都需要继承RuntimeException),分别是无库存异常、重复预约异常、预约未知错误异常,用于业务层非成功情况下的返回(即成功返回结果,失败抛出异常)。

NoNumberException.java

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

package com.soecode.lyf.exception;

 

/**

 * 库存不足异常

 */

public class NoNumberException extends RuntimeException {

 

 public NoNumberException(String message) {

 super(message);

 }

 

 public NoNumberException(String message, Throwable cause) {

 super(message, cause);

 }

 

}

RepeatAppointException.java

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

package com.soecode.lyf.exception;

 

/**

 * 重复预约异常

 */

public class RepeatAppointException extends RuntimeException {

 

 public RepeatAppointException(String message) {

 super(message);

 }

 

 public RepeatAppointException(String message, Throwable cause) {

 super(message, cause);

 }

 

}

AppointException.java

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

package com.soecode.lyf.exception;

 

/**

 * 预约业务异常

 */

public class AppointException extends RuntimeException {

 

 public AppointException(String message) {

 super(message);

 }

 

 public AppointException(String message, Throwable cause) {

 super(message, cause);

 }

 

}

咱们终于可以编写业务代码了,在service包下新建BookService.java图书业务接口。

BookService.java

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

package com.soecode.lyf.service;

 

import java.util.List;

 

import com.soecode.lyf.dto.AppointExecution;

import com.soecode.lyf.entity.Book;

 

/**

 * 业务接口:站在"使用者"角度设计接口 三个方面:方法定义粒度,参数,返回类型(return 类型/异常)

 */

public interface BookService {

 

 /**

 * 查询一本图书

 *

 * @param bookId

 * @return

 */

 Book getById(long bookId);

 

 /**

 * 查询所有图书

 *

 * @return

 */

 List<Book> getList();

 

 /**

 * 预约图书

 *

 * @param bookId

 * @param studentId

 * @return

 */

 AppointExecution appoint(long bookId, long studentId);

 

}

在service.impl包下新建BookServiceImpl.java使用BookService接口,并实现里面的方法。

BookServiceImpl

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

package com.soecode.lyf.service.impl;

 

import java.util.List;

 

import org.slf4j.Logger;

import org.slf4j.LoggerFactory;

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.stereotype.Service;

import org.springframework.transaction.annotation.Transactional;

 

import com.soecode.lyf.dao.AppointmentDao;

import com.soecode.lyf.dao.BookDao;

import com.soecode.lyf.dto.AppointExecution;

import com.soecode.lyf.entity.Appointment;

import com.soecode.lyf.entity.Book;

import com.soecode.lyf.enums.AppointStateEnum;

import com.soecode.lyf.exception.AppointException;

import com.soecode.lyf.exception.NoNumberException;

import com.soecode.lyf.exception.RepeatAppointException;

import com.soecode.lyf.service.BookService;

 

@Service

public class BookServiceImpl implements BookService {

 

 private Logger logger = LoggerFactory.getLogger(this.getClass());

 

 // 注入Service依赖

 @Autowired

 private BookDao bookDao;

 

 @Autowired

 private AppointmentDao appointmentDao;

 

 

 @Override

 public Book getById(long bookId) {

 return bookDao.queryById(bookId);

 }

 

 @Override

 public List<Book> getList() {

 return bookDao.queryAll(0, 1000);

 }

 

 @Override

 @Transactional

 /**

 * 使用注解控制事务方法的优点: 1.开发团队达成一致约定,明确标注事务方法的编程风格

 * 2.保证事务方法的执行时间尽可能短,不要穿插其他网络操作,RPC/HTTP请求或者剥离到事务方法外部

 * 3.不是所有的方法都需要事务,如只有一条修改操作,只读操作不需要事务控制

 */

 public AppointExecution appoint(long bookId, long studentId) {

 try {

 // 减库存

 int update = bookDao.reduceNumber(bookId);

 if (update <= 0) {// 库存不足

 //return new AppointExecution(bookId, AppointStateEnum.NO_NUMBER);//错误写法

 throw new NoNumberException("no number");

 } else {

 // 执行预约操作

 int insert = appointmentDao.insertAppointment(bookId, studentId);

 if (insert <= 0) {// 重复预约

 //return new AppointExecution(bookId, AppointStateEnum.REPEAT_APPOINT);//错误写法

 throw new RepeatAppointException("repeat appoint");

 } else {// 预约成功

 Appointment appointment = appointmentDao.queryByKeyWithBook(bookId, studentId);

 return new AppointExecution(bookId, AppointStateEnum.SUCCESS, appointment);

 }

 }

 // 要先于catch Exception异常前先catch住再抛出,不然自定义的异常也会被转换为AppointException,导致控制层无法具体识别是哪个异常

 } catch (NoNumberException e1) {

 throw e1;

 } catch (RepeatAppointException e2) {

 throw e2;

 } catch (Exception e) {

 logger.error(e.getMessage(), e);

 // 所有编译期异常转换为运行期异常

 //return new AppointExecution(bookId, AppointStateEnum.INNER_ERROR);//错误写法

 throw new AppointException("appoint inner error:" + e.getMessage());

 }

 }

 

}

下面我们来测试一下我们的业务代码吧~因为查询图书的业务不复杂,所以这里只演示我们最重要的预约图书业务!!

BookServiceImplTest.java

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

package com.soecode.lyf.service.impl;

 

import static org.junit.Assert.fail;

 

import org.junit.Test;

import org.springframework.beans.factory.annotation.Autowired;

 

import com.soecode.lyf.BaseTest;

import com.soecode.lyf.dto.AppointExecution;

import com.soecode.lyf.service.BookService;

 

public class BookServiceImplTest extends BaseTest {

 

 @Autowired

 private BookService bookService;

 

 @Test

 public void testAppoint() throws Exception {

 long bookId = 1001;

 long studentId = 12345678910L;

 AppointExecution execution = bookService.appoint(bookId, studentId);

 System.out.println(execution);

 }

 

}

BookServiceImplTest测试结果

testAppoint 

首次执行是“预约成功”,如果再次执行的话,应该会出现“重复预约”,哈哈,我们所有的后台代码都通过单元测试啦~~是不是很开心~

咱们还需要在dto包里新建一个封装json返回结果的类Result.java,设计成泛型。

Result.java

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

package com.soecode.lyf.dto;

 

/**

 * 封装json对象,所有返回结果都使用它

 */

public class Result<T> {

 

 private boolean success;// 是否成功标志

 

 private T data;// 成功时返回的数据

 

 private String error;// 错误信息

 

 public Result() {

 }

 

 // 成功时的构造器

 public Result(boolean success, T data) {

 this.success = success;

 this.data = data;

 }

 

 // 错误时的构造器

 public Result(boolean success, String error) {

 this.success = success;

 this.error = error;

 }

 

 // 省略getter和setter方法

}

最后,我们写web层,也就是controller,我们在web包下新建BookController.java文件。

BookController.java

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

package com.soecode.lyf.web;

 

import java.util.List;

 

import org.apache.ibatis.annotations.Param;

import org.slf4j.Logger;

import org.slf4j.LoggerFactory;

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.stereotype.Controller;

import org.springframework.ui.Model;

import org.springframework.web.bind.annotation.PathVariable;

import org.springframework.web.bind.annotation.RequestMapping;

import org.springframework.web.bind.annotation.RequestMethod;

import org.springframework.web.bind.annotation.ResponseBody;

 

import com.soecode.lyf.dto.AppointExecution;

import com.soecode.lyf.dto.Result;

import com.soecode.lyf.entity.Book;

import com.soecode.lyf.enums.AppointStateEnum;

import com.soecode.lyf.exception.NoNumberException;

import com.soecode.lyf.exception.RepeatAppointException;

import com.soecode.lyf.service.BookService;

 

@Controller

@RequestMapping("/book") // url:/模块/资源/{id}/细分 /seckill/list

public class BookController {

 

 private Logger logger = LoggerFactory.getLogger(this.getClass());

 

 @Autowired

 private BookService bookService;

 

 @RequestMapping(value = "/list", method = RequestMethod.GET)

 private String list(Model model) {

 List<Book> list = bookService.getList();

 model.addAttribute("list", list);

 // list.jsp + model = ModelAndView

 return "list";// WEB-INF/jsp/"list".jsp

 }

 

 @RequestMapping(value = "/{bookId}/detail", method = RequestMethod.GET)

 private String detail(@PathVariable("bookId") Long bookId, Model model) {

 if (bookId == null) {

 return "redirect:/book/list";

 }

 Book book = bookService.getById(bookId);

 if (book == null) {

 return "forward:/book/list";

 }

 model.addAttribute("book", book);

 return "detail";

 }

 

 //ajax json

 @RequestMapping(value = "/{bookId}/appoint", method = RequestMethod.POST, produces = {

 "application/json; charset=utf-8" })

 @ResponseBody

 private Result<AppointExecution> appoint(@PathVariable("bookId") Long bookId, @RequestParam("studentId") Long studentId) {

 if (studentId == null || studentId.equals("")) {

 return new Result<>(false, "学号不能为空");

 }

 //AppointExecution execution = bookService.appoint(bookId, studentId);//错误写法,不能统一返回,要处理异常(失败)情况

 AppointExecution execution = null;

 try {

 execution = bookService.appoint(bookId, studentId);

 } catch (NoNumberException e1) {

 execution = new AppointExecution(bookId, AppointStateEnum.NO_NUMBER);

 } catch (RepeatAppointException e2) {

 execution = new AppointExecution(bookId, AppointStateEnum.REPEAT_APPOINT);

 } catch (Exception e) {

 execution = new AppointExecution(bookId, AppointStateEnum.INNER_ERROR);

 }

 return new Result<AppointExecution>(true, execution);

 }

 

}

因为我比较懒,所以我们就不测试controller了,好讨厌写前端,呜呜呜~

到此,我们的SSM框架整合配置,与应用实例部分已经结束了,我把所有源码和jar包一起打包放在了我的GitHub上,需要的可以去下载,喜欢就给个star吧,这篇东西写了两个晚上也不容易啊。

补充更新

修改预约业务代码,失败时抛异常,成功时才返回结果,控制层根据捕获的异常返回相应信息给客户端,而不是业务层直接返回错误结果。上面的代码已经作了修改,而且错误示范也注释保留着,之前误人子弟了,还好有位网友前几天提出质疑,我也及时做了修改。

修改BookController几处错误 

1.detail方法不是返回json的,故不用加@ResponseBody注解 

2.appoint方法应该加上@ResponseBody注解 

3.另外studentId参数注解应该是@RequestParam 

4.至于controller测试,测试appoint方法可不必写jsp,用curl就行,比如 
curl -H “Accept: application/json; charset=utf-8” -d “studentId=1234567890” localhost:8080/book/1003/appoint

源码下载:

github下载地址:http://github.com/liyifeng1994/ssm

本地下载地址:http://xiazai.jb51.net/201707/yuanma/ssm-master(jb51.net).rar

总结

以上就是这篇文章的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,如果有疑问大家可以留言交流,谢谢大家对脚本之家的支持。

查看全文
如若内容造成侵权/违法违规/事实不符,请联系编程学习网邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!

相关文章

  1. Base64加密与解密的三种方法

    前言:加密与解密一直是程序猿经常需要面对的东东,下面了解一下常见的base64的三种加密与解密的方法。public static final String str="zhangtao";1. 基于JDKpublic static void JdkBase64(){try {//加密BASE64Encoder encoder = new BASE64Encoder();String enco…...

    2024/4/20 16:56:57
  2. "我才是世界上最好的编程语言" - 门口传来了一声大吼!

    周末的"Hello World咖啡馆"还是热闹非凡。 Ruby 一边喝咖啡一边和对面的Python聊天: “兄弟,我觉得这届程序员真的不行!” “此话怎讲?” “主要没眼光,你看我1995就诞生了,一直没什么程序员搭理我,他们就是发现不了我的好,就这么过了25年,整整二十五年啊,…...

    2024/5/5 19:24:28
  3. MyBatis入门到精通

    MyBatis是什么?开源的持久层框架,底层仍然是jdbc。 (了解) Jdbc:易掌握、性能好、代码繁琐 Hibernate:难掌握、性能不好(复杂的查询经常需要优化sql),代码简介,可以不写sql。 Mybatis:比较容易掌握,性能一般,代码简洁,需要些sql。编程步骤()Step1:导包(mybatis,…...

    2024/5/3 14:01:27
  4. Java base64加密解密 两种实现方式

    1、为什么要使用Base 64Base 64主要用途不是加密,而是把一些二进制数转成普通字符,方便在网络上传输。 由于一些二进制字符在传输协议中属于控制字符,不能直接传送,所以需要转换一下才可以。由于某些系统中只能使用ASCII字符,Base64就是用来将非ASCII字符的数据转换成ASCI…...

    2024/4/21 11:43:40
  5. HCIP-AI EI Developer V2.0 考试大纲

    最后更新时间:2019-06-12 13:58:041 华为HCIP-AI EI Developer V2.0认证考试 本文主要介绍HCIP-AI EI Developer V2.0考试大纲,其它认证项目的考试大纲可参考相应的培训教材或通过华为公司网站 https://support.huawei.com/learning获取。 华为企业AI开发高级工程师认证HCIP-A…...

    2024/5/5 18:56:21
  6. 送书首秀,中奖概率大

    首发公众号:Android程序员日记 作者:贤榆的榆 如果你觉得有帮助欢迎关注、赞赏、转发 阅读时间:2650字 4分钟前言 正如标题所言,这是本公众号第一次送书。借着送书这个活动也想再次介绍一下该公众号。虽然公众号的名字是Android程序员日记,但这里除了安卓技术分享,还有会…...

    2024/4/21 11:43:37
  7. base64加密原理详解

    base64加密原理详解声明:本文是在看了他人总结,并摘抄大部分图文,和少量自己的总结写成原作者地址链接:Base64算法原理Base64编码,是我们程序开发中经常使用到的编码方法。它是一种基于用64个可打印字符来表示二进制数据的表示方法。它通常用作存储、传输一些二进制数据编…...

    2024/4/21 11:43:36
  8. mybatis实战教程(mybatis in action),mybatis入门到精通(修改)

    MyBatis目录(?)[]这个mybatis教程也不错:http://limingnihao.iteye.com/blog/781671MyBatis目录(?)[-]mybatis实战教程mybatis in action之一开发环境搭建mybatis实战教程mybatis in action之二以接口的方式编程mybatis实战教程mybatis in action之三实现数据的增删改查myba…...

    2024/4/21 11:43:37
  9. 华为云计算2019.7.15 云计算HCIP

    华为HCIP-Cloud云计算课程全新而来 华为存储+虚拟化+Fusionstorage+FusionAccess教程内容:华为最新的云计算证书课程4.0版本及考试前几个月刚刚发布,而这套课程虽然没有冠名为4.0,但是大家通过下面的课程目录 基本上可以看到新增了非常多的与4.0考纲和版本技术相同的内容,完…...

    2024/4/21 11:43:34
  10. Base64加密和解密JDK8

    在 Java8中 Base64编码已经成为Java类库的标准,且内置了Base64编码的编码器和解码器。一、什么是Base64? -- 来自百度百科Base64是网络上最常见的用于传输 8Bit字节码的编码方式之一,Base64就是一种基于64个可打印字符来表示二进制数据的方法。1、什么是“可打印字符”呢?…...

    2024/4/21 11:43:33
  11. springboot-静态文件 js,css,html等

    静态页面spring boot项目只有src目录,没有webapp目录,会将静态访问(html/图片等)映射到其自动配置的静态目录,如下/static/public/resources/META-INF/resources比如,在resources建立一个static目录和index.htm静态文件,访问地址 http://localhost:8080/index.html 动…...

    2024/5/5 21:58:12
  12. base64加密原理

    今天面试被问到以前的项目有没有用到网络传输加密,当时脑袋抽风没想起来直接说了没有。回来后看书看到了base64几个字,顿时醒悟了过来。Shit!明明最近的项目就用到了base64方法加密的,只是做的比较久远了,后面又没怎么改动过,就把它忽略了。既然这样,那就白纸黑字记下来…...

    2024/4/26 0:14:59
  13. 求 HCDA认证题库

    小弟 想考个HCDA认证 从网上找不到完整的题库。 跪求 各位网络高手 给小弟一份 非常感谢。。。。...

    2024/4/20 17:25:53
  14. 简单方法,高效管理

    我认识了在北京IT公司的研发管理部的孙经理,当了两年程序员便升为经理。当我和他聊到项目的现状时,他感叹道:“我们的项目总是没法如期完成。每个程序员和测试人员看起来都很忙,但效率却很低。我怀疑他们常常在做与工作无关的事,但我唯一能做的也就是越过他们肩膀往前看了…...

    2024/4/20 16:57:13
  15. base64加密

    import org.apache.commons.codec.binary.Base64; public class Bae64 {public static void main(String[] args) {String string = "q12weassda12";String encode = encode(string.getBytes());System.out.println(string + "编码加密后的字符串为:" + e…...

    2024/4/20 16:57:12
  16. HCIE-Cloud云计算认证考试心得

    2016年8月26日,是一个值得铭记的日子,经过了一周的漫长等待,誉天邹老师终于等到了这张沉甸甸HCIE-Cloud成绩单。8月26日,誉天邹圣林老师在杭州一次通过HCIE-Cloud面试,成为亚太区首位云计算HCIE!(邹老师HCIE-Cloud成绩单)早在2014年6月,誉天邹老师成为全球首位华为HCI…...

    2024/4/20 16:57:09
  17. java web 之mybatis使用教程(三)

    前两篇文章介绍了mybatis如何使用,这篇文章简单解释下xml文件中各标签的意义。映射文件在此,咱们仅以前两篇博文中的代码为例,给出映射文件 Mapper.xml 的总结:① 设置 namespace 命名空间,目的是为了区分映射文件中的方法;② 结果集 resultMap 是 MyBatis 最大的特色,对…...

    2024/4/20 5:51:20
  18. PHP写的几个基础算法 (转载)

    这里是用PHP写的几个基础算法,算法的重要性貌似对于PHP程序员不怎么重要,其实是非常重要的,经典名句:算法+数据结构=程序。作为一名真正的高级PHP程序员,我认为应该熟悉C,如果你想成为真正的程序员,请好好学C,学好数据结构与算法。这里仅仅只是几个基础算法,还有很多东…...

    2024/4/20 16:57:06
  19. 华为云鲲鹏弹性云服务器高可用性架构实践(微认证)

    华为云鲲鹏弹性云服务器高可用性架构实践(微认证)思维导图自测题 100分(计分) 1. (判断题)ARM计算架构所用的指令集为CISC,是重核架构,高性能高功耗。 A.true B.false2. (单选题)华为云鲲鹏弹性云服务器绑定了( )后,可以通过固定的公网IP地址对外提供访问? A.镜像…...

    2024/4/20 16:57:05
  20. 关于base64前端加密,后端解密

    公司做的系统是给某公司内网的系统。做了一个渗透测试。提出一点漏洞,关于用户名和密码在传输中是用明文传输的,但后台接到后已经做了MD5加密进行校验而且还是内网,一般这个是没问题的。但提出了漏洞就改呗,加个密。思路是前端加密,后端解密。 前端 <script src="…...

    2024/4/20 16:57:10

最新文章

  1. 【银角大王——Django课程——靓号搜索实现/单独一篇】

    搜索框功能实现 靓号搜索在Django框架中搜索功能实现——底层就是模糊查询添加一个搜索框&#xff0c;使用bootstrap框架将GO&#xff01;修改成一个放大镜靓号列表函数代码解释效果演示 靓号搜索 在Django框架中搜索功能实现——底层就是模糊查询 数字条件用法字符串条件用法…...

    2024/5/6 1:26:06
  2. 梯度消失和梯度爆炸的一些处理方法

    在这里是记录一下梯度消失或梯度爆炸的一些处理技巧。全当学习总结了如有错误还请留言&#xff0c;在此感激不尽。 权重和梯度的更新公式如下&#xff1a; w w − η ⋅ ∇ w w w - \eta \cdot \nabla w ww−η⋅∇w 个人通俗的理解梯度消失就是网络模型在反向求导的时候出…...

    2024/3/20 10:50:27
  3. 【Java】假如把集合体系看作购物中心

    购物中心入口&#xff1a;Java集合框架 “Java集合广场”的购物中心&#xff0c;这是一个集合了各种奇特商店的地方&#xff0c;每个商店都充满了不同的宝藏&#xff08;数据结构&#xff09;。 一楼&#xff1a;基础集合区 - Collection接口 一楼是基础集合区&#xff0c;这…...

    2024/5/5 15:55:12
  4. ASP.NET Core 标识(Identity)框架系列(一):如何使用 ASP.NET Core 标识(Identity)框架创建用户和角色?

    前言 ASP.NET Core 内置的标识&#xff08;identity&#xff09;框架&#xff0c;采用的是 RBAC&#xff08;role-based access control&#xff0c;基于角色的访问控制&#xff09;策略&#xff0c;是一个用于管理用户身份验证、授权和安全性的框架。 它提供了一套工具和库&…...

    2024/5/5 15:45:29
  5. 【外汇早评】美通胀数据走低,美元调整

    原标题:【外汇早评】美通胀数据走低,美元调整昨日美国方面公布了新一期的核心PCE物价指数数据,同比增长1.6%,低于前值和预期值的1.7%,距离美联储的通胀目标2%继续走低,通胀压力较低,且此前美国一季度GDP初值中的消费部分下滑明显,因此市场对美联储后续更可能降息的政策…...

    2024/5/4 23:54:56
  6. 【原油贵金属周评】原油多头拥挤,价格调整

    原标题:【原油贵金属周评】原油多头拥挤,价格调整本周国际劳动节,我们喜迎四天假期,但是整个金融市场确实流动性充沛,大事频发,各个商品波动剧烈。美国方面,在本周四凌晨公布5月份的利率决议和新闻发布会,维持联邦基金利率在2.25%-2.50%不变,符合市场预期。同时美联储…...

    2024/5/4 23:54:56
  7. 【外汇周评】靓丽非农不及疲软通胀影响

    原标题:【外汇周评】靓丽非农不及疲软通胀影响在刚结束的周五,美国方面公布了新一期的非农就业数据,大幅好于前值和预期,新增就业重新回到20万以上。具体数据: 美国4月非农就业人口变动 26.3万人,预期 19万人,前值 19.6万人。 美国4月失业率 3.6%,预期 3.8%,前值 3…...

    2024/5/4 23:54:56
  8. 【原油贵金属早评】库存继续增加,油价收跌

    原标题:【原油贵金属早评】库存继续增加,油价收跌周三清晨公布美国当周API原油库存数据,上周原油库存增加281万桶至4.692亿桶,增幅超过预期的74.4万桶。且有消息人士称,沙特阿美据悉将于6月向亚洲炼油厂额外出售更多原油,印度炼油商预计将每日获得至多20万桶的额外原油供…...

    2024/5/4 23:55:17
  9. 【外汇早评】日本央行会议纪要不改日元强势

    原标题:【外汇早评】日本央行会议纪要不改日元强势近两日日元大幅走强与近期市场风险情绪上升,避险资金回流日元有关,也与前一段时间的美日贸易谈判给日本缓冲期,日本方面对汇率问题也避免继续贬值有关。虽然今日早间日本央行公布的利率会议纪要仍然是支持宽松政策,但这符…...

    2024/5/4 23:54:56
  10. 【原油贵金属早评】欧佩克稳定市场,填补伊朗问题的影响

    原标题:【原油贵金属早评】欧佩克稳定市场,填补伊朗问题的影响近日伊朗局势升温,导致市场担忧影响原油供给,油价试图反弹。此时OPEC表态稳定市场。据消息人士透露,沙特6月石油出口料将低于700万桶/日,沙特已经收到石油消费国提出的6月份扩大出口的“适度要求”,沙特将满…...

    2024/5/4 23:55:05
  11. 【外汇早评】美欲与伊朗重谈协议

    原标题:【外汇早评】美欲与伊朗重谈协议美国对伊朗的制裁遭到伊朗的抗议,昨日伊朗方面提出将部分退出伊核协议。而此行为又遭到欧洲方面对伊朗的谴责和警告,伊朗外长昨日回应称,欧洲国家履行它们的义务,伊核协议就能保证存续。据传闻伊朗的导弹已经对准了以色列和美国的航…...

    2024/5/4 23:54:56
  12. 【原油贵金属早评】波动率飙升,市场情绪动荡

    原标题:【原油贵金属早评】波动率飙升,市场情绪动荡因中美贸易谈判不安情绪影响,金融市场各资产品种出现明显的波动。随着美国与中方开启第十一轮谈判之际,美国按照既定计划向中国2000亿商品征收25%的关税,市场情绪有所平复,已经开始接受这一事实。虽然波动率-恐慌指数VI…...

    2024/5/4 23:55:16
  13. 【原油贵金属周评】伊朗局势升温,黄金多头跃跃欲试

    原标题:【原油贵金属周评】伊朗局势升温,黄金多头跃跃欲试美国和伊朗的局势继续升温,市场风险情绪上升,避险黄金有向上突破阻力的迹象。原油方面稍显平稳,近期美国和OPEC加大供给及市场需求回落的影响,伊朗局势并未推升油价走强。近期中美贸易谈判摩擦再度升级,美国对中…...

    2024/5/4 23:54:56
  14. 【原油贵金属早评】市场情绪继续恶化,黄金上破

    原标题:【原油贵金属早评】市场情绪继续恶化,黄金上破周初中国针对于美国加征关税的进行的反制措施引发市场情绪的大幅波动,人民币汇率出现大幅的贬值动能,金融市场受到非常明显的冲击。尤其是波动率起来之后,对于股市的表现尤其不安。隔夜美国股市出现明显的下行走势,这…...

    2024/5/4 18:20:48
  15. 【外汇早评】美伊僵持,风险情绪继续升温

    原标题:【外汇早评】美伊僵持,风险情绪继续升温昨日沙特两艘油轮再次发生爆炸事件,导致波斯湾局势进一步恶化,市场担忧美伊可能会出现摩擦生火,避险品种获得支撑,黄金和日元大幅走强。美指受中美贸易问题影响而在低位震荡。继5月12日,四艘商船在阿联酋领海附近的阿曼湾、…...

    2024/5/4 23:54:56
  16. 【原油贵金属早评】贸易冲突导致需求低迷,油价弱势

    原标题:【原油贵金属早评】贸易冲突导致需求低迷,油价弱势近日虽然伊朗局势升温,中东地区几起油船被袭击事件影响,但油价并未走高,而是出于调整结构中。由于市场预期局势失控的可能性较低,而中美贸易问题导致的全球经济衰退风险更大,需求会持续低迷,因此油价调整压力较…...

    2024/5/4 23:55:17
  17. 氧生福地 玩美北湖(上)——为时光守候两千年

    原标题:氧生福地 玩美北湖(上)——为时光守候两千年一次说走就走的旅行,只有一张高铁票的距离~ 所以,湖南郴州,我来了~ 从广州南站出发,一个半小时就到达郴州西站了。在动车上,同时改票的南风兄和我居然被分到了一个车厢,所以一路非常愉快地聊了过来。 挺好,最起…...

    2024/5/4 23:55:06
  18. 氧生福地 玩美北湖(中)——永春梯田里的美与鲜

    原标题:氧生福地 玩美北湖(中)——永春梯田里的美与鲜一觉醒来,因为大家太爱“美”照,在柳毅山庄去寻找龙女而错过了早餐时间。近十点,向导坏坏还是带着饥肠辘辘的我们去吃郴州最富有盛名的“鱼头粉”。说这是“十二分推荐”,到郴州必吃的美食之一。 哇塞!那个味美香甜…...

    2024/5/4 23:54:56
  19. 氧生福地 玩美北湖(下)——奔跑吧骚年!

    原标题:氧生福地 玩美北湖(下)——奔跑吧骚年!让我们红尘做伴 活得潇潇洒洒 策马奔腾共享人世繁华 对酒当歌唱出心中喜悦 轰轰烈烈把握青春年华 让我们红尘做伴 活得潇潇洒洒 策马奔腾共享人世繁华 对酒当歌唱出心中喜悦 轰轰烈烈把握青春年华 啊……啊……啊 两…...

    2024/5/4 23:55:06
  20. 扒开伪装医用面膜,翻六倍价格宰客,小姐姐注意了!

    原标题:扒开伪装医用面膜,翻六倍价格宰客,小姐姐注意了!扒开伪装医用面膜,翻六倍价格宰客!当行业里的某一品项火爆了,就会有很多商家蹭热度,装逼忽悠,最近火爆朋友圈的医用面膜,被沾上了污点,到底怎么回事呢? “比普通面膜安全、效果好!痘痘、痘印、敏感肌都能用…...

    2024/5/5 8:13:33
  21. 「发现」铁皮石斛仙草之神奇功效用于医用面膜

    原标题:「发现」铁皮石斛仙草之神奇功效用于医用面膜丽彦妆铁皮石斛医用面膜|石斛多糖无菌修护补水贴19大优势: 1、铁皮石斛:自唐宋以来,一直被列为皇室贡品,铁皮石斛生于海拔1600米的悬崖峭壁之上,繁殖力差,产量极低,所以古代仅供皇室、贵族享用 2、铁皮石斛自古民间…...

    2024/5/4 23:55:16
  22. 丽彦妆\医用面膜\冷敷贴轻奢医学护肤引导者

    原标题:丽彦妆\医用面膜\冷敷贴轻奢医学护肤引导者【公司简介】 广州华彬企业隶属香港华彬集团有限公司,专注美业21年,其旗下品牌: 「圣茵美」私密荷尔蒙抗衰,产后修复 「圣仪轩」私密荷尔蒙抗衰,产后修复 「花茵莳」私密荷尔蒙抗衰,产后修复 「丽彦妆」专注医学护…...

    2024/5/4 23:54:58
  23. 广州械字号面膜生产厂家OEM/ODM4项须知!

    原标题:广州械字号面膜生产厂家OEM/ODM4项须知!广州械字号面膜生产厂家OEM/ODM流程及注意事项解读: 械字号医用面膜,其实在我国并没有严格的定义,通常我们说的医美面膜指的应该是一种「医用敷料」,也就是说,医用面膜其实算作「医疗器械」的一种,又称「医用冷敷贴」。 …...

    2024/5/4 23:55:01
  24. 械字号医用眼膜缓解用眼过度到底有无作用?

    原标题:械字号医用眼膜缓解用眼过度到底有无作用?医用眼膜/械字号眼膜/医用冷敷眼贴 凝胶层为亲水高分子材料,含70%以上的水分。体表皮肤温度传导到本产品的凝胶层,热量被凝胶内水分子吸收,通过水分的蒸发带走大量的热量,可迅速地降低体表皮肤局部温度,减轻局部皮肤的灼…...

    2024/5/4 23:54:56
  25. 配置失败还原请勿关闭计算机,电脑开机屏幕上面显示,配置失败还原更改 请勿关闭计算机 开不了机 这个问题怎么办...

    解析如下&#xff1a;1、长按电脑电源键直至关机&#xff0c;然后再按一次电源健重启电脑&#xff0c;按F8健进入安全模式2、安全模式下进入Windows系统桌面后&#xff0c;按住“winR”打开运行窗口&#xff0c;输入“services.msc”打开服务设置3、在服务界面&#xff0c;选中…...

    2022/11/19 21:17:18
  26. 错误使用 reshape要执行 RESHAPE,请勿更改元素数目。

    %读入6幅图像&#xff08;每一幅图像的大小是564*564&#xff09; f1 imread(WashingtonDC_Band1_564.tif); subplot(3,2,1),imshow(f1); f2 imread(WashingtonDC_Band2_564.tif); subplot(3,2,2),imshow(f2); f3 imread(WashingtonDC_Band3_564.tif); subplot(3,2,3),imsho…...

    2022/11/19 21:17:16
  27. 配置 已完成 请勿关闭计算机,win7系统关机提示“配置Windows Update已完成30%请勿关闭计算机...

    win7系统关机提示“配置Windows Update已完成30%请勿关闭计算机”问题的解决方法在win7系统关机时如果有升级系统的或者其他需要会直接进入一个 等待界面&#xff0c;在等待界面中我们需要等待操作结束才能关机&#xff0c;虽然这比较麻烦&#xff0c;但是对系统进行配置和升级…...

    2022/11/19 21:17:15
  28. 台式电脑显示配置100%请勿关闭计算机,“准备配置windows 请勿关闭计算机”的解决方法...

    有不少用户在重装Win7系统或更新系统后会遇到“准备配置windows&#xff0c;请勿关闭计算机”的提示&#xff0c;要过很久才能进入系统&#xff0c;有的用户甚至几个小时也无法进入&#xff0c;下面就教大家这个问题的解决方法。第一种方法&#xff1a;我们首先在左下角的“开始…...

    2022/11/19 21:17:14
  29. win7 正在配置 请勿关闭计算机,怎么办Win7开机显示正在配置Windows Update请勿关机...

    置信有很多用户都跟小编一样遇到过这样的问题&#xff0c;电脑时发现开机屏幕显现“正在配置Windows Update&#xff0c;请勿关机”(如下图所示)&#xff0c;而且还需求等大约5分钟才干进入系统。这是怎样回事呢&#xff1f;一切都是正常操作的&#xff0c;为什么开时机呈现“正…...

    2022/11/19 21:17:13
  30. 准备配置windows 请勿关闭计算机 蓝屏,Win7开机总是出现提示“配置Windows请勿关机”...

    Win7系统开机启动时总是出现“配置Windows请勿关机”的提示&#xff0c;没过几秒后电脑自动重启&#xff0c;每次开机都这样无法进入系统&#xff0c;此时碰到这种现象的用户就可以使用以下5种方法解决问题。方法一&#xff1a;开机按下F8&#xff0c;在出现的Windows高级启动选…...

    2022/11/19 21:17:12
  31. 准备windows请勿关闭计算机要多久,windows10系统提示正在准备windows请勿关闭计算机怎么办...

    有不少windows10系统用户反映说碰到这样一个情况&#xff0c;就是电脑提示正在准备windows请勿关闭计算机&#xff0c;碰到这样的问题该怎么解决呢&#xff0c;现在小编就给大家分享一下windows10系统提示正在准备windows请勿关闭计算机的具体第一种方法&#xff1a;1、2、依次…...

    2022/11/19 21:17:11
  32. 配置 已完成 请勿关闭计算机,win7系统关机提示“配置Windows Update已完成30%请勿关闭计算机”的解决方法...

    今天和大家分享一下win7系统重装了Win7旗舰版系统后&#xff0c;每次关机的时候桌面上都会显示一个“配置Windows Update的界面&#xff0c;提示请勿关闭计算机”&#xff0c;每次停留好几分钟才能正常关机&#xff0c;导致什么情况引起的呢&#xff1f;出现配置Windows Update…...

    2022/11/19 21:17:10
  33. 电脑桌面一直是清理请关闭计算机,windows7一直卡在清理 请勿关闭计算机-win7清理请勿关机,win7配置更新35%不动...

    只能是等着&#xff0c;别无他法。说是卡着如果你看硬盘灯应该在读写。如果从 Win 10 无法正常回滚&#xff0c;只能是考虑备份数据后重装系统了。解决来方案一&#xff1a;管理员运行cmd&#xff1a;net stop WuAuServcd %windir%ren SoftwareDistribution SDoldnet start WuA…...

    2022/11/19 21:17:09
  34. 计算机配置更新不起,电脑提示“配置Windows Update请勿关闭计算机”怎么办?

    原标题&#xff1a;电脑提示“配置Windows Update请勿关闭计算机”怎么办&#xff1f;win7系统中在开机与关闭的时候总是显示“配置windows update请勿关闭计算机”相信有不少朋友都曾遇到过一次两次还能忍但经常遇到就叫人感到心烦了遇到这种问题怎么办呢&#xff1f;一般的方…...

    2022/11/19 21:17:08
  35. 计算机正在配置无法关机,关机提示 windows7 正在配置windows 请勿关闭计算机 ,然后等了一晚上也没有关掉。现在电脑无法正常关机...

    关机提示 windows7 正在配置windows 请勿关闭计算机 &#xff0c;然后等了一晚上也没有关掉。现在电脑无法正常关机以下文字资料是由(历史新知网www.lishixinzhi.com)小编为大家搜集整理后发布的内容&#xff0c;让我们赶快一起来看一下吧&#xff01;关机提示 windows7 正在配…...

    2022/11/19 21:17:05
  36. 钉钉提示请勿通过开发者调试模式_钉钉请勿通过开发者调试模式是真的吗好不好用...

    钉钉请勿通过开发者调试模式是真的吗好不好用 更新时间:2020-04-20 22:24:19 浏览次数:729次 区域: 南阳 > 卧龙 列举网提醒您:为保障您的权益,请不要提前支付任何费用! 虚拟位置外设器!!轨迹模拟&虚拟位置外设神器 专业用于:钉钉,外勤365,红圈通,企业微信和…...

    2022/11/19 21:17:05
  37. 配置失败还原请勿关闭计算机怎么办,win7系统出现“配置windows update失败 还原更改 请勿关闭计算机”,长时间没反应,无法进入系统的解决方案...

    前几天班里有位学生电脑(windows 7系统)出问题了&#xff0c;具体表现是开机时一直停留在“配置windows update失败 还原更改 请勿关闭计算机”这个界面&#xff0c;长时间没反应&#xff0c;无法进入系统。这个问题原来帮其他同学也解决过&#xff0c;网上搜了不少资料&#x…...

    2022/11/19 21:17:04
  38. 一个电脑无法关闭计算机你应该怎么办,电脑显示“清理请勿关闭计算机”怎么办?...

    本文为你提供了3个有效解决电脑显示“清理请勿关闭计算机”问题的方法&#xff0c;并在最后教给你1种保护系统安全的好方法&#xff0c;一起来看看&#xff01;电脑出现“清理请勿关闭计算机”在Windows 7(SP1)和Windows Server 2008 R2 SP1中&#xff0c;添加了1个新功能在“磁…...

    2022/11/19 21:17:03
  39. 请勿关闭计算机还原更改要多久,电脑显示:配置windows更新失败,正在还原更改,请勿关闭计算机怎么办...

    许多用户在长期不使用电脑的时候&#xff0c;开启电脑发现电脑显示&#xff1a;配置windows更新失败&#xff0c;正在还原更改&#xff0c;请勿关闭计算机。。.这要怎么办呢&#xff1f;下面小编就带着大家一起看看吧&#xff01;如果能够正常进入系统&#xff0c;建议您暂时移…...

    2022/11/19 21:17:02
  40. 还原更改请勿关闭计算机 要多久,配置windows update失败 还原更改 请勿关闭计算机,电脑开机后一直显示以...

    配置windows update失败 还原更改 请勿关闭计算机&#xff0c;电脑开机后一直显示以以下文字资料是由(历史新知网www.lishixinzhi.com)小编为大家搜集整理后发布的内容&#xff0c;让我们赶快一起来看一下吧&#xff01;配置windows update失败 还原更改 请勿关闭计算机&#x…...

    2022/11/19 21:17:01
  41. 电脑配置中请勿关闭计算机怎么办,准备配置windows请勿关闭计算机一直显示怎么办【图解】...

    不知道大家有没有遇到过这样的一个问题&#xff0c;就是我们的win7系统在关机的时候&#xff0c;总是喜欢显示“准备配置windows&#xff0c;请勿关机”这样的一个页面&#xff0c;没有什么大碍&#xff0c;但是如果一直等着的话就要两个小时甚至更久都关不了机&#xff0c;非常…...

    2022/11/19 21:17:00
  42. 正在准备配置请勿关闭计算机,正在准备配置windows请勿关闭计算机时间长了解决教程...

    当电脑出现正在准备配置windows请勿关闭计算机时&#xff0c;一般是您正对windows进行升级&#xff0c;但是这个要是长时间没有反应&#xff0c;我们不能再傻等下去了。可能是电脑出了别的问题了&#xff0c;来看看教程的说法。正在准备配置windows请勿关闭计算机时间长了方法一…...

    2022/11/19 21:16:59
  43. 配置失败还原请勿关闭计算机,配置Windows Update失败,还原更改请勿关闭计算机...

    我们使用电脑的过程中有时会遇到这种情况&#xff0c;当我们打开电脑之后&#xff0c;发现一直停留在一个界面&#xff1a;“配置Windows Update失败&#xff0c;还原更改请勿关闭计算机”&#xff0c;等了许久还是无法进入系统。如果我们遇到此类问题应该如何解决呢&#xff0…...

    2022/11/19 21:16:58
  44. 如何在iPhone上关闭“请勿打扰”

    Apple’s “Do Not Disturb While Driving” is a potentially lifesaving iPhone feature, but it doesn’t always turn on automatically at the appropriate time. For example, you might be a passenger in a moving car, but your iPhone may think you’re the one dri…...

    2022/11/19 21:16:57