diff --git a/3103085836@qq.com b/3103085836@qq.com
new file mode 100644
index 0000000..8b23b2c
--- /dev/null
+++ b/3103085836@qq.com
@@ -0,0 +1,49 @@
+-----BEGIN OPENSSH PRIVATE KEY-----
+b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAACFwAAAAdzc2gtcn
+NhAAAAAwEAAQAAAgEA1PZ8qk5AuMiF7Tsbd6D5jVo7rQqCwjmdA5lB3AxTae/cVwO1VQPp
+M44kLI9i7rI5MAP4zfIc8sKJpVRyFwzdghKOJfj16kNgTAH9h0VFVqI9RQ3Z1i7ELXp60O
+14zdpolx0zRxts+WBYE1sl7KwlKvigG9YuMK4nfCjtoXuuo/nMU6NUMb0xooBfWpULoXNQ
+LkNxUYaNIsctrs2VDWDIqdQ7XsAaa0vzb2GTVorNbXG4PB8KR+FfeVF5GcVdBrLPz1li9u
+GxC9Q4zK3UD7dJyvQXcT04eQ8s/cy5bAZH0zN7Gxy6kaMNfNNeD/Rcus1WgfDWjJUB4T6s
+/P3srwCSd5ql3D9bb0rdyJwf8ubckBI6xLHsPdW0nia2lK2lXpJlcLby0FupSpO/ZsV7Bv
+O+aE/gGMB/rytjtqj0wKPy588lK16wOcM8tJRnJH8QprRg2FbXsRcxJmWe7LrNESfmDJZM
+wbMc5Sfkadi8RQ+WaqJl/xh9YORbQlOKgoupYil9XQcj8Xz0mpGvdpErxOJFWPAFuSOYqb
+hCWeQGP6jBzu/1mBqZL8qPSDr+ct2bIvA+L9nSkYI4CUoZIBb1ktKJehwarE2lR9iwFiFm
+9xSmiahiVJtjJI0SsJUeWzPFzrMbjIi4yv4NT8GeqAbeCIJDWSFIIUCbb9ou3CRJOvgOk5
+MAAAdAnwm1up8JtboAAAAHc3NoLXJzYQAAAgEA1PZ8qk5AuMiF7Tsbd6D5jVo7rQqCwjmd
+A5lB3AxTae/cVwO1VQPpM44kLI9i7rI5MAP4zfIc8sKJpVRyFwzdghKOJfj16kNgTAH9h0
+VFVqI9RQ3Z1i7ELXp60O14zdpolx0zRxts+WBYE1sl7KwlKvigG9YuMK4nfCjtoXuuo/nM
+U6NUMb0xooBfWpULoXNQLkNxUYaNIsctrs2VDWDIqdQ7XsAaa0vzb2GTVorNbXG4PB8KR+
+FfeVF5GcVdBrLPz1li9uGxC9Q4zK3UD7dJyvQXcT04eQ8s/cy5bAZH0zN7Gxy6kaMNfNNe
+D/Rcus1WgfDWjJUB4T6s/P3srwCSd5ql3D9bb0rdyJwf8ubckBI6xLHsPdW0nia2lK2lXp
+JlcLby0FupSpO/ZsV7BvO+aE/gGMB/rytjtqj0wKPy588lK16wOcM8tJRnJH8QprRg2FbX
+sRcxJmWe7LrNESfmDJZMwbMc5Sfkadi8RQ+WaqJl/xh9YORbQlOKgoupYil9XQcj8Xz0mp
+GvdpErxOJFWPAFuSOYqbhCWeQGP6jBzu/1mBqZL8qPSDr+ct2bIvA+L9nSkYI4CUoZIBb1
+ktKJehwarE2lR9iwFiFm9xSmiahiVJtjJI0SsJUeWzPFzrMbjIi4yv4NT8GeqAbeCIJDWS
+FIIUCbb9ou3CRJOvgOk5MAAAADAQABAAACAQCYZgfSjAtO8Ni+asT+N+k92WvJKjNmsHoH
+YD48LWnn7qlcb5/tRc41gaurY7Tlog7AqKb9IhzLMKH1+Vdn3WIKuiKVU/MPgMXBvs7iZZ
+T4KUP1TbMszey/qt2G89m2XmzobxIJ+btjPinpOBoMoyg59xAEu6H0XjyNYnCjVfIlEBbD
+Z6dRrNV/N6SFGxHmqLGhWcwXDlWjpKuxYxceKruOpP0Tkh+V1xVPCKG6lbvqbS3tgD0IMW
+T0WXRzF8S5jW6fMJVcnSfokidPebm+wWiCX2kDNU9bepu0yDOM9XWi0z1uqoFsxSVaxZuT
+iUhuuZEFjgbLNbrRqNt8dG5S0fL9a/A9sssFVOoiU6VYSPB3W9mPUqJlTURDc8IHN6nLJu
+1323/g1GTj7R+v0DjNcdcu3fsADALwAeCQOO3ckba4sQuofwpeJmWVESQr//FjgiY0JCgJ
+4n9g5PCAC169yJTrrCuxbp35iWs5THHP+b39Xy0jPYeZtpXbSATl7TQNZTO+WPZmLE0TlA
+jjFZpRHlFVOYxQHyJo3iKwESD5xcYLuWATH/JQbSsIO6NQ+dlvuSAKJrKbIXh2Ntr01ahd
+bCiQZKRNQeNfyajy/jeYTCHJGNDhCS5g2yEUaPkyMNmFH3V+Ow4wjs5+LfjgdwVNJeS5Ls
+cevPcSBNnnEvfWbEWPQQAAAQEAurTDCIq6SQJSkF2Edbi9G/Ae5tCb3M3zb6VJptHUgxT0
+uCg8LRZiX9rtmROioz5lHw7KMvt5ExTphaXEz0cHkxjsp3XC2gh8/JyVVRbaSy9x58Gg14
+X5KgFMibWQzUH63RP1s3r50aKQkgbB1fOkuEO0AIjWv0hFaDTOzzd6rAALn++XfsH5vDUw
+8SJLCx9TI8DdgyHRqd74C7EhGm8ZG+ugl033+ei2/RQ3yTXFY5JmqhyQKWC9RxKii4nyT4
+XlQwP/Encwx+RZ88QdvLO6jVWf00dZpV1W/gjqQECJ2jIlPzbBjoByJnZ89kh9DGgJOVwu
+aAZnbmBxszVoUefV0QAAAQEA8vZeJBXZsW8slc8f7VPqJByTxLtgyXxaUliRiQQM4ZY+q1
+j+HxmjsLCZUHBuM3zIDp1JFEyEUUqbdsftnbkuAiBUjuAA3/8nJCKMAvyH+UirzAoR15iA
+qoafbbuPJ2rDqQsjdbJ+dt0jKR0PI8ZjmPWzK0vJ7mjVg+Gg0ooB3ZyNRoah+7VeZ4qZzN
+QOm/LnBmr38yA8qjjSsj/AMn8aLOZe8rqZF7buXHkYo5SbncKYtBvzCMRmLxr9ln2pDsrO
+7TSA3XUm8w0Fn7tKf59APZGbMfXoVJ+2YgoPb7/yvOXlO8M7meyKPRedXleknzw4+WKiYa
+PfaW0XlLihnLFO8wAAAQEA4GQCKi48zj8QdN0kRc1FcuGGI4KkxaSsTk2LQ6w8uHFFhuqI
+6+QTznnNGlbFvJyxQH33GuYssqxjUos0huziO8gavU3gcbnj1+ALCtr/2rptbmxckcdSOt
+bFtMmJQSftF4JFbulT4+GoTCOyrxYofcjdU9N2GWyjEdlU/vnArSo50wcME8Ie2gbHm2P2
+ZeytsIsg72QMnEMJxOYuBwLWptcE+NSzgvii2KIz81MCsWncDUhCXdsGCMVsGJBk7aDUTR
+6GMNwsKGV2GC/EmehvEoo7xxv9ei/JBfSoSaZE+ou264LXEpq+H9ExiNmvwmtSdubV6Cpt
+TeTGGc7qw9MQ4QAAAAQuY29tAQIDBAU=
+-----END OPENSSH PRIVATE KEY-----
diff --git a/3103085836@qq.com.pub b/3103085836@qq.com.pub
new file mode 100644
index 0000000..f944d90
--- /dev/null
+++ b/3103085836@qq.com.pub
@@ -0,0 +1 @@
+ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQDU9nyqTkC4yIXtOxt3oPmNWjutCoLCOZ0DmUHcDFNp79xXA7VVA+kzjiQsj2LusjkwA/jN8hzywomlVHIXDN2CEo4l+PXqQ2BMAf2HRUVWoj1FDdnWLsQtenrQ7XjN2miXHTNHG2z5YFgTWyXsrCUq+KAb1i4wrid8KO2he66j+cxTo1QxvTGigF9alQuhc1AuQ3FRho0ixy2uzZUNYMip1DtewBprS/NvYZNWis1tcbg8HwpH4V95UXkZxV0Gss/PWWL24bEL1DjMrdQPt0nK9BdxPTh5Dyz9zLlsBkfTM3sbHLqRow18014P9Fy6zVaB8NaMlQHhPqz8/eyvAJJ3mqXcP1tvSt3InB/y5tyQEjrEsew91bSeJraUraVekmVwtvLQW6lKk79mxXsG875oT+AYwH+vK2O2qPTAo/LnzyUrXrA5wzy0lGckfxCmtGDYVtexFzEmZZ7sus0RJ+YMlkzBsxzlJ+Rp2LxFD5ZqomX/GH1g5FtCU4qCi6liKX1dByPxfPSaka92kSvE4kVY8AW5I5ipuEJZ5AY/qMHO7/WYGpkvyo9IOv5y3Zsi8D4v2dKRgjgJShkgFvWS0ol6HBqsTaVH2LAWIWb3FKaJqGJUm2MkjRKwlR5bM8XOsxuMiLjK/g1PwZ6oBt4IgkNZIUghQJtv2i7cJEk6+A6Tkw== .com
diff --git a/tamguo-oms/src/main/java/com/tamguo/Application.java b/tamguo-oms/src/main/java/com/tamguo/Application.java
index 46b8e8a..5823901 100644
--- a/tamguo-oms/src/main/java/com/tamguo/Application.java
+++ b/tamguo-oms/src/main/java/com/tamguo/Application.java
@@ -10,26 +10,58 @@ import com.alibaba.fastjson.serializer.SerializerFeature;
import com.alibaba.fastjson.support.config.FastJsonConfig;
import com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter;
+// @SpringBootApplication是一个组合注解,它整合了多个Spring相关的注解,例如:
+// @Configuration:表明这个类可以作为一个配置类,用于定义Spring容器中的Bean等配置信息。
+// @EnableAutoConfiguration:启用Spring Boot的自动配置功能,会根据项目依赖等情况自动配置很多默认的组件,比如数据源、Web相关配置等,大大简化了项目的配置过程。
+// @ComponentScan:用于指定Spring要扫描的组件所在的包路径,默认会扫描当前类所在的包及其子包下的所有标注了Spring相关组件注解(如@Component、@Service、@Controller等)的类,并将它们注册到Spring容器中,以便进行依赖注入等操作。
+// 这个注解标注在类上,意味着这是一个Spring Boot应用的主启动类,整个应用从这里开始启动并加载相关配置。
@SpringBootApplication
public class Application {
+ /**
+ * 这是Java应用程序的入口方法,在Spring Boot应用中,通过调用SpringApplicationBuilder来构建并启动Spring Boot应用。
+ * SpringApplicationBuilder允许以编程方式对Spring Boot应用的启动过程进行更多的定制化配置(虽然这里只是简单传入Application类本身作为参数启动应用),
+ * 它会根据配置类(这里就是标注了@SpringBootApplication注解的Application类)以及相关依赖、配置等信息,初始化Spring容器,加载各种自动配置的组件,最终启动整个应用程序。
+ *
+ * @param args 命令行参数,可以在启动应用时传入一些自定义的参数,在应用中可以通过相应的方式获取并使用这些参数来进行一些初始化操作或者配置调整等,不过这里暂时没有对传入的参数进行额外处理。
+ */
public static void main(String[] args) {
new SpringApplicationBuilder(Application.class).run(args);
}
-
+
/**
- * FastJson替代Jackson
- * @return
+ * 自定义方法,用于创建并配置一个基于FastJSON的HttpMessageConverter,目的是让Spring Boot应用在处理HTTP消息(比如请求和响应的JSON数据转换)时,使用FastJSON替代默认的Jackson进行JSON序列化和反序列化操作。
+ * 通过将这个方法标记为@Bean注解,Spring会将该方法返回的对象作为一个Bean注册到Spring容器中,以便在需要进行HTTP消息转换时能够自动使用它。
+ *
+ * @return 返回一个HttpMessageConverters对象,其中包含了配置好的FastJsonHttpMessageConverter,用于在Spring Boot应用的Web相关处理中进行JSON格式的数据转换。
*/
@Bean
public HttpMessageConverters fastJsonHttpMessageConverters() {
+ // 创建一个FastJsonHttpMessageConverter实例,它是Spring中用于将对象转换为JSON格式以及将JSON数据反序列化为对象的一个实现类,
+ // 这里我们要使用FastJSON的功能,所以创建它的实例来进行后续配置,使其能按照我们期望的方式处理JSON数据转换。
FastJsonHttpMessageConverter fastConverter = new FastJsonHttpMessageConverter();
+
+ // 创建一个FastJsonConfig对象,用于配置FastJSON的各种序列化和反序列化相关的参数、特性等,以便让FastJSON按照我们的业务需求来处理JSON数据。
FastJsonConfig fastJsonConfig = new FastJsonConfig();
+
+ // 设置FastJSON序列化日期类型数据时的日期格式,这里指定为"yyyy-MM-dd HH:mm:ss",这样在将包含日期属性的Java对象序列化为JSON字符串时,日期字段会按照这个格式进行展示,
+ // 使得前端或者其他调用方接收到的日期格式更加规范和统一,便于处理和展示。
fastJsonConfig.setDateFormat("yyyy-MM-dd HH:mm:ss");
+
+ // 设置FastJSON的序列化特性,SerializerFeature.DisableCircularReferenceDetect表示禁用循环引用检测,
+ // 当Java对象之间存在复杂的相互引用关系时,如果不进行处理,在序列化过程中可能会陷入死循环或者生成不符合预期的JSON结构,
+ // 通过禁用这个检测(具体根据业务场景,如果确定不会出现循环引用问题或者有其他处理方式时可以这样设置),可以按照一定的规则来处理这种引用关系,生成期望的JSON数据。
fastJsonConfig.setSerializerFeatures(SerializerFeature.DisableCircularReferenceDetect);
+
+ // 将配置好的FastJsonConfig对象设置到FastJsonHttpMessageConverter中,这样FastJsonHttpMessageConverter在进行JSON序列化和反序列化操作时,
+ // 就会按照我们配置好的FastJsonConfig中的参数和特性来进行处理了。
fastConverter.setFastJsonConfig(fastJsonConfig);
+
+ // 这里再次将fastConverter赋值给converter变量,其实是多余的操作,因为前面已经完成了配置,可以直接使用fastConverter变量,不过这并不影响整体功能,只是代码上有些冗余。
FastJsonHttpMessageConverter converter = fastConverter;
+
+ // 创建并返回一个HttpMessageConverters对象,将配置好的FastJsonHttpMessageConverter作为参数传入,
+ // 这样Spring Boot在处理HTTP消息时,就会识别到这个自定义的消息转换器,并使用它来进行JSON相关的数据转换了。
return new HttpMessageConverters(converter);
}
-
-}
+}
\ No newline at end of file
diff --git a/tamguo-oms/src/main/java/com/tamguo/config/WebConfig.java b/tamguo-oms/src/main/java/com/tamguo/config/WebConfig.java
index 30ee016..79181a4 100644
--- a/tamguo-oms/src/main/java/com/tamguo/config/WebConfig.java
+++ b/tamguo-oms/src/main/java/com/tamguo/config/WebConfig.java
@@ -9,22 +9,39 @@ import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import com.tamguo.modules.sys.interceptor.SettingsInterceptor;
+// 表明这是一个Spring的配置类,Spring会扫描这个类并处理其中实现了WebMvcConfigurer接口的方法,用于对Spring Web相关功能进行配置,比如添加拦截器、配置资源处理器等。
@Configuration
public class WebConfig implements WebMvcConfigurer {
-
+
+ // 使用@Value注解从配置文件(通常是application.properties或application.yml等)中读取名为"file.storage.path"的配置项的值,并注入到fileStoragePath变量中,
+ // 该变量用于存储文件存储的路径信息,后续在配置资源处理器时会用到这个路径来指定静态资源的实际存放位置。
@Value("${file.storage.path}")
private String fileStoragePath;
+
+ // 通过@Autowired注解自动注入SettingsInterceptor实例,SettingsInterceptor应该是自定义的拦截器类,
+ // 用于在请求处理过程中进行一些通用的业务逻辑处理,比如权限验证、设置一些通用的请求参数等,具体功能取决于该拦截器类的实现逻辑。
@Autowired
private SettingsInterceptor settingsInterceptor;
-
+
+ /**
+ * 重写WebMvcConfigurer接口的addInterceptors方法,用于向Spring Web的拦截器注册表中添加自定义的拦截器。
+ * 在这里将之前注入的SettingsInterceptor添加到拦截器注册表中,并设置其拦截的路径模式为"/**",意味着所有的请求都会经过这个拦截器进行处理。
+ * 这样可以在拦截器的具体实现中对请求进行统一的前置或后置处理,例如检查用户权限、记录请求日志等操作。
+ */
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(settingsInterceptor).addPathPatterns("/**");
}
-
- @Override
- public void addResourceHandlers(ResourceHandlerRegistry registry) {
- registry.addResourceHandler("/files/**").addResourceLocations("file:"+fileStoragePath);
- }
-
-}
+
+ /**
+ * 重写WebMvcConfigurer接口的addResourceHandlers方法,用于配置Spring Web的资源处理器,使得应用能够正确处理和访问特定路径下的静态资源。
+ * 在这里配置了对"/files/**"路径下的资源请求的处理方式,通过addResourceLocations方法指定了这些资源实际所在的位置,
+ * 格式为"file:" + fileStoragePath,表示资源位于文件系统中,具体路径由fileStoragePath变量所指定的值来确定,
+ * 例如可以将项目中的图片、文档等静态文件存放在这个指定路径下,然后通过"/files/"开头的URL路径来访问这些资源。
+ */
+ @Override
+ public void addResourceHandlers(ResourceHandlerRegistry registry) {
+ registry.addResourceHandler("/files/**").addResourceLocations("file:" + fileStoragePath);
+ }
+
+}
\ No newline at end of file
diff --git a/tamguo-oms/src/main/java/com/tamguo/config/dao/MyMetaObjectHandler.java b/tamguo-oms/src/main/java/com/tamguo/config/dao/MyMetaObjectHandler.java
index d0c8b11..fc2ef86 100644
--- a/tamguo-oms/src/main/java/com/tamguo/config/dao/MyMetaObjectHandler.java
+++ b/tamguo-oms/src/main/java/com/tamguo/config/dao/MyMetaObjectHandler.java
@@ -10,24 +10,43 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
- * 注入公共字段自动填充,任选注入方式即可
+ * 此类用于注入公共字段自动填充功能,它继承自MyBatis Plus的MetaObjectHandler类。
+ * 可以根据实际情况选择这种注入方式来实现自动填充公共字段的需求。
+ * 注意,当前类被注释掉的@Component注解表明它原本可能是想作为Spring的组件被管理,以便能在项目中自动生效,但可能由于某些配置原因等暂未启用这种方式,任选注入方式即可表示可能还有其他等价的实现方式来达到同样的自动填充效果。
*/
//@Component
public class MyMetaObjectHandler extends MetaObjectHandler {
+ // 创建一个名为logger的静态常量,用于记录日志,LoggerFactory根据当前类的类型(MyMetaObjectHandler.class)创建对应的Logger实例,方便后续在代码中输出相关的日志信息。
protected final static Logger logger = LoggerFactory.getLogger(MyMetaObjectHandler.class);
-
+
+ /**
+ * 重写父类的insertFill方法,此方法会在执行插入操作(比如插入数据到数据库表)时被调用,用于自动填充一些公共字段的值。
+ *
+ * @param metaObject MyBatis的MetaObject对象,通过它可以获取和设置对象的属性值等相关操作,在这里就是利用它来为要插入的实体对象设置相应的公共字段值。
+ */
@Override
public void insertFill(MetaObject metaObject) {
- setFieldValByName("createBy", ShiroUtils.getUserCode() , metaObject);
- setFieldValByName("updateBy", ShiroUtils.getUserCode() , metaObject);
- setFieldValByName("createDate", new Date() , metaObject);
- setFieldValByName("updateDate", new Date() , metaObject);
+ // 使用MyBatis Plus提供的方法setFieldValByName,通过字段名"createBy",将值(从ShiroUtils.getUserCode()获取,可能是获取当前用户的代码等标识信息)设置到metaObject所对应的实体对象中,实现自动填充创建者字段的功能。
+ setFieldValByName("createBy", ShiroUtils.getUserCode(), metaObject);
+ // 同样的方式,为更新者字段"updateBy"也设置为当前用户的代码,因为在插入时,创建者和首次更新者可能是同一个人,具体可根据业务逻辑调整。
+ setFieldValByName("updateBy", ShiroUtils.getUserCode(), metaObject);
+ // 通过字段名"createDate",将当前的日期时间(new Date()获取当前系统时间)设置到实体对象中,自动填充创建时间字段。
+ setFieldValByName("createDate", new Date(), metaObject);
+ // 为更新时间字段"updateDate"也设置为当前系统时间,插入操作时可以认为首次更新时间就是创建时间,后续更新操作会再次触发更新时间的更新逻辑。
+ setFieldValByName("updateDate", new Date(), metaObject);
}
+ /**
+ * 重写父类的updateFill方法,此方法会在执行更新操作(比如更新数据库表中的数据)时被调用,用于自动填充更新相关的公共字段的值。
+ *
+ * @param metaObject MyBatis的MetaObject对象,用于操作要更新的实体对象的属性值设置等,在这里就是利用它来为实体对象设置更新相关的公共字段值。
+ */
@Override
public void updateFill(MetaObject metaObject) {
- setFieldValByName("updateBy", ShiroUtils.getUserCode() , metaObject);
- setFieldValByName("updateDate", new Date() , metaObject);
+ // 使用setFieldValByName方法,通过字段名"updateBy",将值(从ShiroUtils.getUserCode()获取当前用户代码)设置到metaObject对应的实体对象中,自动填充更新者字段,确保记录更新操作是谁执行的。
+ setFieldValByName("updateBy", ShiroUtils.getUserCode(), metaObject);
+ // 通过字段名"updateDate",将当前系统时间(new Date()获取)设置到实体对象中,自动更新更新时间字段,保证更新时间的准确性。
+ setFieldValByName("updateDate", new Date(), metaObject);
}
-}
+}
\ No newline at end of file
diff --git a/tamguo-oms/src/main/java/com/tamguo/config/dao/MybatisPlusConfig.java b/tamguo-oms/src/main/java/com/tamguo/config/dao/MybatisPlusConfig.java
index 47d0386..aba580c 100644
--- a/tamguo-oms/src/main/java/com/tamguo/config/dao/MybatisPlusConfig.java
+++ b/tamguo-oms/src/main/java/com/tamguo/config/dao/MybatisPlusConfig.java
@@ -19,10 +19,13 @@ import com.baomidou.mybatisplus.plugins.parser.tenant.TenantSqlParser;
import net.sf.jsqlparser.expression.Expression;
import net.sf.jsqlparser.expression.LongValue;
+// 表示这是一个配置类,Spring会扫描这个类并将其中带有@Bean注解的方法返回的对象注册为Bean
@Configuration
+// 配置MyBatis Mapper接口的扫描路径,会扫描指定包及其子包下的所有Mapper接口,方便Spring与MyBatis整合时能找到对应的Mapper
@MapperScan("com.tamguo.modules.*.dao*")
public class MybatisPlusConfig {
+ // 创建并返回一个PerformanceInterceptor实例,用于拦截MyBatis执行的SQL语句,可用于性能监控,例如记录SQL执行时间等
@Bean
public PerformanceInterceptor performanceInterceptor() {
return new PerformanceInterceptor();
@@ -31,63 +34,78 @@ public class MybatisPlusConfig {
/**
* mybatis-plus分页插件
* 文档:http://mp.baomidou.com
+ * 此方法创建并配置一个PaginationInterceptor实例,用于实现MyBatis Plus的分页功能,同时还进行了与多租户相关的一些配置。
*/
@Bean
public PaginationInterceptor paginationInterceptor() {
PaginationInterceptor paginationInterceptor = new PaginationInterceptor();
- paginationInterceptor.setLocalPage(true);// 开启 PageHelper 的支持
+ // 设置开启PageHelper的支持,以便更好地兼容一些分页相关的操作习惯等情况
+ paginationInterceptor.setLocalPage(true);
+
/*
* 【测试多租户】 SQL 解析处理拦截器
- * 这里固定写成住户 1 实际情况你可以从cookie读取,因此数据看不到 【 麻花藤 】 这条记录( 注意观察 SQL )
+ * 这里固定写成住户1实际情况你可以从cookie读取,因此数据看不到 【 麻花藤 】 这条记录( 注意观察 SQL )
+ * 以下代码是配置多租户相关的SQL解析拦截逻辑,用于在执行SQL时根据租户规则对SQL语句进行处理。
*/
List sqlParserList = new ArrayList<>();
TenantSqlParser tenantSqlParser = new TenantSqlParser();
+
+ // 设置租户处理器,用于定义获取租户ID、租户ID对应的列名以及判断是否过滤表等逻辑
tenantSqlParser.setTenantHandler(new TenantHandler() {
+ // 返回租户ID对应的表达式,这里固定返回值为1L,表示租户ID为1
@Override
public Expression getTenantId() {
return new LongValue(1L);
}
+ // 返回租户ID在数据库表中对应的列名,此处为"course_id"
@Override
public String getTenantIdColumn() {
return "course_id";
}
+ // 判断是否对指定表进行过滤,这里返回true表示需要进行过滤操作,具体过滤逻辑可根据实际情况调整
@Override
public boolean doTableFilter(String tableName) {
- // 这里可以判断是否过滤表
return true;
}
});
-
+ // 将配置好的租户SQL解析器添加到SQL解析器列表中
sqlParserList.add(tenantSqlParser);
+
+ // 将包含租户相关配置的SQL解析器列表设置到分页拦截器中,使得分页拦截器在处理SQL时能应用多租户逻辑
paginationInterceptor.setSqlParserList(sqlParserList);
+
// 以下过滤方式与 @SqlParser(filter = true) 注解等效
+ // 配置SQL解析过滤器,用于根据具体的MappedStatement的ID来决定是否对SQL进行过滤,这里是针对特定的自定义查询进行过滤
// paginationInterceptor.setSqlParserFilter(new ISqlParserFilter() {
// @Override
// public boolean doFilter(MetaObject metaObject) {
// MappedStatement ms = PluginUtils.getMappedStatement(metaObject);
-// // 过滤自定义查询此时无租户信息约束【 麻花藤 】出现
+// // 过滤自定义查询此时无租户信息约束【 麻花藤 】出现,即如果是指定的这个查询方法,则返回true表示过滤该查询,不应用租户相关逻辑
// if ("com.baomidou.springboot.mapper.UserMapper.selectListBySQL".equals(ms.getId())) {
// return true;
// }
// return false;
// }
// });
+
return paginationInterceptor;
}
+ // 创建并返回一个MetaObjectHandler实例,用于在执行MyBatis相关操作时,自动填充一些公共字段等元数据处理逻辑,具体填充逻辑在返回的MyMetaObjectHandler类中实现
@Bean
- public MetaObjectHandler metaObjectHandler(){
+ public MetaObjectHandler metaObjectHandler() {
return new MyMetaObjectHandler();
}
/**
* 注入sql注入器
+ * 此方法创建并返回一个ISqlInjector实例,这里使用的是LogicSqlInjector,用于实现一些逻辑删除等特定的SQL注入功能(MyBatis Plus特性相关)。
*/
@Bean
- public ISqlInjector sqlInjector(){
+ public ISqlInjector sqlInjector() {
return new LogicSqlInjector();
}
-}
+}
\ No newline at end of file
diff --git a/tamguo-oms/src/main/java/com/tamguo/config/redis/SessionConfig.java b/tamguo-oms/src/main/java/com/tamguo/config/redis/SessionConfig.java
index c2376a1..2550735 100644
--- a/tamguo-oms/src/main/java/com/tamguo/config/redis/SessionConfig.java
+++ b/tamguo-oms/src/main/java/com/tamguo/config/redis/SessionConfig.java
@@ -5,24 +5,36 @@ import org.springframework.context.annotation.Bean;
import org.springframework.data.redis.connection.jedis.JedisConnectionFactory;
import org.springframework.session.data.redis.config.annotation.web.http.EnableRedisHttpSession;
-//这个类用配置redis服务器的连接
-@EnableRedisHttpSession(maxInactiveIntervalInSeconds= 1800)
+// 这个类用于配置redis服务器的连接,通过该类可以设置与Redis服务器建立连接所需的各项参数,如主机名、端口、密码等,并创建对应的Jedis连接工厂对象。
+@EnableRedisHttpSession(maxInactiveIntervalInSeconds = 1800)
+// @EnableRedisHttpSession注解用于启用Spring Session基于Redis的HTTP会话管理功能。
+// maxInactiveIntervalInSeconds属性设置了会话的最大非活动时间间隔,这里设置为1800秒,即30分钟,表示如果一个会话在30分钟内没有任何活动,将会被视为过期并失效。
public class SessionConfig {
+ // 使用@Value注解从配置文件(通常是application.properties或application.yml等)中读取名为"redis.hostname"的配置项的值,并注入到HostName变量中,该变量用于存储Redis服务器的主机名。
@Value("${redis.hostname}")
String HostName;
+
+ // 同样通过@Value注解从配置文件中读取"redis.port"配置项的值,注入到Port变量中,用于存储Redis服务器的端口号。
@Value("${redis.port}")
int Port;
+
+ // 从配置文件读取"redis.password"配置项的值,注入到password变量中,用于存储连接Redis服务器所需的密码(如果有的话)。
@Value("${redis.password}")
String password;
+ // @SuppressWarnings("deprecation")注解用于抑制编译器对于使用已过时方法或类等情况的警告提示。
+ // 这里定义了一个名为connectionFactory的方法,并使用@Bean注解将该方法返回的对象注册为Spring容器中的一个Bean,该Bean就是Jedis连接工厂对象,用于创建与Redis服务器的连接。
@SuppressWarnings("deprecation")
@Bean
public JedisConnectionFactory connectionFactory() {
JedisConnectionFactory connection = new JedisConnectionFactory();
+ // 设置Jedis连接工厂对象的端口号,使用之前从配置文件中读取并注入的Port变量来指定具体的端口值。
connection.setPort(Port);
+ // 设置Jedis连接工厂对象的主机名,使用HostName变量来指定连接的Redis服务器的主机名称。
connection.setHostName(HostName);
+ // 设置Jedis连接工厂对象的密码,通过password变量来传入连接Redis服务器所需的密码,确保连接的安全性(如果有密码要求的话)。
connection.setPassword(password);
return connection;
}
-}
+}
\ No newline at end of file
diff --git a/tamguo-oms/src/main/java/com/tamguo/config/redis/SessionInitializer.java b/tamguo-oms/src/main/java/com/tamguo/config/redis/SessionInitializer.java
index 3477712..59d5979 100644
--- a/tamguo-oms/src/main/java/com/tamguo/config/redis/SessionInitializer.java
+++ b/tamguo-oms/src/main/java/com/tamguo/config/redis/SessionInitializer.java
@@ -2,9 +2,15 @@ package com.tamguo.config.redis;
import org.springframework.session.web.context.AbstractHttpSessionApplicationInitializer;
-//初始化Session配置
-public class SessionInitializer extends AbstractHttpSessionApplicationInitializer{
+// 这个类用于初始化Session配置,它继承自Spring框架提供的AbstractHttpSessionApplicationInitializer类,
+// 通过继承该抽象类并实现相应的构造函数等逻辑,来协助完成与Http Session相关配置的初始化工作,确保Session相关功能能够正常启用和配置生效。
+public class SessionInitializer extends AbstractHttpSessionApplicationInitializer {
+
+ // 定义构造函数,在创建SessionInitializer类的实例时会调用该构造函数。
+ // 这里调用父类(AbstractHttpSessionApplicationInitializer)的构造函数,并传入SessionConfig.class作为参数。
+ // 其目的是告知Spring框架要使用SessionConfig这个配置类来初始化Http Session相关的配置,
+ // 使得在整个应用启动过程中,基于之前在SessionConfig类中定义的如Redis连接等相关配置能够正确地应用到Http Session的管理中,从而保证Session功能的正常运行。
public SessionInitializer() {
super(SessionConfig.class);
}
-}
+}
\ No newline at end of file
diff --git a/tamguo-oms/src/main/java/com/tamguo/config/shiro/ShiroConfiguration.java b/tamguo-oms/src/main/java/com/tamguo/config/shiro/ShiroConfiguration.java
index b26913f..fecf3d6 100644
--- a/tamguo-oms/src/main/java/com/tamguo/config/shiro/ShiroConfiguration.java
+++ b/tamguo-oms/src/main/java/com/tamguo/config/shiro/ShiroConfiguration.java
@@ -11,15 +11,24 @@ import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreato
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
+// 表明这是一个Spring的配置类,Spring会扫描这个类并处理其中带有@Bean注解的方法,将这些方法返回的对象注册为Spring容器中的Bean,用于配置Shiro相关的功能组件。
@Configuration
public class ShiroConfiguration {
+
+ // 创建一个静态的LinkedHashMap,用于存储Shiro的过滤链定义。LinkedHashMap可以保证元素的插入顺序,便于按照定义顺序来匹配过滤规则。
+ // 键为请求的URL路径模式,值为对应的访问控制规则(如"anon"表示匿名可访问,"authc"表示需要认证后才能访问等)。
private static Map filterChainDefinitionMap = new LinkedHashMap();
+ // 定义一个名为"shiroRealm"的Bean,该Bean返回一个UserRealm实例。UserRealm通常是自定义的实现了Shiro的Realm接口的类,
+ // 用于从数据源(如数据库)中获取用户认证和授权相关的信息,是Shiro进行身份验证和权限验证的核心逻辑所在。
@Bean(name = "shiroRealm")
public UserRealm getShiroRealm() {
return new UserRealm();
}
+ // 定义一个名为"shiroEhcacheManager"的Bean,用于创建并配置EhCacheManager实例。EhCacheManager是Shiro用于缓存的管理器,
+ // 在这里通过设置缓存配置文件(classpath:ehcache-shiro.xml)来指定缓存的相关配置信息,比如缓存的存活时间、缓存区域划分等,
+ // 以提高Shiro在处理认证和授权过程中的性能,避免频繁地从数据源获取相同的数据。
@Bean(name = "shiroEhcacheManager")
public EhCacheManager getEhCacheManager() {
EhCacheManager em = new EhCacheManager();
@@ -27,11 +36,17 @@ public class ShiroConfiguration {
return em;
}
+ // 定义一个名为"lifecycleBeanPostProcessor"的Bean,创建并返回一个LifecycleBeanPostProcessor实例。
+ // LifecycleBeanPostProcessor是Shiro提供的一个用于管理Shiro相关Bean生命周期的后置处理器,
+ // 它能确保Shiro的各种组件(如Realm、SecurityManager等)在Spring容器中的生命周期方法(如初始化、销毁等)得到正确调用。
@Bean(name = "lifecycleBeanPostProcessor")
public LifecycleBeanPostProcessor getLifecycleBeanPostProcessor() {
return new LifecycleBeanPostProcessor();
}
+ // 定义一个名为"defaultAdvisorAutoProxyCreator"的Bean,创建并配置DefaultAdvisorAutoProxyCreator实例。
+ // 它是Spring AOP中的一个自动代理创建器,用于根据Advisor(通知器,包含了切点和增强逻辑)来自动创建代理对象,
+ // 设置proxyTargetClass为true表示使用基于类的代理方式(而不是基于接口的代理),这样可以确保Shiro的安全切面等逻辑能够正确应用到目标对象上。
@Bean
public DefaultAdvisorAutoProxyCreator getDefaultAdvisorAutoProxyCreator() {
DefaultAdvisorAutoProxyCreator daap = new DefaultAdvisorAutoProxyCreator();
@@ -39,6 +54,9 @@ public class ShiroConfiguration {
return daap;
}
+ // 定义一个名为"securityManager"的Bean,创建并返回一个DefaultWebSecurityManager实例,它是Shiro在Web环境下的核心安全管理器。
+ // 在这里配置了它所使用的Realm(通过调用getShiroRealm()方法获取自定义的UserRealm实例)以及缓存管理器(通过调用getEhCacheManager()方法获取EhCacheManager实例),
+ // 负责协调Shiro的各个组件,如认证、授权、会话管理等功能的执行,是整个Shiro安全框架在应用中的核心控制组件。
@Bean(name = "securityManager")
public DefaultWebSecurityManager getDefaultWebSecurityManager() {
DefaultWebSecurityManager dwsm = new DefaultWebSecurityManager();
@@ -47,19 +65,30 @@ public class ShiroConfiguration {
return dwsm;
}
+ // 定义一个名为"authorizationAttributeSourceAdvisor"的Bean,创建并返回一个AuthorizationAttributeSourceAdvisor实例。
+ // 它是Shiro与Spring AOP结合的一个通知器,用于在方法级别进行权限控制,通过设置安全管理器(调用getDefaultWebSecurityManager()方法获取),
+ // 可以基于方法上的权限注解(如@RequiresPermissions等)来自动进行权限验证,实现细粒度的访问控制。
@Bean
public AuthorizationAttributeSourceAdvisor getAuthorizationAttributeSourceAdvisor() {
AuthorizationAttributeSourceAdvisor aasa = new AuthorizationAttributeSourceAdvisor();
aasa.setSecurityManager(getDefaultWebSecurityManager());
return new AuthorizationAttributeSourceAdvisor();
}
-
+
+ // 定义一个名为"shiroFilter"的Bean,创建并返回一个ShiroFilterFactoryBean实例,它是Shiro在Web应用中用于配置过滤链的核心组件。
+ // 首先设置了安全管理器(通过调用getDefaultWebSecurityManager()方法获取),确定了整个过滤链的安全控制基础。
+ // 然后设置了登录页面的URL("/login"),即当用户未认证访问受保护资源时,会被重定向到该登录页面进行认证操作。
+ // 接着设置了认证成功后的跳转页面URL("/index"),用于用户成功登录后自动跳转到相应的页面。
+ // 之后通过往filterChainDefinitionMap中添加一系列的URL路径模式和对应的访问控制规则,来定义哪些资源是匿名可访问(如各种前端框架相关的静态资源路径),哪些资源需要认证访问("/**"表示除了前面配置的匿名可访问路径外的其他所有路径)。
+ // 最后将配置好的过滤链定义Map设置到ShiroFilterFactoryBean中,使其生效,从而实现整个Web应用基于Shiro的访问控制。
@Bean(name = "shiroFilter")
public ShiroFilterFactoryBean getShiroFilterFactoryBean() {
ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
shiroFilterFactoryBean.setSecurityManager(getDefaultWebSecurityManager());
shiroFilterFactoryBean.setLoginUrl("/login");
shiroFilterFactoryBean.setSuccessUrl("/index");
+
+ // 以下是配置各种静态资源路径为匿名可访问,这些资源通常是前端框架的相关文件,不需要进行认证就能访问,方便页面正常加载和展示。
filterChainDefinitionMap.put("/jquery/**", "anon");
filterChainDefinitionMap.put("/adminlte/**", "anon");
filterChainDefinitionMap.put("/bootstrap/**", "anon");
@@ -86,11 +115,12 @@ public class ShiroConfiguration {
filterChainDefinitionMap.put("/jquery-timeago/**", "anon");
filterChainDefinitionMap.put("/favicon.ico", "anon");
filterChainDefinitionMap.put("/global.min.js", "anon");
-
-
+
+ // 将除了上述配置的匿名可访问路径之外的所有请求路径都设置为需要认证访问("authc"表示需要认证),实现了对整个Web应用的基本访问控制。
filterChainDefinitionMap.put("/**", "authc");
+
shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
+
return shiroFilterFactoryBean;
}
-
}
\ No newline at end of file
diff --git a/tamguo-oms/src/main/java/com/tamguo/config/shiro/UserRealm.java b/tamguo-oms/src/main/java/com/tamguo/config/shiro/UserRealm.java
index 5b26aa1..6441e87 100644
--- a/tamguo-oms/src/main/java/com/tamguo/config/shiro/UserRealm.java
+++ b/tamguo-oms/src/main/java/com/tamguo/config/shiro/UserRealm.java
@@ -17,55 +17,66 @@ import com.tamguo.modules.sys.model.enums.SysUserStatusEnum;
import com.tamguo.modules.sys.service.ISysUserService;
/**
- * 认证
- *
+ * 这个类 `UserRealm` 继承自 `AuthorizingRealm`,是Shiro框架中用于实现认证和授权逻辑的核心类。
+ * 它负责与业务层的用户服务进行交互,完成用户登录认证以及权限验证相关的操作,是整个应用基于Shiro进行安全控制的关键部分。
+ *
*/
public class UserRealm extends AuthorizingRealm {
-
+
+ // 通过Spring的依赖注入(@Autowired注解),自动注入 `ISysUserService` 接口的实现类实例,
+ // 用于后续从业务层获取用户相关信息,比如根据用户名查询用户实体对象等操作,实现与业务逻辑层的交互,以完成认证和授权的具体业务判断。
@Autowired
private ISysUserService sysUserService;
-
+
/**
* 授权(验证权限时调用)
+ * 此方法是Shiro框架要求必须实现的用于获取授权信息的方法。当需要验证用户是否具有某个权限时(例如访问受权限控制的资源),Shiro会调用该方法来获取用户的权限信息。
+ * 目前该方法中只是创建了一个空的 `SimpleAuthorizationInfo` 对象返回,实际应用中通常需要根据业务逻辑从数据库等数据源获取用户对应的权限信息,并设置到 `info` 对象中返回给Shiro框架进行权限判断。
*/
- @Override
- protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
- SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
- // info.setStringPermissions(permsSet);
-
- return info;
- }
+ @Override
+ protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
+ SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
+ // info.setStringPermissions(permsSet); // 此处可能原本计划设置用户的权限集合,但目前未实现具体逻辑,可能需要根据实际业务从数据库查询用户权限并设置进来
+
+ return info;
+ }
- /**
- * 认证(登录时调用)
- */
- @Override
- protected AuthenticationInfo doGetAuthenticationInfo(
- AuthenticationToken token) throws AuthenticationException {
- String username = (String) token.getPrincipal();
+ /**
+ * 认证(登录时调用)
+ * 此方法是Shiro框架用于进行用户登录认证的核心方法。当用户发起登录请求时,Shiro会调用该方法来验证用户输入的账号(用户名)和密码是否正确,以及账号状态是否正常等情况。
+ */
+ @Override
+ protected AuthenticationInfo doGetAuthenticationInfo(
+ AuthenticationToken token) throws AuthenticationException {
+ // 从传入的 `AuthenticationToken` 对象中获取用户名(通常作为登录的标识),这里将其强制转换为 `String` 类型,因为在实际应用中一般用户名是以字符串形式存在的。
+ String username = (String) token.getPrincipal();
+ // 从 `AuthenticationToken` 对象中获取用户输入的密码,并将其从字符数组转换为 `String` 类型,以便后续与数据库中存储的密码进行比对。
String password = new String((char[]) token.getCredentials());
-
- //查询用户信息
+
+ // 通过注入的 `ISysUserService` 实例,调用其 `queryByLoginCode` 方法,根据用户名去查询对应的用户信息,该方法会与业务层的数据访问层交互,从数据库中获取用户实体对象(如果存在的话)。
SysUserEntity user = sysUserService.queryByLoginCode(username);
-
- //账号不存在
- if(user == null) {
+
+ // 如果查询到的用户对象为 `null`,说明输入的用户名不存在,此时抛出 `UnknownAccountException` 异常,Shiro会捕获该异常并根据配置进行相应的处理(比如提示用户账号不存在等)。
+ if (user == null) {
throw new UnknownAccountException("账号或密码不正确");
}
-
- //密码错误
- if(!password.equals(user.getPassword())) {
+
+ // 将用户输入的密码与从数据库中查询到的用户实体对象中存储的密码进行比对,如果不一致,说明密码错误,抛出 `IncorrectCredentialsException` 异常,Shiro同样会根据配置进行处理(例如提示密码错误等)。
+ if (!password.equals(user.getPassword())) {
throw new IncorrectCredentialsException("账号或密码不正确");
}
-
- //账号锁定
- if(user.getStatus() == SysUserStatusEnum.LOCKED){
- throw new LockedAccountException("账号已被锁定,请联系管理员");
+
+ // 判断用户账号的状态,如果状态为 `SysUserStatusEnum.LOCKED`(表示账号已被锁定,这里 `SysUserStatusEnum` 应该是一个自定义的枚举类型,用于表示用户账号的不同状态),
+ // 则抛出 `LockedAccountException` 异常,告知用户账号已被锁定,需联系管理员处理,Shiro会相应地进行处理,比如禁止登录等操作。
+ if (user.getStatus() == SysUserStatusEnum.LOCKED) {
+ throw new LockedAccountException("账号已被锁定,请联系管理员");
}
-
+
+ // 如果上述验证都通过,创建一个 `SimpleAuthenticationInfo` 对象,将查询到的用户对象、密码以及当前 `Realm` 的名称(通过 `getName()` 方法获取)传入构造函数。
+ // 这个对象会被Shiro用于后续的认证相关处理,表示当前用户的认证信息已通过验证,后续在会话等相关处理中会用到这些信息。
SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(user, password, getName());
-
+
return info;
- }
+ }
-}
+}
\ No newline at end of file
diff --git a/tamguo-oms/src/main/java/com/tamguo/modules/sys/interceptor/SettingsInterceptor.java b/tamguo-oms/src/main/java/com/tamguo/modules/sys/interceptor/SettingsInterceptor.java
index d0c947a..6a13f6b 100644
--- a/tamguo-oms/src/main/java/com/tamguo/modules/sys/interceptor/SettingsInterceptor.java
+++ b/tamguo-oms/src/main/java/com/tamguo/modules/sys/interceptor/SettingsInterceptor.java
@@ -10,12 +10,28 @@ import org.springframework.web.servlet.ModelAndView;
import com.tamguo.modules.sys.utils.Setting;
+// 使用@Component注解将这个类标记为Spring组件,使得Spring能够扫描并管理这个类,在需要的时候可以自动将其实例注入到其他依赖它的类中。
+// 这个类实现了HandlerInterceptor接口,用于拦截Spring Web应用中的请求,在请求处理的不同阶段执行自定义的逻辑,比如在请求前做一些准备工作、在请求处理后设置一些属性或者在整个请求结束后进行资源清理等。
@Component
public class SettingsInterceptor implements HandlerInterceptor {
- @Resource
- private Setting setting;
+ // 使用@Resource注解进行依赖注入,将名为"setting"的Bean(从Spring容器中查找,这里应该是一个实现了相关业务逻辑的Setting类的实例,可能用于获取系统相关的设置信息等)注入到当前类的setting属性中,
+ // 以便后续在拦截器的各个方法中使用这些设置信息来完成相应的功能,比如传递给视图层等操作。
+ @Resource
+ private Setting setting;
+ /**
+ * 这个方法在请求处理之前被调用,也就是在请求到达具体的Controller方法之前执行。
+ * 它可以用于进行一些前置的验证、权限检查或者准备工作等操作。
+ * 返回值为布尔类型,如果返回true,则表示允许请求继续向后传递,进入到Controller方法进行处理;如果返回false,则会中断请求,后续的Controller方法以及其他拦截器的后续方法都不会被执行。
+ * 在当前实现中,直接返回了true,表示允许所有请求继续往后处理,不做额外的前置拦截操作(可根据实际业务需求添加具体逻辑)。
+ *
+ * @param request 当前的HttpServletRequest对象,包含了请求的相关信息,如请求头、请求参数等,可以通过它获取请求相关的数据进行前置判断等操作。
+ * @param response 当前的HttpServletResponse对象,用于设置响应相关的信息,比如响应头、状态码等,如果在前置处理中发现问题需要返回特定的响应给客户端,可以通过它来进行设置。
+ * @param handler 表示被拦截的请求对应的处理器对象,通常是Controller中的方法对应的处理器,可以通过它获取一些关于处理方法的信息(在某些复杂的场景下可能会用到)。
+ * @return boolean 返回true表示允许请求继续处理,返回false表示拦截请求,中断后续处理流程。
+ * @throws Exception 如果在前置处理过程中出现异常,可以抛出异常,Spring会根据配置进行相应的异常处理,比如返回错误页面等操作。
+ */
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
@@ -23,17 +39,39 @@ public class SettingsInterceptor implements HandlerInterceptor {
return true;
}
+ /**
+ * 这个方法在请求被Controller方法处理之后,但在视图渲染之前被调用。
+ * 可以用于对请求处理后的结果进行一些修改、添加额外的模型数据或者进行一些通用的设置等操作,使得这些信息能够传递到视图层进行展示等。
+ * 在当前实现中,将之前注入的Setting实例通过request.setAttribute方法设置到请求的属性中,键为"setting",这样在视图层(如JSP、Thymeleaf等模板文件中)就可以获取到这个系统设置相关的对象,用于展示系统设置信息或者基于设置信息进行页面逻辑的处理等。
+ *
+ * @param request 当前的HttpServletRequest对象,包含了请求相关的信息,在这里可以通过它来设置一些属性,传递给后续的视图渲染阶段使用。
+ * @param response 当前的HttpServletResponse对象,同样可用于设置响应相关的信息,如果在这个阶段需要调整响应的一些内容,可以通过它进行操作。
+ * @param handler 表示被拦截的请求对应的处理器对象,即Controller中的方法对应的处理器,可用于获取处理方法相关的一些信息(视具体业务场景决定是否使用)。
+ * @param modelAndView 如果Controller方法返回了ModelAndView对象(用于指定视图和传递模型数据),则在这里可以获取并对其进行修改、添加数据等操作;如果Controller方法没有返回ModelAndView(比如直接返回数据等情况),则这个参数可能为null。
+ * @throws Exception 如果在这个阶段出现异常,同样可以抛出异常,Spring会根据配置进行相应的异常处理,比如返回错误页面等操作。
+ */
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
- ModelAndView modelAndView) throws Exception {
- // 设置系统变量
- request.setAttribute("setting", setting);
+ ModelAndView modelAndView) throws Exception {
+ // 设置系统变量
+ request.setAttribute("setting", setting);
}
+ /**
+ * 这个方法在整个请求结束之后被调用,也就是在DispatcherServlet渲染了对应的视图之后执行。
+ * 它主要用于进行资源清理工作,比如关闭一些在请求处理过程中打开的资源(如数据库连接、文件流等),释放占用的内存等操作,确保资源的合理使用,避免资源泄漏等问题。
+ * 在当前实现中,没有具体的资源清理逻辑(可根据实际业务需求添加,例如关闭自定义的缓存连接、释放一些自定义的线程资源等),只是保留了方法的结构,满足HandlerInterceptor接口的要求。
+ *
+ * @param request 当前的HttpServletRequest对象,包含了请求相关的所有信息,虽然在这个阶段请求已经处理完毕,但可以通过它获取一些请求相关的上下文信息,以便进行针对性的资源清理等操作。
+ * @param response 当前的HttpServletResponse对象,用于设置响应相关的信息,同样在这个阶段可以根据响应情况进行一些后续的资源清理等操作(比如清理响应缓存等,不过通常情况较少涉及)。
+ * @param handler 表示被拦截的请求对应的处理器对象,即Controller中的方法对应的处理器,通过它可以获取处理方法相关的一些信息,用于判断是否需要进行特定的资源清理操作(视具体业务场景而定)。
+ * @param ex 如果在请求处理过程中出现了异常,会将异常对象传递到这里,可以根据异常情况进行一些额外的资源清理或者记录异常相关的日志等操作;如果没有异常发生,则这个参数为null。
+ * @throws Exception 如果在进行资源清理等操作过程中又出现了异常,可以再次抛出异常,Spring会根据配置进行相应的异常处理,比如记录错误日志、返回错误页面等操作。
+ */
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
throws Exception {
- //在整个请求结束之后被调用,也就是在DispatcherServlet 渲染了对应的视图之后执行(主要是用于进行资源清理工作)
+ //在整个请求结束之后被调用,也就是在DispatcherServlet 渲染了对应的视图之后执行(主要是用于进行资源清理工作)
}
-
-}
+
+}
\ No newline at end of file
diff --git a/tamguo-oms/src/main/java/com/tamguo/modules/sys/utils/Setting.java b/tamguo-oms/src/main/java/com/tamguo/modules/sys/utils/Setting.java
index e1eb604..a8fa4de 100644
--- a/tamguo-oms/src/main/java/com/tamguo/modules/sys/utils/Setting.java
+++ b/tamguo-oms/src/main/java/com/tamguo/modules/sys/utils/Setting.java
@@ -4,29 +4,62 @@ import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
/**
- * Setting - 系统
- *
+ * Setting类用于存放系统相关的配置信息和一些常量定义,它在整个项目中可以作为一个统一获取系统设置的地方,方便不同模块使用这些配置和常量。
+ * 这个类被标记为@Component,意味着它会被Spring容器管理,成为一个Spring Bean,可以通过依赖注入的方式在其他需要的地方使用。
+ * 同时,这个类被定义为final,表示它不能被继承,保证了其配置信息和常量的唯一性与稳定性(避免子类对其进行修改导致不符合预期的情况)。
+ *
* @author candy.tam
*
*/
@Component
public final class Setting {
- /** 域名 */
- @Value(value="${domain.name}")
+ /**
+ * 域名属性,用于存储系统所使用的域名信息。
+ * 通过@Value注解,从配置文件(通常是application.properties或application.yml等)中读取名为"domain.name"的配置项的值,并注入到这个domain属性中。
+ * 在项目中,例如生成完整的URL地址、进行域名相关的验证或者配置跨域等场景时可能会用到该域名信息。
+ */
+ @Value(value = "${domain.name}")
public String domain;
- /** 静态资源地址*/
- @Value(value="${static.domain}")
+
+ /**
+ * 静态资源地址属性,用于存储系统中静态资源(如图片、样式文件、脚本文件等)所在的域名或者路径相关信息。
+ * 同样使用@Value注解从配置文件中获取名为"static.domain"的配置项的值,注入到这个staticDomain属性中。
+ * 当项目需要引用静态资源时,就可以通过这个属性来构建正确的资源访问路径,确保静态资源能够被正确加载和显示。
+ */
+ @Value(value = "${static.domain}")
public String staticDomain;
- @Value(value="${version}")
+
+ /**
+ * 版本属性,用于存储系统的版本信息。
+ * 借助@Value注解从配置文件里读取名为"version"的配置项的值,并赋给这个version属性。
+ * 在项目的版本管理、接口版本控制或者前端展示当前系统版本等场景中,该版本信息会发挥相应的作用。
+ */
+ @Value(value = "${version}")
public String version;
- /** 真题 */
+
+ /**
+ * 真题类型的常量定义,值为"1",用于在项目中标识试卷类型为真题的情况。
+ * 例如在处理试卷相关业务逻辑时,通过判断试卷的类型是否等于这个常量来确定它是否是真题,方便进行不同类型试卷的分类处理、查询或者展示等操作。
+ */
public final String PAPER_TYPE_ZHENTI = "1";
- /** 模拟*/
+
+ /**
+ * 模拟类型的常量定义,值为"2",用于表示试卷类型是模拟题的情况。
+ * 和真题类型常量类似,在试卷业务逻辑中可用于区分模拟题试卷,按照模拟题的特定规则进行相关处理,比如生成模拟题试卷、统计模拟题答题情况等。
+ */
public final String PAPER_TYPE_MONI = "2";
- /** 押题*/
+
+ /**
+ * 押题类型的常量定义,值为"3",用于标记试卷类型为押题的情况。
+ * 在涉及押题试卷相关的业务流程中,依靠这个常量来识别押题试卷,进而执行诸如押题试卷的推荐、分析押题命中率等相关操作。
+ */
public final String PAPER_TYPE_YATI = "3";
- /** 名校 */
+
+ /**
+ * 名校类型的常量定义,值为"4",用于界定试卷类型是与名校相关的情况(具体含义可能根据业务场景而定,比如名校的真题、名校的模拟题等)。
+ * 在处理与名校试卷有关的业务逻辑时,利用这个常量来区分名校试卷,进行相应的展示、筛选或者分析等操作。
+ */
public final String PAPER_TYPE_MINGXIAO = "4";
-
-}
+
+}
\ No newline at end of file
diff --git a/tamguo-oms/src/main/java/com/tamguo/modules/sys/utils/ShiroUtils.java b/tamguo-oms/src/main/java/com/tamguo/modules/sys/utils/ShiroUtils.java
index d2604ef..5628572 100644
--- a/tamguo-oms/src/main/java/com/tamguo/modules/sys/utils/ShiroUtils.java
+++ b/tamguo-oms/src/main/java/com/tamguo/modules/sys/utils/ShiroUtils.java
@@ -6,44 +6,100 @@ import org.apache.shiro.subject.Subject;
import com.tamguo.modules.sys.model.SysUserEntity;
+// 这个类是一个工具类,提供了一系列与Shiro框架交互的便捷方法,用于获取Shiro相关的对象(如会话、当前用户等)以及执行一些常见的操作(如设置会话属性、判断登录状态、注销等),方便在项目的不同地方复用这些操作逻辑,避免重复编写获取Shiro相关信息的代码。
public class ShiroUtils {
+ /**
+ * 获取当前用户的Shiro会话对象。
+ * 通过调用Shiro的SecurityUtils工具类的getSubject()方法获取当前的Subject(代表当前执行的用户主体),然后再调用其getSession()方法获取对应的会话对象。
+ * 会话对象可以用于存储用户在一次会话期间的相关数据,例如临时的用户状态、权限缓存等信息,在整个应用中不同模块间共享这些会话数据来实现一些功能。
+ * @return 返回当前用户的Shiro会话对象。
+ */
public static Session getSession() {
return SecurityUtils.getSubject().getSession();
}
+ /**
+ * 获取当前的Subject对象。
+ * Subject对象代表了当前执行操作的用户主体,通过它可以进行很多与认证、授权以及会话管理等相关的操作,比如获取用户信息、判断用户是否具有某个权限等。
+ * 在Shiro框架中,它是与当前用户交互的核心入口点,很多Shiro相关的功能调用都依赖于获取到的这个Subject对象。
+ * @return 返回当前的Subject对象。
+ */
public static Subject getSubject() {
return SecurityUtils.getSubject();
}
+ /**
+ * 获取当前登录用户对应的SysUserEntity对象。
+ * 通过调用SecurityUtils.getSubject().getPrincipal()方法获取当前用户主体的认证信息(在通常情况下,登录成功后会将用户相关的实体对象或者关键信息存储在这里作为认证信息),
+ * 然后将其强制转换为SysUserEntity类型,该类型应该是项目中自定义的表示系统用户的实体类,包含了如用户名、密码、用户权限等用户相关的详细信息,方便在业务逻辑中使用具体的用户信息进行后续操作。
+ * @return 返回当前登录用户对应的SysUserEntity对象,如果当前用户未登录,则可能会抛出类型转换异常(实际使用中可根据业务场景进行更合理的异常处理)。
+ */
public static SysUserEntity getUser() {
- return (SysUserEntity)SecurityUtils.getSubject().getPrincipal();
+ return (SysUserEntity) SecurityUtils.getSubject().getPrincipal();
}
+ /**
+ * 获取当前登录用户的用户代码(具体含义根据项目中SysUserEntity类里userCode属性的定义而定,可能是用户名、用户编号等唯一标识用户的代码)。
+ * 先调用getUser()方法获取当前登录用户对应的SysUserEntity对象,然后再调用其getUserCode()方法获取用户代码属性的值,方便在业务逻辑中使用用户代码进行一些操作,比如记录操作日志时关联用户、进行权限判断等基于用户代码的业务场景。
+ * @return 返回当前登录用户的用户代码。
+ */
public static String getUserCode() {
return getUser().getUserCode();
}
-
+
+ /**
+ * 设置当前用户会话中的属性值。
+ * 通过先调用getSession()方法获取当前用户的会话对象,然后使用其setAttribute()方法将要存储的键值对(key-value)形式的数据存入会话中,
+ * 这样在同一会话的其他地方(比如后续的请求处理中)就可以通过相同的键来获取对应的值,实现会话级别的数据共享和传递。
+ * @param key 要设置的属性的键,用于后续获取属性值时作为标识。
+ * @param value 要设置的属性的值,即要存入会话中的具体数据内容。
+ */
public static void setSessionAttribute(Object key, Object value) {
getSession().setAttribute(key, value);
}
+ /**
+ * 获取当前用户会话中指定键对应的属性值。
+ * 首先获取当前用户的会话对象(通过调用getSession()方法),然后使用其getAttribute()方法根据传入的键(key)来获取对应的属性值,
+ * 如果键不存在,则返回null,可用于在会话中获取之前存储的临时数据,比如从一个请求中存入会话的中间计算结果,在后续请求中通过这个方法获取并继续使用。
+ * @param key 要获取的属性对应的键,用于在会话中查找相应的值。
+ * @return 返回当前用户会话中指定键对应的属性值,如果键不存在则返回null。
+ */
public static Object getSessionAttribute(Object key) {
return getSession().getAttribute(key);
}
+ /**
+ * 判断当前用户是否已经登录。
+ * 通过检查SecurityUtils.getSubject().getPrincipal()返回的用户主体认证信息是否为null来判断当前用户是否登录,
+ * 如果不为null,表示当前有用户已经通过认证登录系统了,返回true;如果为null,则表示当前没有用户登录,返回false,方便在业务逻辑中根据登录状态来决定是否允许执行某些操作,比如只有登录用户才能访问的页面或接口等情况。
+ * @return 返回布尔值,true表示当前用户已登录,false表示当前用户未登录。
+ */
public static boolean isLogin() {
- return SecurityUtils.getSubject().getPrincipal() != null;
+ return SecurityUtils.getSubject().getPrincipal()!= null;
}
+ /**
+ * 执行用户注销操作。
+ * 调用SecurityUtils.getSubject().logout()方法,该方法会清除当前用户的认证信息、会话数据等相关内容,使当前用户退出登录状态,
+ * 常用于用户主动点击注销按钮或者系统根据某些条件(如长时间未操作等)自动执行注销的场景,确保用户退出系统后相关数据的安全性以及资源的合理释放。
+ */
public static void logout() {
SecurityUtils.getSubject().logout();
}
-
+
+ /**
+ * 获取保存在会话中的验证码信息(根据传入的键来查找对应的验证码值)。
+ * 先通过调用getSessionAttribute(key)方法从会话中获取指定键对应的对象,然后将其转换为字符串类型(假设验证码在会话中是以字符串形式存储的),
+ * 这里有一行被注释掉的代码getSession().removeAttribute(key),可能原本的意图是在获取验证码后从会话中移除该验证码,以避免重复使用等情况(可根据实际业务需求决定是否启用该逻辑)。
+ * @param key 用于在会话中查找验证码的键,在生成验证码并存储到会话时使用的相同键来获取对应的验证码信息。
+ * @return 返回从会话中获取到的验证码字符串,如果键不存在或者获取到的对象转换字符串失败等情况,可能会抛出异常(实际使用中可根据业务场景进行合理的异常处理)。
+ */
public static String getKaptcha(String key) {
String kaptcha = getSessionAttribute(key).toString();
-// getSession().removeAttribute(key);
+// getSession().removeAttribute(key);
return kaptcha;
}
-}
+}
\ No newline at end of file
diff --git a/tamguo-oms/src/main/java/com/tamguo/modules/sys/web/CommonController.java b/tamguo-oms/src/main/java/com/tamguo/modules/sys/web/CommonController.java
index 67f2a31..e17a711 100644
--- a/tamguo-oms/src/main/java/com/tamguo/modules/sys/web/CommonController.java
+++ b/tamguo-oms/src/main/java/com/tamguo/modules/sys/web/CommonController.java
@@ -4,29 +4,56 @@ import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;
+// 使用@Controller注解将这个类标记为Spring MVC中的控制器类,表明它负责处理Web请求,并将请求转发到相应的视图进行展示,是Web应用中实现页面交互逻辑的重要组成部分。
@Controller
public class CommonController {
-
+
+ // 定义一个常量字符串,表示树状选择页面的视图名称(具体路径格式遵循Spring MVC视图解析的配置规则,这里的"modules/sys/common/treeselect"可能对应的是一个JSP、Thymeleaf等模板文件的路径,用于展示树状选择相关的页面内容)。
private final String TREE_SELECT_PAGE = "modules/sys/common/treeselect";
+ // 定义常量字符串,代表树状图标选择页面的视图名称,同样对应着用于展示树状图标选择相关内容的模板文件路径。
private final String TREE_ICON_PAGE = "modules/sys/common/iconselect";
+ // 定义常量字符串,用于表示系统桌面页面的视图名称,即对应展示系统桌面相关内容的模板文件路径。
private final String SYS_DESKTOP_PAGE = "modules/sys/common/desktop";
- @RequestMapping(path="sys/treeselect")
- public ModelAndView index(ModelAndView model , String url) {
- model.addObject("url" , url);
+ /**
+ * 处理路径为"sys/treeselect"的请求的方法,用于准备并返回树状选择页面相关的数据和视图。
+ * 通过Spring MVC的@RequestMapping注解将该方法与指定的请求路径进行映射,当客户端发起对应的请求时,这个方法就会被调用执行。
+ * 方法接收一个ModelAndView对象,用于向视图传递数据以及设置要返回的视图名称,同时还接收一个名为"url"的字符串参数(该参数的值应该是从请求中传递过来的,具体取决于前端页面如何发起请求及传递参数)。
+ *
+ * @param model ModelAndView对象,用于添加模型数据(可以在视图中通过相应的表达式获取这些数据)以及设置视图名称,实现数据与视图的整合。
+ * @param url 从请求中传递过来的字符串参数,用于在视图中可能需要根据不同的URL进行相关逻辑处理(具体用途取决于视图层的实现逻辑),在这里将其添加到ModelAndView对象中,传递给视图。
+ * @return 返回包含了准备好的数据以及设置好视图名称的ModelAndView对象,Spring MVC会根据这个对象将数据传递给对应的视图进行渲染展示。
+ */
+ @RequestMapping(path = "sys/treeselect")
+ public ModelAndView index(ModelAndView model, String url) {
+ model.addObject("url", url);
model.setViewName(TREE_SELECT_PAGE);
return model;
}
-
- @RequestMapping(path="sys/iconselect")
+
+ /**
+ * 处理路径为"sys/iconselect"的请求的方法,用于返回树状图标选择页面相关的视图。
+ * 通过@RequestMapping注解将方法与请求路径进行映射,当客户端发起对应请求时执行该方法,该方法主要负责设置要返回的视图名称,将对应的视图展示给客户端。
+ *
+ * @param model ModelAndView对象,用于设置视图名称,以确定要返回给客户端的视图页面。
+ * @return 返回设置好视图名称的ModelAndView对象,使得Spring MVC能够找到对应的视图进行渲染展示,这里返回的是树状图标选择页面的视图。
+ */
+ @RequestMapping(path = "sys/iconselect")
public ModelAndView iconselect(ModelAndView model) {
model.setViewName(TREE_ICON_PAGE);
return model;
}
- @RequestMapping(path="sys/desktop")
+ /**
+ * 处理路径为"sys/desktop"的请求的方法,用于返回系统桌面页面相关的视图。
+ * 同样借助@RequestMapping注解与请求路径建立映射关系,当收到对应请求时,此方法被调用,其主要工作是设置好要返回的系统桌面页面的视图名称,让Spring MVC将对应的视图呈现给客户端。
+ *
+ * @param model ModelAndView对象,用于指定要返回的视图名称,确保正确的视图能够被渲染展示。
+ * @return 返回已设置好视图名称的ModelAndView对象,从而使得系统桌面页面的视图能够展示给客户端,实现相应的页面展示功能。
+ */
+ @RequestMapping(path = "sys/desktop")
public ModelAndView index(ModelAndView model) {
model.setViewName(SYS_DESKTOP_PAGE);
return model;
}
-}
+}
\ No newline at end of file
diff --git a/tamguo-oms/src/main/java/com/tamguo/modules/sys/web/CompanyController.java b/tamguo-oms/src/main/java/com/tamguo/modules/sys/web/CompanyController.java
index 1118e5c..9b0b552 100644
--- a/tamguo-oms/src/main/java/com/tamguo/modules/sys/web/CompanyController.java
+++ b/tamguo-oms/src/main/java/com/tamguo/modules/sys/web/CompanyController.java
@@ -18,33 +18,63 @@ import com.tamguo.modules.sys.model.condition.SysCompanyCondition;
import com.tamguo.modules.sys.service.ISysAreaService;
import com.tamguo.modules.sys.service.ISysCompanyService;
+// 使用@Controller注解将这个类标记为Spring MVC中的控制器类,表明它负责处理与公司相关的Web请求,并根据不同的请求调用相应的业务逻辑方法,将处理结果返回给客户端或者转发到对应的视图进行展示,是实现公司业务模块页面交互和数据处理的核心部分。
@Controller
-@RequestMapping(path="sys/company")
+// 通过@RequestMapping注解为这个控制器类下的所有请求路径设置一个公共的前缀,即该控制器处理的请求路径都以"sys/company"开头,方便对公司相关的各种请求进行统一管理和分类。
+@RequestMapping(path = "sys/company")
public class CompanyController {
-
+
+ // 定义一个常量字符串,表示公司列表页面(或首页)的视图名称,遵循Spring MVC视图解析的配置规则,对应着展示公司列表相关内容的模板文件路径(如JSP、Thymeleaf等模板文件的具体路径)。
private final String COMPANY_INDEX_PAGE = "modules/sys/company/index";
+ // 定义常量字符串,代表公司详情页面(可能用于新增公司时展示相关信息的页面,也可能用于查看已有公司详情的页面,具体取决于业务逻辑)的视图名称,对应着展示公司详细信息相关内容的模板文件路径。
private final String COMPANY_DETAIL_PAGE = "modules/sys/company/add";
+ // 定义常量字符串,用于表示公司信息更新页面的视图名称,对应展示修改公司信息相关内容的模板文件路径。
private final String COMPANY_UPDATE_PAGE = "modules/sys/company/update";
+ // 通过@Autowired注解自动注入ISysCompanyService接口的实现类实例,用于调用与公司相关的业务逻辑方法,比如查询、保存、更新公司信息等操作,实现控制器层与业务逻辑层的交互。
@Autowired
ISysCompanyService iSysCompanyService;
+ // 同样使用@Autowired注解注入ISysAreaService接口的实现类实例,用于获取与地区相关的服务,可能在处理公司信息时涉及到关联地区信息等业务场景(比如公司所属地区的查询等操作),实现与其他相关业务模块的交互。
@Autowired
ISysAreaService iSysAreaService;
-
- @RequestMapping(path="index")
+
+ /**
+ * 处理路径为"sys/company/index"的请求的方法,用于返回公司列表页面的视图名称。
+ * 当客户端发起对应的请求时,该方法被调用,其主要功能就是告诉Spring MVC要渲染展示的视图对应的名称,以便找到对应的模板文件进行页面展示(这里只是简单返回视图名称,具体页面内容的渲染由视图层根据配置和模板文件来完成)。
+ *
+ * @param model ModelAndView对象,虽然在这里没有向其添加额外的数据,但在Spring MVC的请求处理流程中,这个对象是用于传递数据和设置视图名称的常用载体,此处主要利用它来遵循方法签名的统一要求,在其他方法中可能会向其添加数据后再返回。
+ * @return 返回公司列表页面的视图名称(即常量COMPANY_INDEX_PAGE所定义的值),Spring MVC根据这个名称去查找并渲染对应的视图模板文件,展示公司列表页面给客户端。
+ */
+ @RequestMapping(path = "index")
public String index(ModelAndView model) {
return COMPANY_INDEX_PAGE;
}
-
- @RequestMapping(path="add")
- public ModelAndView add(String parentCode , ModelAndView model) {
+
+ /**
+ * 处理路径为"sys/company/add"的请求的方法,用于准备并返回公司详情页面相关的数据和视图。
+ * 当客户端发起该请求时,方法会被调用,先设置要返回的视图名称为公司详情页面的视图名称(COMPANY_DETAIL_PAGE),然后通过注入的ISysCompanyService实例,根据传入的parentCode参数查询对应的公司信息,并将查询到的公司对象添加到ModelAndView对象中,传递给视图层使用(例如在视图中展示公司的基本信息等),最后返回包含了视图名称和相关数据的ModelAndView对象,使得Spring MVC能够正确渲染展示公司详情页面。
+ *
+ * @param parentCode 从请求中传递过来的字符串参数,用于指定要查询的公司的标识(具体含义取决于业务中公司实体类的设计以及业务逻辑,可能是公司编号等唯一标识),通过这个参数去查询对应的公司信息。
+ * @param model ModelAndView对象,用于设置视图名称以及添加要传递给视图的数据(在这里是查询到的公司对象),实现数据与视图的整合,确保视图层能够获取到正确的数据进行页面展示。
+ * @return 返回包含了设置好的视图名称(COMPANY_DETAIL_PAGE)以及添加了公司对象数据的ModelAndView对象,供Spring MVC进行视图渲染展示,呈现公司详情页面给客户端。
+ */
+ @RequestMapping(path = "add")
+ public ModelAndView add(String parentCode, ModelAndView model) {
model.setViewName(COMPANY_DETAIL_PAGE);
model.addObject("company", iSysCompanyService.selectById(parentCode));
return model;
}
-
- @RequestMapping(path="update")
- public ModelAndView update(String companyCode , ModelAndView model) {
+
+ /**
+ * 处理路径为"sys/company/update"的请求的方法,用于准备并返回公司信息更新页面相关的数据和视图。
+ * 当客户端发起对应请求时,该方法首先设置要返回的视图名称为公司信息更新页面的视图名称(COMPANY_UPDATE_PAGE),然后通过ISysCompanyService查询要更新的公司本身的信息、其上级公司信息(通过公司实体类中的parentCode属性关联查询)以及所属地区信息(通过调用ISysAreaService根据公司的areaCode属性查询),并将这些查询到的公司、上级公司、地区的实体对象分别添加到ModelAndView对象中,传递给视图层,方便在更新页面中展示相关信息供用户修改,最后返回包含了视图名称和这些数据的ModelAndView对象,以便Spring MVC进行视图渲染展示更新页面给客户端。
+ *
+ * @param companyCode 从请求中传递过来的字符串参数,用于指定要更新的公司的唯一标识(如公司编号等,具体由业务中公司实体类的设计决定),根据这个标识去查询相关的公司及其关联信息。
+ * @param model ModelAndView对象,用于设置视图名称以及添加要传递给视图的多个数据对象(包括公司、上级公司、地区实体对象),实现数据与视图的整合,确保视图层能获取到完整信息用于更新页面的展示和操作。
+ * @return 返回包含了设置好视图名称(COMPANY_UPDATE_PAGE)以及添加了相关公司及关联信息数据的ModelAndView对象,供Spring MVC渲染展示公司信息更新页面给客户端。
+ */
+ @RequestMapping(path = "update")
+ public ModelAndView update(String companyCode, ModelAndView model) {
model.setViewName(COMPANY_UPDATE_PAGE);
SysCompanyEntity company = iSysCompanyService.selectById(companyCode);
SysCompanyEntity parentCompany = iSysCompanyService.selectById(company.getParentCode());
@@ -54,44 +84,80 @@ public class CompanyController {
model.addObject("area", area);
return model;
}
-
- @RequestMapping(path="info/{code}")
+
+ /**
+ * 处理路径为"sys/company/info/{code}"的请求的方法,用于根据传入的公司代码查询并返回公司的详细信息,返回结果以JSON格式响应给客户端。
+ * 通过@PathVariable注解获取请求路径中占位符{code}对应的实际值(即公司代码),然后调用ISysCompanyService的selectByCode方法查询对应的公司信息,最后将查询结果包装在Result对象中(Result对象可能是自定义的用于统一返回结果格式的类,包含了如状态码、提示信息、数据等属性),并通过@ResponseBody注解将其转换为JSON格式返回给客户端,方便前端进行数据处理和展示。
+ *
+ * @param code 从请求路径中通过@PathVariable注解获取的字符串参数,代表要查询的公司的代码,用于在业务逻辑层准确查找对应的公司信息。
+ * @return 返回一个Result对象,其中包含了查询到的公司信息(如果查询成功)以及相应的状态码和提示信息等,该Result对象会被转换为JSON格式响应给客户端,展示公司的详细信息。
+ */
+ @RequestMapping(path = "info/{code}")
@ResponseBody
public Result info(@PathVariable("code") String code) {
return Result.successResult(iSysCompanyService.selectByCode(code));
}
-
- @RequestMapping(path="listData")
+
+ /**
+ * 处理路径为"sys/company/listData"的请求的方法,用于查询并返回符合条件的公司列表数据,返回结果以JSON格式响应给客户端。
+ * 该方法接收一个SysCompanyCondition对象作为参数,这个对象应该是自定义的用于封装查询公司列表时的各种条件的类(例如可以包含查询关键字、分页信息等条件),通过调用ISysCompanyService的listData方法,根据传入的条件查询公司列表,最后直接返回查询到的公司实体对象列表(List),Spring MVC会借助@ResponseBody注解将其转换为JSON格式发送给客户端,供前端进行列表展示等操作。
+ *
+ * @param condition SysCompanyCondition对象,用于传递查询公司列表的各种条件,使得业务逻辑层能够根据这些条件筛选出符合要求的公司列表数据。
+ * @return 返回符合条件的公司实体对象列表,会被自动转换为JSON格式响应给客户端,用于前端展示公司列表信息。
+ */
+ @RequestMapping(path = "listData")
@ResponseBody
public List listData(SysCompanyCondition condition) {
return iSysCompanyService.listData(condition);
}
- @RequestMapping(path="treeData")
+ /**
+ * 处理路径为"sys/company/treeData"的请求的方法,用于查询并返回公司数据的树形结构表示形式(可能用于前端展示公司层级关系等场景),返回结果以JSON格式响应给客户端。
+ * 方法接收一个字符串参数excludeId(具体含义可能是用于排除某个特定公司节点的标识,比如在生成树形结构时不包含某个特定公司及其子公司等情况,具体取决于业务逻辑),然后调用ISysCompanyService的treeData方法根据这个参数生成公司数据的树形结构,返回的结果是JSONArray类型(通常用于表示JSON格式的数组,方便存储树形结构的节点数据等),通过@ResponseBody注解将其转换为JSON格式返回给客户端,便于前端进行树形结构的展示和交互操作。
+ *
+ * @param excludeId 从请求中传递过来的字符串参数,用于在生成公司数据树形结构时作为排除某些节点的依据,具体作用取决于业务中对树形结构生成的相关逻辑和要求。
+ * @return 返回表示公司数据树形结构的JSONArray对象,会被转换为JSON格式响应给客户端,供前端展示公司的层级关系等树形结构相关内容。
+ */
+ @RequestMapping(path = "treeData")
@ResponseBody
public JSONArray treeData(String excludeId) {
return iSysCompanyService.treeData(excludeId);
}
-
- @RequestMapping(path="save")
+
+ /**
+ * 处理路径为"sys/company/save"的请求的方法,用于保存新的公司信息,并返回保存结果给客户端,结果以JSON格式响应。
+ * 方法接收一个SysCompanyEntity对象作为参数,这个对象应该包含了要保存的公司的各项信息(如公司名称、地址、联系方式等,具体属性取决于业务中公司实体类的设计),通过调用ISysCompanyService的save方法尝试保存公司信息,如果保存成功,返回一个包含成功状态码、提示信息以及空数据的Result对象(通过Result.result方法构建,提示信息表明保存成功以及公司名称等相关内容);如果保存过程中出现异常,则调用ExceptionSupport的resolverResult方法处理异常,并将处理后的结果(同样包装在Result对象中)返回给客户端,客户端可以根据返回的结果判断保存操作是否成功以及获取相应的提示信息等。
+ *
+ * @param company SysCompanyEntity对象,包含了要保存的新公司的各项详细信息,将其传递给业务逻辑层进行保存操作。
+ * @return 返回一个Result对象,包含了保存操作的状态码、提示信息等内容,会被转换为JSON格式响应给客户端,告知客户端公司保存操作的结果情况。
+ */
+ @RequestMapping(path = "save")
@ResponseBody
public Result save(SysCompanyEntity company) {
try {
iSysCompanyService.save(company);
- return Result.result(0, null, "公司【"+company.getCompanyName()+"】保存成功!");
+ return Result.result(0, null, "公司【" + company.getCompanyName() + "】保存成功!");
} catch (Exception e) {
return ExceptionSupport.resolverResult("保存公司", this.getClass(), e);
}
}
-
- @RequestMapping(path="update" , method=RequestMethod.POST)
+
+ /**
+ * 处理路径为"sys/company/update"(使用POST方法提交的请求)的请求的方法,用于更新公司信息,并返回更新结果给客户端,结果以JSON格式响应。
+ * 与保存公司信息的方法类似,接收一个SysCompanyEntity对象作为参数,包含了要更新的公司的各项信息,通过调用ISysCompanyService的update方法进行公司信息更新操作,如果更新成功,返回一个包含成功状态码、提示信息以及空数据的Result对象(提示信息表明更新成功以及公司名称等相关内容);若更新过程中出现异常,则调用ExceptionSupport的resolverResult方法处理异常,并将处理后的结果(包装在Result对象中)返回给客户端,方便客户端知晓更新操作的结果情况。
+ * 这里特别指定了请求方法为RequestMethod.POST,意味着该方法只处理POST类型的更新公司信息的请求,与其他可能存在的同名但不同请求方法的请求进行区分,符合RESTful风格的接口设计原则(例如可以有GET方式的查询请求、POST方式的更新请求等)。
+ *
+ * @param company SysCompanyEntity对象,包含了要更新的公司的详细信息,传递给业务逻辑层用于执行更新操作。
+ * @return 返回一个Result对象,包含了更新操作的状态码、提示信息等内容,会被转换为JSON格式响应给客户端,告知客户端公司更新操作的结果情况。
+ */
+ @RequestMapping(path = "update", method = RequestMethod.POST)
@ResponseBody
public Result update(SysCompanyEntity company) {
try {
iSysCompanyService.update(company);
- return Result.result(0, null, "公司【"+company.getCompanyName()+"】修改成功!");
+ return Result.result(0, null, "公司【" + company.getCompanyName() + "】修改成功!");
} catch (Exception e) {
return ExceptionSupport.resolverResult("修改公司", this.getClass(), e);
}
}
-}
+}
\ No newline at end of file
diff --git a/tamguo-oms/src/main/java/com/tamguo/modules/sys/web/CorpAdminController.java b/tamguo-oms/src/main/java/com/tamguo/modules/sys/web/CorpAdminController.java
index 96d5d2f..5bba204 100644
--- a/tamguo-oms/src/main/java/com/tamguo/modules/sys/web/CorpAdminController.java
+++ b/tamguo-oms/src/main/java/com/tamguo/modules/sys/web/CorpAdminController.java
@@ -15,55 +15,99 @@ import com.tamguo.modules.sys.model.SysUserEntity;
import com.tamguo.modules.sys.model.condition.SysUserCondition;
import com.tamguo.modules.sys.service.ISysUserService;
+// 使用@Controller注解将这个类标记为Spring MVC中的控制器类,负责处理与企业管理员相关的Web请求,调用相应的业务逻辑方法,并根据处理结果返回给客户端合适的响应或者转发到对应的视图进行展示,是实现企业管理员业务模块页面交互和数据处理的关键部分。
@Controller
-@RequestMapping(path="sys/corpAdmin")
+// 通过@RequestMapping注解为这个控制器类下的所有请求路径设置一个公共的前缀,即该控制器处理的请求路径都以"sys/corpAdmin"开头,便于对企业管理员相关的各种请求进行统一管理和分类。
+@RequestMapping(path = "sys/corpAdmin")
public class CorpAdminController {
+ // 定义一个常量字符串,表示企业管理员列表页面(或首页)的视图名称,遵循Spring MVC视图解析的配置规则,对应着展示企业管理员列表相关内容的模板文件路径(如JSP、Thymeleaf等模板文件的具体路径)。
private final String CORPADMIN_INDEX_PAGE = "modules/sys/corpAdmin/index";
+ // 定义常量字符串,代表企业管理员信息更新页面的视图名称,对应展示修改企业管理员信息相关内容的模板文件路径。
private final String CORPADMIN_UPDATE_PAGE = "modules/sys/corpAdmin/update";
-
+
+ // 通过@Autowired注解自动注入ISysUserService接口的实现类实例,用于调用与系统用户(这里特指企业管理员相关的用户操作,因为从类名和业务逻辑推测,处理的是企业管理员相关的业务)相关的业务逻辑方法,比如查询、保存、更新管理员信息等操作,实现控制器层与业务逻辑层的交互。
@Autowired
private ISysUserService iSysUserService;
- @RequestMapping(path="index")
+ /**
+ * 处理路径为"sys/corpAdmin/index"的请求的方法,用于返回企业管理员列表页面的视图名称。
+ * 当客户端发起对应的请求时,该方法被调用,其主要功能就是告知Spring MVC要渲染展示的视图对应的名称,以便找到对应的模板文件进行页面展示(这里只是简单返回视图名称,具体页面内容的渲染由视图层根据配置和模板文件来完成)。
+ *
+ * @param model ModelAndView对象,虽然在这里没有向其添加额外的数据,但在Spring MVC的请求处理流程中,这个对象是用于传递数据和设置视图名称的常用载体,此处主要利用它来遵循方法签名的统一要求,在其他方法中可能会向其添加数据后再返回。
+ * @return 返回企业管理员列表页面的视图名称(即常量CORPADMIN_INDEX_PAGE所定义的值),Spring MVC根据这个名称去查找并渲染对应的视图模板文件,展示企业管理员列表页面给客户端。
+ */
+ @RequestMapping(path = "index")
public String index(ModelAndView model) {
return CORPADMIN_INDEX_PAGE;
}
-
- @RequestMapping(path="update")
- public ModelAndView update(String userCode , ModelAndView model) {
+
+ /**
+ * 处理路径为"sys/corpAdmin/update"的请求的方法,用于准备并返回企业管理员信息更新页面相关的数据和视图。
+ * 当客户端发起该请求时,方法会被调用,先通过注入的ISysUserService实例,根据传入的userCode参数查询对应的企业管理员信息,并将查询到的管理员对象添加到ModelAndView对象中,然后设置要返回的视图名称为企业管理员信息更新页面的视图名称(CORPADMIN_UPDATE_PAGE),最后返回包含了视图名称和管理员对象数据的ModelAndView对象,使得Spring MVC能够正确渲染展示企业管理员信息更新页面。
+ *
+ * @param userCode 从请求中传递过来的字符串参数,用于指定要查询的企业管理员的标识(具体含义取决于业务中用户实体类的设计以及业务逻辑,可能是用户编号等唯一标识),通过这个参数去查询对应的管理员信息。
+ * @param model ModelAndView对象,用于设置视图名称以及添加要传递给视图的数据(在这里是查询到的管理员对象),实现数据与视图的整合,确保视图层能够获取到正确的数据进行页面展示。
+ * @return 返回包含了设置好的视图名称(CORPADMIN_UPDATE_PAGE)以及添加了管理员对象数据的ModelAndView对象,供Spring MVC进行视图渲染展示,呈现企业管理员信息更新页面给客户端。
+ */
+ @RequestMapping(path = "update")
+ public ModelAndView update(String userCode, ModelAndView model) {
model.addObject("user", iSysUserService.selectById(userCode));
model.setViewName(CORPADMIN_UPDATE_PAGE);
return model;
}
-
- @RequestMapping(path="save",method=RequestMethod.POST)
+
+ /**
+ * 处理路径为"sys/corpAdmin/save"(且请求方法为POST的请求)的请求的方法,用于保存新的企业管理员信息,并返回保存结果给客户端,结果以JSON格式响应。
+ * 该方法接收一个SysUserEntity对象作为参数,这个对象应该包含了要保存的企业管理员的各项信息(如用户名、密码、权限等,具体属性取决于业务中用户实体类的设计),通过调用ISysUserService的saveAdmin方法尝试保存管理员信息,如果保存成功,返回一个包含成功状态码、提示信息以及空数据的Result对象(通过Result.result方法构建,提示信息表明保存成功以及管理员的用户名等相关内容);如果保存过程中出现异常,则调用ExceptionSupport的resolverResult方法处理异常,并将处理后的结果(同样包装在Result对象中)返回给客户端,客户端可以根据返回的结果判断保存操作是否成功以及获取相应的提示信息等。
+ * 这里指定请求方法为RequestMethod.POST,符合常见的RESTful风格接口设计原则,通常POST方法用于创建资源(在这里就是创建新的企业管理员记录),确保该接口只处理正确请求方法的保存管理员信息的请求,与其他可能的请求进行区分。
+ *
+ * @param user SysUserEntity对象,包含了要保存的新企业管理员的各项详细信息,将其传递给业务逻辑层进行保存操作。
+ * @return 返回一个Result对象,包含了保存操作的状态码、提示信息等内容,会被转换为JSON格式响应给客户端,告知客户端企业管理员保存操作的结果情况。
+ */
+ @RequestMapping(path = "save", method = RequestMethod.POST)
@ResponseBody
public Result save(SysUserEntity user) {
try {
iSysUserService.saveAdmin(user);
- return Result.result(0, null, "管理员【"+user.getUserName()+"】添加成功");
+ return Result.result(0, null, "管理员【" + user.getUserName() + "】添加成功");
} catch (Exception e) {
return ExceptionSupport.resolverResult("添加管理员错误", this.getClass(), e);
}
}
-
- @RequestMapping(path="update",method=RequestMethod.POST)
+
+ /**
+ * 处理路径为"sys/corpAdmin/update"(且请求方法为POST的请求)的请求的方法,用于更新企业管理员信息,并返回更新结果给客户端,结果以JSON格式响应。
+ * 与保存管理员信息的方法类似,接收一个SysUserEntity对象作为参数,包含了要更新的企业管理员的各项信息,通过调用ISysUserService的updateAdmin方法进行管理员信息更新操作,如果更新成功,返回一个包含成功状态码、提示信息以及空数据的Result对象(提示信息表明更新成功以及管理员的用户名等相关内容);若更新过程中出现异常,则调用ExceptionSupport的resolverResult方法处理异常,并将处理后的结果(包装在Result对象中)返回给客户端,方便客户端知晓更新操作的结果情况。
+ * 同样指定请求方法为RequestMethod.POST,符合RESTful风格接口设计要求,用于明确该接口只处理POST请求方式的更新管理员信息的操作,避免与其他同名但不同请求方法的请求混淆。
+ *
+ * @param user SysUserEntity对象,包含了要更新的企业管理员的详细信息,传递给业务逻辑层用于执行更新操作。
+ * @return 返回一个Result对象,包含了更新操作的状态码、提示信息等内容,会被转换为JSON格式响应给客户端,告知客户端企业管理员更新操作的结果情况。
+ */
+ @RequestMapping(path = "update", method = RequestMethod.POST)
@ResponseBody
public Result update(SysUserEntity user) {
try {
iSysUserService.updateAdmin(user);
- return Result.result(0, null, "管理员【"+user.getUserName()+"】修改成功");
+ return Result.result(0, null, "管理员【" + user.getUserName() + "】修改成功");
} catch (Exception e) {
return ExceptionSupport.resolverResult("修改管理员错误", this.getClass(), e);
}
}
-
- @RequestMapping(path="listData",method=RequestMethod.POST)
+
+ /**
+ * 处理路径为"sys/corpAdmin/listData"(且请求方法为POST的请求)的请求的方法,用于查询并返回符合条件的企业管理员列表数据,返回结果以适合前端表格组件(如jqGrid等)使用的格式包装在Map中,并以JSON格式响应给客户端。
+ * 该方法接收一个SysUserCondition对象作为参数,这个对象应该是自定义的用于封装查询企业管理员列表时的各种条件的类(例如可以包含查询关键字、分页信息等条件),通过调用ISysUserService的listData方法,根据传入的条件查询企业管理员列表,返回的结果是一个Page对象(表示分页后的用户实体对象列表,由MyBatis Plus的分页插件生成相关分页信息),然后调用Result.jqGridResult方法将分页信息(总记录数、每页记录数、当前页码、总页数等)以及实际的管理员记录数据进行整合,包装成一个Map对象(符合前端表格组件期望的格式),最后通过@ResponseBody注解将这个Map对象转换为JSON格式返回给客户端,供前端表格组件进行数据展示和分页等操作。
+ * 这里指定请求方法为RequestMethod.POST,可能是基于业务逻辑要求或者与前端交互的约定,确保该接口只处理POST请求方式的查询管理员列表数据的操作。
+ *
+ * @param condition SysUserCondition对象,用于传递查询企业管理员列表的各种条件,使得业务逻辑层能够根据这些条件筛选出符合要求的管理员列表数据。
+ * @return 返回一个Map对象,其中包含了适合前端表格组件展示的企业管理员列表数据以及相关的分页信息,该Map对象会被转换为JSON格式响应给客户端,用于前端展示管理员列表信息并进行分页等操作。
+ */
+ @RequestMapping(path = "listData", method = RequestMethod.POST)
@ResponseBody
public Map listData(SysUserCondition condition) {
Page page = iSysUserService.listData(condition);
return Result.jqGridResult(page.getRecords(), page.getTotal(), page.getSize(), page.getCurrent(), page.getPages());
}
-
-}
+
+}
\ No newline at end of file
diff --git a/tamguo-oms/src/main/java/com/tamguo/modules/sys/web/IndexController.java b/tamguo-oms/src/main/java/com/tamguo/modules/sys/web/IndexController.java
index b6d954f..7522ba9 100644
--- a/tamguo-oms/src/main/java/com/tamguo/modules/sys/web/IndexController.java
+++ b/tamguo-oms/src/main/java/com/tamguo/modules/sys/web/IndexController.java
@@ -4,12 +4,21 @@ import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;
+// 使用@Controller注解将这个类标记为Spring MVC中的控制器类,意味着它负责处理Web请求,并将请求转发到相应的视图进行展示,在整个Web应用中承担着页面交互逻辑的一部分,这里大概率是用于处理系统首页相关的请求逻辑。
@Controller
public class IndexController {
- @RequestMapping(path="index")
+ /**
+ * 这个方法使用@RequestMapping注解将其与路径为"index"的请求进行映射,意味着当客户端发起对"index"路径的请求时,该方法就会被调用执行。
+ * 它接收一个ModelAndView对象,不过在当前实现中并没有向这个对象添加额外的数据(虽然ModelAndView常用于传递数据给视图,但此处只是简单利用它遵循Spring MVC方法签名的常规要求)。
+ * 方法的主要功能是返回一个字符串"index",这个字符串在Spring MVC的视图解析机制下,会对应到一个具体的视图模板文件(例如JSP、Thymeleaf等格式的文件,具体取决于项目的视图解析配置),Spring MVC会根据这个返回的视图名称去查找并渲染对应的视图,最终展示给客户端作为系统的首页(这里假设"index"对应的视图就是系统首页相关的展示页面)。
+ *
+ * @param model ModelAndView对象,用于在一般情况下添加模型数据以及设置视图名称,不过在此方法中目前仅作为方法参数的形式存在,未实际添加数据,主要是为了符合Spring MVC请求处理方法的统一签名规范。
+ * @return 返回视图名称"index",以便Spring MVC根据此名称查找并渲染对应的视图模板文件,展示系统首页给客户端。
+ */
+ @RequestMapping(path = "index")
public String sysLogin(ModelAndView model) {
return "index";
}
-
-}
+
+}
\ No newline at end of file
diff --git a/tamguo-oms/src/main/java/com/tamguo/modules/sys/web/LoginController.java b/tamguo-oms/src/main/java/com/tamguo/modules/sys/web/LoginController.java
index 697cda9..7007559 100644
--- a/tamguo-oms/src/main/java/com/tamguo/modules/sys/web/LoginController.java
+++ b/tamguo-oms/src/main/java/com/tamguo/modules/sys/web/LoginController.java
@@ -22,49 +22,89 @@ import com.tamguo.common.utils.SystemConstant;
import com.tamguo.modules.sys.service.ISysUserService;
import com.tamguo.modules.sys.utils.ShiroUtils;
+// 使用@Controller注解将这个类标记为Spring MVC中的控制器类,负责处理与用户登录相关的Web请求,在登录流程中与Shiro框架以及业务逻辑层进行交互,根据不同情况返回相应的响应给客户端,是实现用户登录功能的核心控制器类。
@Controller
public class LoginController {
-
+
+ // 通过@Autowired注解自动注入ISysUserService接口的实现类实例,用于调用与系统用户相关的业务逻辑方法,比如查询用户权限菜单等操作,实现控制器层与业务逻辑层的交互,辅助完成登录相关的业务处理。
@Autowired
private ISysUserService iSysUserService;
- @RequestMapping(path="login")
+ /**
+ * 处理路径为"login"的GET请求的方法,用于根据用户当前的登录状态返回相应的视图名称,引导用户进入正确的页面。
+ * 通过ShiroUtils工具类的isLogin方法判断当前用户是否已经登录,如果已经登录(返回true),则直接返回"index"视图名称,让Spring MVC渲染展示系统的首页;如果未登录(返回false),则返回"login"视图名称,引导用户进入登录页面进行登录操作。
+ *
+ * @param model ModelAndView对象,虽然在这里没有向其添加额外的数据,但在Spring MVC的请求处理流程中,它是常用的用于传递数据和设置视图名称的载体,此处主要是为了遵循方法签名的统一要求,在其他相关方法中可能会向其添加数据后再返回。
+ * @return 返回相应的视图名称,根据用户登录状态决定是返回系统首页视图名称"index"还是登录页面视图名称"login",以便Spring MVC查找并渲染对应的视图模板文件进行展示。
+ */
+ @RequestMapping(path = "login")
public String sysLogin(ModelAndView model) {
- if(ShiroUtils.isLogin()) {
+ if (ShiroUtils.isLogin()) {
return "index";
}
return "login";
}
-
+
+ /**
+ * 处理路径为"login"的POST请求的方法,用于处理用户提交的登录表单数据,进行登录验证以及相关业务逻辑处理,并返回登录结果给客户端,结果以JSON格式响应。
+ * 通过@ResponseBody注解将方法返回的Result对象转换为JSON格式发送给客户端,方便前端根据返回结果进行相应的提示和页面跳转等操作。同时,指定请求方法为RequestMethod.POST,表明该方法只处理POST类型的登录请求,符合常见的RESTful风格接口设计原则,与GET请求的登录页面展示方法(sysLogin方法)区分开来,分别处理不同阶段的登录相关操作。
+ *
+ * @param request HttpServletRequest对象,用于获取请求相关的信息,比如从请求中获取用户输入的用户名、密码、验证码等参数,还可以在登录成功后通过它设置会话属性等操作,与客户端和服务器的交互紧密相关。
+ * @param response HttpServletResponse对象,用于设置响应相关的信息,例如在验证码错误等情况下可以通过它设置响应状态码、返回错误提示信息给客户端等,确保客户端能正确接收到服务器的响应内容并进行相应处理。
+ * @param username 从请求中获取的字符串参数,代表用户输入的用户名,是登录验证的关键信息之一,将用于后续与数据库中存储的用户信息进行比对验证。
+ * @param rememberUser 从请求中获取的布尔类型参数,用于表示用户是否选择记住登录状态(具体实现可能涉及到设置相应的Cookie或者Shiro的记住我功能等相关逻辑,不过此处代码未详细展示这部分,仅接收该参数),根据其值来决定是否启用记住登录状态的相关处理。
+ * @param password 从请求中获取的字符串参数,代表用户输入的密码,同样是登录验证的重要信息,会经过加密等处理后与数据库中的密码进行比对验证。
+ * @param validCode 从请求中获取的字符串参数,代表用户输入的验证码,用于和服务器端生成并存储在会话中的验证码进行比对,验证用户输入的合法性,防止恶意登录等情况。
+ * @return 返回一个Result对象,包含了登录操作的状态码、提示信息以及可能的数据内容(如登录成功后返回用户名等),该Result对象会被转换为JSON格式响应给客户端,告知客户端登录操作的结果情况,方便前端根据结果进行相应的页面跳转、提示用户等操作。
+ * @throws IOException 如果在处理登录过程中涉及到输入输出操作(例如读取验证码、设置响应内容等情况)出现异常,可能会抛出IOException异常,这里声明抛出该异常以便由上层调用者(通常是Spring MVC框架)进行相应的异常处理,比如返回错误页面等操作。
+ */
@ResponseBody
@RequestMapping(value = "login", method = RequestMethod.POST)
- public Result toLogin(HttpServletRequest request, HttpServletResponse response , String username , Boolean rememberUser, String password, String validCode)
- throws IOException {
+ public Result toLogin(HttpServletRequest request, HttpServletResponse response, String username,
+ Boolean rememberUser, String password, String validCode) throws IOException {
try {
+ // 通过ShiroUtils工具类获取存储在会话中的验证码(使用SystemConstant.KAPTCHA_SESSION_KEY作为键来查找对应的验证码,SystemConstant应该是一个用于存放系统常量的类),并将获取到的验证码与用户输入的验证码进行不区分大小写的比对,如果不一致,说明验证码错误,直接返回包含相应错误提示信息的Result对象给客户端。
String kaptcha = ShiroUtils.getKaptcha(SystemConstant.KAPTCHA_SESSION_KEY);
if (!validCode.equalsIgnoreCase(kaptcha)) {
return Result.failResult("验证码错误");
}
+
+ // 通过ShiroUtils工具类获取当前的Subject对象,Subject代表当前执行操作的用户主体,在Shiro框架中是进行认证、授权等操作的核心入口点,后续将基于这个对象进行用户登录认证操作。
Subject subject = ShiroUtils.getSubject();
- // sha256加密
+
+ // 使用Sha256Hash对用户输入的密码进行加密处理,将加密后的结果转换为十六进制字符串形式,以提高密码存储和传输的安全性,确保在与数据库中存储的密码进行比对时使用的是经过相同加密算法处理后的密码,符合安全规范。
password = new Sha256Hash(password).toHex();
+
+ // 创建一个UsernamePasswordToken对象,将用户名和加密后的密码传入构造函数,这个对象在Shiro框架中用于表示用户登录的凭证信息,后续会传递给Shiro的认证机制进行登录验证。
UsernamePasswordToken token = new UsernamePasswordToken(username, password);
+
+ // 通过Subject对象调用login方法,传入之前创建的包含用户凭证信息的UsernamePasswordToken对象,触发Shiro框架的登录认证流程,Shiro会根据配置的Realm(通常是自定义的实现了认证逻辑的类)去验证用户名和密码等信息是否正确,如果认证通过则登录成功,否则会抛出相应的认证异常。
subject.login(token);
-
- // 获取权限菜单
+
+ // 登录成功后,通过注入的ISysUserService实例,调用其findUserMenuList方法,根据当前登录用户的用户代码(通过ShiroUtils.getUserCode方法获取)查询该用户对应的权限菜单信息,并将查询到的权限菜单列表存储到当前会话中,键为"userMenuList",方便后续在系统中根据用户权限展示不同的菜单选项,实现权限控制和菜单展示的功能。
request.getSession().setAttribute("userMenuList", iSysUserService.findUserMenuList(ShiroUtils.getUserCode()));
+
+ // 将当前登录用户的信息(通过ShiroUtils.getUser方法获取)存储到当前会话中,键为"currAdmin",方便在系统的其他地方获取当前登录用户的详细信息进行相关业务处理,例如在页面上展示当前登录用户的相关信息等操作。
request.getSession().setAttribute("currAdmin", ShiroUtils.getUser());
} catch (UnknownAccountException e) {
+ // 如果在Shiro的登录认证过程中抛出UnknownAccountException异常,说明找不到对应的用户账户(可能是用户名不存在等原因),则返回一个包含相应错误状态码和提示信息("找不到账户")的Result对象给客户端,告知用户登录失败的原因。
return Result.result(501, null, "找不到账户");
} catch (IncorrectCredentialsException e) {
+ // 当抛出IncorrectCredentialsException异常时,表示用户输入的账户验证失败,通常是密码错误等原因导致,返回包含对应错误状态码和提示信息("账户验证失败")的Result对象给客户端,提示用户登录失败。
return Result.result(502, null, "账户验证失败");
} catch (LockedAccountException e) {
+ // 如果出现LockedAccountException异常,意味着用户账户被锁定(可能是由于多次错误登录等原因,具体锁定逻辑通常在业务层或相关配置中设置),同样返回包含相应错误状态码和提示信息("账户验证失败")的Result对象给客户端,告知用户账户状态异常导致登录失败。
return Result.result(503, null, "账户验证失败");
} catch (AuthenticationException e) {
+ // 捕获其他类型的AuthenticationException异常,这类异常通常涵盖了各种登录认证过程中出现的问题(除了上述明确处理的几种常见异常情况外),同样返回包含错误状态码和提示信息("账户验证失败")的Result对象给客户端,提示用户登录失败以及可能存在的未知认证问题。
return Result.result(504, null, "账户验证失败");
}
+
+ // 再次将当前登录用户的信息存储到会话中(这里可能是为了确保会话中一定存在该用户信息,或者在后续可能的业务逻辑中方便再次获取等原因,代码逻辑上有一定的重复,但不影响功能实现),键为"currAdmin"。
request.getSession().setAttribute("currAdmin", ShiroUtils.getUser());
+
+ // 如果登录过程顺利,没有抛出任何异常,说明登录成功,返回一个包含成功状态码以及用户名信息的Result对象给客户端,告知客户端登录成功以及登录的用户名等情况,方便前端进行相应的页面跳转和提示操作,例如跳转到系统首页等。
return Result.successResult(username);
}
-
-}
+
+}
\ No newline at end of file
diff --git a/tamguo-oms/src/main/java/com/tamguo/modules/sys/web/LogoutController.java b/tamguo-oms/src/main/java/com/tamguo/modules/sys/web/LogoutController.java
index b7626c9..9399bee 100644
--- a/tamguo-oms/src/main/java/com/tamguo/modules/sys/web/LogoutController.java
+++ b/tamguo-oms/src/main/java/com/tamguo/modules/sys/web/LogoutController.java
@@ -6,14 +6,27 @@ import org.springframework.web.servlet.ModelAndView;
import com.tamguo.modules.sys.utils.ShiroUtils;
+// 使用@Controller注解将这个类标记为Spring MVC中的控制器类,负责处理与用户注销相关的Web请求,通过调用Shiro框架提供的注销方法来实现用户注销功能,并将页面重定向到登录页面,是实现用户退出登录操作的关键部分。
@Controller
public class LogoutController {
- @RequestMapping(path="logout")
+ /**
+ * 处理路径为"logout"的请求的方法,用于执行用户注销操作,并返回重定向到登录页面的视图信息。
+ * 通过@RequestMapping注解将该方法与"logout"路径的请求进行映射,当客户端发起对应的注销请求时,这个方法就会被调用执行。
+ * 方法接收一个ModelAndView对象,用于设置要返回的视图名称以及传递可能的数据(在当前方法中主要是设置视图名称),实现将用户注销后的页面重定向到登录页面的功能,同时借助ShiroUtils工具类来执行具体的注销操作逻辑,清除用户相关的认证信息和会话数据等。
+ *
+ * @param model ModelAndView对象,用于设置视图名称,在这个方法中主要是将其设置为"login",使得Spring MVC能够找到对应的登录页面视图进行渲染展示,引导用户回到登录页面,完成注销后的页面跳转操作。
+ * @return 返回包含了设置好视图名称("login")的ModelAndView对象,Spring MVC会根据这个对象将页面重定向到登录页面,让用户重新登录或者进行其他操作。
+ */
+ @RequestMapping(path = "logout")
public ModelAndView logout(ModelAndView model) {
+ // 调用ShiroUtils工具类的logout方法,该方法会触发Shiro框架执行用户注销的相关操作,清除当前用户的认证信息、会话数据等相关内容,使当前用户退出登录状态,确保用户注销后相关数据的安全性以及资源的合理释放。
ShiroUtils.logout();
+
+ // 设置要返回的视图名称为"login",这样Spring MVC在处理这个ModelAndView对象时,会将页面重定向到登录页面,方便用户在注销后重新进行登录操作或者进行其他相应的操作(比如忘记密码等相关操作,如果登录页面有提供相应入口的话)。
model.setViewName("login");
+
return model;
}
-
-}
+
+}
\ No newline at end of file
diff --git a/tamguo-oms/src/main/java/com/tamguo/modules/sys/web/SecAdminController.java b/tamguo-oms/src/main/java/com/tamguo/modules/sys/web/SecAdminController.java
index 59b009d..d5576e8 100644
--- a/tamguo-oms/src/main/java/com/tamguo/modules/sys/web/SecAdminController.java
+++ b/tamguo-oms/src/main/java/com/tamguo/modules/sys/web/SecAdminController.java
@@ -15,40 +15,77 @@ import com.tamguo.modules.sys.model.condition.SysUserCondition;
import com.tamguo.modules.sys.model.enums.SysUserMgrTypeEnum;
import com.tamguo.modules.sys.service.ISysUserService;
+// 使用@Controller注解将这个类标记为Spring MVC中的控制器类,负责处理与安全管理员相关的Web请求,调用相应的业务逻辑方法,并根据处理结果返回给客户端合适的响应或者转发到对应的视图进行展示,是实现安全管理员业务模块页面交互和数据处理的关键部分。
@Controller
-@RequestMapping(path="sys/secAdmin")
+// 通过@RequestMapping注解为这个控制器类下的所有请求路径设置一个公共的前缀,即该控制器处理的请求路径都以"sys/secAdmin"开头,便于对安全管理员相关的各种请求进行统一管理和分类。
+@RequestMapping(path = "sys/secAdmin")
public class SecAdminController {
-
+
+ // 定义一个常量字符串,表示安全管理员列表页面(或首页)的视图名称,遵循Spring MVC视图解析的配置规则,对应着展示安全管理员列表相关内容的模板文件路径(如JSP、Thymeleaf等模板文件的具体路径)。
private final String SECADMIN_INDEX_PAGE = "modules/sys/secAdmin/index";
+ // 定义常量字符串,代表安全管理员添加(或编辑相关信息,具体取决于业务逻辑)页面的视图名称,对应展示添加安全管理员信息相关内容的模板文件路径。
private final String SECADMIN_ADD_PAGE = "modules/sys/secAdmin/add";
-
+
+ // 通过@Autowired注解自动注入ISysUserService接口的实现类实例,用于调用与系统用户(这里特指安全管理员相关的用户操作,因为从类名和业务逻辑推测,处理的是安全管理员相关的业务)相关的业务逻辑方法,比如查询、保存、设置数据权限等操作,实现控制器层与业务逻辑层的交互。
@Autowired
private ISysUserService iSysUserService;
- @RequestMapping(path="index")
+ /**
+ * 处理路径为"sys/secAdmin/index"的请求的方法,用于返回安全管理员列表页面的视图名称。
+ * 当客户端发起对应的请求时,该方法被调用,其主要功能就是告知Spring MVC要渲染展示的视图对应的名称,以便找到对应的模板文件进行页面展示(这里只是简单返回视图名称,具体页面内容的渲染由视图层根据配置和模板文件来完成)。
+ *
+ * @param model ModelAndView对象,虽然在这里没有向其添加额外的数据,但在Spring MVC的请求处理流程中,这个对象是用于传递数据和设置视图名称的常用载体,此处主要利用它来遵循方法签名的统一要求,在其他方法中可能会向其添加数据后再返回。
+ * @return 返回安全管理员列表页面的视图名称(即常量SECADMIN_INDEX_PAGE所定义的值),Spring MVC根据这个名称去查找并渲染对应的视图模板文件,展示安全管理员列表页面给客户端。
+ */
+ @RequestMapping(path = "index")
public String index(ModelAndView model) {
return SECADMIN_INDEX_PAGE;
}
-
- @RequestMapping(path="add")
- public ModelAndView add(String userCode , ModelAndView model) {
+
+ /**
+ * 处理路径为"sys/secAdmin/add"的请求的方法,用于准备并返回安全管理员添加(或编辑)页面相关的数据和视图。
+ * 当客户端发起该请求时,方法会被调用,先设置要返回的视图名称为安全管理员添加页面的视图名称(SECADMIN_ADD_PAGE),然后通过注入的ISysUserService实例,根据传入的userCode参数查询对应的安全管理员信息,并将查询到的管理员对象添加到ModelAndView对象中,同时还调用iSysUserService的selectUserDataScope方法,根据userCode查询该管理员的数据权限范围信息,并将其也添加到ModelAndView对象中,最后返回包含了视图名称、管理员对象以及数据权限范围信息数据的ModelAndView对象,使得Spring MVC能够正确渲染展示安全管理员添加(或编辑)页面。
+ *
+ * @param userCode 从请求中传递过来的字符串参数,用于指定要查询的安全管理员的标识(具体含义取决于业务中用户实体类的设计以及业务逻辑,可能是用户编号等唯一标识),通过这个参数去查询对应的管理员信息以及其数据权限范围信息。
+ * @param model ModelAndView对象,用于设置视图名称以及添加要传递给视图的数据(在这里是查询到的管理员对象和数据权限范围信息),实现数据与视图的整合,确保视图层能够获取到正确的数据进行页面展示。
+ * @return 返回包含了设置好的视图名称(SECADMIN_ADD_PAGE)以及添加了管理员对象和数据权限范围信息数据的ModelAndView对象,供Spring MVC进行视图渲染展示,呈现安全管理员添加(或编辑)页面给客户端。
+ */
+ @RequestMapping(path = "add")
+ public ModelAndView add(String userCode, ModelAndView model) {
model.setViewName(SECADMIN_ADD_PAGE);
model.addObject("user", iSysUserService.selectById(userCode));
model.addObject("userDataScopeList", iSysUserService.selectUserDataScope(userCode));
return model;
}
-
- @RequestMapping(path="save")
+
+ /**
+ * 处理路径为"sys/secAdmin/save"的请求的方法,用于保存安全管理员的数据权限信息,并返回保存结果给客户端,结果以JSON格式响应。
+ * 该方法接收一个SysUserEntity对象作为参数,这个对象应该包含了要保存数据权限的安全管理员的各项信息(如用户名、用户编号等,具体属性取决于业务中用户实体类的设计),同时还接收一个ModelAndView对象(不过在当前方法中未对其进行实质性操作,主要是为了遵循方法签名的统一要求),通过调用ISysUserService的saveUserDataScope方法,传入管理员对象和表示安全管理员类型的枚举值(SysUserMgrTypeEnum.SEC_ADMIN),尝试保存该管理员的数据权限信息,如果保存成功,返回一个包含成功状态码、提示信息以及空数据的Result对象(通过Result.result方法构建,提示信息表明保存成功以及管理员的用户名等相关内容);如果保存过程中出现异常(此处代码未详细处理异常情况,实际应用中可根据需要添加更完善的异常处理逻辑),则返回的结果可能不符合预期,客户端可以根据返回的结果判断保存操作是否成功以及获取相应的提示信息等。
+ *
+ * @param user SysUserEntity对象,包含了要保存数据权限的安全管理员的各项详细信息,将其传递给业务逻辑层进行数据权限保存操作。
+ * @param model ModelAndView对象,在当前方法中未实际使用,主要是为了符合Spring MVC请求处理方法的统一签名格式,可根据业务需求在后续扩展中对其进行相应的操作,比如添加更多的数据传递等功能。
+ * @return 返回一个Result对象,包含了保存操作的状态码、提示信息等内容,会被转换为JSON格式响应给客户端,告知客户端安全管理员数据权限保存操作的结果情况。
+ */
+ @RequestMapping(path = "save")
@ResponseBody
- public Result save(SysUserEntity user , ModelAndView model) {
- iSysUserService.saveUserDataScope(user , SysUserMgrTypeEnum.SEC_ADMIN);
- return Result.result(0, null, "【"+user.getUserName()+"】保存数据权限成功!");
+ public Result save(SysUserEntity user, ModelAndView model) {
+ iSysUserService.saveUserDataScope(user, SysUserMgrTypeEnum.SEC_ADMIN);
+ return Result.result(0, null, "【" + user.getUserName() + "】保存数据权限成功!");
}
-
- @RequestMapping(path="listData",method=RequestMethod.POST)
+
+ /**
+ * 处理路径为"sys/secAdmin/listData"(且请求方法为POST的请求)的请求的方法,用于查询并返回符合条件的安全管理员列表数据,返回结果以适合前端表格组件(如jqGrid等)使用的格式包装在Map中,并以JSON格式响应给客户端。
+ * 该方法接收一个SysUserCondition对象作为参数,这个对象应该是自定义的用于封装查询安全管理员列表时的各种条件的类(例如可以包含查询关键字、分页信息等条件),通过调用ISysUserService的listData方法,根据传入的条件查询安全管理员列表,返回的结果是一个Page对象(表示分页后的用户实体对象列表,由MyBatis Plus的分页插件生成相关分页信息),然后调用Result.jqGridResult方法将分页信息(总记录数、每页记录数、当前页码、总页数等)以及实际的管理员记录数据进行整合,包装成一个Map对象(符合前端表格组件期望的格式),最后通过@ResponseBody注解将这个Map对象转换为JSON格式返回给客户端,供前端表格组件进行数据展示和分页等操作。
+ * 这里指定请求方法为RequestMethod.POST,可能是基于业务逻辑要求或者与前端交互的约定,确保该接口只处理POST请求方式的查询管理员列表数据的操作。
+ *
+ * @param condition SysUserCondition对象,用于传递查询安全管理员列表的各种条件,使得业务逻辑层能够根据这些条件筛选出符合要求的管理员列表数据。
+ * @return 返回一个Map对象,其中包含了适合前端表格组件展示的安全管理员列表数据以及相关的分页信息,该Map对象会被转换为JSON格式响应给客户端,用于前端展示管理员列表信息并进行分页等操作。
+ */
+ @RequestMapping(path = "listData", method = RequestMethod.POST)
@ResponseBody
public Map listData(SysUserCondition condition) {
Page page = iSysUserService.listData(condition);
return Result.jqGridResult(page.getRecords(), page.getTotal(), page.getSize(), page.getCurrent(), page.getPages());
}
-}
+
+}
\ No newline at end of file
diff --git a/tamguo-oms/src/main/java/com/tamguo/modules/sys/web/SysAreaController.java b/tamguo-oms/src/main/java/com/tamguo/modules/sys/web/SysAreaController.java
index 1e6b630..4a62924 100644
--- a/tamguo-oms/src/main/java/com/tamguo/modules/sys/web/SysAreaController.java
+++ b/tamguo-oms/src/main/java/com/tamguo/modules/sys/web/SysAreaController.java
@@ -15,31 +15,59 @@ import com.tamguo.modules.sys.model.SysAreaEntity;
import com.tamguo.modules.sys.model.condition.SysAreaCondition;
import com.tamguo.modules.sys.service.ISysAreaService;
+// 使用@Controller注解将这个类标记为Spring MVC中的控制器类,负责处理与系统地区相关的Web请求,它会根据不同的请求路径调用对应的业务逻辑方法,然后将处理结果以合适的形式(如视图展示或JSON数据返回)反馈给客户端,是实现地区业务模块在Web端交互的核心部分。
@Controller
-@RequestMapping(path="sys/area")
+// 通过@RequestMapping注解为这个控制器类下的所有请求路径设置一个公共的前缀,表明该控制器主要处理以"sys/area"开头的请求,便于对地区相关的各类请求进行统一管理与分类。
+@RequestMapping(path = "sys/area")
public class SysAreaController {
+ // 定义一个常量字符串,表示地区列表页面(通常作为地区管理模块的首页)的视图名称,遵循Spring MVC视图解析的配置规则,其对应着实际用于展示地区列表相关内容的模板文件路径(例如可能是JSP、Thymeleaf等模板文件的具体路径)。
private final String AREA_INDEX_PAGE = "modules/sys/area/index";
+ // 定义常量字符串,代表添加地区页面的视图名称,对应着展示添加地区相关表单及信息的模板文件路径,用于在添加新地区时向用户呈现相应的输入界面。
private final String AREA_ADD_PAGE = "modules/sys/area/add";
+ // 定义常量字符串,用于表示修改地区信息页面的视图名称,对应展示修改地区已有信息相关内容的模板文件路径,方便用户对已存在的地区记录进行编辑操作。
private final String AREA_UPDATE_PAGE = "modules/sys/area/update";
+ // 通过@Autowired注解自动注入ISysAreaService接口的实现类实例,用于调用与地区相关的业务逻辑方法,例如查询地区信息、保存地区数据、更新地区记录以及获取地区数据的树形结构等操作,以此实现控制器层与业务逻辑层之间的交互,完成地区相关业务的具体处理。
@Autowired
- private ISysAreaService iSysAreaService;
-
- @RequestMapping(path="index")
+ private ISysAreaService iSysAreaService;
+
+ /**
+ * 处理路径为"sys/area/index"的请求的方法,该方法的作用是返回地区列表页面的视图名称。
+ * 当客户端发起对应的请求时,此方法被调用,它仅仅是简单地将预先定义好的地区列表页面视图名称(AREA_INDEX_PAGE)返回给Spring MVC框架,然后由框架根据视图解析配置找到对应的模板文件进行渲染展示,向客户端呈现地区列表页面。
+ * 此方法没有接收额外的参数,也未对ModelAndView对象进行数据添加等操作,只是负责视图名称的返回,以引导页面展示。
+ * @return 返回地区列表页面的视图名称(即常量AREA_INDEX_PAGE所定义的值),供Spring MVC查找并渲染对应的视图模板文件,从而展示地区列表页面给客户端。
+ */
+ @RequestMapping(path = "index")
public String index() {
return AREA_INDEX_PAGE;
}
-
- @RequestMapping(path="add")
- public ModelAndView add(String parentCode , ModelAndView model) {
+
+ /**
+ * 处理路径为"sys/area/add"的请求的方法,用于准备并返回添加地区页面相关的数据和视图信息。
+ * 当客户端发起该请求时,方法会被调用,首先将返回的视图名称设置为添加地区页面的视图名称(AREA_ADD_PAGE),然后通过注入的ISysAreaService实例,依据传入的parentCode参数去查询对应的上级地区信息,并将查询到的上级地区对象添加到ModelAndView对象中,以便在视图层(如对应的模板文件中)可以获取并展示该上级地区相关信息(可能用于显示当前要添加地区所属的上级区域等场景),最后返回包含了设置好的视图名称以及上级地区对象数据的ModelAndView对象,使得Spring MVC能够依据这些信息正确渲染展示添加地区页面。
+ *
+ * @param parentCode 从请求中传递过来的字符串参数,用于指定要查询的上级地区的唯一标识(具体的标识形式取决于业务中地区实体类的设计以及业务逻辑,可能是地区编号等),借助这个参数去获取对应的上级地区信息,用于添加地区页面的相关展示和关联操作。
+ * @param model ModelAndView对象,用于设置视图名称以及添加要传递给视图的数据(在这里是查询到的上级地区对象),实现数据与视图的整合,确保视图层能够获取到正确的数据进行页面展示,满足添加地区页面的业务需求。
+ * @return 返回包含了设置好的视图名称(AREA_ADD_PAGE)以及添加了上级地区对象数据的ModelAndView对象,供Spring MVC进行视图渲染展示,呈现添加地区页面给客户端。
+ */
+ @RequestMapping(path = "add")
+ public ModelAndView add(String parentCode, ModelAndView model) {
model.setViewName(AREA_ADD_PAGE);
model.addObject("parentArea", iSysAreaService.selectById(parentCode));
return model;
}
-
- @RequestMapping(path="update")
- public ModelAndView update(String areaCode , ModelAndView model) {
+
+ /**
+ * 处理路径为"sys/area/update"的请求的方法,用于准备并返回修改地区信息页面相关的数据和视图。
+ * 当客户端发起对应请求时,该方法首先设置要返回的视图名称为修改地区信息页面的视图名称(AREA_UPDATE_PAGE),接着通过ISysAreaService查询要修改的地区本身的信息以及其上级地区信息(通过地区实体类中的parentCode属性关联查询),并分别将查询到的地区对象和上级地区对象添加到ModelAndView对象中,以便在视图层展示地区当前信息以及所属的上级地区情况,方便用户进行修改操作,最后返回包含了视图名称和这些数据的ModelAndView对象,以便Spring MVC进行视图渲染展示修改地区信息页面给客户端。
+ *
+ * @param areaCode 从请求中传递过来的字符串参数,用于指定要修改的地区的唯一标识(如地区编号等,具体由业务中地区实体类的设计决定),根据这个标识去查询相关的地区及其上级地区信息。
+ * @param model ModelAndView对象,用于设置视图名称以及添加要传递给视图的地区对象和上级地区对象数据,实现数据与视图的整合,确保视图层能获取到完整信息用于修改地区信息页面的展示和操作。
+ * @return 返回包含了设置好视图名称(AREA_UPDATE_PAGE)以及添加了地区对象和上级地区对象数据的ModelAndView对象,供Spring MVC渲染展示修改地区信息页面给客户端。
+ */
+ @RequestMapping(path = "update")
+ public ModelAndView update(String areaCode, ModelAndView model) {
model.setViewName(AREA_UPDATE_PAGE);
SysAreaEntity area = iSysAreaService.selectById(areaCode);
SysAreaEntity parentArea = iSysAreaService.selectById(area.getParentCode());
@@ -47,41 +75,69 @@ public class SysAreaController {
model.addObject("parentArea", parentArea);
return model;
}
-
- @RequestMapping(path="save")
+
+ /**
+ * 处理路径为"sys/area/save"的请求的方法,用于保存新的地区信息,并返回保存结果给客户端,结果以JSON格式响应。
+ * 该方法接收一个SysAreaEntity对象作为参数,这个对象包含了要保存的地区的各项详细信息(如地区名称、上级地区编号、地区描述等,具体属性取决于业务中地区实体类的设计),通过调用ISysAreaService的save方法尝试保存地区信息,如果保存成功,返回一个包含成功状态码、提示信息以及空数据的Result对象(通过Result.result方法构建,提示信息表明保存成功以及地区的名称等相关内容);若保存过程中出现异常,则调用ExceptionSupport的resolverResult方法处理异常,并将处理后的结果(同样包装在Result对象中)返回给客户端,客户端可以根据返回的结果判断保存操作是否成功以及获取相应的提示信息等。
+ *
+ * @param area SysAreaEntity对象,包含了要保存的新地区的各项详细信息,将其传递给业务逻辑层进行保存操作。
+ * @return 返回一个Result对象,包含了保存操作的状态码、提示信息等内容,会被转换为JSON格式响应给客户端,告知客户端地区保存操作的结果情况。
+ */
+ @RequestMapping(path = "save")
@ResponseBody
public Result save(SysAreaEntity area) {
try {
iSysAreaService.save(area);
- return Result.result(0, null, "保存【"+area.getAreaName()+"】地区成功!");
+ return Result.result(0, null, "保存【" + area.getAreaName() + "】地区成功!");
} catch (Exception e) {
return ExceptionSupport.resolverResult("保存地区", this.getClass(), e);
}
}
-
- @RequestMapping(path="update",method=RequestMethod.POST)
+
+ /**
+ * 处理路径为"sys/area/update"(且请求方法为POST的请求)的请求的方法,用于更新地区信息,并返回更新结果给客户端,结果以JSON格式响应。
+ * 与保存地区信息的方法类似,接收一个SysAreaEntity对象作为参数,包含了要更新的地区的各项信息,通过调用ISysAreaService的update方法进行地区信息更新操作,如果更新成功,返回一个包含成功状态码、提示信息以及空数据的Result对象(提示信息表明更新成功以及地区的名称等相关内容);若更新过程中出现异常,则调用ExceptionSupport的resolverResult方法处理异常,并将处理后的结果(包装在Result对象中)返回给客户端,方便客户端知晓更新操作的结果情况。
+ * 这里特别指定了请求方法为RequestMethod.POST,符合常见的RESTful风格接口设计原则,表明该方法只处理POST类型的更新地区信息的请求,以此与其他可能存在的同名但不同请求方法的请求进行区分,确保接口的规范性和准确性。
+ *
+ * @param area SysAreaEntity对象,包含了要更新的地区的详细信息,传递给业务逻辑层用于执行更新操作。
+ * @return 返回一个Result对象,包含了更新操作的状态码、提示信息等内容,会被转换为JSON格式响应给客户端,告知客户端地区更新操作的结果情况。
+ */
+ @RequestMapping(path = "update", method = RequestMethod.POST)
@ResponseBody
public Result update(SysAreaEntity area) {
try {
iSysAreaService.update(area);
- return Result.result(0, null, "修改【"+area.getAreaName()+"】地区成功!");
+ return Result.result(0, null, "修改【" + area.getAreaName() + "】地区成功!");
} catch (Exception e) {
return ExceptionSupport.resolverResult("修改地区", this.getClass(), e);
}
}
-
- @RequestMapping(path="listData",method=RequestMethod.POST)
+
+ /**
+ * 处理路径为"sys/area/listData"(且请求方法为POST的请求)的请求的方法,用于查询并返回符合条件的地区列表数据,返回结果以JSON格式响应给客户端。
+ * 该方法接收一个SysAreaCondition对象作为参数,这个对象是自定义的用于封装查询地区列表时各种条件的类(例如可以包含查询关键字、分页信息、地区级别筛选等条件,具体取决于业务需求),通过调用ISysAreaService的listData方法,依据传入的条件查询地区列表,最后直接返回查询到的地区实体对象列表(List),Spring MVC会借助@ResponseBody注解将其转换为JSON格式发送给客户端,供前端进行列表展示等操作,方便用户查看和管理地区信息。
+ *
+ * @param condition SysAreaCondition对象,用于传递查询地区列表的各种条件,使得业务逻辑层能够根据这些条件筛选出符合要求的地区列表数据,满足不同业务场景下对地区数据查询的需求。
+ * @return 返回符合条件的地区实体对象列表,会被自动转换为JSON格式响应给客户端,用于前端展示地区列表信息。
+ */
+ @RequestMapping(path = "listData", method = RequestMethod.POST)
@ResponseBody
public List listData(SysAreaCondition condition) {
List list = iSysAreaService.listData(condition);
return list;
}
-
- @RequestMapping(path="treeData")
+
+ /**
+ * 处理路径为"sys/area/treeData"的请求的方法,用于查询并返回地区数据的树形结构表示形式(常用于在前端以树形结构展示地区的层级关系,例如省、市、县等层级),返回结果以JSON格式响应给客户端。
+ * 方法接收一个字符串参数excludeId(具体含义可能是用于排除某个特定地区节点及其子节点的标识,比如在生成树形结构时不包含某个特定地区及其下属地区等情况,具体取决于业务逻辑和需求),然后调用ISysAreaService的treeData方法根据这个参数生成地区数据的树形结构,返回的结果是JSONArray类型(适合表示JSON格式的数组,方便存储树形结构的节点数据以及节点之间的层级关系等信息),通过@ResponseBody注解将其转换为JSON格式返回给客户端,便于前端进行树形结构的展示和交互操作,例如展开、收缩树形节点,查看不同层级地区信息等。
+ *
+ * @param excludeId 从请求中传递过来的字符串参数,用于在生成地区数据树形结构时作为排除某些节点的依据,根据业务需求来控制树形结构的生成内容,满足不同场景下展示地区层级关系的要求。
+ * @return 返回表示地区数据树形结构的JSONArray对象,会被转换为JSON格式响应给客户端,供前端展示地区的层级关系等树形结构相关内容。
+ */
+ @RequestMapping(path = "treeData")
@ResponseBody
public JSONArray treeData(String excludeId) {
return iSysAreaService.treeData(excludeId);
}
-
-
-}
+
+}
\ No newline at end of file
diff --git a/tamguo-oms/src/main/java/com/tamguo/modules/sys/web/SysMenuController.java b/tamguo-oms/src/main/java/com/tamguo/modules/sys/web/SysMenuController.java
index eed6614..ba86bc7 100644
--- a/tamguo-oms/src/main/java/com/tamguo/modules/sys/web/SysMenuController.java
+++ b/tamguo-oms/src/main/java/com/tamguo/modules/sys/web/SysMenuController.java
@@ -15,23 +15,42 @@ import com.tamguo.modules.sys.model.SysMenuEntity;
import com.tamguo.modules.sys.model.condition.SysMenuCondition;
import com.tamguo.modules.sys.service.ISysMenuService;
+// 使用@Controller注解将这个类标记为Spring MVC中的控制器类,负责处理与系统菜单相关的Web请求,它依据不同的请求路径调用对应的业务逻辑方法,来实现诸如菜单展示、保存、更新以及获取菜单列表、树形结构等功能,并将处理结果以合适的形式(视图展示或JSON数据返回)反馈给客户端,是系统菜单业务模块在Web端交互的关键部分。
@Controller
-@RequestMapping(path="sys/menu")
+// 通过@RequestMapping注解为该控制器类下所有请求路径设置公共前缀,表明此控制器主要处理以"sys/menu"开头的请求,便于对系统菜单相关的各类请求进行统一管理和分类。
+@RequestMapping(path = "sys/menu")
public class SysMenuController {
+ // 定义一个常量字符串,表示系统菜单列表页面(通常作为菜单管理模块的首页)的视图名称,按照Spring MVC视图解析的配置规则,其对应着实际用于展示系统菜单列表相关内容的模板文件路径(例如可能是JSP、Thymeleaf等模板文件的具体路径)。
private final String MENU_INDEX_PAGE = "modules/sys/menu/index";
+ // 定义常量字符串,代表修改系统菜单信息页面的视图名称,对应展示修改菜单已有信息相关内容的模板文件路径,方便用户对已存在的菜单记录进行编辑操作。
private final String MENU_UPDATE_PAGE = "modules/sys/menu/update";
+ // 通过@Autowired注解自动注入ISysMenuService接口的实现类实例,用于调用与系统菜单相关的业务逻辑方法,比如查询菜单信息、保存菜单数据、更新菜单记录以及获取菜单数据的树形结构、列表数据等操作,以此实现控制器层与业务逻辑层之间的交互,完成系统菜单相关业务的具体处理。
@Autowired
private ISysMenuService iSysMenuService;
- @RequestMapping(path="index")
+ /**
+ * 处理路径为"sys/menu/index"的请求的方法,该方法的作用是返回系统菜单列表页面的视图名称。
+ * 当客户端发起对应的请求时,此方法被调用,它简单地将预先定义好的系统菜单列表页面视图名称(MENU_INDEX_PAGE)返回给Spring MVC框架,然后框架会依据视图解析配置找到对应的模板文件进行渲染展示,向客户端呈现系统菜单列表页面。
+ * 此方法没有接收额外参数,也未对返回结果做更多复杂处理,仅是负责返回视图名称以引导页面展示。
+ * @return 返回系统菜单列表页面的视图名称(即常量MENU_INDEX_PAGE所定义的值),供Spring MVC查找并渲染对应的视图模板文件,从而展示系统菜单列表页面给客户端。
+ */
+ @RequestMapping(path = "index")
public String index() {
return MENU_INDEX_PAGE;
}
-
- @RequestMapping(path="update")
- public ModelAndView update(String menuCode , ModelAndView model) {
+
+ /**
+ * 处理路径为"sys/menu/update"的请求的方法,用于准备并返回修改系统菜单信息页面相关的数据和视图。
+ * 当客户端发起该请求时,方法会被调用,首先将返回的视图名称设置为修改系统菜单信息页面的视图名称(MENU_UPDATE_PAGE),接着通过注入的ISysMenuService实例,依据传入的menuCode参数去查询要修改的菜单本身信息以及其上级菜单信息(通过菜单实体类中的parentCode属性关联查询),并分别将查询到的菜单对象和上级菜单对象添加到ModelAndView对象中,以便在视图层展示菜单当前信息以及所属的上级菜单情况,方便用户进行修改操作,最后返回包含了视图名称和这些数据的ModelAndView对象,以便Spring MVC进行视图渲染展示修改系统菜单信息页面给客户端。
+ *
+ * @param menuCode 从请求中传递过来的字符串参数,用于指定要修改的菜单的唯一标识(如菜单编号等,具体由业务中菜单实体类的设计决定),根据这个标识去查询相关的菜单及其上级菜单信息。
+ * @param model ModelAndView对象,用于设置视图名称以及添加要传递给视图的菜单对象和上级菜单对象数据,实现数据与视图的整合,确保视图层能获取到完整信息用于修改系统菜单信息页面的展示和操作。
+ * @return 返回包含了设置好视图名称(MENU_UPDATE_PAGE)以及添加了菜单对象和上级菜单对象数据的ModelAndView对象,供Spring MVC渲染展示修改系统菜单信息页面给客户端。
+ */
+ @RequestMapping(path = "update")
+ public ModelAndView update(String menuCode, ModelAndView model) {
model.setViewName(MENU_UPDATE_PAGE);
SysMenuEntity menu = iSysMenuService.selectById(menuCode);
SysMenuEntity parentMenu = iSysMenuService.selectById(menu.getParentCode());
@@ -39,40 +58,71 @@ public class SysMenuController {
model.addObject("parentMenu", parentMenu);
return model;
}
-
- @RequestMapping(path="listData",method=RequestMethod.POST)
+
+ /**
+ * 处理路径为"sys/menu/listData"(且请求方法为POST的请求)的请求的方法,用于查询并返回符合条件的系统菜单列表数据,返回结果以JSON格式响应给客户端。
+ * 该方法接收一个SysMenuCondition对象作为参数,这个对象是自定义的用于封装查询系统菜单列表时各种条件的类(例如可以包含查询关键字、分页信息、菜单类型筛选等条件,具体取决于业务需求),通过调用ISysMenuService的listData方法,依据传入的条件查询系统菜单列表,最后直接返回查询到的系统菜单实体对象列表(List),Spring MVC会借助@ResponseBody注解将其转换为JSON格式发送给客户端,供前端进行列表展示等操作,方便用户查看和管理系统菜单信息。
+ *
+ * @param condition SysMenuCondition对象,用于传递查询系统菜单列表的各种条件,使得业务逻辑层能够根据这些条件筛选出符合要求的系统菜单列表数据,满足不同业务场景下对系统菜单数据查询的需求。
+ * @return 返回符合条件的系统菜单实体对象列表,会被自动转换为JSON格式响应给客户端,用于前端展示系统菜单列表信息。
+ */
+ @RequestMapping(path = "listData", method = RequestMethod.POST)
@ResponseBody
public List listData(SysMenuCondition condition) {
List list = iSysMenuService.listData(condition);
return list;
}
-
- @RequestMapping(path="save")
+
+ /**
+ * 处理路径为"sys/menu/save"的请求的方法,用于保存新的系统菜单信息,并返回保存结果给客户端,结果以JSON格式响应。
+ * 该方法接收一个SysMenuEntity对象作为参数,这个对象包含了要保存的系统菜单的各项详细信息(如菜单名称、上级菜单编号、菜单链接、菜单图标等,具体属性取决于业务中菜单实体类的设计),通过调用ISysMenuService的save方法尝试保存菜单信息,如果保存成功,返回一个包含成功状态码、提示信息以及空数据的Result对象(通过Result.result方法构建,提示信息表明保存成功以及菜单的名称等相关内容);若保存过程中出现异常,则调用ExceptionSupport的resolverResult方法处理异常,并将处理后的结果(同样包装在Result对象中)返回给客户端,客户端可以根据返回的结果判断保存操作是否成功以及获取相应的提示信息等。
+ *
+ * @param menu SysMenuEntity对象,包含了要保存的新系统菜单的各项详细信息,将其传递给业务逻辑层进行保存操作。
+ * @return 返回一个Result对象,包含了保存操作的状态码、提示信息等内容,会被转换为JSON格式响应给客户端,告知客户端系统菜单保存操作的结果情况。
+ */
+ @RequestMapping(path = "save")
@ResponseBody
public Result save(SysMenuEntity menu) {
try {
iSysMenuService.save(menu);
- return Result.result(0, null, "新增菜单【"+menu.getMenuName()+"】成功!");
+ return Result.result(0, null, "新增菜单【" + menu.getMenuName() + "】成功!");
} catch (Exception e) {
return ExceptionSupport.resolverResult("新增菜单", this.getClass(), e);
}
}
-
- @RequestMapping(path="update" , method=RequestMethod.POST)
+
+ /**
+ * 处理路径为"sys/menu/update"(且请求方法为POST的请求)的请求的方法,用于更新系统菜单信息,并返回更新结果给客户端,结果以JSON格式响应。
+ * 与保存系统菜单信息的方法类似,接收一个SysMenuEntity对象作为参数,包含了要更新的系统菜单的各项信息,通过调用ISysMenuService的update方法进行系统菜单信息更新操作,如果更新成功,返回一个包含成功状态码、提示信息以及空数据的Result对象(提示信息表明更新成功以及菜单的名称等相关内容);若更新过程中出现异常,则调用ExceptionSupport的resolverResult方法处理异常,并将处理后的结果(包装在Result对象中)返回给客户端,方便客户端知晓更新操作的结果情况。
+ * 这里指定请求方法为RequestMethod.POST,符合常见的RESTful风格接口设计原则,表明该方法只处理POST类型的更新系统菜单信息的请求,以此与其他可能存在的同名但不同请求方法的请求进行区分,确保接口的规范性和准确性。
+ *
+ * @param menu SysMenuEntity对象,包含了要更新的系统菜单的详细信息,传递给业务逻辑层用于执行更新操作。
+ * @return 返回一个Result对象,包含了更新操作的状态码、提示信息等内容,会被转换为JSON格式响应给客户端,告知客户端系统菜单更新操作的结果情况。
+ */
+ @RequestMapping(path = "update", method = RequestMethod.POST)
@ResponseBody
public Result post(SysMenuEntity menu) {
try {
iSysMenuService.update(menu);
- return Result.result(0, null, "修改菜单【"+menu.getMenuName()+"】成功!");
+ return Result.result(0, null, "修改菜单【" + menu.getMenuName() + "】成功!");
} catch (Exception e) {
return ExceptionSupport.resolverResult("修改菜单", this.getClass(), e);
}
}
-
- @RequestMapping(path="treeData")
+
+ /**
+ * 处理路径为"sys/menu/treeData"的请求的方法,用于查询并返回系统菜单数据的树形结构表示形式(常用于在前端以树形结构展示菜单的层级关系,例如一级菜单、二级菜单等层级),返回结果以JSON格式响应给客户端。
+ * 方法接收三个字符串参数,其中excludeId(具体含义可能是用于排除某个特定菜单节点及其子节点的标识,比如在生成树形结构时不包含某个特定菜单及其下属菜单等情况,具体取决于业务逻辑和需求),另外两个参数sysCode和isShowNameOrig在当前代码中虽然传入了方法,但并没有在调用iSysMenuService.treeData方法时使用(可能是后续需要扩展功能或者原本设计有其他用途但暂未实现相关逻辑),然后调用ISysMenuService的treeData方法根据excludeId参数生成系统菜单数据的树形结构,返回的结果是JSONArray类型(适合表示JSON格式的数组,方便存储树形结构的节点数据以及节点之间的层级关系等信息),通过@ResponseBody注解将其转换为JSON格式返回给客户端,便于前端进行树形结构的展示和交互操作,例如展开、收缩树形节点,查看不同层级菜单信息等。
+ *
+ * @param excludeId 从请求中传递过来的字符串参数,用于在生成系统菜单数据树形结构时作为排除某些节点的依据,根据业务需求来控制树形结构的生成内容,满足不同场景下展示系统菜单层级关系的要求。
+ * @param sysCode 从请求中传递过来的字符串参数,当前代码未使用其参与业务逻辑处理,可能是预留用于后续功能扩展或者原本有其他相关设计意图但暂未实现对应逻辑。
+ * @param isShowNameOrig 从请求中传递过来的字符串参数,同样当前代码未使用其参与业务逻辑处理,可能是为了后续功能拓展等情况预留的参数。
+ * @return 返回表示系统菜单数据树形结构的JSONArray对象,会被转换为JSON格式响应给客户端,供前端展示系统菜单的层级关系等树形结构相关内容。
+ */
+ @RequestMapping(path = "treeData")
@ResponseBody
- public JSONArray treeData(String excludeId , String sysCode , String isShowNameOrig) {
+ public JSONArray treeData(String excludeId, String sysCode, String isShowNameOrig) {
return iSysMenuService.treeData(excludeId);
}
-
-}
+
+}
\ No newline at end of file
diff --git a/tamguo-oms/src/main/java/com/tamguo/modules/sys/web/SysOfficeController.java b/tamguo-oms/src/main/java/com/tamguo/modules/sys/web/SysOfficeController.java
index 56b74fb..ef4ffd5 100644
--- a/tamguo-oms/src/main/java/com/tamguo/modules/sys/web/SysOfficeController.java
+++ b/tamguo-oms/src/main/java/com/tamguo/modules/sys/web/SysOfficeController.java
@@ -1,7 +1,6 @@
package com.tamguo.modules.sys.web;
import java.util.List;
-
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
@@ -18,69 +17,133 @@ import com.tamguo.modules.sys.service.ISysOfficeService;
/**
* Controller - 组织
- *
+ * 这个类是Spring MVC中的控制器类,主要负责处理与系统组织(机构)相关的Web请求,
+ * 通过调用对应的业务服务层方法,实现诸如组织信息的添加、更新、查询列表以及获取树形结构等功能,
+ * 并将相应的处理结果以合适的形式(如视图展示或JSON数据返回)反馈给客户端,是组织业务模块在Web应用中进行交互操作的核心部分。
+ *
* @author tamguo
*
*/
@Controller
-@RequestMapping(path="sys/office")
+// 通过@RequestMapping注解为这个控制器类下所有请求路径设置公共前缀,表明该控制器主要处理以"sys/office"开头的请求,便于对组织(机构)相关的各类请求进行统一管理与分类。
+@RequestMapping(path = "sys/office")
public class SysOfficeController {
-
+
+ // 定义一个常量字符串,表示添加组织(机构)页面的视图名称,按照Spring MVC视图解析的配置规则,其对应着实际用于展示添加机构相关表单及信息的模板文件路径(例如可能是JSP、Thymeleaf等模板文件的具体路径),用于在新增机构时向用户呈现相应的输入界面。
private final String OFFICE_ADD_PAGE = "modules/sys/office/add";
+ // 定义常量字符串,用于表示修改组织(机构)信息页面的视图名称,对应展示修改机构已有信息相关内容的模板文件路径,方便用户对已存在的机构记录进行编辑操作。
private final String OFFICE_UPDATE_PAGE = "modules/sys/office/update";
+ // 通过@Autowired注解自动注入ISysOfficeService接口的实现类实例,用于调用与组织(机构)相关的业务逻辑方法,例如查询机构信息、保存机构数据、更新机构记录以及获取机构数据的树形结构、列表数据等操作,以此实现控制器层与业务逻辑层之间的交互,完成组织(机构)相关业务的具体处理。
@Autowired
- private ISysOfficeService iSysOfficeService;
-
- @RequestMapping(path="add")
- public ModelAndView add(String parentCode , ModelAndView model) {
+ private ISysOfficeService iSysOfficeService;
+
+ /**
+ * 处理路径为"sys/office/add"的请求的方法,用于准备并返回添加组织(机构)页面相关的数据和视图信息。
+ * 当客户端发起该请求时,此方法会被调用,首先将返回的视图名称设置为添加组织(机构)页面的视图名称(OFFICE_ADD_PAGE),
+ * 然后通过注入的ISysOfficeService实例,依据传入的parentCode参数去查询对应的上级组织(机构)信息,并将查询到的上级机构对象添加到ModelAndView对象中,
+ * 以便在视图层(如对应的模板文件中)可以获取并展示该上级机构相关信息(可能用于显示当前要添加机构所属的上级组织等场景),
+ * 最后返回包含了设置好的视图名称以及上级机构对象数据的ModelAndView对象,使得Spring MVC能够依据这些信息正确渲染展示添加组织(机构)页面。
+ *
+ * @param parentCode 从请求中传递过来的字符串参数,用于指定要查询的上级组织(机构)的唯一标识(具体的标识形式取决于业务中机构实体类的设计以及业务逻辑,可能是机构编号等),借助这个参数去获取对应的上级机构信息,用于添加机构页面的相关展示和关联操作。
+ * @param model ModelAndView对象,用于设置视图名称以及添加要传递给视图的数据(在这里是查询到的上级机构对象),实现数据与视图的整合,确保视图层能够获取到正确的数据进行页面展示,满足添加机构页面的业务需求。
+ * @return 返回包含了设置好的视图名称(OFFICE_ADD_PAGE)以及添加了上级机构对象数据的ModelAndView对象,供Spring MVC进行视图渲染展示,呈现添加组织(机构)页面给客户端。
+ */
+ @RequestMapping(path = "add")
+ public ModelAndView add(String parentCode, ModelAndView model) {
model.setViewName(OFFICE_ADD_PAGE);
model.addObject("parentOffice", iSysOfficeService.selectById(parentCode));
return model;
}
-
- @RequestMapping(path="update")
- public ModelAndView update(String officeCode , ModelAndView model) {
+
+ /**
+ * 处理路径为"sys/office/update"的请求的方法,用于准备并返回修改组织(机构)信息页面相关的数据和视图。
+ * 当客户端发起对应请求时,该方法首先设置要返回的视图名称为修改组织(机构)信息页面的视图名称(OFFICE_UPDATE_PAGE),
+ * 接着通过ISysOfficeService查询要修改的机构本身的信息以及其上级机构信息(通过机构实体类中的parentCode属性关联查询),并分别将查询到的机构对象和上级机构对象添加到ModelAndView对象中,
+ * 以便在视图层展示机构当前信息以及所属的上级机构情况,方便用户进行修改操作,最后返回包含了视图名称和这些数据的ModelAndView对象,以便Spring MVC进行视图渲染展示修改组织(机构)信息页面给客户端。
+ *
+ * @param officeCode 从请求中传递过来的字符串参数,用于指定要修改的机构的唯一标识(如机构编号等,具体由业务中机构实体类的设计决定),根据这个标识去查询相关的机构及其上级机构信息。
+ * @param model ModelAndView对象,用于设置视图名称以及添加要传递给视图的机构对象和上级机构对象数据,实现数据与视图的整合,确保视图层能获取到完整信息用于修改组织(机构)信息页面的展示和操作。
+ * @return 返回包含了设置好视图名称(OFFICE_UPDATE_PAGE)以及添加了机构对象和上级机构对象数据的ModelAndView对象,供Spring MVC渲染展示修改组织(机构)信息页面给客户端。
+ */
+ @RequestMapping(path = "update")
+ public ModelAndView update(String officeCode, ModelAndView model) {
model.setViewName(OFFICE_UPDATE_PAGE);
SysOfficeEntity office = iSysOfficeService.selectById(officeCode);
SysOfficeEntity parentOffice = iSysOfficeService.selectById(office.getParentCode());
model.addObject("office", office);
- model.addObject("parentOffice" , parentOffice);
+ model.addObject("parentOffice", parentOffice);
return model;
}
-
- @RequestMapping(path="listData")
+
+ /**
+ * 处理路径为"sys/office/listData"的请求的方法,用于查询并返回符合条件的组织(机构)列表数据,返回结果以JSON格式响应给客户端。
+ * 该方法接收一个SysOfficeCondition对象作为参数,这个对象是自定义的用于封装查询机构列表时各种条件的类(例如可以包含查询关键字、分页信息、机构级别筛选等条件,具体取决于业务需求),
+ * 通过调用ISysOfficeService的listData方法,依据传入的条件查询机构列表,最后直接返回查询到的机构实体对象列表(List),
+ * Spring MVC会借助@ResponseBody注解将其转换为JSON格式发送给客户端,供前端进行列表展示等操作,方便用户查看和管理机构信息。
+ *
+ * @param condition SysOfficeCondition对象,用于传递查询组织(机构)列表的各种条件,使得业务逻辑层能够根据这些条件筛选出符合要求的机构列表数据,满足不同业务场景下对机构数据查询的需求。
+ * @return 返回符合条件的组织(机构)实体对象列表,会被自动转换为JSON格式响应给客户端,用于前端展示机构列表信息。
+ */
+ @RequestMapping(path = "listData")
@ResponseBody
public List listData(SysOfficeCondition condition) {
return iSysOfficeService.listData(condition);
}
-
- @RequestMapping(path="treeData")
+
+ /**
+ * 处理路径为"sys/office/treeData"的请求的方法,用于查询并返回组织(机构)数据的树形结构表示形式(常用于在前端以树形结构展示机构的层级关系,例如总公司、分公司、部门等层级),返回结果以JSON格式响应给客户端。
+ * 方法接收一个字符串参数excludeId(具体含义可能是用于排除某个特定机构节点及其子节点的标识,比如在生成树形结构时不包含某个特定机构及其下属机构等情况,具体取决于业务逻辑和需求),
+ * 然后调用ISysOfficeService的treeData方法根据这个参数生成机构数据的树形结构,返回的结果是JSONArray类型(适合表示JSON格式的数组,方便存储树形结构的节点数据以及节点之间的层级关系等信息),
+ * 通过@ResponseBody注解将其转换为JSON格式返回给客户端,便于前端进行树形结构的展示和交互操作,例如展开、收缩树形节点,查看不同层级机构信息等。
+ *
+ * @param excludeId 从请求中传递过来的字符串参数,用于在生成组织(机构)数据树形结构时作为排除某些节点的依据,根据业务需求来控制树形结构的生成内容,满足不同场景下展示机构层级关系的要求。
+ * @return 返回表示组织(机构)数据树形结构的JSONArray对象,会被转换为JSON格式响应给客户端,供前端展示机构的层级关系等树形结构相关内容。
+ */
+ @RequestMapping(path = "treeData")
@ResponseBody
public JSONArray treeData(String excludeId) {
return iSysOfficeService.treeData(excludeId);
}
-
- @RequestMapping(path="save")
+
+ /**
+ * 处理路径为"sys/office/save"的请求的方法,用于保存新的组织(机构)信息,并返回保存结果给客户端,结果以JSON格式响应。
+ * 该方法接收一个SysOfficeEntity对象作为参数,这个对象包含了要保存的机构的各项详细信息(如机构名称、上级机构编号、机构描述等,具体属性取决于业务中机构实体类的设计),
+ * 通过调用ISysOfficeService的save方法尝试保存机构信息,如果保存成功,返回一个包含成功状态码、提示信息以及空数据的Result对象(通过Result.result方法构建,提示信息表明保存成功以及机构的名称等相关内容);
+ * 若保存过程中出现异常,则调用ExceptionSupport的resolverResult方法处理异常,并将处理后的结果(同样包装在Result对象中)返回给客户端,客户端可以根据返回的结果判断保存操作是否成功以及获取相应的提示信息等。
+ *
+ * @param office SysOfficeEntity对象,包含了要保存的新组织(机构)的各项详细信息,将其传递给业务逻辑层进行保存操作。
+ * @return 返回一个Result对象,包含了保存操作的状态码、提示信息等内容,会被转换为JSON格式响应给客户端,告知客户端组织(机构)保存操作的结果情况。
+ */
+ @RequestMapping(path = "save")
@ResponseBody
public Result save(SysOfficeEntity office) {
try {
iSysOfficeService.save(office);
- return Result.result(0, null, "新增机构【"+office.getOfficeName()+"】成功!");
+ return Result.result(0, null, "新增机构【" + office.getOfficeName() + "】成功!");
} catch (Exception e) {
return ExceptionSupport.resolverResult("新增机构", this.getClass(), e);
}
}
-
- @RequestMapping(path="update",method=RequestMethod.POST)
+
+ /**
+ * 处理路径为"sys/office/update"(且请求方法为POST的请求)的请求的方法,用于更新组织(机构)信息,并返回更新结果给客户端,结果以JSON格式响应。
+ * 与保存机构信息的方法类似,接收一个SysOfficeEntity对象作为参数,包含了要更新的机构的各项信息,通过调用ISysOfficeService的update方法进行机构信息更新操作,如果更新成功,返回一个包含成功状态码、提示信息以及空数据的Result对象(提示信息表明更新成功以及机构的名称等相关内容);
+ * 若更新过程中出现异常,则调用ExceptionSupport的resolverResult方法处理异常,并将处理后的结果(包装在Result对象中)返回给客户端,方便客户端知晓更新操作的结果情况。
+ * 这里指定请求方法为RequestMethod.POST,符合常见的RESTful风格接口设计原则,表明该方法只处理POST类型的更新组织(机构)信息的请求,以此与其他可能存在的同名但不同请求方法的请求进行区分,确保接口的规范性和准确性。
+ *
+ * @param office SysOfficeEntity对象,包含了要更新的组织(机构)的详细信息,传递给业务逻辑层用于执行更新操作。
+ * @return 返回一个Result对象,包含了更新操作的状态码、提示信息等内容,会被转换为JSON格式响应给客户端,告知客户端组织(机构)更新操作的结果情况。
+ */
+ @RequestMapping(path = "update", method = RequestMethod.POST)
@ResponseBody
public Result update(SysOfficeEntity office) {
try {
iSysOfficeService.update(office);
- return Result.result(0, null, "修改机构【"+office.getOfficeName()+"】成功!");
+ return Result.result(0, null, "修改机构【" + office.getOfficeName() + "】成功!");
} catch (Exception e) {
return ExceptionSupport.resolverResult("修改机构", this.getClass(), e);
}
}
-
-}
+
+}
\ No newline at end of file
diff --git a/tamguo-oms/src/main/java/com/tamguo/modules/sys/web/SysPageController.java b/tamguo-oms/src/main/java/com/tamguo/modules/sys/web/SysPageController.java
index 65f110b..7432391 100644
--- a/tamguo-oms/src/main/java/com/tamguo/modules/sys/web/SysPageController.java
+++ b/tamguo-oms/src/main/java/com/tamguo/modules/sys/web/SysPageController.java
@@ -6,18 +6,38 @@ import org.springframework.web.bind.annotation.RequestMapping;
/**
* 页面视图
+ * 这个类是Spring MVC中的控制器类,主要负责根据不同的请求路径,返回对应的视图名称,以引导Spring MVC框架找到相应的模板文件进行页面渲染展示,
+ * 起到了将请求与具体视图进行映射的作用,方便在Web应用中实现不同模块下不同页面的展示逻辑,这里涉及到了系统模块("sys"相关)和题库模块("tiku"相关)的页面视图处理。
*/
@Controller
public class SysPageController {
-
+
+ /**
+ * 处理路径格式为"sys/{fn}/{page}"的请求的方法,用于根据请求路径中的参数动态返回对应的系统模块下的视图名称。
+ * 通过 @PathVariable 注解,从请求路径中提取出 "fn" 和 "page" 这两个占位符对应的实际值,然后将它们拼接成完整的视图名称路径格式(遵循项目中视图解析配置对应的路径规则,这里是拼接成 "modules/sys/" 加上具体的 "fn" 和 "page" 值),
+ * 最后返回这个拼接好的视图名称字符串,Spring MVC框架会依据此名称去查找对应的模板文件(如JSP、Thymeleaf等格式的文件,具体取决于项目配置),并进行渲染展示,呈现出相应的系统模块下的页面给客户端。
+ *
+ * @param fn 从请求路径中通过 @PathVariable 注解获取的字符串参数,代表系统模块下的功能分类或者文件夹名称等(具体含义取决于项目中视图文件的组织方式和业务逻辑),用于构建完整的视图名称路径。
+ * @param page 从请求路径中通过 @PathVariable 注解获取的字符串参数,代表具体的页面文件名(同样具体含义取决于项目的视图组织和业务逻辑),与 "fn" 参数一起构成完整的视图名称路径,指向要展示的具体页面视图文件。
+ * @return 返回拼接好的视图名称字符串(格式为 "modules/sys/" + fn + "/" + page),供Spring MVC查找并渲染对应的视图模板文件,展示系统模块下相应的页面给客户端。
+ */
@RequestMapping("sys/{fn}/{page}")
- public String sys(@PathVariable("fn") String fn , @PathVariable("page") String page){
+ public String sys(@PathVariable("fn") String fn, @PathVariable("page") String page) {
return "modules/sys/" + fn + "/" + page;
}
-
+
+ /**
+ * 处理路径格式为"tiku/{fn}/{page}"的请求的方法,与上面的 "sys" 相关的方法类似,用于根据请求路径中的参数动态返回对应的题库模块下的视图名称。
+ * 同样借助 @PathVariable 注解获取请求路径中的 "fn" 和 "page" 参数值,将它们按照既定的路径格式拼接成完整的视图名称(即 "modules/tiku/" 加上具体的 "fn" 和 "page" 值),再返回这个视图名称字符串给Spring MVC框架,
+ * 使得框架能依据其找到对应的题库模块下的模板文件进行渲染展示,从而向客户端呈现相应的题库模块页面。
+ *
+ * @param fn 从请求路径中通过 @PathVariable 注解获取的字符串参数,在题库模块下代表相应的功能分类或者文件夹名称等(具体含义由项目中视图文件的组织情况和业务逻辑决定),用于构建准确的视图名称路径指向相应页面。
+ * @param page 从请求路径中通过 @PathVariable 注解获取的字符串参数,代表题库模块下具体的页面文件名(具体取决于项目视图组织和业务逻辑),与 "fn" 参数共同组成完整的视图名称路径,确定要展示的具体页面视图文件。
+ * @return 返回拼接好的视图名称字符串(格式为 "modules/tiku/" + fn + "/" + page),供Spring MVC查找并渲染对应的视图模板文件,展示题库模块下相应的页面给客户端。
+ */
@RequestMapping("tiku/{fn}/{page}")
- public String ti(@PathVariable("fn") String fn , @PathVariable("page") String page){
+ public String ti(@PathVariable("fn") String fn, @PathVariable("page") String page) {
return "modules/tiku/" + fn + "/" + page;
}
-
-}
+
+}
\ No newline at end of file
diff --git a/tamguo-oms/src/main/java/com/tamguo/modules/sys/web/SysPostController.java b/tamguo-oms/src/main/java/com/tamguo/modules/sys/web/SysPostController.java
index ec3ab56..4581354 100644
--- a/tamguo-oms/src/main/java/com/tamguo/modules/sys/web/SysPostController.java
+++ b/tamguo-oms/src/main/java/com/tamguo/modules/sys/web/SysPostController.java
@@ -15,43 +15,85 @@ import com.tamguo.modules.sys.model.SysPostEntity;
import com.tamguo.modules.sys.model.condition.SysPostCondition;
import com.tamguo.modules.sys.service.ISysPostService;
+// 使用@Controller注解将这个类标记为Spring MVC中的控制器类,负责处理与系统岗位相关的Web请求,调用相应的业务逻辑方法,并根据处理结果返回给客户端合适的响应或者转发到对应的视图进行展示,是实现岗位业务模块页面交互和数据处理的关键部分。
@Controller
-@RequestMapping(path="sys/post")
+// 通过@RequestMapping注解为这个控制器类下的所有请求路径设置一个公共的前缀,即该控制器处理的请求路径都以"sys/post"开头,便于对岗位相关的各种请求进行统一管理和分类。
+@RequestMapping(path = "sys/post")
public class SysPostController {
+ // 定义一个常量字符串,表示岗位列表页面(或首页)的视图名称,遵循Spring MVC视图解析的配置规则,对应着展示岗位列表相关内容的模板文件路径(如JSP、Thymeleaf等模板文件的具体路径)。
private final String POST_INDEX_PAGE = "modules/sys/post/index";
+ // 定义常量字符串,代表岗位信息更新页面的视图名称,对应展示修改岗位信息相关内容的模板文件路径。
private final String POST_UPDATE_PAGE = "modules/sys/post/update";
+ // 定义常量字符串,用于表示岗位添加页面的视图名称,对应展示添加新岗位相关内容的模板文件路径。
private final String POST_ADD_PAGE = "modules/sys/post/add";
-
+
+ // 通过@Autowired注解自动注入ISysPostService接口的实现类实例,用于调用与系统岗位相关的业务逻辑方法,比如查询、保存、更新岗位信息等操作,实现控制器层与业务逻辑层的交互。
@Autowired
private ISysPostService iSysPostService;
- @RequestMapping(path="index")
+ /**
+ * 处理路径为"sys/post/index"的请求的方法,用于返回岗位列表页面的视图名称。
+ * 当客户端发起对应的请求时,该方法被调用,其主要功能就是告知Spring MVC要渲染展示的视图对应的名称,以便找到对应的模板文件进行页面展示(这里只是简单返回视图名称,具体页面内容的渲染由视图层根据配置和模板文件来完成)。
+ *
+ * @return 返回岗位列表页面的视图名称(即常量POST_INDEX_PAGE所定义的值),Spring MVC根据这个名称去查找并渲染对应的视图模板文件,展示岗位列表页面给客户端。
+ */
+ @RequestMapping(path = "index")
public String index() {
return POST_INDEX_PAGE;
}
-
- @RequestMapping(path="update")
- public ModelAndView update(ModelAndView model , String id) {
+
+ /**
+ * 处理路径为"sys/post/update"的请求的方法,用于准备并返回岗位信息更新页面相关的数据和视图。
+ * 当客户端发起该请求时,方法会被调用,先向ModelAndView对象中添加一些用于页面展示的数据,比如设置页面标题为"修改岗位",然后通过注入的ISysPostService实例,根据传入的id参数查询对应的岗位信息,并将查询到的岗位对象添加到ModelAndView对象中,接着设置要返回的视图名称为岗位信息更新页面的视图名称(POST_UPDATE_PAGE),最后返回包含了视图名称和相关数据的ModelAndView对象,使得Spring MVC能够正确渲染展示岗位信息更新页面。
+ *
+ * @param model ModelAndView对象,用于设置视图名称以及添加要传递给视图的数据(在这里是页面标题和查询到的岗位对象),实现数据与视图的整合,确保视图层能够获取到正确的数据进行页面展示。
+ * @param id 从请求中传递过来的字符串参数,用于指定要查询的岗位的标识(具体含义取决于业务中岗位实体类的设计以及业务逻辑,可能是岗位编号等唯一标识),通过这个参数去查询对应的岗位信息,用于在更新页面展示和后续的更新操作。
+ * @return 返回包含了设置好的视图名称(POST_UPDATE_PAGE)以及添加了页面标题和岗位对象数据的ModelAndView对象,供Spring MVC进行视图渲染展示,呈现岗位信息更新页面给客户端。
+ */
+ @RequestMapping(path = "update")
+ public ModelAndView update(ModelAndView model, String id) {
model.addObject("title", "修改岗位");
model.addObject("post", iSysPostService.selectById(id));
model.setViewName(POST_UPDATE_PAGE);
return model;
}
-
- @RequestMapping(path="add")
+
+ /**
+ * 处理路径为"sys/post/add"的请求的方法,用于返回岗位添加页面的视图名称。
+ * 当客户端发起对应的请求时,该方法被调用,其主要功能就是简单地返回岗位添加页面的视图名称(POST_ADD_PAGE),以便Spring MVC根据这个名称去查找对应的模板文件进行页面展示,引导用户进入岗位添加页面进行新岗位信息的录入操作。
+ *
+ * @return 返回岗位添加页面的视图名称(即常量POST_ADD_PAGE所定义的值),Spring MVC根据这个名称去查找并渲染对应的视图模板文件,展示岗位添加页面给客户端。
+ */
+ @RequestMapping(path = "add")
public String add() {
return POST_ADD_PAGE;
}
-
- @RequestMapping(path="listData",method=RequestMethod.POST)
+
+ /**
+ * 处理路径为"sys/post/listData"(且请求方法为POST的请求)的请求的方法,用于查询并返回符合条件的岗位列表数据,返回结果以适合前端表格组件(如jqGrid等)使用的格式包装在Map中,并以JSON格式响应给客户端。
+ * 该方法接收一个SysPostCondition对象作为参数,这个对象应该是自定义的用于封装查询岗位列表时的各种条件的类(例如可以包含查询关键字、分页信息等条件),通过调用ISysPostService的listData方法,根据传入的条件查询岗位列表,返回的结果是一个Page对象(表示分页后的岗位实体对象列表,由MyBatis Plus的分页插件生成相关分页信息),然后调用Result.jqGridResult方法将分页信息(总记录数、每页记录数、当前页码、总页数等)以及实际的岗位记录数据进行整合,包装成一个Map对象(符合前端表格组件期望的格式),最后通过@ResponseBody注解将这个Map对象转换为JSON格式返回给客户端,供前端表格组件进行数据展示和分页等操作。
+ * 这里指定请求方法为RequestMethod.POST,可能是基于业务逻辑要求或者与前端交互的约定,确保该接口只处理POST请求方式的查询管理员列表数据的操作。
+ *
+ * @param condition SysPostCondition对象,用于传递查询岗位列表的各种条件,使得业务逻辑层能够根据这些条件筛选出符合要求的岗位列表数据。
+ * @return 返回一个Map对象,其中包含了适合前端表格组件展示的岗位列表数据以及相关的分页信息,该Map对象会被转换为JSON格式响应给客户端,用于前端展示岗位列表信息并进行分页等操作。
+ */
+ @RequestMapping(path = "listData", method = RequestMethod.POST)
@ResponseBody
public Map listData(SysPostCondition condition) {
Page page = iSysPostService.listData(condition);
return Result.jqGridResult(page.getRecords(), page.getTotal(), page.getSize(), page.getCurrent(), page.getPages());
}
-
- @RequestMapping(path="save",method=RequestMethod.POST)
+
+ /**
+ * 处理路径为"sys/post/save"(且请求方法为POST的请求)的请求的方法,用于保存新的岗位信息,并返回保存结果给客户端,结果以JSON格式响应。
+ * 该方法接收一个SysPostEntity对象作为参数,这个对象应该包含了要保存的岗位的各项信息(如岗位名称、岗位描述、岗位所属部门等,具体属性取决于业务中岗位实体类的设计),通过调用ISysPostService的add方法尝试保存岗位信息,如果保存成功,返回一个包含成功状态码、提示信息以及空数据的Result对象(通过Result.result方法构建,提示信息表明保存成功);如果保存过程中出现异常,则调用ExceptionSupport的resolverResult方法处理异常,并将处理后的结果(同样包装在Result对象中)返回给客户端,客户端可以根据返回的结果判断保存操作是否成功以及获取相应的提示信息等。
+ * 这里指定请求方法为RequestMethod.POST,符合常见的RESTful风格接口设计原则,通常POST方法用于创建资源(在这里就是创建新的岗位记录),确保该接口只处理正确请求方法的保存岗位信息的请求,与其他可能的请求进行区分。
+ *
+ * @param post SysPostEntity对象,包含了要保存的新岗位的各项详细信息,将其传递给业务逻辑层进行保存操作。
+ * @return 返回一个Result对象,包含了保存操作的状态码、提示信息等内容,会被转换为JSON格式响应给客户端,告知客户端岗位保存操作的结果情况。
+ */
+ @RequestMapping(path = "save", method = RequestMethod.POST)
@ResponseBody
public Result save(SysPostEntity post) {
try {
@@ -61,8 +103,16 @@ public class SysPostController {
return ExceptionSupport.resolverResult("保存岗位", this.getClass(), e);
}
}
-
- @RequestMapping(path="update",method=RequestMethod.POST)
+
+ /**
+ * 处理路径为"sys/post/update"(且请求方法为POST的请求)的请求的方法,用于更新岗位信息,并返回更新结果给客户端,结果以JSON格式响应。
+ * 与保存岗位信息的方法类似,接收一个SysPostEntity对象作为参数,包含了要更新的岗位的各项信息,通过调用ISysPostService的update方法进行岗位信息更新操作,如果更新成功,返回一个包含成功状态码、提示信息以及空数据的Result对象(提示信息表明更新成功);若更新过程中出现异常,则调用ExceptionSupport的resolverResult方法处理异常,并将处理后的结果(包装在Result对象中)返回给客户端,方便客户端知晓更新操作的结果情况。
+ * 同样指定请求方法为RequestMethod.POST,符合RESTful风格接口设计要求,用于明确该接口只处理POST请求方式的更新岗位信息的操作,避免与其他同名但不同请求方法的请求混淆。
+ *
+ * @param post SysPostEntity对象,包含了要更新的岗位的详细信息,传递给业务逻辑层用于执行更新操作。
+ * @return 返回一个Result对象,包含了更新操作的状态码、提示信息等内容,会被转换为JSON格式响应给客户端,告知客户端岗位更新操作的结果情况。
+ */
+ @RequestMapping(path = "update", method = RequestMethod.POST)
@ResponseBody
public Result update(SysPostEntity post) {
try {
@@ -71,6 +121,6 @@ public class SysPostController {
} catch (Exception e) {
return ExceptionSupport.resolverResult("修改岗位", this.getClass(), e);
}
-
+
}
-}
+}
\ No newline at end of file
diff --git a/tamguo-oms/src/main/java/com/tamguo/modules/sys/web/SysRoleController.java b/tamguo-oms/src/main/java/com/tamguo/modules/sys/web/SysRoleController.java
index fe76a35..f7135ab 100644
--- a/tamguo-oms/src/main/java/com/tamguo/modules/sys/web/SysRoleController.java
+++ b/tamguo-oms/src/main/java/com/tamguo/modules/sys/web/SysRoleController.java
@@ -18,50 +18,81 @@ import com.tamguo.modules.sys.model.condition.SysRoleCondition;
import com.tamguo.modules.sys.service.ISysRoleDataScopeService;
import com.tamguo.modules.sys.service.ISysRoleService;
+// 使用@Controller注解将这个类标记为Spring MVC中的控制器类,负责处理与系统角色相关的Web请求,通过调用相应的业务逻辑服务方法,实现诸如角色信息查询、角色授权(包括菜单权限、数据权限等)、角色列表展示、角色的增删改等功能,并将处理结果以合适的形式(视图展示或JSON数据返回)反馈给客户端,是系统角色业务模块在Web端交互操作的核心部分。
@Controller
-@RequestMapping(path="sys/role")
+// 通过@RequestMapping注解为该控制器类下所有请求路径设置公共前缀,表明此控制器主要处理以"sys/role"开头的请求,便于对系统角色相关的各类请求进行统一管理和分类。
+@RequestMapping(path = "sys/role")
public class SysRoleController {
- // 分配角色菜单权限
+ // 分配角色菜单权限页面的视图名称,按照Spring MVC视图解析的配置规则,对应着实际用于展示分配角色菜单权限相关内容的模板文件路径(例如可能是JSP、Thymeleaf等模板文件的具体路径),用于在为角色分配菜单权限时向用户呈现相应的操作界面。
private final String ROLE_MENU_INDEX_PAGE = "modules/sys/role/menu";
- // 数据权限
+ // 数据权限页面的视图名称,对应展示角色数据权限相关内容的模板文件路径,方便用户对角色的数据权限进行设置等操作。
private final String ROLE_DATA_INDEX_PAGE = "modules/sys/role/dataScope";
- // 修改角色
+ // 修改角色信息页面的视图名称,对应展示修改角色已有信息相关内容的模板文件路径,便于用户对已存在的角色记录进行编辑操作。
private final String ROLE_MENU_UPDATE_PAGE = "modules/sys/role/update";
+ // 通过@Autowired注解自动注入ISysRoleService接口的实现类实例,用于调用与系统角色相关的业务逻辑方法,比如查询角色信息、保存角色数据、更新角色记录、角色授权(菜单权限、数据权限等)等操作,以此实现控制器层与业务逻辑层之间的交互,完成系统角色相关业务的主要处理。
@Autowired
private ISysRoleService iSysRoleService;
+ // 通过@Autowired注解自动注入ISysRoleDataScopeService接口的实现类实例,用于专门处理角色数据权限相关的业务逻辑操作,例如查询角色的数据权限列表、保存角色的数据权限设置等,辅助完成角色数据权限方面的业务处理,与ISysRoleService共同协作实现完整的角色相关业务功能。
@Autowired
private ISysRoleDataScopeService iSysRoleDataScopeService;
- /** 角色授权功能菜单*/
- @RequestMapping(path="menu")
- public ModelAndView menu(String roleCode , ModelAndView model) {
+ /**
+ * 角色授权功能菜单相关的请求处理方法,用于准备并返回角色授权功能菜单页面相关的数据和视图。
+ * 当客户端发起路径为"sys/role/menu"的请求时,此方法会被调用,它首先通过注入的ISysRoleService实例,依据传入的roleCode参数去查询对应的角色信息,并将查询到的角色对象添加到ModelAndView对象中,然后设置要返回的视图名称为角色授权功能菜单页面的视图名称(ROLE_MENU_INDEX_PAGE),最后返回包含了视图名称和角色对象数据的ModelAndView对象,使得Spring MVC能够依据这些信息正确渲染展示角色授权功能菜单页面,方便用户在该页面上进行菜单权限分配等操作。
+ *
+ * @param roleCode 从请求中传递过来的字符串参数,用于指定要查询的角色的唯一标识(如角色编号等,具体由业务中角色实体类的设计决定),根据这个标识去查询相关的角色信息,用于在授权功能菜单页面展示该角色的基础信息等内容。
+ * @param model ModelAndView对象,用于设置视图名称以及添加要传递给视图的数据(在这里是查询到的角色对象),实现数据与视图的整合,确保视图层能够获取到正确的数据进行页面展示,满足角色授权功能菜单页面的业务需求。
+ * @return 返回包含了设置好的视图名称(ROLE_MENU_INDEX_PAGE)以及添加了角色对象数据的ModelAndView对象,供Spring MVC进行视图渲染展示,呈现角色授权功能菜单页面给客户端。
+ */
+ @RequestMapping(path = "menu")
+ public ModelAndView menu(String roleCode, ModelAndView model) {
model.addObject("role", iSysRoleService.selectById(roleCode));
model.setViewName(ROLE_MENU_INDEX_PAGE);
return model;
}
-
- /** 修改角色*/
- @RequestMapping(path="update")
- public ModelAndView update(String roleCode , ModelAndView model) {
+
+ /**
+ * 修改角色相关的请求处理方法,用于准备并返回修改角色信息页面相关的数据和视图。
+ * 当客户端发起路径为"sys/role/update"的请求时(此方法有两个,一个处理GET请求用于页面展示,一个处理POST请求用于实际的修改操作提交,这里是处理GET请求的情况),方法会被调用,首先通过ISysRoleService根据传入的roleCode参数查询对应的角色信息,并将查询到的角色对象添加到ModelAndView对象中,接着设置要返回的视图名称为修改角色信息页面的视图名称(ROLE_MENU_UPDATE_PAGE),最后返回包含了视图名称和角色对象数据的ModelAndView对象,以便Spring MVC进行视图渲染展示修改角色信息页面给客户端,方便用户查看并编辑角色的相关信息。
+ *
+ * @param roleCode 从请求中传递过来的字符串参数,用于指定要查询并修改的角色的唯一标识(如角色编号等,具体取决于业务中角色实体类的设计),通过这个参数去获取角色的现有信息,用于在修改页面展示给用户进行编辑操作。
+ * @param model ModelAndView对象,用于设置视图名称以及添加要传递给视图的角色对象数据,实现数据与视图的整合,确保视图层能获取到完整信息用于修改角色信息页面的展示和操作。
+ * @return 返回包含了设置好视图名称(ROLE_MENU_UPDATE_PAGE)以及添加了角色对象数据的ModelAndView对象,供Spring MVC渲染展示修改角色信息页面给客户端。
+ */
+ @RequestMapping(path = "update")
+ public ModelAndView update(String roleCode, ModelAndView model) {
model.addObject("role", iSysRoleService.selectById(roleCode));
model.setViewName(ROLE_MENU_UPDATE_PAGE);
return model;
}
-
- /** 数据权限 */
+
+ /**
+ * 数据权限相关的请求处理方法,用于准备并返回角色数据权限页面相关的数据和视图。
+ * 当客户端发起路径为"sys/role/dataScope"的请求时,该方法被调用,首先通过ISysRoleService根据传入的roleCode参数查询对应的角色信息,并添加到ModelAndView对象中,然后通过ISysRoleDataScopeService,利用MyBatis Plus的条件构造器(Condition.create().eq("role_code", roleCode))查询该角色对应的数据权限列表,并将其添加到ModelAndView对象中,接着设置要返回的视图名称为角色数据权限页面的视图名称(ROLE_DATA_INDEX_PAGE),最后返回包含了视图名称以及角色对象、角色数据权限列表数据的ModelAndView对象,使得Spring MVC能够正确渲染展示角色数据权限页面,方便用户对角色的数据权限进行查看和设置等操作。
+ *
+ * @param roleCode 从请求中传递过来的字符串参数,用于指定要查询的数据权限相关的角色的唯一标识(如角色编号等,具体由业务中角色实体类的设计决定),根据这个标识去获取角色信息以及其对应的数据权限列表信息,用于在数据权限页面展示相关内容。
+ * @param model ModelAndView对象,用于设置视图名称以及添加要传递给视图的角色对象和角色数据权限列表数据,实现数据与视图的整合,确保视图层能获取到完整信息用于角色数据权限页面的展示和操作。
+ * @return 返回包含了设置好的视图名称(ROLE_DATA_INDEX_PAGE)以及添加了角色对象和角色数据权限列表数据的ModelAndView对象,供Spring MVC进行视图渲染展示,呈现角色数据权限页面给客户端。
+ */
@SuppressWarnings("unchecked")
- @RequestMapping(path="dataScope")
- public ModelAndView dataScope(String roleCode , ModelAndView model) {
+ @RequestMapping(path = "dataScope")
+ public ModelAndView dataScope(String roleCode, ModelAndView model) {
model.addObject("role", iSysRoleService.selectById(roleCode));
- model.addObject("roleDataScopeList" , iSysRoleDataScopeService.selectList(Condition.create().eq("role_code", roleCode)));
+ model.addObject("roleDataScopeList", iSysRoleDataScopeService.selectList(Condition.create().eq("role_code", roleCode)));
model.setViewName(ROLE_DATA_INDEX_PAGE);
return model;
}
-
- /** 角色列表数据*/
- @RequestMapping(path="listData",method=RequestMethod.POST)
+
+ /**
+ * 处理路径为"sys/role/listData"(且请求方法为POST的请求)的请求的方法,用于查询并返回符合条件的角色列表数据,返回结果以适合前端表格组件(如jqGrid等)使用的格式包装在Map中,并以JSON格式响应给客户端。
+ * 该方法接收一个SysRoleCondition对象作为参数,这个对象是自定义的用于封装查询角色列表时各种条件的类(例如可以包含查询关键字、分页信息、角色类型筛选等条件,具体取决于业务需求),通过调用ISysRoleService的listData方法,依据传入的条件查询角色列表,若查询过程顺利,返回的结果是一个Page对象(表示分页后的角色实体对象列表,由MyBatis Plus的分页插件生成相关分页信息),然后调用Result.jqGridResult方法将分页信息(总记录数、每页记录数、当前页码、总页数等)以及实际的角色记录数据进行整合,包装成一个Map对象(符合前端表格组件期望的格式),最后通过@ResponseBody注解将这个Map对象转换为JSON格式返回给客户端,供前端表格组件进行数据展示和分页等操作;若查询过程中出现异常,则调用ExceptionSupport的resolverResult方法处理异常,并返回null,客户端可以根据返回结果判断是否获取到正确的角色列表数据以及是否出现异常情况。
+ *
+ * @param condition SysRoleCondition对象,用于传递查询角色列表的各种条件,使得业务逻辑层能够根据这些条件筛选出符合要求的角色列表数据,满足不同业务场景下对角色数据查询的需求。
+ * @return 返回一个Map对象,其中包含了适合前端表格组件展示的角色列表数据以及相关的分页信息,该Map对象会被转换为JSON格式响应给客户端,用于前端展示角色列表信息并进行分页等操作;若出现异常则返回null。
+ */
+ @RequestMapping(path = "listData", method = RequestMethod.POST)
@ResponseBody
public Map listData(SysRoleCondition condition) {
try {
@@ -72,9 +103,15 @@ public class SysRoleController {
return null;
}
}
-
- /** 菜单树*/
- @RequestMapping(path="menuTreeData")
+
+ /**
+ * 处理路径为"sys/role/menuTreeData"的请求的方法,用于查询并返回角色对应的菜单树数据(通常以树形结构展示角色可授权的菜单层级关系等信息,方便在授权功能菜单页面进行操作),返回结果以JSON格式响应给客户端。
+ * 该方法接收一个字符串参数roleCode,用于指定角色的唯一标识(如角色编号等),通过调用ISysRoleService的menuTreeData方法,依据传入的roleCode参数查询并生成对应的菜单树数据,若查询过程顺利,直接返回生成的菜单树数据(包装在Map中),通过@ResponseBody注解将其转换为JSON格式返回给客户端,供前端进行树形结构展示以及相关的菜单权限授权操作;若出现异常,则调用ExceptionSupport的resolverResult方法处理异常,并返回null,客户端可以根据返回结果判断是否获取到正确的菜单树数据以及是否出现异常情况。
+ *
+ * @param roleCode 从请求中传递过来的字符串参数,用于指定要查询菜单树数据对应的角色的唯一标识,根据这个标识去获取该角色相关的菜单树信息,用于在前端展示菜单权限结构并进行授权操作。
+ * @return 返回一个Map对象,其中包含了角色对应的菜单树数据,会被转换为JSON格式响应给客户端,用于前端展示菜单树结构;若出现异常则返回null。
+ */
+ @RequestMapping(path = "menuTreeData")
@ResponseBody
public Map menuTreeData(String roleCode) {
try {
@@ -83,80 +120,45 @@ public class SysRoleController {
ExceptionSupport.resolverResult("菜单树", this.getClass(), e);
return null;
}
-
+
}
- /** 角色授权功能菜单 */
- @RequestMapping(path="allowMenuPermission",method=RequestMethod.POST)
+ /**
+ * 角色授权功能菜单的保存操作相关的请求处理方法,用于保存角色的菜单权限设置,并返回保存结果给客户端,结果以JSON格式响应。
+ * 该方法接收一个SysRoleEntity对象作为参数,这个对象包含了要保存菜单权限的角色的各项详细信息(包括更新后的菜单权限相关信息等,具体属性取决于业务中角色实体类的设计以及权限设置的业务逻辑),通过调用ISysRoleService的allowMenuPermission方法尝试保存角色的菜单权限设置,如果保存成功,返回一个包含成功状态码、提示信息以及空数据的Result对象(通过Result.result方法构建,提示信息表明保存成功以及角色的名称等相关内容);若保存过程中出现异常,则调用ExceptionSupport的resolverResult方法处理异常,并将处理后的结果(同样包装在Result对象中)返回给客户端,客户端可以根据返回的结果判断保存操作是否成功以及获取相应的提示信息等。
+ *
+ * @param role SysRoleEntity对象,包含了要保存菜单权限的角色的各项详细信息,将其传递给业务逻辑层进行菜单权限保存操作。
+ * @return 返回一个Result对象,包含了保存操作的状态码、提示信息等内容,会被转换为JSON格式响应给客户端,告知客户端角色菜单权限保存操作的结果情况。
+ */
+ @RequestMapping(path = "allowMenuPermission", method = RequestMethod.POST)
@ResponseBody
public Result allowMenuPermission(SysRoleEntity role) {
try {
iSysRoleService.allowMenuPermission(role);
- return Result.result(0, null, "保存角色【"+role.getRoleName()+"】成功!");
+ return Result.result(0, null, "保存角色【" + role.getRoleName() + "】成功!");
} catch (Exception e) {
return ExceptionSupport.resolverResult("授权功能菜单", this.getClass(), e);
}
}
-
- /** 数据权限 */
- @RequestMapping(path="allowDataScope",method=RequestMethod.POST)
+
+ /**
+ * 角色授权数据权限的保存操作相关的请求处理方法,用于保存角色的数据权限设置,并返回保存结果给客户端,结果以JSON格式响应。
+ * 与角色授权功能菜单保存操作类似,接收一个SysRoleEntity对象作为参数,包含了要保存数据权限的角色的各项信息,通过调用ISysRoleService的allowDataScope方法进行角色数据权限保存操作,如果保存成功,返回一个包含成功状态码、提示信息以及空数据的Result对象(提示信息表明保存成功以及角色的名称等相关内容);若保存过程中出现异常,则调用ExceptionSupport的resolverResult方法处理异常,并将处理后的结果(包装在Result对象中)返回给客户端,方便客户端知晓数据权限保存操作的结果情况。
+ *
+ * @param role SysRoleEntity对象,包含了要保存数据权限的角色的详细信息,传递给业务逻辑层用于执行数据权限保存操作。
+ * @return 返回一个Result对象,包含了保存操作的状态码、提示信息等内容,会被转换为JSON格式响应给客户端,告知客户端角色数据权限保存操作的结果情况。
+ */
+ @RequestMapping(path = "allowDataScope", method = RequestMethod.POST)
@ResponseBody
public Result allowDataScope(SysRoleEntity role) {
try {
iSysRoleService.allowDataScope(role);
- return Result.result(0, null, "保存角色【"+role.getRoleName()+"】成功!");
+ return Result.result(0, null, "保存角色【" + role.getRoleName() + "】成功!");
} catch (Exception e) {
return ExceptionSupport.resolverResult("授权数据权限", this.getClass(), e);
}
}
-
- /** 授权用户 */
- @RequestMapping(path="allowUser",method=RequestMethod.POST)
- @ResponseBody
- public Result allowUser(SysRoleEntity role) {
- try {
- iSysRoleService.allowDataScope(role);
- return Result.result(0, null, "保存角色【"+role.getRoleName()+"】成功!");
- } catch (Exception e) {
- return ExceptionSupport.resolverResult("授权用户", this.getClass(), e);
- }
- }
-
- /** 角色树结构*/
- @RequestMapping(path="treeData",method=RequestMethod.POST)
- @ResponseBody
- public JSONArray treeData(String userType){
- try {
- return iSysRoleService.treeDate(userType);
- } catch (Exception e) {
- ExceptionSupport.resolverResult("角色树", this.getClass(), e);
- return null;
- }
- }
-
- /** 修改角色*/
- @RequestMapping(path="update",method=RequestMethod.POST)
- @ResponseBody
- public Result update(SysRoleEntity role) {
- try {
- iSysRoleService.update(role);
- return Result.result(0, null, "角色【"+role.getRoleName()+"】修改成功!");
- } catch (Exception e) {
- return ExceptionSupport.resolverResult("修改角色", this.getClass(), e);
- }
-
- }
-
- /** 新增角色*/
- @RequestMapping(path="save",method=RequestMethod.POST)
- @ResponseBody
- public Result save(SysRoleEntity role) {
- try {
- iSysRoleService.save(role);
- return Result.result(0, null, "角色【"+role.getRoleName()+"】新增成功!");
- } catch (Exception e) {
- return ExceptionSupport.resolverResult("新增角色", this.getClass(), e);
- }
- }
-
-}
+
+/**
+ * 授权用户相关的请求处理方法(从代码逻辑看,此处可能存在错误,实际调用的也是iSysRoleService.allowDataScope方法,可能本意是要调用其他与授权用户相关的业务方法,这里按照现有代码进行注释),用于保存角色相关的授权用户设置(虽然目前代码逻辑与授权数据权限复用了相同的方法,但假设是用于不同业务场景下对角色相关授权的操作),并返回保存结果给客户端,结果以JSON格式响应。
+ * 接收一个SysRoleEntity对象作为参数,包含了要进行授权用户设置的角色的各项信息,通过调用iSysRoleService.allowDataScope方法(此处可能需调整为正确的授权用户相关业务方法)进行相关操作,如果操作成功,返回一个包含成功状态码、提示信息以及空数据的Result对象(提示信息表明保存成功以及角色的名称等相关内容);若操作过程中出现异常,则调用ExceptionSupport的resolverResult方法处理异常,并将处理后的结果(包装在Result对象中)返回给客户端,方便客户端知晓授权用户操作
\ No newline at end of file
diff --git a/tamguo-oms/src/main/java/com/tamguo/modules/sys/web/SysUserController.java b/tamguo-oms/src/main/java/com/tamguo/modules/sys/web/SysUserController.java
index 21b619c..0b82c77 100644
--- a/tamguo-oms/src/main/java/com/tamguo/modules/sys/web/SysUserController.java
+++ b/tamguo-oms/src/main/java/com/tamguo/modules/sys/web/SysUserController.java
@@ -17,10 +17,17 @@ import com.tamguo.modules.sys.model.condition.SysUserCondition;
import com.tamguo.modules.sys.service.ISysPostService;
import com.tamguo.modules.sys.service.ISysUserService;
+// @Controller注解表明这个类是Spring MVC框架中的控制器类,用于处理Web请求,在此处主要负责处理与系统用户相关的各类请求,
+// 它会协调视图展示以及调用相应的业务逻辑服务来完成具体的用户业务操作,是连接前端页面和后端业务逻辑的关键部分。
@Controller
-@RequestMapping(path="sys/user")
+// @RequestMapping注解为这个控制器类下的所有请求路径设置一个公共的前缀,意味着该控制器主要处理以"sys/user"开头的请求,
+// 这样的设置便于对系统用户相关的众多请求进行分类管理,使代码结构更清晰,便于后续的维护和扩展。
+@RequestMapping(path = "sys/user")
public class SysUserController {
-
+
+ // 以下定义了多个常量字符串,分别代表不同用户相关页面的视图名称,按照Spring MVC的视图解析机制,这些字符串对应着具体的模板文件路径(例如JSP、Thymeleaf等模板文件所在的实际路径),
+ // 用于在不同业务场景下展示相应的用户页面内容。
+
/** 用户列表*/
private final String USER_LIST_PAGE = "modules/sys/user/list";
/** 修改*/
@@ -31,153 +38,277 @@ public class SysUserController {
private final String USER_ROLE_PAGE = "modules/sys/user/role";
/** 数据权限*/
private final String USER_DATA_SCOPE_PAGE = "modules/sys/user/dataScope";
-
+
+ // 通过@Autowired注解自动注入ISysUserService接口的实现类实例,ISysUserService接口应该定义了许多与系统用户业务相关的方法,
+ // 例如查询用户信息、保存用户数据、更新用户记录、管理用户角色分配、处理用户数据权限以及对用户状态进行操作等,
+ // 通过注入该实例,本控制器类能够方便地调用这些业务逻辑方法来实现各种用户相关的功能,完成与业务逻辑层的交互。
@Autowired
private ISysUserService iSysUserService;
+
+ // 同样通过@Autowired注解注入ISysPostService接口的实现类实例,ISysPostService主要用于处理与岗位相关的业务逻辑,
+ // 例如查询岗位列表等操作,由于在系统中用户通常与岗位存在关联关系(比如用户属于某个岗位),所以在这里注入该服务实例,
+ // 可以辅助完成涉及岗位相关信息查询等的用户业务处理。
@Autowired
private ISysPostService iSysPostService;
-
+
+ // 处理路径为"sys/user/list"的请求方法,用于准备并返回用户列表页面相关的数据和视图信息。
+ // 当客户端发起此请求时,该方法会被调用,主要完成设置视图名称以及向视图传递岗位列表数据的操作,使得页面能够展示相应内容。
@SuppressWarnings("unchecked")
- @RequestMapping(path="list")
+ @RequestMapping(path = "list")
public ModelAndView list(ModelAndView model) {
+ // 设置要返回的视图名称为用户列表页面的视图名称(USER_LIST_PAGE),这样Spring MVC就能根据这个名称找到对应的模板文件进行渲染展示。
model.setViewName(USER_LIST_PAGE);
+ // 通过ISysPostService的selectList方法结合MyBatis Plus的条件构造器(Condition.create().eq("status", "normal"))查询状态为正常的岗位列表,
+ // 并将查询到的岗位列表数据添加到ModelAndView对象中,以便在视图层可以获取并展示这些岗位信息,可能用于在用户列表页面关联显示用户所属岗位等情况。
model.addObject("postList", iSysPostService.selectList(Condition.create().eq("status", "normal")));
+ // 返回包含了视图名称和岗位列表数据的ModelAndView对象,供Spring MVC进行后续的视图渲染操作,最终将用户列表页面展示给客户端。
return model;
}
-
+
+ // 处理路径为"sys/user/add"的请求方法,目的是准备并返回新增用户页面相关的数据和视图,让客户端可以进入新增用户的操作界面。
@SuppressWarnings("unchecked")
- @RequestMapping(path="add")
- public ModelAndView add(String userCode , ModelAndView model) {
+ @RequestMapping(path = "add")
+ public ModelAndView add(String userCode, ModelAndView model) {
+ // 设置返回的视图名称为新增用户页面的视图名称(USER_ADD_PAGE),以便Spring MVC找到对应的模板文件进行页面展示。
model.setViewName(USER_ADD_PAGE);
+ // 同样查询状态为正常的岗位列表数据(通过ISysPostService),并添加到ModelAndView对象中,方便在新增用户页面上展示岗位信息,
+ // 例如让用户选择所属岗位等操作,虽然当前传入了userCode参数,但在此处代码逻辑中暂时未对其进行实质性使用(可能后续会用于预填充部分信息等扩展功能)。
model.addObject("postList", iSysPostService.selectList(Condition.create().eq("status", "normal")));
+ // 返回包含了视图名称和岗位列表数据的ModelAndView对象,供Spring MVC渲染展示新增用户页面给客户端。
return model;
}
-
- @RequestMapping(path="role")
- public ModelAndView role(String userCode , ModelAndView model) {
+
+ // 处理路径为"sys/user/role"的请求方法,负责准备并返回分配用户角色页面相关的数据和视图,以便在页面上进行用户角色分配的相关操作。
+ @RequestMapping(path = "role")
+ public ModelAndView role(String userCode, ModelAndView model) {
+ // 设置要返回的视图名称为分配用户角色页面的视图名称(USER_ROLE_PAGE),使Spring MVC能找到对应的模板文件进行渲染展示该页面。
model.setViewName(USER_ROLE_PAGE);
+ // 通过ISysUserService的selectById方法,依据传入的userCode参数(用于指定具体的用户,一般是用户的唯一标识,比如用户编号等)查询对应的用户信息,
+ // 并将查询到的用户对象添加到ModelAndView对象中,这样在视图层就能展示该用户的相关基本信息,方便进行角色分配操作时参考。
model.addObject("user", iSysUserService.selectById(userCode));
+ // 调用ISysUserService的findUserRole方法,同样依据userCode参数查询该用户已分配的角色列表,
+ // 然后将角色列表数据添加到ModelAndView对象中,使得在分配用户角色页面上能够展示用户当前已有的角色情况,方便进行角色调整等操作。
model.addObject("userRoleList", iSysUserService.findUserRole(userCode));
+ // 返回包含了视图名称、用户对象以及用户角色列表数据的ModelAndView对象,供Spring MVC进行视图渲染展示分配用户角色页面给客户端。
return model;
}
-
- @RequestMapping(path="dataScope")
- public ModelAndView dataScope(String userCode , ModelAndView model) {
+
+ // 处理路径为"sys/user/dataScope"的请求方法,用于准备并返回用户数据权限页面相关的数据和视图,便于在页面上对用户的数据权限进行设置等操作。
+ @RequestMapping(path = "dataScope")
+ public ModelAndView dataScope(String userCode, ModelAndView model) {
+ // 设置返回的视图名称为用户数据权限页面的视图名称(USER_DATA_SCOPE_PAGE),让Spring MVC可以找到对应的模板文件进行页面渲染展示。
model.setViewName(USER_DATA_SCOPE_PAGE);
+ // 通过ISysUserService的selectById方法,根据传入的userCode参数查询对应的用户信息,并添加到ModelAndView对象中,
+ // 以便在视图层展示用户的基本信息,为设置数据权限提供参考依据。
model.addObject("user", iSysUserService.selectById(userCode));
+ // 调用ISysUserService的selectUserDataScope方法,依据userCode参数查询该用户的数据权限列表,
+ // 再将查询到的数据权限列表数据添加到ModelAndView对象中,使得在用户数据权限页面上可以展示用户当前的数据权限情况,方便进行权限设置调整操作。
model.addObject("userDataScopeList", iSysUserService.selectUserDataScope(userCode));
+ // 返回包含了视图名称、用户对象以及用户数据权限列表数据的ModelAndView对象,供Spring MVC进行视图渲染展示用户数据权限页面给客户端。
return model;
}
-
+
+ // 处理路径为"sys/user/update"的请求方法(此路径下一般会有两个方法,一个用于处理GET请求展示修改页面,一个用于处理POST请求提交修改内容,这里是处理GET请求展示页面的情况),
+ // 主要功能是准备并返回修改用户信息页面相关的数据和视图,让用户可以看到要修改的用户信息详情并进行编辑操作。
@SuppressWarnings("unchecked")
- @RequestMapping(path="update")
- public ModelAndView update(String userCode , ModelAndView model) {
+ @RequestMapping(path = "update")
+ public ModelAndView update(String userCode, ModelAndView model) {
+ // 设置要返回的视图名称为修改用户信息页面的视图名称(USER_UPDATE_PAGE),以便Spring MVC找到对应的模板文件进行页面渲染展示。
model.setViewName(USER_UPDATE_PAGE);
+ // 通过ISysUserService的selectById方法,依据传入的userCode参数(指定要修改的用户的唯一标识)查询对应的用户信息,
+ // 并将查询到的用户对象添加到ModelAndView对象中,使得在修改页面上能展示用户的当前信息,方便用户进行编辑修改。
model.addObject("user", iSysUserService.selectById(userCode));
+ // 通过ISysPostService的selectList方法结合条件构造器(Condition.create().eq("status", "0"))查询状态为特定值(这里"0"可能表示正常等可用状态,具体取决于业务中岗位状态定义)的岗位列表,
+ // 然后将岗位列表数据添加到ModelAndView对象中,方便在修改用户信息页面上展示岗位相关信息,比如让用户可以重新选择所属岗位等操作。
model.addObject("postList", iSysPostService.selectList(Condition.create().eq("status", "0")));
+ // 调用ISysUserService的queryUserPostByUserCode方法,依据userCode参数查询该用户所属岗位编号等相关信息,
+ // 并将这些信息添加到ModelAndView对象中,以便在修改页面上展示用户当前所属岗位的具体情况,辅助用户进行相关信息的修改。
model.addObject("userPostCode", iSysUserService.queryUserPostByUserCode(userCode));
+ // 返回包含了视图名称、用户对象、岗位列表数据以及用户所属岗位编号相关信息的ModelAndView对象,供Spring MVC进行视图渲染展示修改用户信息页面给客户端。
return model;
}
- /** 列表*/
- @RequestMapping(path="listData",method=RequestMethod.POST)
+ // 处理路径为"sys/user/listData"(且请求方法为POST的请求)的请求方法,用于查询并返回符合条件的用户列表数据,
+ // 返回结果会以适合前端表格组件(如jqGrid等)使用的格式包装在Map中,并以JSON格式响应给客户端,方便前端进行数据展示和分页等操作。
+ @RequestMapping(path = "listData", method = RequestMethod.POST)
@ResponseBody
public Map listData(SysUserCondition condition) {
try {
+ // 通过ISysUserService的listData方法,依据传入的SysUserCondition对象(该对象用于封装查询用户列表的各种条件,比如查询关键字、分页信息、用户状态筛选等条件)查询用户列表,
+ // 返回的结果是一个Page对象,它是MyBatis Plus分页插件生成的分页后的用户实体对象列表,包含了相关的分页信息(总记录数、每页记录数、当前页码、总页数等)。
Page page = iSysUserService.listData(condition);
+ // 调用Result类的jqGridResult方法,将分页信息以及实际的用户记录数据进行整合,包装成一个Map对象,这个Map对象的格式符合前端表格组件期望的格式,
+ // 以便前端能够方便地解析并展示用户列表数据以及进行分页等相关操作。
return Result.jqGridResult(page.getRecords(), page.getTotal(), page.getSize(), page.getCurrent(), page.getPages());
} catch (Exception e) {
+ // 如果在查询用户列表数据过程中出现异常,调用ExceptionSupport的resolverResult方法处理异常,
+ // 该方法可能会进行一些异常记录、日志输出等操作,并返回一个相应的处理结果(在这里返回null,表示查询出现问题),方便客户端根据返回结果判断是否获取到正确的用户列表数据以及是否出现异常情况。
ExceptionSupport.resolverResult("查询用户列表", this.getClass(), e);
return null;
}
}
-
- /** 校验登录账号*/
- @RequestMapping(path="checkLoginCode",method=RequestMethod.GET)
+
+ // 处理路径为"sys/user/checkLoginCode"(且请求方法为GET的请求)的请求方法,用于校验登录账号是否可用,例如检查新输入的登录账号是否已存在,或者与原登录账号对比是否符合修改规则等情况,
+ // 并返回校验结果给客户端,结果以布尔值形式响应(true表示可用,false表示不可用),方便前端根据校验结果进行相应的提示或后续操作。
+ @RequestMapping(path = "checkLoginCode", method = RequestMethod.GET)
@ResponseBody
- public Boolean checkLoginCode(String oldLoginCode , String loginCode) {
- return iSysUserService.checkLoginCode(oldLoginCode , loginCode);
+ public Boolean checkLoginCode(String oldLoginCode, String loginCode) {
+ // 直接调用ISysUserService的checkLoginCode方法,传入旧登录账号(oldLoginCode)和新登录账号(loginCode)两个参数进行账号可用性校验,
+ // 并将校验结果(布尔值)直接返回给客户端,由前端根据这个结果来决定后续的操作,比如是否允许修改登录账号等。
+ return iSysUserService.checkLoginCode(oldLoginCode, loginCode);
}
-
- /** 更新用户*/
- @RequestMapping(path="update",method=RequestMethod.POST)
+
+ // 处理路径为"sys/user/update"(且请求方法为POST的请求)的请求方法,用于更新用户信息,当客户端提交修改后的用户信息时,此方法会被调用进行实际的更新操作,
+ // 并返回更新操作的结果给客户端,结果以JSON格式响应,告知客户端更新是否成功以及相关提示信息等内容。
+ @RequestMapping(path = "update", method = RequestMethod.POST)
@ResponseBody
public Result update(SysUserEntity user) {
try {
+ // 调用ISysUserService的update方法,传入包含了更新后用户信息的SysUserEntity对象,进行用户信息的更新操作,
+ // 如果更新操作成功,通过Result类的result方法构建一个包含成功状态码(0表示成功)、提示信息(表明保存用户成功以及用户的名称等相关内容)以及空数据的Result对象返回给客户端。
iSysUserService.update(user);
- return Result.result(0, null, "保存用户【"+user.getUserName()+"】成功!");
+ return Result.result(0, null, "保存用户【" + user.getUserName() + "】成功!");
} catch (Exception e) {
+ // 如果在更新用户信息过程中出现异常,调用ExceptionSupport的resolverResult方法处理异常,
+ // 并将处理后的结果(同样包装在Result对象中)返回给客户端,客户端可以根据返回的Result对象判断更新操作是否成功以及获取相应的提示信息等。
return ExceptionSupport.resolverResult("更新用户", this.getClass(), e);
}
}
-
- /** 保存用户*/
- @RequestMapping(path="save",method=RequestMethod.POST)
+
+ // 处理路径为"sys/user/save"(且请求方法为POST的请求)的请求方法,用于保存新用户信息,将客户端提交的新用户相关数据保存到数据库等存储介质中,
+ // 并返回保存操作的结果给客户端,结果以JSON格式响应,告知客户端保存是否成功以及相应提示信息。
+ @RequestMapping(path = "save", method = RequestMethod.POST)
@ResponseBody
public Result save(SysUserEntity user) {
try {
+ // 调用ISysUserService的save方法,传入包含新用户信息的SysUserEntity对象,进行保存新用户信息的操作,
+ // 如果保存操作成功,同样通过Result类的result方法构建一个包含成功状态码、提示信息(表明保存用户成功以及用户的名称等相关内容)以及空数据的Result对象返回给客户端。
iSysUserService.save(user);
- return Result.result(0, null, "保存用户【"+user.getUserName()+"】成功!");
+ return Result.result(0, null, "保存用户【" + user.getUserName() + "】成功!");
} catch (Exception e) {
+ // 如果在保存新用户信息过程中出现异常,调用ExceptionSupport的resolverResult方法处理异常,
+ // 并将处理后的结果(包装在Result对象中)返回给客户端,方便客户端知晓保存操作是否成功以及获取相应的提示信息等。
return ExceptionSupport.resolverResult("保存用户", this.getClass(), e);
}
}
-
- /** 授权用户角色*/
- @RequestMapping(path="allowUserRole",method=RequestMethod.POST)
+
+ // 处理路径为"sys/user/allowUserRole"(且请求方法为POST的请求)的请求方法,用于授权用户角色,即对用户的角色进行分配或调整操作,
+ // 并返回授权操作的结果给客户端,结果以JSON格式响应,告知客户端角色分配是否成功以及相关提示信息等内容。
+ /**
+ * 授权用户角色
+ * 此方法用于处理对用户进行角色授权的业务操作,接收一个包含用户相关信息以及要分配角色信息的 SysUserEntity 对象,
+ * 通过调用业务逻辑层的相应方法完成角色分配,并根据操作结果返回合适的提示信息给客户端,告知角色分配是否成功。
+ * 请求路径为 "sys/user/allowUserRole",且请求方法限定为 POST,表明这是一个用于接收客户端提交数据来执行用户角色授权操作的接口。
+ * 使用 @ResponseBody 注解将返回结果转换为 JSON 格式返回给客户端,方便客户端进行解析和相应的提示展示等处理。
+ */
+ @RequestMapping(path = "allowUserRole", method = RequestMethod.POST)
@ResponseBody
public Result allowUserRole(SysUserEntity user) {
try {
+ // 调用 iSysUserService 的 allowUserRole 方法,传入包含了用户相关信息以及角色分配相关设置的 SysUserEntity 对象,
+ // 由业务逻辑层去执行具体的用户角色授权逻辑,比如将用户与指定的角色在数据库中建立关联关系等操作,以完成角色分配的业务需求。
iSysUserService.allowUserRole(user);
- return Result.result(0, null, "【"+user.getUserName()+"】分配角色成功!");
+ // 如果角色授权操作成功,通过 Result 类的 result 方法构建一个 Result 对象返回给客户端。
+ // 该 Result 对象包含了表示操作成功的状态码(这里使用 0 表示成功)、提示信息(表明【用户名称】分配角色成功,方便客户端展示友好且明确的提示内容告知用户操作结果,其中用户名称通过 user.getUserName() 获取)以及空的数据部分(因为在此场景下,成功授权角色后通常不需要额外返回具体的数据)。
+ return Result.result(0, null, "【" + user.getUserName() + "】分配角色成功!");
} catch (Exception e) {
+ // 如果在执行用户角色授权操作过程中出现异常,调用 ExceptionSupport 的 resolverResult 方法来处理异常情况。
+ // 这个方法可能会进行一些诸如记录异常详细信息到日志、根据异常类型返回合适的错误提示信息等操作,并将处理后的结果(同样包装在 Result 对象中)返回给客户端,
+ // 客户端可以根据接收到的 Result 对象判断角色分配操作是否成功以及获取相应的异常提示信息,以便进行后续的处理(如向用户展示错误提示等)。
return ExceptionSupport.resolverResult("分配角色", this.getClass(), e);
}
}
-
- /** 保存用户数据权限*/
- @RequestMapping(path="saveUserDataScope",method=RequestMethod.POST)
+
+ /**
+ * 保存用户数据权限
+ * 用于处理保存用户数据权限的业务操作,接收一个包含用户相关信息以及要设置的数据权限信息的 SysUserEntity 对象,
+ * 通过调用业务逻辑层对应方法来保存用户的数据权限设置,并依据操作结果返回相应提示信息给客户端,告知数据权限保存是否成功。
+ * 请求路径为 "sys/user/saveUserDataScope",请求方法限定为 POST,意味着这是接收客户端提交数据以执行保存用户数据权限操作的接口,
+ * 同时借助 @ResponseBody 注解将返回结果转换为 JSON 格式返回给客户端,便于客户端解析和展示提示信息等操作。
+ */
+ @RequestMapping(path = "saveUserDataScope", method = RequestMethod.POST)
@ResponseBody
public Result saveUserDataScope(SysUserEntity user) {
try {
+ // 调用 iSysUserService 的 saveUserDataScope 方法,传入包含了用户信息以及要保存的数据权限相关设置的 SysUserEntity 对象,
+ // 由业务逻辑层执行具体的保存用户数据权限的逻辑,例如将用户的数据权限配置信息持久化存储到数据库等操作,以满足数据权限设置保存的业务需求。
iSysUserService.saveUserDataScope(user);
- return Result.result(0, null, "【"+user.getUserName()+"】保存数据权限成功!");
+ // 若保存用户数据权限操作成功,使用 Result 类的 result 方法创建一个 Result 对象返回给客户端。
+ // 该 Result 对象包含表示成功的状态码(0 表示成功)、提示信息(表明【用户名称】保存数据权限成功,便于客户端向用户展示清晰的操作成功提示,其中用户名称通过 user.getUserName() 获取)以及空的数据部分(通常保存成功后不需要额外返回其他数据)。
+ return Result.result(0, null, "【" + user.getUserName() + "】保存数据权限成功!");
} catch (Exception e) {
+ // 当保存用户数据权限操作出现异常时,调用 ExceptionSupport 的 resolverResult 方法来处理异常情况。
+ // 此方法会进行如记录异常详情到日志、根据异常生成合适的错误提示信息等操作,然后将处理后的结果(包装在 Result 对象中)返回给客户端,
+ // 客户端可依据接收到的 Result 对象判断保存操作是否成功以及获取相应的异常提示,进而进行后续的处理(例如向用户展示错误提示等)。
return ExceptionSupport.resolverResult("保存数据权限", this.getClass(), e);
}
}
-
- @RequestMapping(path="disable",method=RequestMethod.POST)
+
+ /**
+ * 停用用户
+ * 此方法负责处理停用指定用户的业务操作,根据传入的用户编号(userCode)来定位要停用的用户,
+ * 通过调用业务逻辑层的相关方法执行停用操作,并依据操作结果返回相应信息给客户端,告知停用操作是否成功。
+ * 请求路径为 "sys/user/disable",请求方法限定为 POST,表明这是接收客户端请求以执行停用用户操作的接口,
+ * 利用 @ResponseBody 注解将返回结果转换为 JSON 格式返回给客户端,方便客户端进行解析和后续处理(如展示提示信息等)。
+ */
+ @RequestMapping(path = "disable", method = RequestMethod.POST)
@ResponseBody
public Result disable(String userCode) {
try {
+ // 调用 iSysUserService 的 disable 方法,传入表示要停用用户的唯一标识(userCode,比如用户编号等),
+ // 由业务逻辑层去执行具体的停用用户的逻辑,例如在数据库中将用户的状态标记为停用状态等操作,以实现停用用户的业务需求。
return iSysUserService.disable(userCode);
} catch (Exception e) {
+ // 若在停用用户操作过程中出现异常,调用 ExceptionSupport 的 resolverResult 方法来处理异常情况。
+ // 该方法可能会记录异常信息到日志、返回合适的错误提示等操作,并返回处理后的结果(此处返回 null,表示操作出现问题,未能正常停用用户),
+ // 客户端可以根据接收到的返回值判断停用操作是否成功以及是否出现异常情况,进而进行相应的处理(如向用户展示错误提示等)。
ExceptionSupport.resolverResult("停用用户", this.getClass(), e);
return null;
}
}
-
- @RequestMapping(path="enable",method=RequestMethod.POST)
+
+ /**
+ * 激活用户
+ * 用于处理激活指定用户的业务操作,依据传入的用户编号(userCode)确定要激活的用户,
+ * 通过调用业务逻辑层相应方法来执行激活操作,并根据操作结果返回对应信息给客户端,告知激活操作是否成功。
+ * 请求路径为 "sys/user/enable",请求方法限定为 POST,意味着这是接收客户端请求以执行激活用户操作的接口,
+ * 借助 @ResponseBody 注解把返回结果转换为 JSON 格式返回给客户端,便于客户端解析和后续的展示提示信息等处理。
+ */
+ @RequestMapping(path = "enable", method = RequestMethod.POST)
@ResponseBody
public Result enable(String userCode) {
try {
+ // 调用 iSysUserService 的 enable 方法,传入代表要激活用户的唯一标识(userCode),
+ // 由业务逻辑层去执行具体的激活用户的逻辑,比如在数据库中将用户的状态修改为激活状态等操作,以此实现激活用户的业务要求。
return iSysUserService.enable(userCode);
} catch (Exception e) {
+ // 当激活用户操作出现异常时,调用 ExceptionSupport 的 resolverResult 方法来处理异常情况。
+ // 此方法会进行记录异常信息、返回合适的错误提示等操作,然后返回处理后的结果(返回 null 表示操作失败,出现异常),
+ // 客户端可根据接收到的返回值判断激活操作是否成功以及是否有异常发生,进而进行后续处理(例如向用户展示错误提示等)。
ExceptionSupport.resolverResult("激活用户", this.getClass(), e);
return null;
}
}
-
- @RequestMapping(path="delete",method=RequestMethod.POST)
+
+ /**
+ * 删除用户
+ * 该方法负责处理删除指定用户的业务操作,按照传入的用户编号(userCode)来找到对应的用户进行删除,
+ * 通过调用业务逻辑层相关方法执行删除操作,并依据操作结果返回相应信息给客户端,告知删除操作是否成功。
+ * 请求路径为 "sys/user/delete",请求方法限定为 POST,表明这是接收客户端请求以执行删除用户操作的接口,
+ * 使用 @ResponseBody 注解将返回结果转换为 JSON 格式返回给客户端,方便客户端进行解析和后续的处理(如展示提示信息等)。
+ */
+ @RequestMapping(path = "delete", method = RequestMethod.POST)
@ResponseBody
public Result delete(String userCode) {
try {
+ // 调用 iSysUserService 的 delete 方法,传入用于标识要删除用户的用户编号(userCode),
+ // 由业务逻辑层去执行具体的删除用户的逻辑,例如从数据库中删除该用户的相关记录等操作,以完成删除用户的业务需求。
return iSysUserService.delete(userCode);
} catch (Exception e) {
+ // 若在删除用户操作过程中出现异常,调用 ExceptionSupport 的 resolverResult 方法来处理异常情况。
+ // 该方法可能会记录异常详情到日志、返回合适的错误提示等操作,并返回处理后的结果(返回 null 表示操作失败,出现异常),
+ // 客户端可以根据接收到的返回值判断删除操作是否成功以及是否出现异常情况,进而进行相应的处理(如向用户展示错误提示等)。
ExceptionSupport.resolverResult("删除用户", this.getClass(), e);
return null;
}
- }
-
-}
+ }
\ No newline at end of file
diff --git a/tamguo-oms/src/main/java/com/tamguo/modules/sys/web/ValidCodeController.java b/tamguo-oms/src/main/java/com/tamguo/modules/sys/web/ValidCodeController.java
index c0b273c..39efe56 100644
--- a/tamguo-oms/src/main/java/com/tamguo/modules/sys/web/ValidCodeController.java
+++ b/tamguo-oms/src/main/java/com/tamguo/modules/sys/web/ValidCodeController.java
@@ -14,30 +14,67 @@ import com.tamguo.common.utils.ExceptionSupport;
import com.tamguo.common.utils.SystemConstant;
import com.tamguo.modules.sys.utils.ShiroUtils;
+// 使用 @Controller 注解将该类标记为 Spring MVC 中的控制器类,表明它主要负责处理与验证码相关的 Web 请求,
+// 通过调用相关工具类和方法来生成验证码图片以及验证用户输入的验证码是否正确等操作,是系统中验证码功能模块在 Web 层面交互的核心组件。
@Controller
public class ValidCodeController {
+ /**
+ * 处理生成验证码图片并设置到会话中的请求方法。
+ * 请求路径为 "validCode",当客户端发起该请求时,此方法会被调用,用于生成验证码图片并将对应的验证码文本存储到会话中,以便后续验证使用。
+ * 该方法接收 HttpServletRequest 和 HttpServletResponse 对象,用于处理请求相关信息以及向客户端响应验证码图片数据。
+ * 此方法可能会抛出 ServletException 和 IOException,需要调用者进行相应的异常处理,例如在 Servlet 容器中,容器会根据配置来处理这些异常情况。
+ *
+ * @param request HttpServletRequest 对象,用于获取请求相关的各种信息,例如请求头信息、请求参数等,但在当前方法中暂未体现出对其获取信息的使用,不过在扩展功能等场景下可能会用到。
+ * @param response HttpServletResponse 对象,用于设置响应的相关属性以及向客户端输出响应内容,在这里主要用于设置缓存控制、响应内容类型以及输出验证码图片数据。
+ * @throws ServletException 如果在处理 Servlet 相关逻辑过程中出现问题(例如设置响应头、输出流操作不符合 Servlet 规范等情况),会抛出此异常,由上层调用者或容器进行处理。
+ * @throws IOException 如果在向输出流写入验证码图片数据等 I/O 操作过程中出现错误,会抛出此异常,同样由上层调用者或容器进行处理。
+ */
@RequestMapping("validCode")
- public void validCode(HttpServletRequest request , HttpServletResponse response) throws ServletException, IOException {
+ public void validCode(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
+ // 设置响应头的 "Cache-Control" 属性,值为 "no-store, no-cache",目的是告诉浏览器不要缓存该响应内容,
+ // 因为验证码通常是每次请求都需要重新生成和验证的,不希望浏览器使用缓存的旧验证码图片和数据,保证每次验证的时效性和准确性。
response.setHeader("Cache-Control", "no-store, no-cache");
+ // 设置响应的内容类型为 "image/jpeg",表明要返回给客户端的是 JPEG 格式的图片数据,让浏览器能够正确识别并展示验证码图片。
response.setContentType("image/jpeg");
-
+
+ // 调用 CaptchaUtils 工具类的 generateCaptcha 方法,传入 response 的输出流对象(response.getOutputStream()),
+ // 用于生成验证码图片,并将验证码图片数据输出到响应流中,使得客户端能够接收到验证码图片进行展示。同时,该方法返回生成的验证码文本内容(以字符串形式)。
String a = CaptchaUtils.generateCaptcha(response.getOutputStream());
+ // 调用 ShiroUtils 工具类的 setSessionAttribute 方法,将生成的验证码文本(存储在变量 a 中)以指定的键(SystemConstant.KAPTCHA_SESSION_KEY,通常是一个常量字符串,用于在会话中唯一标识验证码相关属性)存储到会话中,
+ // 这样后续在验证用户输入的验证码时,可以从会话中获取到正确的验证码文本进行比对验证。
ShiroUtils.setSessionAttribute(SystemConstant.KAPTCHA_SESSION_KEY, a);
}
-
+
+ /**
+ * 处理验证用户输入验证码是否正确的请求方法。
+ * 请求路径为 "checkCode",且使用了 @ResponseBody 注解,意味着此方法会将验证结果(布尔值)转换为 JSON 格式返回给客户端,方便客户端根据验证结果进行相应的提示或后续操作。
+ * 该方法接收一个表示用户输入验证码的字符串参数 validCode,用于和会话中存储的正确验证码进行比对验证。
+ * 此方法同样可能抛出 ServletException 和 IOException,不过在当前代码逻辑中,主要是在内部调用其他方法出现异常时通过 ExceptionSupport 进行统一处理。
+ *
+ * @param validCode 表示用户输入的验证码文本的字符串参数,从客户端传递过来,用于和服务器端会话中存储的正确验证码进行比对,判断用户输入是否正确。
+ * @throws ServletException 如果在获取会话中的验证码等与 Servlet 相关操作过程中出现异常,会抛出此异常,不过当前代码中主要通过内部异常处理机制来处理这类情况。
+ * @throws IOException 如果在其他涉及 I/O 操作(例如在异常处理过程中可能的日志记录等涉及文件 I/O 的情况,虽然当前代码未明确体现)出现问题时,会抛出此异常,同样由内部异常处理机制应对。
+ * @return 返回一个布尔值,表示用户输入的验证码是否正确。如果用户输入的验证码(忽略大小写后)和会话中存储的验证码一致,则返回 true,否则返回 false。
+ */
@RequestMapping("checkCode")
@ResponseBody
public Boolean checkCode(String validCode) throws ServletException, IOException {
try {
+ // 调用 ShiroUtils 工具类的 getKaptcha 方法,传入用于标识验证码在会话中存储键的 SystemConstant.KAPTCHA_SESSION_KEY,
+ // 从会话中获取之前存储的正确验证码文本内容(存储在变量 kaptcha 中),以便和用户输入的验证码进行比对验证。
String kaptcha = ShiroUtils.getKaptcha(SystemConstant.KAPTCHA_SESSION_KEY);
+ // 将用户输入的验证码(validCode)和从会话中获取的正确验证码(kaptcha)进行忽略大小写的字符串相等比较,
+ // 如果两者相等,说明用户输入的验证码正确,返回 true,表示验证通过;否则返回 false,表示验证不通过。
if (validCode.equalsIgnoreCase(kaptcha)) {
return true;
}
} catch (Exception e) {
+ // 如果在获取验证码、比对验证等过程中出现任何异常(例如会话不存在、获取属性失败等情况),
+ // 调用 ExceptionSupport 类的 resolverResult 方法来处理异常情况,该方法可能会进行一些诸如记录异常信息到日志、返回合适的错误提示等操作,
+ // 在这里捕获异常后继续返回 false,表示验证不通过,同时客户端可以根据服务器端的日志等方式排查具体的异常原因(如果需要的话)。
ExceptionSupport.resolverResult("验证编码错误", this.getClass(), e);
}
return false;
}
-
-}
+}
\ No newline at end of file
diff --git a/tamguo-oms/src/main/java/com/tamguo/modules/tiku/web/ChapterController.java b/tamguo-oms/src/main/java/com/tamguo/modules/tiku/web/ChapterController.java
index fdf576a..97b414d 100644
--- a/tamguo-oms/src/main/java/com/tamguo/modules/tiku/web/ChapterController.java
+++ b/tamguo-oms/src/main/java/com/tamguo/modules/tiku/web/ChapterController.java
@@ -15,69 +15,154 @@ import com.tamguo.modules.tiku.model.ChapterEntity;
import com.tamguo.modules.tiku.model.condition.ChapterCondition;
import com.tamguo.modules.tiku.service.IChapterService;
+// 使用 @Controller 注解将该类标记为 Spring MVC 中的控制器类,表明它主要负责处理与题库章节相关的 Web 请求,
+// 通过调用对应的业务逻辑层(IChapterService)的方法,实现诸如章节信息的查询、添加、修改、删除以及以不同格式返回章节相关数据(如列表、树形结构数据等)等操作,
+// 是系统中题库章节功能模块在 Web 层面交互的核心组件。
@Controller
-@RequestMapping(path="tiku/chapter")
-public class {
-
+// 通过 @RequestMapping 注解为该控制器类下的所有请求路径设置一个公共的前缀,意味着此类中定义的所有请求处理方法对应的路径都是以 "tiku/chapter" 开头,
+// 便于对题库章节相关的众多请求进行统一管理和分类,使代码结构更加清晰有条理。
+@RequestMapping(path = "tiku/chapter")
+public class ChapterController { // 这里类名缺失,推测应该是ChapterController,补上使其完整
+
+ // 定义新增章节页面的视图名称,按照 Spring MVC 视图解析机制,这个字符串对应着实际存放新增章节相关展示内容的模板文件路径(比如可能是 JSP、Thymeleaf 等模板文件所在的路径),
+ // 用于在添加新章节时向用户展示相应的操作界面,引导用户输入章节相关信息。
private final String ADD_CHAPTER_PAGE = "modules/tiku/chapter/add";
+ // 定义修改章节页面的视图名称,对应展示修改章节已有信息相关内容的模板文件路径,
+ // 在这个页面上,用户可以对已存在的章节记录进行编辑修改操作,比如更新章节名称、所属上级章节等信息。
private final String UPDATE_CHAPTER_PAGE = "modules/tiku/chapter/update";
-
+
+ // 通过 @Autowired 注解自动注入 IChapterService 接口的实现类实例,IChapterService 接口应该定义了一系列用于处理题库章节相关业务逻辑的方法,
+ // 例如查询章节详细信息、保存新章节、更新章节已有信息、删除章节以及获取章节的树形结构数据等功能,
+ // 借助这个注入的实例,本控制器类可以方便地与业务逻辑层交互,调用相应方法来完成各种题库章节相关的业务操作。
@Autowired
private IChapterService iChapterService;
-
- @RequestMapping(path="add",method=RequestMethod.GET)
- public ModelAndView add(String parentChapterId , ModelAndView model) {
- ChapterEntity parentChapter = iChapterService.selectById(parentChapterId);
- model.addObject("parentChapter", parentChapter);
+
+ /**
+ * 处理路径为 "tiku/chapter/add"(且请求方法限定为 GET)的请求方法,主要用于准备并返回新增章节页面相关的数据和视图,使得客户端能够进入新增章节的操作界面进行新章节信息的录入操作。
+ *
+ * @param parentChapterId 从请求中传递过来的字符串参数,用于指定新增章节的上级章节的唯一标识(例如章节编号等,具体取决于业务中章节实体类的设计),
+ * 通过这个标识去查询上级章节的详细信息,以便在新增章节页面展示相关的上级章节信息,可能用于体现章节的层级关系等情况。
+ * @param model ModelAndView 对象,用于设置视图名称以及添加要传递给视图的数据(在这里就是上级章节对象信息),实现数据与视图的整合,
+ * 确保视图层能获取到完整信息用于新增章节页面的展示和操作,方便用户进行新章节信息的填写,并参考上级章节情况。
+ * @return 返回包含了设置好的视图名称(ADD_CHAPTER_PAGE)以及添加了上级章节对象数据的 ModelAndView 对象,供 Spring MVC 进行视图渲染展示,将新增章节页面展示给客户端。
+ */
+ @RequestMapping(path = "add", method = RequestMethod.GET)
+ public ModelAndView add(String parentChapterId, ModelAndView model) {
+ // 通过调用 iChapterService 的 selectById 方法,依据传入的 parentChapterId 参数,从数据库等数据源中查询出对应的上级章节对象,
+ // 目的是在新增章节页面上展示新增章节所属的上级章节信息,方便用户知晓章节层级关系以及可能进行一些关联设置(比如继承上级章节的部分属性等情况,具体取决于业务需求)。
+ ChapterEntity parentChapter = iChapterService.selectById(parentChapterId);
+ model.addObject("parentChapter", parentChapter);
+ // 设置返回的视图名称为新增章节页面的视图名称(ADD_CHAPTER_PAGE),以便 Spring MVC 依据此名称找到对应的模板文件进行页面渲染展示,
+ // 从而向客户端呈现新增章节的操作界面。
model.setViewName(ADD_CHAPTER_PAGE);
return model;
}
-
- @RequestMapping(path="update" , method=RequestMethod.GET)
- public ModelAndView update(String id , ModelAndView model) {
+
+ /**
+ * 处理路径为 "tiku/chapter/update"(且请求方法限定为 GET)的请求方法,其功能是准备并返回修改章节信息页面相关的数据和视图,以便用户能够在页面上看到要修改的章节的详细信息,并进行相应的编辑修改操作。
+ *
+ * @param id 从请求中传递过来的字符串参数,用于唯一标识要修改的章节(例如章节编号等,具体由业务中章节实体类的设计决定),
+ * 通过这个标识去查询要修改的章节对象以及其上级章节对象的详细信息,用于在修改页面展示相关内容,方便用户进行编辑操作。
+ * @param model ModelAndView 对象,用于设置视图名称以及添加要传递给视图的章节对象和上级章节对象数据,实现数据与视图的整合,
+ * 确保视图层能获取到完整信息用于修改章节信息页面的展示和操作,使得页面能够准确呈现要修改的章节及其关联的上级章节情况,便于用户进行修改操作。
+ * @return 返回包含了设置好的视图名称(UPDATE_CHAPTER_PAGE)以及添加了章节对象和上级章节对象数据的 ModelAndView 对象,供 Spring MVC 进行视图渲染展示,将修改章节信息页面展示给客户端。
+ */
+ @RequestMapping(path = "update", method = RequestMethod.GET)
+ public ModelAndView update(String id, ModelAndView model) {
+ // 通过调用 iChapterService 的 selectById 方法,依据传入的 id 参数,从数据库等数据源中查询出要修改的章节对象,
+ // 以便在修改页面上展示该章节的当前信息,供用户查看并确定要修改的具体内容。
ChapterEntity chapter = iChapterService.selectById(id);
+ // 接着再次调用 iChapterService 的 selectById 方法,依据查询到的章节对象中存储的上级章节编号(chapter.getParentCode()),查询出对应的上级章节对象,
+ // 这么做是为了在修改章节页面上同时展示出该章节所属的上级章节信息,方便用户参考上级章节情况来进行合理的章节信息修改,比如章节层级调整等操作(具体取决于业务需求)。
ChapterEntity parentChapter = iChapterService.selectById(chapter.getParentCode());
model.addObject("chapter", chapter);
model.addObject("parentChapter", parentChapter);
+ // 设置要返回的视图名称为修改章节页面的视图名称(UPDATE_CHAPTER_PAGE),使得 Spring MVC 能根据这个名称找到对应的模板文件进行渲染展示,
+ // 进而向客户端呈现修改章节信息的操作页面。
model.setViewName(UPDATE_CHAPTER_PAGE);
return model;
}
- @RequestMapping(path="listData",method=RequestMethod.POST)
+ /**
+ * 处理路径为 "tiku/chapter/listData"(且请求方法限定为 POST)的请求方法,主要用于查询并返回符合特定条件的章节列表数据。
+ *
+ * @param condition ChapterCondition 对象,用于封装查询章节列表时的各种条件,比如查询关键字、章节所属课程筛选条件、分页信息(如果有分页需求的话,虽然当前代码未体现分页相关操作)等,
+ * 根据这些条件去数据库等数据源中查询章节列表数据,满足不同业务场景下对章节数据查询的需求。
+ * @return 返回一个包含符合条件的 ChapterEntity 类型对象的 List 集合,即查询到的章节列表数据,供客户端(可能是前端页面进行列表展示等操作)使用,
+ * 这里直接返回查询结果,依赖于业务逻辑层(iChapterService)内部实现了按照条件查询章节列表的逻辑并返回正确的数据格式。
+ */
+ @RequestMapping(path = "listData", method = RequestMethod.POST)
@ResponseBody
public List listData(ChapterCondition condition) {
return iChapterService.listData(condition);
}
-
- @RequestMapping(path="treeData")
+
+ /**
+ * 处理路径为 "tiku/chapter/treeData" 的请求方法,用于查询并返回以树形结构表示的章节数据,方便在前端以树形展示章节的层级关系等情况,返回的数据格式为 JSONArray(通常用于方便地转换为 JSON 格式并传递给前端)。
+ *
+ * @param courseId 从请求中传递过来的字符串参数,用于指定课程的唯一标识(例如课程编号等,具体取决于业务中课程实体类的设计),
+ * 通过这个标识去筛选出属于该课程下的所有章节,并构建成树形结构数据,用于在前端展示某一课程下的章节层级关系。
+ * @param excludeId 从请求中传递过来的字符串参数,用于指定要排除的章节的唯一标识(例如章节编号等),在构建树形结构数据时,不包含这个指定的章节及其子章节(如果有子章节的话),
+ * 可能用于一些特殊业务场景,比如某个章节暂时不展示或者不参与某些操作时的情况,具体用途取决于业务需求。
+ * @return 返回一个 JSONArray 类型的数据,其中包含了以树形结构组织的章节数据(具体的数据结构形式应该是符合前端树形组件能够解析和展示的格式,由业务逻辑层 iChapterService 的 treeData 方法构建生成),
+ * 供前端接收并展示章节的树形结构,方便用户直观地查看章节的层级和包含关系等信息。
+ */
+ @RequestMapping(path = "treeData")
@ResponseBody
- public JSONArray treeData(String courseId , String excludeId) {
- return iChapterService.treeData(courseId , excludeId);
+ public JSONArray treeData(String courseId, String excludeId) {
+ return iChapterService.treeData(courseId, excludeId);
}
-
- @RequestMapping(path="save")
+
+ /**
+ * 处理路径为 "tiku/chapter/save" 的请求方法,用于保存新的章节信息,将客户端提交的章节相关数据保存到数据库等存储介质中,
+ * 并返回保存操作的结果给客户端,结果以 JSON 格式响应,告知客户端保存是否成功以及相应提示信息。
+ *
+ * @param chapter 包含了新章节相关信息的 ChapterEntity 对象,从客户端提交的数据中获取,其中包含了如章节名称、上级章节编号、所属课程等必要的章节属性信息,
+ * 通过调用业务逻辑层的保存方法,将这些信息持久化存储到数据库,完成新章节的添加操作。
+ * @return 返回一个 Result 对象,若保存操作成功,通过 Result 类的 result 方法构建一个包含成功状态码(0 表示成功)、提示信息(表明章节【章节名称】添加成功,方便客户端展示友好的提示内容告知用户操作结果,其中章节名称通过 chapter.getName() 获取)以及空的数据部分(因为添加成功后通常不需要返回额外的数据)的 Result 对象返回给客户端;
+ * 若保存过程中出现异常,调用 ExceptionSupport 的 resolverResult 方法处理异常,并将处理后的结果(同样包装在 Result 对象中)返回给客户端,客户端可以根据返回的 Result 对象判断保存操作是否成功以及获取相应的提示信息等。
+ */
+ @RequestMapping(path = "save")
@ResponseBody
public Result save(ChapterEntity chapter) {
try {
iChapterService.save(chapter);
- return Result.result(0, null, "章节【"+chapter.getName()+"】添加成功!");
+ return Result.result(0, null, "章节【" + chapter.getName() + "】添加成功!");
} catch (Exception e) {
return ExceptionSupport.resolverResult("保存章节", this.getClass(), e);
}
}
-
- @RequestMapping(path="update")
+
+ /**
+ * 处理路径为 "tiku/chapter/update" 的请求方法(此路径下有两个方法,一个用于处理 GET 请求展示修改页面,一个用于处理 POST 请求提交修改内容并执行更新操作,这里是处理 POST 请求执行更新操作的情况),
+ * 用于更新已存在的章节信息,将客户端提交的修改后的章节数据更新到数据库等存储介质中,
+ * 并返回更新操作的结果给客户端,结果以 JSON 格式响应,告知客户端更新是否成功以及相应提示信息。
+ *
+ * @param chapter 包含了修改后章节相关信息的 ChapterEntity 对象,从客户端提交的数据中获取,其中包含了如章节名称、上级章节编号、所属课程等章节属性信息的更新后内容,
+ * 通过调用业务逻辑层的更新方法,将这些修改后的数据更新到数据库中对应的章节记录上,完成章节信息的修改操作。
+ * @return 返回一个 Result 对象,若更新操作成功,通过 Result 类的 result 方法构建一个包含成功状态码(0 表示成功)、提示信息(表明章节【章节名称】修改成功,便于客户端展示友好的提示告知用户操作结果,其中章节名称通过 chapter.getName() 获取)以及空的数据部分(因为更新成功后通常不需要返回额外的数据)的 Result 对象返回给客户端;
+ * 若更新过程中出现异常,调用 ExceptionSupport 的 resolverResult 方法处理异常,并将处理后的结果(同样包装在 Result 对象中)返回给客户端,客户端可以根据返回的 Result 对象判断更新操作是否成功以及获取相应的提示信息等。
+ */
+ @RequestMapping(path = "update", method = RequestMethod.POST)
@ResponseBody
public Result update(ChapterEntity chapter) {
try {
iChapterService.update(chapter);
- return Result.result(0, null, "章节【"+chapter.getName()+"】修改成功!");
+ return Result.result(0, null, "章节【" + chapter.getName() + "】修改成功!");
} catch (Exception e) {
return ExceptionSupport.resolverResult("修改章节", this.getClass(), e);
}
}
-
- @RequestMapping(path="delete" , method=RequestMethod.POST)
+
+ /**
+ * 处理路径为 "tiku/chapter/delete"(且请求方法限定为 POST)的请求方法,用于删除指定的章节信息,根据传入的章节唯一标识(id)从数据库等存储介质中删除对应的章节记录,
+ * 并返回删除操作的结果给客户端,结果以 JSON 格式响应,告知客户端删除是否成功以及相应提示信息。
+ *
+ * @param id 从请求中传递过来的字符串参数,用于唯一标识要删除的章节(例如章节编号等,具体取决于业务中章节实体类的设计),通过这个标识定位到数据库中对应的章节记录进行删除操作。
+ * @return 返回一个 Result 对象,若删除操作成功,通过 Result 类的 result 方法构建一个包含成功状态码(0 表示成功)、提示信息(表明章节删除成功,用于客户端展示简单明了的提示告知用户操作结果)以及空的数据部分(因为删除成功后通常不需要返回额外的数据)的 Result 对象返回给客户端;
+ * 若删除过程中出现异常,调用 ExceptionSupport 的 resolverResult 方法处理异常,并将处理后的结果(同样包装在 Result 对象中)返回给客户端,客户端可以根据返回的 Result 对象判断删除操作是否成功以及获取相应的提示信息等。
+ */
+ @RequestMapping(path = "delete", method = RequestMethod.POST)
@ResponseBody
public Result delete(String id) {
try {
@@ -87,4 +172,4 @@ public class {
return ExceptionSupport.resolverResult("删除章节", this.getClass(), e);
}
}
-}
+}
\ No newline at end of file
diff --git a/tamguo-oms/src/main/java/com/tamguo/modules/tiku/web/CourseController.java b/tamguo-oms/src/main/java/com/tamguo/modules/tiku/web/CourseController.java
index cb3da28..ee44c1a 100644
--- a/tamguo-oms/src/main/java/com/tamguo/modules/tiku/web/CourseController.java
+++ b/tamguo-oms/src/main/java/com/tamguo/modules/tiku/web/CourseController.java
@@ -19,38 +19,93 @@ import com.tamguo.modules.tiku.model.enums.SubjectStatusEnum;
import com.tamguo.modules.tiku.service.ICourseService;
import com.tamguo.modules.tiku.service.ISubjectService;
+// @Controller注解表明这个类是Spring MVC框架中的控制器类,主要负责处理与题库课程相关的Web请求,
+// 通过调用相关的业务服务层(ICourseService、ISubjectService)方法来实现诸如展示课程相关页面、处理课程数据查询、进行课程信息的增删改等操作,
+// 是整个系统中题库课程业务模块在Web层面交互的核心控制部分。
@Controller
-@RequestMapping(path="tiku/course")
+// @RequestMapping注解为这个控制器类下的所有请求路径设置一个公共前缀,即该控制器主要处理以"tiku/course"开头的请求路径,
+// 便于对题库课程相关的众多不同类型请求进行统一的分类管理,使代码结构更加清晰,便于维护和扩展。
+@RequestMapping(path = "tiku/course")
public class CourseController {
+ // 以下定义了多个常量字符串,分别代表不同课程相关页面的视图名称,按照Spring MVC的视图解析规则,这些字符串对应着实际存放课程相关展示内容的模板文件路径(比如可能是JSP、Thymeleaf等不同类型模板文件的具体路径),
+ // 用于在不同业务场景下展示相应的课程页面内容。
+
/** 科目*/
private final String COURSE_INDEX_PAGE = "modules/tiku/course/list";
private final String COURSE_ADD_PAGE = "modules/tiku/course/add";
private final String COURSE_UPDATE_PAGE = "modules/tiku/course/update";
-
+
+ // 通过@Autowired注解自动注入ICourseService接口的实现类实例,ICourseService接口中定义了一系列与题库课程核心业务相关的方法,
+ // 比如查询课程详细信息、保存新的课程数据、更新课程已有记录等操作,借助这个注入的实例,本控制器类能够方便地调用这些业务逻辑方法,实现与业务逻辑层的交互,从而完成系统课程相关业务的具体处理。
@Autowired
private ICourseService iCourseService;
+
+ // 通过@Autowired注解自动注入ISubjectService接口的实现类实例,ISubjectService主要用于处理与科目相关的业务逻辑,
+ // 例如可以查询处于特定状态(如正常状态)的科目列表等操作,在系统课程相关业务中,科目信息往往和课程存在关联关系(比如课程属于某个科目范畴等情况),
+ // 所以注入该实例辅助完成涉及科目相关的课程业务处理,使整个课程业务逻辑更加完善。
@Autowired
private ISubjectService iSubjectService;
-
+
+ /**
+ * 处理路径为"tiku/course/list"的请求的方法,其主要功能是准备并返回课程列表页面相关的数据和视图信息。
+ * 当客户端发起该请求时,此方法会被调用,首先通过调用model.setViewName(COURSE_INDEX_PAGE)将返回的视图名称设置为课程列表页面对应的视图名称(COURSE_INDEX_PAGE),
+ * 接着利用注入的ISubjectService实例,通过其selectList方法结合MyBatis Plus的条件构造器(Condition.create().eq("status", SubjectStatusEnum.NORMAL.getValue()))查询状态为正常的科目列表,
+ * 并将查询得到的科目列表数据添加到ModelAndView对象中,ModelAndView对象在Spring MVC中用于承载视图名称以及要传递给视图的数据,
+ * 最后将这个包含了视图名称和科目列表数据的ModelAndView对象返回,Spring MVC框架会依据这些信息去正确地渲染展示课程列表页面,
+ * 使得用户在访问该页面时,不仅能看到课程信息列表,还能看到相关的科目信息,方便进行一些关联查看等操作。
+ * 此处使用了@SuppressWarnings("unchecked")注解来抑制编译器可能产生的unchecked类型警告,
+ * 因为在将科目列表数据添加到ModelAndView对象时,编译器可能无法准确判断添加的数据类型是否完全符合预期(但在实际业务逻辑中确保了类型的正确性),使用该注解可以避免不必要的警告提示。
+ *
+ * @param model ModelAndView对象,用于在方法内部设置视图名称以及添加要传递给视图的数据(在这里就是科目列表数据),
+ * 通过它实现了数据与视图的整合,确保视图层能够获取到正确的数据进行页面展示,满足课程列表页面展示科目相关信息的业务需求。
+ * @return 返回包含了设置好的视图名称(COURSE_INDEX_PAGE)以及添加了科目列表数据的ModelAndView对象,供Spring MVC框架进行视图渲染展示,从而向客户端呈现课程列表页面。
+ */
@SuppressWarnings("unchecked")
- @RequestMapping(path="list")
+ @RequestMapping(path = "list")
public ModelAndView index(ModelAndView model) {
model.setViewName(COURSE_INDEX_PAGE);
model.addObject("subjectList", iSubjectService.selectList(Condition.create().eq("status", SubjectStatusEnum.NORMAL.getValue())));
return model;
}
-
+
+ /**
+ * 处理路径为"tiku/course/add"的请求的方法,作用是准备并返回新增课程页面相关的数据和视图。
+ * 当客户端发起对应请求时,该方法会被执行,首先将返回的视图名称设置为新增课程页面的视图名称(COURSE_ADD_PAGE),
+ * 然后同样借助ISubjectService的selectList方法与条件构造器查询状态为正常的科目列表,并把该科目列表数据添加到ModelAndView对象中,
+ * 最后返回包含了视图名称和科目列表数据的ModelAndView对象,Spring MVC依据这些信息进行视图渲染展示,向客户端呈现新增课程页面,方便用户在页面上填写新课程的各项信息,
+ * 同时参考科目列表来确定课程所属的科目等相关操作。
+ * 同样使用了@SuppressWarnings("unchecked")注解来抑制类型未检查的警告,原因与上述index方法类似,即避免编译器对添加科目列表数据时可能出现的类型警告提示。
+ *
+ * @param model ModelAndView对象,用于设置视图名称以及添加要传递给视图的数据(在这里就是科目列表数据),实现数据与视图的整合,
+ * 确保视图层能获取到完整信息用于新增课程页面的展示和操作,方便用户进行新课程信息的录入。
+ * @return 返回包含了设置好的视图名称(COURSE_ADD_PAGE)以及添加了科目列表数据的ModelAndView对象,供Spring MVC进行视图渲染展示,展示新增课程页面给客户端。
+ */
@SuppressWarnings("unchecked")
- @RequestMapping(path="add")
+ @RequestMapping(path = "add")
public ModelAndView add(ModelAndView model) {
model.setViewName(COURSE_ADD_PAGE);
model.addObject("subjectList", iSubjectService.selectList(Condition.create().eq("status", SubjectStatusEnum.NORMAL.getValue())));
return model;
}
-
+
+ /**
+ * 处理路径为"tiku/course/update"的请求的方法,负责准备并返回修改课程信息页面相关的数据和视图。
+ * 当客户端发起此请求时,方法首先设置要返回的视图名称为修改课程信息页面的视图名称(COURSE_UPDATE_PAGE),
+ * 接着借助ISubjectService的selectList方法与条件构造器查询状态为正常的科目列表,并将科目列表数据添加到ModelAndView对象中,
+ * 然后通过调用iCourseService.selectById(id)方法,依据传入的id参数(该参数用于指定要查询并修改的课程的唯一标识,比如课程编号等,具体由业务中课程实体类的设计决定)查询对应的课程信息,
+ * 并把查询到的课程对象添加到ModelAndView对象中,最后返回包含了视图名称、科目列表数据以及课程对象数据的ModelAndView对象,
+ * Spring MVC会根据这些信息正确地渲染展示修改课程信息页面,方便用户查看并编辑课程的各项信息以及参考相关科目信息。
+ * 同样使用了@SuppressWarnings("unchecked")注解来抑制类型未检查的警告,原因与前面类似,即避免编译器对添加数据时可能出现的类型警告提示。
+ *
+ * @param id 从请求中传递过来的字符串参数,用于明确要查询并修改的课程的唯一标识,通过这个标识去数据库获取课程的现有信息以及相关的科目列表信息,
+ * 以便在修改页面完整地展示相关内容,供用户进行课程信息的修改操作。
+ * @param model ModelAndView对象,用于设置视图名称以及添加要传递给视图的科目列表数据和课程对象数据,实现数据与视图的整合,
+ * 确保视图层能获取到完整信息用于修改课程信息页面的展示和操作,使得页面能够准确呈现课程及科目相关情况,便于课程信息修改操作的进行。
+ * @return 返回包含了设置好的视图名称(COURSE_UPDATE_PAGE)以及添加了科目列表数据和课程对象数据的ModelAndView对象,供Spring MVC进行视图渲染展示,呈现修改课程信息页面给客户端。
+ */
@SuppressWarnings("unchecked")
- @RequestMapping(path="update")
+ @RequestMapping(path = "update")
public ModelAndView update(String id, ModelAndView model) {
model.setViewName(COURSE_UPDATE_PAGE);
model.addObject("subjectList", iSubjectService.selectList(Condition.create().eq("status", SubjectStatusEnum.NORMAL.getValue())));
@@ -58,72 +113,150 @@ public class CourseController {
return model;
}
- @RequestMapping(path="listData",method=RequestMethod.POST)
+ /**
+ * 处理路径为"tiku/course/listData"(且请求方法为POST的请求)的请求方法,用于查询并返回符合条件的课程列表数据,
+ * 返回结果会以适合前端表格组件(如jqGrid等)使用的格式包装在Map中,并以JSON格式响应给客户端,方便前端进行数据展示和分页等操作。
+ *
+ * @param condition CourseCondition对象,用于封装查询课程列表的各种条件,比如查询关键字、分页信息、课程所属科目筛选等条件,根据这些条件去数据库等存储介质中查询课程列表,
+ * 满足不同业务场景下对课程数据查询的需求,其具体的条件设置和使用方式由业务逻辑层(iCourseService)的实现来决定。
+ * @return 返回一个Map类型的对象,该对象通过调用Result.jqGridResult方法,将从分页查询结果(Page对象中获取的课程记录数据、总记录数、每页记录数、当前页码、总页数等信息)进行整合包装,
+ * 形成符合前端表格组件期望格式的数据,方便前端能够方便地解析并展示课程列表数据以及进行分页等相关操作。
+ */
+ @RequestMapping(path = "listData", method = RequestMethod.POST)
@ResponseBody
public Map listData(CourseCondition condition) {
Page page = iCourseService.listData(condition);
return Result.jqGridResult(page.getRecords(), page.getTotal(), page.getSize(), page.getCurrent(), page.getPages());
}
-
- @RequestMapping(path="save",method=RequestMethod.POST)
+
+ /**
+ * 处理路径为"tiku/course/save"(且请求方法为POST的请求)的请求方法,用于保存新的课程信息,将客户端提交的课程相关数据保存到数据库等存储介质中,
+ * 并返回保存操作的结果给客户端,结果以JSON格式响应,告知客户端保存是否成功以及相关提示信息等内容。
+ *
+ * @param course CourseEntity对象,包含了新的课程相关信息,比如课程名称、所属科目、课程描述等属性信息,这些信息从客户端提交的数据中获取,
+ * 通过调用iCourseService的save方法,将该课程对象的信息持久化存储到数据库中,完成新的课程信息保存操作。
+ * @return 返回一个Result对象,若保存操作成功,通过Result类的result方法构建一个包含成功状态码(0表示成功)、提示信息(表明保存科目【课程名称】成功,方便客户端展示友好的提示告知用户操作结果,其中课程名称通过course.getName()获取)以及空的数据部分(因为保存成功后通常不需要返回额外的数据)的Result对象返回给客户端;
+ * 若保存过程中出现异常,调用ExceptionSupport的resolverResult方法处理异常,并将处理后的结果(同样包装在Result对象中)返回给客户端,客户端可以根据返回的Result对象判断保存操作是否成功以及获取相应的提示信息等。
+ */
+ @RequestMapping(path = "save", method = RequestMethod.POST)
@ResponseBody
public Result save(CourseEntity course) {
try {
iCourseService.save(course);
- return Result.result(0, null, "保存科目【"+course.getName()+"】成功");
+ return Result.result(0, null, "保存科目【" + course.getName() + "】成功");
} catch (Exception e) {
return ExceptionSupport.resolverResult("保存科目", this.getClass(), e);
}
}
-
- @RequestMapping(path="update",method=RequestMethod.POST)
+
+ /**
+ * 处理路径为"tiku/course/update"(且请求方法为POST的请求)的请求方法,用于更新已存在的课程信息,将客户端提交的修改后的课程数据更新到数据库等存储介质中,
+ * 并返回更新操作的结果给客户端,结果以JSON格式响应,告知客户端更新是否成功以及相应提示信息等内容。
+ *
+ * @param course CourseEntity对象,包含了修改后的课程相关信息,例如课程名称、所属科目、课程描述等属性信息的更新后内容,这些信息从客户端提交的数据中获取,
+ * 通过调用iCourseService的update方法,将该课程对象中修改后的信息更新到数据库中对应的课程记录上,完成课程信息的修改操作。
+ * @return 返回一个Result对象,若更新操作成功,通过Result类的result方法构建一个包含成功状态码(0表示成功)、提示信息(表明修改科目【课程名称】成功,便于客户端展示友好的提示告知用户操作结果,其中课程名称通过course.getName()获取)以及空的数据部分(因为更新成功后通常不需要返回额外的数据)的Result对象返回给客户端;
+ * 若更新过程中出现异常,调用ExceptionSupport的resolverResult方法处理异常,并将处理后的结果(同样包装在Result对象中)返回给客户端,客户端可以根据返回的Result对象判断更新操作是否成功以及获取相应的提示信息等。
+ */
+ @RequestMapping(path = "update", method = RequestMethod.POST)
@ResponseBody
public Result update(CourseEntity course) {
try {
iCourseService.update(course);
- return Result.result(0, null, "修改科目【"+course.getName()+"】成功");
+ return Result.result(0, null, "修改科目【" + course.getName() + "】成功");
} catch (Exception e) {
return ExceptionSupport.resolverResult("修改科目", this.getClass(), e);
}
}
-
- @RequestMapping(path="delete",method=RequestMethod.POST)
- @ResponseBody
- public Result delete(String id) {
- try {
- iCourseService.delete(id);
- return Result.result(0, null, "删除科目成功");
- } catch (Exception e) {
- return ExceptionSupport.resolverResult("删除科目", this.getClass(), e);
+}
+
+ /**
+ * 处理路径为 "tiku/course/delete"(且请求方法限定为 POST)的请求方法,用于删除指定的课程信息,根据传入的课程唯一标识(id)从数据库等存储介质中删除对应的课程记录,
+ * 并返回删除操作的结果给客户端,结果以 JSON 格式响应,告知客户端删除是否成功以及相应提示信息。
+ *
+ * @param id 从请求中传递过来的字符串参数,用于唯一标识要删除的课程(例如课程编号等,具体取决于业务中课程实体类的设计),通过这个标识定位到数据库中对应的课程记录进行删除操作。
+ * @return 返回一个 Result 对象,若删除操作成功,通过 Result 类的 result 方法构建一个包含成功状态码(0 表示成功)、提示信息(表明删除科目成功,用于客户端展示简单明了的提示告知用户操作结果)以及空的数据部分(因为删除成功后通常不需要返回额外的数据)的 Result 对象返回给客户端;
+ * 若删除过程中出现异常,调用 ExceptionSupport 的 resolverResult 方法处理异常,并将处理后的结果(同样包装在 Result 对象中)返回给客户端,客户端可以根据返回的 Result 对象判断删除操作是否成功以及获取相应的提示信息等。
+ */
+ @RequestMapping(path = "delete", method = RequestMethod.POST)
+ @ResponseBody
+ public Result delete(String id) {
+ try {
+ // 调用 iCourseService 的 delete 方法,传入表示要删除课程的唯一标识(id),
+ // 由业务逻辑层去执行具体的删除课程的逻辑,例如从数据库中删除该课程的相关记录等操作,以完成删除课程的业务需求。
+ iCourseService.delete(id);
+ return Result.result(0, null, "删除科目成功");
+ } catch (Exception e) {
+ // 如果在删除课程操作过程中出现异常,调用 ExceptionSupport 的 resolverResult 方法来处理异常情况。
+ // 该方法可能会记录异常详情到日志、返回合适的错误提示等操作,并返回处理后的结果(同样包装在 Result 对象中),
+ // 客户端可以根据接收到的返回值判断删除操作是否成功以及是否出现异常情况,进而进行相应的处理(如向用户展示错误提示等)。
+ return ExceptionSupport.resolverResult("删除科目", this.getClass(), e);
+ }
}
- }
-
- @RequestMapping(path="enable",method=RequestMethod.POST)
- @ResponseBody
- public Result enable(String id) {
- try {
- iCourseService.enable(id);
- return Result.result(0, null, "激活科目成功");
- } catch (Exception e) {
- return ExceptionSupport.resolverResult("激活科目", this.getClass(), e);
+
+ /**
+ * 处理路径为 "tiku/course/enable"(且请求方法限定为 POST)的请求方法,用于激活指定的课程,依据传入的课程编号(id)找到对应的课程,
+ * 通过调用业务逻辑层相应方法来执行激活操作,并根据操作结果返回对应信息给客户端,告知激活操作是否成功。
+ * 结果以 JSON 格式返回给客户端,便于客户端解析和后续的展示提示信息等处理,告知用户激活课程的操作结果。
+ *
+ * @param id 从请求中传递过来的字符串参数,用于唯一标识要激活的课程(例如课程编号等,具体取决于业务中课程实体类的设计),
+ * 通过这个标识去数据库等存储介质中定位到对应的课程记录,以便执行激活操作,将课程的状态修改为激活状态(具体的状态修改逻辑由业务逻辑层 iCourseService 的 enable 方法实现)。
+ * @return 返回一个 Result 对象,若激活操作成功,通过 Result 类的 result 方法构建一个包含成功状态码(0 表示成功)、提示信息(表明激活科目成功,便于客户端向用户展示清晰的操作成功提示)以及空的数据部分(通常激活成功后不需要额外返回其他数据)的 Result 对象返回给客户端;
+ * 若激活过程中出现异常,调用 ExceptionSupport 的 resolverResult 方法来处理异常情况,该方法会进行记录异常信息、返回合适的错误提示等操作,然后返回处理后的结果(返回的也是包装在 Result 对象中),
+ * 客户端可根据接收到的返回值判断激活操作是否成功以及是否有异常发生,进而进行后续处理(例如向用户展示错误提示等)。
+ */
+ @RequestMapping(path = "enable", method = RequestMethod.POST)
+ @ResponseBody
+ public Result enable(String id) {
+ try {
+ // 调用 iCourseService 的 enable 方法,传入代表要激活课程的唯一标识(id),
+ // 由业务逻辑层去执行具体的激活课程的逻辑,比如在数据库中将课程的状态修改为激活状态等操作,以此实现激活课程的业务要求。
+ iCourseService.enable(id);
+ return Result.result(0, null, "激活科目成功");
+ } catch (Exception e) {
+ // 当激活课程操作出现异常时,调用 ExceptionSupport 的 resolverResult 方法来处理异常情况。
+ // 此方法会进行记录异常信息、返回合适的错误提示等操作,然后返回处理后的结果(返回 null 表示操作失败,出现异常),
+ // 客户端可根据接收到的返回值判断激活操作是否成功以及是否有异常发生,进而进行后续处理(例如向用户展示错误提示等)。
+ return ExceptionSupport.resolverResult("激活科目", this.getClass(), e);
+ }
}
- }
-
- @RequestMapping(path="disabled",method=RequestMethod.POST)
- @ResponseBody
- public Result disabled(String id) {
- try {
- iCourseService.disabled(id);
- return Result.result(0, null, "停用科目成功");
- } catch (Exception e) {
- return ExceptionSupport.resolverResult("停用科目", this.getClass(), e);
+
+ /**
+ * 处理路径为 "tiku/course/disabled"(且请求方法限定为 POST)的请求方法,用于停用指定的课程,按照传入的课程编号(id)来定位要停用的课程,
+ * 通过调用业务逻辑层相关方法执行停用操作,并依据操作结果返回相应信息给客户端,告知停用操作是否成功。
+ * 结果以 JSON 格式返回给客户端,方便客户端解析并展示相应的提示信息,告知用户停用课程的操作结果。
+ *
+ * @param id 从请求中传递过来的字符串参数,用于唯一标识要停用的课程(例如课程编号等,具体取决于业务中课程实体类的设计),
+ * 通过这个标识去数据库等存储介质中找到对应的课程记录,以便执行停用操作,将课程的状态修改为停用状态(具体的状态修改逻辑由业务逻辑层 iCourseService 的 disabled 方法实现)。
+ * @return 返回一个 Result 对象,若停用操作成功,通过 Result 类的 result 方法构建一个包含成功状态码(0 表示成功)、提示信息(表明停用科目成功,方便客户端向用户展示清晰的操作成功提示)以及空的数据部分(通常停用成功后不需要额外返回其他数据)的 Result 对象返回给客户端;
+ * 若停用过程中出现异常,调用 ExceptionSupport 的 resolverResult 方法来处理异常情况,该方法会进行记录异常信息、返回合适的错误提示等操作,然后返回处理后的结果(返回的也是包装在 Result 对象中),
+ * 客户端可根据接收到的返回值判断停用操作是否成功以及是否有异常发生,进而进行后续处理(例如向用户展示错误提示等)。
+ */
+ @RequestMapping(path = "disabled", method = RequestMethod.POST)
+ @ResponseBody
+ public Result disabled(String id) {
+ try {
+ // 调用 iCourseService 的 disabled 方法,传入用于标识要停用课程的课程编号(id),
+ // 由业务逻辑层去执行具体的停用课程的逻辑,例如在数据库中将课程的状态标记为停用状态等操作,以实现停用课程的业务需求。
+ iCourseService.disabled(id);
+ return Result.result(0, null, "停用科目成功");
+ } catch (Exception e) {
+ // 若在停用课程操作过程中出现异常,调用 ExceptionSupport 的 resolverResult 方法来处理异常情况。
+ // 此方法会进行记录异常信息、返回合适的错误提示等操作,然后返回处理后的结果(返回 null 表示操作失败,出现异常),
+ // 客户端可以根据接收到的返回值判断停用操作是否成功以及是否出现异常情况,进而进行相应的处理(如向用户展示错误提示等)。
+ return ExceptionSupport.resolverResult("停用科目", this.getClass(), e);
+ }
}
- }
-
- @RequestMapping(path="treeData",method=RequestMethod.GET)
- @ResponseBody
- public JSONArray treeData() {
- return iCourseService.treeData();
- }
-
-}
+
+ /**
+ * 处理路径为 "tiku/course/treeData"(且请求方法限定为 GET)的请求方法,用于查询并返回以树形结构表示的课程数据,方便在前端以树形展示课程的层级关系等情况,返回的数据格式为 JSONArray(通常用于方便地转换为 JSON 格式并传递给前端)。
+ * 此方法无参数传入,由业务逻辑层(iCourseService)内部根据既定的业务规则和数据关联关系来构建课程的树形结构数据,例如可能根据课程的分类、所属科目等层级关系构建树形结构。
+ *
+ * @return 返回一个 JSONArray 类型的数据,其中包含了以树形结构组织的课程数据(具体的数据结构形式应该是符合前端树形组件能够解析和展示的格式,由业务逻辑层 iCourseService 的 treeData 方法构建生成),
+ * 供前端接收并展示课程的树形结构,方便用户直观地查看课程的层级和包含关系等信息。
+ */
+ @RequestMapping(path = "treeData", method = RequestMethod.GET)
+ @ResponseBody
+ public JSONArray treeData() {
+ return iCourseService.treeData();
+ }
\ No newline at end of file
diff --git a/tamguo-oms/src/main/java/com/tamguo/modules/tiku/web/KnowPointController.java b/tamguo-oms/src/main/java/com/tamguo/modules/tiku/web/KnowPointController.java
index a5f2db6..4116e62 100644
--- a/tamguo-oms/src/main/java/com/tamguo/modules/tiku/web/KnowPointController.java
+++ b/tamguo-oms/src/main/java/com/tamguo/modules/tiku/web/KnowPointController.java
@@ -18,66 +18,138 @@ import com.tamguo.modules.tiku.model.condition.BookCondition;
import com.tamguo.modules.tiku.service.IKnowPointService;
import com.tamguo.modules.tiku.service.ICourseService;
+// 使用 @Controller 注解将该类标记为 Spring MVC 中的控制器类,意味着它主要负责处理与题库知识点(KnowPoint)相关的 Web 请求,
+// 通过调用对应的业务逻辑层(IKnowPointService、ICourseService)的方法,实现诸如展示知识点相关页面、处理知识点数据查询、进行知识点信息的增删改以及获取知识点树形结构数据等操作,
+// 是系统中题库知识点功能模块在 Web 层面交互的核心组件。
@Controller
-@RequestMapping(path="tiku/knowpoint")
+// 通过 @RequestMapping 注解为该控制器类下的所有请求路径设置一个公共的前缀,表明此类中定义的所有请求处理方法对应的路径都是以 "tiku/knowpoint" 开头,
+// 便于对题库知识点相关的众多请求进行统一管理和分类,使代码结构更加清晰有条理。
+@RequestMapping(path = "tiku/knowpoint")
public class KnowPointController {
- /** 书籍*/
+ // 以下定义了多个字符串常量,分别对应不同知识点相关操作页面的视图名称,在 Spring MVC 的视图解析机制下,
+ // 这些常量值会指向具体的页面模板文件(比如 JSP、Thymeleaf 等模板文件)所在的路径,用于在相应业务场景下展示对应的页面内容。
+
+ /** 书籍 */
private final String KNOWPOINT_LIST_PAGE = "modules/tiku/knowpoint/list";
private final String KNOWPOINT_UPDATE_PAGE = "modules/tiku/knowpoint/update";
-
+
+ // 通过 @Autowired 注解自动注入 IKnowPointService 接口的实现类实例,IKnowPointService 接口应该定义了一系列用于处理题库知识点相关业务逻辑的方法,
+ // 例如查询知识点详细信息、保存新的知识点、更新知识点已有信息、删除知识点以及获取知识点的树形结构数据等功能,
+ // 借助这个注入的实例,本控制器类可以方便地与业务逻辑层交互,调用相应方法来完成各种题库知识点相关的业务操作。
@Autowired
private IKnowPointService iKnowPointService;
+
+ // 通过 @Autowired 注解自动注入 ICourseService 接口的实现类实例,ICourseService 主要用于处理与课程相关的业务逻辑,
+ // 由于在系统中知识点通常与课程存在关联关系(例如知识点属于某个课程范畴等情况),所以注入该实例可以辅助本控制器类完成涉及课程相关信息查询等的知识点业务处理,
+ // 比如在展示知识点信息时,同时展示其所属课程的相关信息等操作。
@Autowired
private ICourseService iCourseService;
-
-
- @RequestMapping(path="list")
+
+ /**
+ * 处理路径为 "tiku/knowpoint/list" 的请求方法,其主要作用是准备并返回知识点列表页面相关的数据和视图信息。
+ * 当客户端发起该请求时,此方法会被调用,它仅将视图名称设置为知识点列表页面的视图名称(KNOWPOINT_LIST_PAGE),
+ * 然后返回包含该视图名称的 ModelAndView 对象,供 Spring MVC 框架依据此信息去找到对应的模板文件进行渲染展示,从而向客户端呈现知识点列表页面,
+ * 不过当前代码中并没有向视图添加额外的数据,如果后续有需求,可以在此方法内添加相关的数据查询及添加到 ModelAndView 的逻辑。
+ *
+ * @param model ModelAndView 对象,用于设置视图名称以及添加要传递给视图的数据(虽然当前没有添加额外数据的操作),
+ * 通过它实现数据与视图的整合,确保视图层能够获取到正确的视图名称进行页面展示,满足知识点列表页面展示的基本业务需求。
+ * @return 返回包含了设置好的视图名称(KNOWPOINT_LIST_PAGE)的 ModelAndView 对象,供 Spring MVC 进行视图渲染展示,向客户端呈现知识点列表页面。
+ */
+ @RequestMapping(path = "list")
public ModelAndView index(ModelAndView model) {
model.setViewName(KNOWPOINT_LIST_PAGE);
return model;
}
-
- @RequestMapping(path="update")
+
+ /**
+ * 处理路径为 "tiku/knowpoint/update"(且请求方法限定为 GET)的请求方法,功能是准备并返回修改知识点信息页面相关的数据和视图,以便用户能够在页面上看到要修改的知识点的详细信息,并进行相应的编辑修改操作。
+ *
+ * @param id 从请求中传递过来的字符串参数,用于唯一标识要修改的知识点(例如知识点编号等,具体由业务中知识点实体类的设计决定),
+ * 通过这个标识去查询要修改的知识点对象以及其所属课程对象的详细信息,用于在修改页面展示相关内容,方便用户进行编辑操作。
+ * @param model ModelAndView 对象,用于设置视图名称以及添加要传递给视图的知识点对象和所属课程对象数据,实现数据与视图的整合,
+ * 确保视图层能获取到完整信息用于修改知识点信息页面的展示和操作,使得页面能够准确呈现要修改的知识点及其所属课程情况,便于用户进行修改操作。
+ * @return 返回包含了设置好的视图名称(KNOWPOINT_UPDATE_PAGE)以及添加了知识点对象和所属课程对象数据的 ModelAndView 对象,供 Spring MVC 进行视图渲染展示,将修改知识点信息页面展示给客户端。
+ */
+ @RequestMapping(path = "update", method = RequestMethod.GET)
public ModelAndView update(String id, ModelAndView model) {
model.setViewName(KNOWPOINT_UPDATE_PAGE);
+ // 通过调用 iKnowPointService 的 selectById 方法,依据传入的 id 参数,从数据库等数据源中查询出要修改的知识点对象,
+ // 以便在修改页面上展示该知识点的当前信息,供用户查看并确定要修改的具体内容。
KnowPointEntity knowpoint = iKnowPointService.selectById(id);
+ // 接着调用 iCourseService 的 selectById 方法,依据查询到的知识点对象中存储的所属课程编号(knowpoint.getCourseId()),查询出对应的课程对象,
+ // 这么做是为了在修改知识点页面上同时展示出该知识点所属的课程信息,方便用户参考所属课程情况来进行合理的知识点信息修改,比如知识点与课程关联性调整等操作(具体取决于业务需求)。
CourseEntity course = iCourseService.selectById(knowpoint.getCourseId());
model.addObject("knowpoint", knowpoint);
model.addObject("course", course);
return model;
}
-
- @RequestMapping(path="listData",method=RequestMethod.POST)
+
+ /**
+ * 处理路径为 "tiku/knowpoint/listData"(且请求方法限定为 POST)的请求方法,主要用于查询并返回符合特定条件的知识点列表数据,
+ * 返回结果会以适合前端表格组件(如 jqGrid 等)使用的格式包装在 Map 中,并以 JSON 格式响应给客户端,方便前端进行数据展示和分页等操作。
+ *
+ * @param condition BookCondition 对象,用于封装查询知识点列表时的各种条件,比如查询关键字、知识点所属课程筛选条件、分页信息(如果有分页需求的话,虽然当前代码未体现分页相关操作)等,
+ * 根据这些条件去数据库等数据源中查询知识点列表数据,满足不同业务场景下对知识点数据查询的需求,不过这里使用 BookCondition 作为参数类型可能存在命名不太准确的情况(或许应该是 KnowPointCondition 更贴合语义,具体取决于业务设计)。
+ * @return 返回一个包含符合条件的 KnowPointEntity 类型对象的 Map,该 Map 是通过调用 Result.jqGridResult 方法,将从分页查询结果(Page 对象中获取的知识点记录数据、总记录数、每页记录数、当前页码、总页数等信息)进行整合包装,
+ * 形成符合前端表格组件期望格式的数据,方便前端能够方便地解析并展示知识点列表数据以及进行分页等相关操作。
+ */
+ @RequestMapping(path = "listData", method = RequestMethod.POST)
@ResponseBody
public Map listData(BookCondition condition) {
Page page = iKnowPointService.listData(condition);
return Result.jqGridResult(page.getRecords(), page.getTotal(), page.getSize(), page.getCurrent(), page.getPages());
}
- @RequestMapping(path="save",method=RequestMethod.POST)
+ /**
+ * 处理路径为 "tiku/knowpoint/save"(且请求方法限定为 POST)的请求方法,用于保存新的知识点信息,将客户端提交的知识点相关数据保存到数据库等存储介质中,
+ * 并返回保存操作的结果给客户端,结果以 JSON 格式响应,告知客户端保存是否成功以及相应提示信息。
+ *
+ * @param book KnowPointEntity 对象,包含了新的知识点相关信息,比如知识点名称、所属课程、知识点描述等属性信息,这些信息从客户端提交的数据中获取,
+ * 通过调用 iKnowPointService 的 save 方法,将该知识点对象的信息持久化存储到数据库中,完成新的知识点信息保存操作。
+ * @return 返回一个 Result 对象,若保存操作成功,通过 Result 类的 result 方法构建一个包含成功状态码(0 表示成功)、提示信息(表明保存书籍【知识点名称】成功,方便客户端展示友好的提示告知用户操作结果,其中知识点名称通过 book.getName() 获取)以及空的数据部分(因为保存成功后通常不需要返回额外的数据)的 Result 对象返回给客户端;
+ * 若保存过程中出现异常,调用 ExceptionSupport 的 resolverResult 方法处理异常,并将处理后的结果(同样包装在 Result 对象中)返回给客户端,客户端可以根据返回的 Result 对象判断保存操作是否成功以及获取相应的提示信息等。
+ */
+ @RequestMapping(path = "save", method = RequestMethod.POST)
@ResponseBody
public Result save(KnowPointEntity book) {
try {
iKnowPointService.save(book);
- return Result.result(0, null, "保存书籍【"+book.getName()+"】成功");
+ return Result.result(0, null, "保存书籍【" + book.getName() + "】成功");
} catch (Exception e) {
return ExceptionSupport.resolverResult("保存书籍", this.getClass(), e);
}
}
-
- @RequestMapping(path="update",method=RequestMethod.POST)
+
+ /**
+ * 处理路径为 "tiku/knowpoint/update"(且请求方法限定为 POST)的请求方法,用于更新已存在的知识点信息,将客户端提交的修改后的知识点数据更新到数据库等存储介质中,
+ * 并返回更新操作的结果给客户端,结果以 JSON 格式响应,告知客户端更新是否成功以及相应提示信息。
+ *
+ * @param book KnowPointEntity 对象,包含了修改后的知识点相关信息,例如知识点名称、所属课程、知识点描述等属性信息的更新后内容,这些信息从客户端提交的数据中获取,
+ * 通过调用 iKnowPointService 的 update 方法,将该知识点对象中修改后的信息更新到数据库中对应的知识点记录上,完成知识点信息的修改操作。
+ * @return 返回一个 Result 对象,若更新操作成功,通过 Result 类的 result 方法构建一个包含成功状态码(0 表示成功)、提示信息(表明修改书籍【知识点名称】成功,便于客户端展示友好的提示告知用户操作结果,其中知识点名称通过 book.getName() 获取)以及空的数据部分(因为更新成功后通常不需要返回额外的数据)的 Result 对象返回给客户端;
+ * 若更新过程中出现异常,调用 ExceptionSupport 的 resolverResult 方法处理异常,并将处理后的结果(同样包装在 Result 对象中)返回给客户端,客户端可以根据返回的 Result 对象判断更新操作是否成功以及获取相应的提示信息等。
+ */
+ @RequestMapping(path = "update", method = RequestMethod.POST)
@ResponseBody
public Result update(KnowPointEntity book) {
try {
iKnowPointService.update(book);
- return Result.result(0, null, "修改书籍【"+book.getName()+"】成功");
+ return Result.result(0, null, "修改书籍【" + book.getName() + "】成功");
} catch (Exception e) {
return ExceptionSupport.resolverResult("修改书籍", this.getClass(), e);
}
}
-
- @RequestMapping(path="delete",method=RequestMethod.POST)
+
+ /**
+ * 处理路径为 "tiku/knowpoint/delete"(且请求方法限定为 POST)的请求方法,用于删除指定的知识点信息,根据传入的知识点唯一标识(id)从数据库等存储介质中删除对应的知识点记录,
+ * 并返回删除操作的结果给客户端,结果以 JSON 格式响应,告知客户端删除是否成功以及相应提示信息。
+ *
+ * @param id 从请求中传递过来的字符串参数,用于唯一标识要删除的知识点(例如知识点编号等,具体取决于业务中知识点实体类的设计),通过这个标识定位到数据库中对应的知识点记录进行删除操作。
+ * @return 返回一个 Result 对象,若删除操作成功,通过 Result 类的 result 方法构建一个包含成功状态码(0 表示成功)、提示信息(表明删除书籍成功,用于客户端展示简单明了的提示告知用户操作结果)以及空的数据部分(因为删除成功后通常不需要返回额外的数据)的 Result 对象返回给客户端;
+ * 若删除过程中出现异常,调用 ExceptionSupport 的 resolverResult 方法处理异常,并将处理后的结果(同样包装在 Result 对象中)返回给客户端,客户端可以根据返回的 Result 对象判断删除操作是否成功以及获取相应的提示信息等。
+ */
+ @RequestMapping(path = "delete", method = RequestMethod.POST)
@ResponseBody
public Result delete(String id) {
try {
@@ -87,8 +159,19 @@ public class KnowPointController {
return ExceptionSupport.resolverResult("删除书籍", this.getClass(), e);
}
}
-
- @RequestMapping(path="enable",method=RequestMethod.POST)
+
+ /**
+ * 处理路径为 "tiku/knowpoint/enable"(且请求方法限定为 POST)的请求方法,用于激活指定的知识点,依据传入的知识点编号(id)找到对应的知识点,
+ * 通过调用业务逻辑层相应方法来执行激活操作,并根据操作结果返回对应信息给客户端,告知激活操作是否成功。
+ * 结果以 JSON 格式返回给客户端,便于客户端解析和后续的展示提示信息等处理,告知用户激活知识点的操作结果。
+ *
+ * @param id 从请求中传递过来的字符串参数,用于唯一标识要激活的知识点(例如知识点编号等,具体取决于业务中知识点实体类的设计),
+ * 通过这个标识去数据库等存储介质中定位到对应的知识点记录,以便执行激活操作,将知识点的状态修改为激活状态(具体的状态修改逻辑由业务逻辑层 iKnowPointService 的 enable 方法实现)。
+ * @return 返回一个 Result 对象,若激活操作成功,通过 Result 类的 result 方法构建一个包含成功状态码(0 表示成功)、提示信息(表明激活书籍成功,便于客户端向用户展示清晰的操作成功提示)以及空的数据部分(通常激活成功后不需要额外返回其他数据)的 Result 对象返回给客户端;
+ * 若激活过程中出现异常,调用 ExceptionSupport 的 resolverResult 方法来处理异常情况,该方法会进行记录异常信息、返回合适的错误提示等操作,然后返回处理后的结果(返回的也是包装在 Result 对象中),
+ * 客户端可根据接收到的返回值判断激活操作是否成功以及是否有异常发生,进而进行后续处理(例如向用户展示错误提示等)。
+ */
+ @RequestMapping(path = "enable", method = RequestMethod.POST)
@ResponseBody
public Result enable(String id) {
try {
@@ -98,21 +181,13 @@ public class KnowPointController {
return ExceptionSupport.resolverResult("激活书籍", this.getClass(), e);
}
}
-
- @RequestMapping(path="disabled",method=RequestMethod.POST)
- @ResponseBody
- public Result disabled(String id) {
- try {
- iKnowPointService.disabled(id);
- return Result.result(0, null, "停用书籍成功");
- } catch (Exception e) {
- return ExceptionSupport.resolverResult("停用书籍", this.getClass(), e);
- }
- }
-
- @RequestMapping(path="treeData",method=RequestMethod.POST)
- @ResponseBody
- public JSONArray treeData() {
- return iKnowPointService.treeData();
- }
-}
+
+/**
+ * 处理路径为 "tiku/knowpoint/disabled"(且请求方法限定为 POST)的请求方法,用于停用指定的知识点,按照传入的知识点编号(id)来定位要停用的知识点,
+ * 通过调用业务逻辑层相关方法执行停用操作,并依据操作结果返回相应信息给客户端,告知停用操作是否成功。
+ * 结果以 JSON 格式返回给客户端,方便客户端解析并展示相应的提示信息,告知用户停用知识点的操作结果。
+ *
+ * @param id 从请求中传递过来的字符串参数,用于唯一标识要停用的知识点(例如知识点编号等,具体取决于业务中知识点实体类的设计),
+ * 通过这个标识去数据库等存储介质中找到对应的知识点记录,以便执行停用操作,将知识点的状态修改为停用状态(具体的状态修改逻辑由业务逻辑层 iKnowPointService 的 disabled 方法实现)。
+ * @return 返回一个 Result 对象,若停用操作成功,通过 Result 类的 result 方法构建一个包含成功状态码(0 表示成功)、提示信息(表明停用书籍成功,方便客户端向用户展示清晰的操作成功提示)以及空的数据部分(通常停用成功后不需要额外返回其他数据)的 Result 对象返回给客户端;
+ * 若停用过程中出现异常,调用 ExceptionSupport 的 resolverResult 方法来处理异常情况,该方法会进行记录异常信息、返回合适的错误提示等操作,然后返回处理后的结果(返回的也是包装在 Result 对象
\ No newline at end of file
diff --git a/tamguo-oms/src/main/java/com/tamguo/modules/tiku/web/MemberController.java b/tamguo-oms/src/main/java/com/tamguo/modules/tiku/web/MemberController.java
index 1acb842..391d004 100644
--- a/tamguo-oms/src/main/java/com/tamguo/modules/tiku/web/MemberController.java
+++ b/tamguo-oms/src/main/java/com/tamguo/modules/tiku/web/MemberController.java
@@ -26,64 +26,141 @@ import com.tamguo.modules.member.model.MemberEntity;
import com.tamguo.modules.member.model.condition.MemberCondition;
import com.tamguo.modules.member.service.IMemberService;
+// 使用 @Controller 注解将该类标记为 Spring MVC 中的控制器类,表明它主要负责处理与题库中会员(Member)相关的 Web 请求,
+// 通过调用对应的业务逻辑层(IMemberService、IBookService、IBookCategoryService)的方法,实现诸如展示会员相关页面、处理会员数据查询、会员奖励操作以及获取与会员相关书籍信息等功能,
+// 是系统中涉及会员在题库业务模块下进行交互操作的核心控制部分。
@Controller
-@RequestMapping(value="tiku/member")
+// 通过 @RequestMapping 注解为这个控制器类下的所有请求路径设置一个公共前缀,即该控制器主要处理以 "tiku/member" 开头的请求路径,
+// 便于对会员相关的众多不同类型请求进行统一的分类管理,使代码结构更加清晰,便于维护和扩展。
+@RequestMapping(value = "tiku/member")
public class MemberController {
-
+
+ // 创建一个日志记录器对象,使用 SLF4J 框架的 LoggerFactory 来获取与当前类对应的 Logger 实例,
+ // 通过这个日志记录器,可以在代码中方便地记录各种级别的日志信息(如 DEBUG、INFO、WARN、ERROR 等),便于在系统运行过程中进行调试、监控以及问题排查等操作。
private Logger logger = LoggerFactory.getLogger(getClass());
-
+
+ // 通过 @Autowired 注解自动注入 IMemberService 接口的实现类实例,IMemberService 接口中定义了一系列与会员核心业务相关的方法,
+ // 比如查询会员详细信息、根据条件查询会员列表、执行会员奖励等操作,借助这个注入的实例,本控制器类能够方便地调用这些业务逻辑方法,实现与业务逻辑层的交互,从而完成系统中会员相关业务的具体处理。
@Autowired
IMemberService iMemberService;
+
+ // 通过 @Autowired 注解自动注入 IBookService 接口的实现类实例,IBookService 主要用于处理与书籍相关的业务逻辑,
+ // 例如查询会员拥有的书籍列表等操作,在系统业务中,会员与书籍可能存在关联关系(比如会员拥有某些书籍等情况),所以注入该实例辅助完成涉及书籍相关的会员业务处理。
@Autowired
IBookService iBookService;
+
+ // 通过 @Autowired 注解自动注入 IBookCategoryService 接口的实现类实例,IBookCategoryService 用于处理书籍分类相关的业务逻辑,
+ // 比如根据书籍分类编号查询分类名称等操作,在涉及会员相关书籍展示等业务场景中,可能需要获取书籍所属分类信息来更全面地展示书籍详情,所以注入该实例辅助完成此类业务操作。
@Autowired
IBookCategoryService iBookCategoryService;
- @RequestMapping(value="list")
+ /**
+ * 处理路径为 "tiku/member/list" 的请求方法,其主要功能是准备并返回会员列表页面相关的数据和视图信息。
+ * 当客户端发起该请求时,此方法会被调用,首先通过调用 model.setViewName("modules/tiku/member/list") 将返回的视图名称设置为会员列表页面对应的视图名称,
+ * 然后直接返回包含了设置好视图名称的 ModelAndView 对象,Spring MVC 框架会依据这个视图名称去正确地渲染展示会员列表页面,
+ * 不过当前代码中并没有向视图添加额外的数据,如果后续有需求,可以在此方法内添加相关的数据查询及添加到 ModelAndView 的逻辑。
+ *
+ * @param model ModelAndView 对象,用于在方法内部设置视图名称以及添加要传递给视图的数据(虽然当前方法暂未添加额外数据),
+ * 通过它实现了数据与视图的整合,确保视图层能够获取到正确的视图名称进行页面展示,满足会员列表页面展示的基本业务需求。
+ * @return 返回包含了设置好的视图名称("modules/tiku/member/list")的 ModelAndView 对象,供 Spring MVC 框架进行视图渲染展示,从而向客户端呈现会员列表页面。
+ */
+ @RequestMapping(value = "list")
public ModelAndView list(ModelAndView model) {
model.setViewName("modules/tiku/member/list");
return model;
}
-
- @RequestMapping(value="listData" , method=RequestMethod.POST)
+
+ /**
+ * 处理路径为 "tiku/member/listData"(且请求方法为 POST 的请求)的请求方法,用于查询并返回符合条件的会员列表数据,
+ * 返回结果会以适合前端表格组件(如 jqGrid 等)使用的格式包装在 Map 中,并以 JSON 格式响应给客户端,方便前端进行数据展示和分页等操作。
+ *
+ * @param condition MemberCondition 对象,用于封装查询会员列表的各种条件,比如查询关键字、会员状态筛选、分页信息等条件,根据这些条件去数据库等存储介质中查询会员列表,
+ * 满足不同业务场景下对会员数据查询的需求,其具体的条件设置和使用方式由业务逻辑层(iMemberService)的实现来决定。
+ * @return 返回一个 Map 类型的对象,该对象通过调用 Result.jqGridResult 方法,将从分页查询结果(Page 对象中获取的会员记录数据、总记录数、每页记录数、当前页码、总页数等信息)进行整合包装,
+ * 形成符合前端表格组件期望格式的数据,方便前端能够方便地解析并展示会员列表数据以及进行分页等相关操作。
+ */
+ @RequestMapping(value = "listData", method = RequestMethod.POST)
@ResponseBody
- public Map listData(MemberCondition condition){
+ public Map listData(MemberCondition condition) {
Page page = iMemberService.listData(condition);
return Result.jqGridResult(page.getRecords(), page.getTotal(), page.getSize(), page.getCurrent(), page.getPages());
}
-
- @RequestMapping(value="reward" , method=RequestMethod.GET)
- public ModelAndView reward(String id , ModelAndView model) {
+
+ /**
+ * 处理路径为 "tiku/member/reward"(且请求方法限定为 GET)的请求方法,作用是准备并返回会员奖励相关的页面数据和视图。
+ * 当客户端发起对应请求时,该方法会被执行,首先将返回的视图名称设置为会员奖励页面的视图名称("modules/tiku/member/reward"),
+ * 然后通过调用 iMemberService.selectById(id) 方法,依据传入的 id 参数(该参数用于指定要查询并展示奖励信息的会员的唯一标识,比如会员编号等,具体由业务中会员实体类的设计决定)查询对应的会员信息,
+ * 并把查询到的会员对象添加到 ModelAndView 对象中,最后返回包含了视图名称和会员对象数据的 ModelAndView 对象,
+ * Spring MVC 依据这些信息进行视图渲染展示,向客户端呈现会员奖励页面,方便用户在页面上查看会员信息并进行奖励相关的操作。
+ *
+ * @param id 从请求中传递过来的字符串参数,用于明确要查询并展示奖励信息的会员的唯一标识,通过这个标识去数据库获取会员的现有信息,
+ * 以便在奖励页面完整地展示相关内容,供用户进行奖励操作(比如填写奖励点数、奖励金额等信息)。
+ * @param model ModelAndView 对象,用于设置视图名称以及添加要传递给视图的会员对象数据,实现数据与视图的整合,
+ * 确保视图层能获取到完整信息用于会员奖励页面的展示和操作,使得页面能够准确呈现会员相关情况,便于奖励操作的进行。
+ * @return 返回包含了设置好的视图名称("modules/tiku/member/reward")以及添加了会员对象数据的 ModelAndView 对象,供 Spring MVC 进行视图渲染展示,呈现会员奖励页面给客户端。
+ */
+ @RequestMapping(value = "reward", method = RequestMethod.GET)
+ public ModelAndView reward(String id, ModelAndView model) {
model.setViewName("modules/tiku/member/reward");
model.addObject("member", iMemberService.selectById(id));
return model;
}
-
+
+ /**
+ * 处理路径为 "tiku/member/bookTreeData"(且请求方法限定为 POST)的请求方法,用于查询并返回与指定会员相关的书籍信息列表,且为这些书籍设置对应的书籍分类名称,
+ * 最终以列表形式返回处理后的书籍信息,方便前端进行展示(可能以树形结构等形式展示会员拥有的书籍及其分类情况,具体取决于前端实现)。
+ *
+ * @param memberId 从请求中传递过来的字符串参数,用于唯一标识会员(例如会员编号等,具体取决于业务中会员实体类的设计),
+ * 通过这个标识去查询该会员所拥有的书籍列表,然后进一步处理这些书籍信息,为它们添加所属分类名称等相关操作。
+ * @return 返回一个包含 BookEntity 类型对象的 List 集合,即经过处理后的会员相关书籍信息列表,其中每个 BookEntity 对象中设置了对应的书籍分类名称(通过查询书籍分类服务获取并设置),
+ * 供前端接收并展示会员拥有书籍的相关信息(例如可能展示书籍名称、所属分类等信息,便于用户直观查看会员的书籍情况)。
+ */
@SuppressWarnings("unchecked")
- @RequestMapping(value="bookTreeData",method=RequestMethod.POST)
+ @RequestMapping(value = "bookTreeData", method = RequestMethod.POST)
@ResponseBody
- public List bookTreeData(String memberId){
- List bookList = iBookService.selectList(Condition.create().eq("owner", memberId).orderDesc(Arrays.asList("create_date")));
- if(!CollectionUtils.isEmpty(bookList)) {
- for(int i=0 ; i bookTreeData(String memberId) {
+ // 通过调用 iBookService 的 selectList 方法,结合 MyBatis Plus 的条件构造器(Condition.create().eq("owner", memberId).orderDesc(Arrays.asList("create_date"))),
+ // 查询出所有者为指定会员(根据 memberId 确定)的书籍列表,并按照创建日期降序排列(以便展示时最新创建的书籍排在前面等情况,具体展示逻辑由前端决定),查询结果存储在 bookList 变量中。
+ List bookList = iBookService.selectList(Condition.create().eq("owner", memberId).orderDesc(Arrays.asList("create_date")));
+ // 使用 Spring 提供的 CollectionUtils.isEmpty 方法判断查询到的书籍列表是否为空,如果不为空,则进行后续的处理操作(为书籍设置分类名称)。
+ if (!CollectionUtils.isEmpty(bookList)) {
+ // 遍历查询到的书籍列表,对每一本书籍进行处理。
+ for (int i = 0; i < bookList.size(); i++) {
+ BookEntity book = bookList.get(i);
+ // 从当前书籍对象中获取其分类编号(book.getCategoryId()),由于可能存在多个分类编号(以逗号分隔等形式存储,具体取决于业务设计),这里取第一个分类编号(split(",")[0]),
+ // 然后通过调用 iBookCategoryService 的 selectById 方法,依据这个分类编号查询对应的书籍分类实体对象,获取其分类名称信息,用于设置到当前书籍对象中。
+ BookCategoryEntity category = iBookCategoryService.selectById(book.getCategoryId().split(",")[0]);
+ book.setCategoryName(category.getName());
+ }
+ }
return bookList;
}
-
- @RequestMapping(value="reward" , method=RequestMethod.POST)
+
+ /**
+ * 处理路径为 "tiku/member/reward"(且请求方法限定为 POST)的请求方法,用于执行会员奖励的实际操作,根据传入的会员编号、书籍编号以及奖励点数、奖励金额等信息,
+ * 通过调用业务逻辑层的相关方法来完成奖励操作,并返回操作结果给客户端,结果以 JSON 格式响应,告知客户端奖励操作是否成功以及相应提示信息。
+ *
+ * @param id 从请求中传递过来的字符串参数,用于唯一标识要进行奖励操作的会员(例如会员编号等,具体取决于业务中会员实体类的设计),通过这个标识定位到具体的会员记录,以便执行奖励相关的业务逻辑。
+ * @param bookId 从请求中传递过来的字符串参数,用于唯一标识与奖励相关的书籍(例如书籍编号等,具体取决于业务中书籍实体类的设计),可能在奖励业务逻辑中与会员奖励存在关联关系(比如根据会员对某本书的贡献等情况给予奖励等,具体业务场景依实际而定)。
+ * @param rewardPoint 从请求中传递过来的整数类型参数,表示奖励给会员的点数,具体点数含义和用途由业务规则定义,例如可以用于会员积分系统,积累一定点数可兑换奖品等操作。
+ * @param rewardMoney 从请求中传递过来的 BigDecimal 类型参数,表示奖励给会员的金额,涉及到金额相关的业务逻辑(比如财务记录、会员账户余额更新等情况,具体依业务而定),以精确的数值形式表示奖励金额。
+ * @return 返回一个 Result 对象,若奖励操作成功,通过 Result 类的 result 方法构建一个包含成功状态码(0 表示成功)、提示信息(表明奖励成功,用于客户端展示简单明了的提示告知用户操作结果)以及空的数据部分(因为奖励成功后通常不需要返回额外的数据)的 Result 对象返回给客户端;
+ * 若奖励过程中出现异常,通过日志记录器(logger)记录异常详细信息(包括异常消息和异常堆栈信息),然后通过 Result 类的 result 方法构建一个包含失败状态码(1 表示失败)、提示信息(表明奖励失败,便于客户端向用户展示操作失败提示)以及空的数据部分的 Result 对象返回给客户端,
+ * 客户端可以根据返回的 Result 对象判断奖励操作是否成功以及获取相应的提示信息等。
+ */
+ @RequestMapping(value = "reward", method = RequestMethod.POST)
@ResponseBody
- public Result submitReward(String id , String bookId , Integer rewardPoint , BigDecimal rewardMoney) {
+ public Result submitReward(String id, String bookId, Integer rewardPoint, BigDecimal rewardMoney) {
try {
- iMemberService.reward(id , bookId , rewardPoint , rewardMoney);
+ // 调用 iMemberService 的 reward 方法,传入会员编号(id)、书籍编号(bookId)、奖励点数(rewardPoint)以及奖励金额(rewardMoney)等参数,
+ // 由业务逻辑层去执行具体的会员奖励逻辑,例如更新会员积分、账户余额等相关操作,以完成会员奖励的业务需求。
+ iMemberService.reward(id, bookId, rewardPoint, rewardMoney);
return Result.result(0, null, "奖励成功!");
} catch (Exception e) {
- logger.error(e.getMessage() , e);
+ // 如果在执行会员奖励操作过程中出现异常,使用日志记录器记录异常详细信息,方便后续排查问题,
+ // 这里记录了异常消息(e.getMessage())以及完整的异常堆栈信息(e),以便准确了解异常产生的原因和位置。
+ logger.error(e.getMessage(), e);
return Result.result(1, null, "奖励失败!");
}
}
-
-}
+}
\ No newline at end of file
diff --git a/tamguo-oms/src/main/java/com/tamguo/modules/tiku/web/SubjectController.java b/tamguo-oms/src/main/java/com/tamguo/modules/tiku/web/SubjectController.java
index 8406795..d582f2a 100644
--- a/tamguo-oms/src/main/java/com/tamguo/modules/tiku/web/SubjectController.java
+++ b/tamguo-oms/src/main/java/com/tamguo/modules/tiku/web/SubjectController.java
@@ -16,72 +16,153 @@ import com.tamguo.modules.tiku.model.SubjectEntity;
import com.tamguo.modules.tiku.model.condition.SubjectCondition;
import com.tamguo.modules.tiku.service.ISubjectService;
+// 使用 @Controller 注解将该类标记为 Spring MVC 中的控制器类,意味着它主要负责处理与题库分类(Subject)相关的 Web 请求,
+// 通过调用对应的业务逻辑层(ISubjectService)的方法,实现诸如展示题库分类相关页面、处理分类数据查询、进行分类信息的增删改查以及激活、停用等操作,
+// 是系统中题库分类功能模块在 Web 层面交互的核心组件。
@Controller
-@RequestMapping(path="tiku/subject")
+// 通过 @RequestMapping 注解为该控制器类下的所有请求路径设置一个公共的前缀,表明此类中定义的所有请求处理方法对应的路径都是以 "tiku/subject" 开头,
+// 便于对题库分类相关的众多请求进行统一管理和分类,使代码结构更加清晰有条理。
+@RequestMapping(path = "tiku/subject")
public class SubjectController {
- /** 题库分类*/
+ // 以下定义了多个字符串常量,分别对应不同题库分类相关操作页面的视图名称,在 Spring MVC 的视图解析机制下,
+ // 这些常量值会指向具体的页面模板文件(比如 JSP、Thymeleaf 等模板文件)所在的路径,用于在相应业务场景下展示对应的页面内容。
+
+ /** 题库分类 */
private final String SUBJECT_INDEX_PAGE = "modules/tiku/subject/list";
private final String SUBJECT_UPDATE_PAGE = "modules/tiku/subject/update";
-
+
+ // 通过 @Autowired 注解自动注入 ISubjectService 接口的实现类实例,ISubjectService 接口定义了一系列用于处理题库分类相关业务逻辑的方法,
+ // 例如查询分类详细信息、保存新的分类、更新分类已有信息、删除分类以及激活、停用分类等功能,
+ // 借助这个注入的实例,本控制器类可以方便地与业务逻辑层交互,调用相应方法来完成各种题库分类相关的业务操作。
@Autowired
private ISubjectService iSubjectService;
- @RequestMapping(path="list")
+ /**
+ * 处理路径为 "tiku/subject/list" 的请求方法,其主要作用是准备并返回题库分类列表页面相关的数据和视图信息。
+ * 当客户端发起该请求时,此方法会被调用,它仅将视图名称设置为题库分类列表页面的视图名称(SUBJECT_INDEX_PAGE),
+ * 然后返回包含该视图名称的 ModelAndView 对象,供 Spring MVC 框架依据此信息去找到对应的模板文件进行渲染展示,从而向客户端呈现题库分类列表页面,
+ * 不过当前代码中并没有向视图添加额外的数据,如果后续有需求,可以在此方法内添加相关的数据查询及添加到 ModelAndView 的逻辑。
+ *
+ * @param model ModelAndView 对象,用于设置视图名称以及添加要传递给视图的数据(虽然当前没有添加额外数据的操作),
+ * 通过它实现数据与视图的整合,确保视图层能够获取到正确的视图名称进行页面展示,满足题库分类列表页面展示的基本业务需求。
+ * @return 返回包含了设置好的视图名称(SUBJECT_INDEX_PAGE)的 ModelAndView 对象,供 Spring MVC 进行视图渲染展示,向客户端呈现题库分类列表页面。
+ */
+ @RequestMapping(path = "list")
public ModelAndView list(ModelAndView model) {
model.setViewName(SUBJECT_INDEX_PAGE);
return model;
}
-
- @RequestMapping(path="update")
- public ModelAndView update(String uid , ModelAndView model) {
+
+ /**
+ * 处理路径为 "tiku/subject/update"(且请求方法限定为 GET)的请求方法,功能是准备并返回修改题库分类信息页面相关的数据和视图,以便用户能够在页面上看到要修改的分类的详细信息,并进行相应的编辑修改操作。
+ *
+ * @param uid 从请求中传递过来的字符串参数,用于唯一标识要修改的题库分类(例如分类编号等,具体由业务中分类实体类的设计决定),
+ * 通过这个标识去查询要修改的分类对象的详细信息,用于在修改页面展示相关内容,方便用户进行编辑操作。
+ * @param model ModelAndView 对象,用于设置视图名称以及添加要传递给视图的分类对象数据,实现数据与视图的整合,
+ * 确保视图层能获取到完整信息用于修改题库分类信息页面的展示和操作,使得页面能够准确呈现要修改的分类情况,便于用户进行修改操作。
+ * @return 返回包含了设置好的视图名称(SUBJECT_UPDATE_PAGE)以及添加了分类对象数据的 ModelAndView 对象,供 Spring MVC 进行视图渲染展示,将修改题库分类信息页面展示给客户端。
+ */
+ @RequestMapping(path = "update", method = RequestMethod.GET)
+ public ModelAndView update(String uid, ModelAndView model) {
model.setViewName(SUBJECT_UPDATE_PAGE);
+ // 通过调用 iSubjectService 的 selectById 方法,依据传入的 uid 参数,从数据库等数据源中查询出要修改的分类对象,
+ // 以便在修改页面上展示该分类的当前信息,供用户查看并确定要修改的具体内容。
model.addObject("subject", iSubjectService.selectById(uid));
return model;
}
-
- @RequestMapping(path="listData",method=RequestMethod.POST)
+
+ /**
+ * 处理路径为 "tiku/subject/listData"(且请求方法限定为 POST)的请求方法,主要用于查询并返回符合特定条件的题库分类列表数据,
+ * 返回结果会以适合前端表格组件(如 jqGrid 等)使用的格式包装在 Map 中,并以 JSON 格式响应给客户端,方便前端进行数据展示和分页等操作。
+ *
+ * @param condition SubjectCondition 对象,用于封装查询题库分类列表时的各种条件,比如查询关键字、分类状态筛选条件、分页信息(如果有分页需求的话,虽然当前代码未体现分页相关操作)等,
+ * 根据这些条件去数据库等数据源中查询题库分类列表数据,满足不同业务场景下对题库分类数据查询的需求。
+ * @return 返回一个包含符合条件的 SubjectEntity 类型对象的 Map,该 Map 是通过调用 Result.jqGridResult 方法,将从分页查询结果(Page 对象中获取的分类记录数据、总记录数、每页记录数、当前页码、总页数等信息)进行整合包装,
+ * 形成符合前端表格组件期望格式的数据,方便前端能够方便地解析并展示题库分类列表数据以及进行分页等相关操作。
+ */
+ @RequestMapping(path = "listData", method = RequestMethod.POST)
@ResponseBody
public Map listData(SubjectCondition condition) {
Page page = iSubjectService.listData(condition);
return Result.jqGridResult(page.getRecords(), page.getTotal(), page.getSize(), page.getCurrent(), page.getPages());
}
-
+
+ /**
+ * 处理路径为 "tiku/subject/checkSubjectCode"(且请求方法限定为 GET)的请求方法,用于检查指定的题库分类编号(uid)是否已存在,返回一个布尔值表示检查结果。
+ * 通过查询数据库中符合给定分类编号条件的记录数量来判断其是否存在,如果数量大于 0,则表示该编号已存在,返回 false;若数量为 0,则表示不存在,返回 true。
+ *
+ * @param uid 从请求中传递过来的字符串参数,用于唯一标识要检查的题库分类(例如分类编号等,具体取决于业务中分类实体类的设计),
+ * 通过这个标识去数据库中查询是否存在对应的分类记录,以此判断该分类编号是否已被使用。
+ * @return 返回一个布尔值,若根据传入的 uid 查询到对应的分类记录数量大于 0,说明该分类编号已存在,返回 false;若查询到的数量为 0,即该分类编号不存在,返回 true,
+ * 客户端可以根据这个返回值来决定后续的操作(比如在新增分类时,若返回 false 则提示编号已存在,不能重复使用等)。
+ */
@SuppressWarnings("unchecked")
- @RequestMapping(path="checkSubjectCode",method=RequestMethod.GET)
+ @RequestMapping(path = "checkSubjectCode", method = RequestMethod.GET)
@ResponseBody
public Boolean checkSubjectCode(String uid) {
+ // 通过调用 iSubjectService 的 selectCount 方法,结合 MyBatis Plus 的条件构造器(Condition.create().eq("uid", uid)),
+ // 查询数据库中满足分类编号(uid)相等条件的记录数量,将查询结果存储在 count 变量中。
Integer count = iSubjectService.selectCount(Condition.create().eq("uid", uid));
- if(count > 0) {
+ if (count > 0) {
return false;
- }else {
+ } else {
return true;
}
}
-
- @RequestMapping(path="save",method=RequestMethod.POST)
+
+ /**
+ * 处理路径为 "tiku/subject/save"(且请求方法限定为 POST)的请求方法,用于保存新的题库分类信息,将客户端提交的分类相关数据保存到数据库等存储介质中,
+ * 并返回保存操作的结果给客户端,结果以 JSON 格式响应,告知客户端保存是否成功以及相应提示信息。
+ *
+ * @param subject SubjectEntity 对象,包含了新的题库分类相关信息,比如分类名称、分类描述等属性信息,这些信息从客户端提交的数据中获取,
+ * 通过调用 iSubjectService 的 save 方法,将该分类对象的信息持久化存储到数据库中,完成新的题库分类信息保存操作。
+ * @return 返回一个 Result 对象,若保存操作成功,通过 Result 类的 result 方法构建一个包含成功状态码(0 表示成功)、提示信息(表明保存分类【分类名称】成功,方便客户端展示友好的提示告知用户操作结果,其中分类名称通过 subject.getName() 获取)以及空的数据部分(因为保存成功后通常不需要返回额外的数据)的 Result 对象返回给客户端;
+ * 若保存过程中出现异常,调用 ExceptionSupport 的 resolverResult 方法处理异常,并将处理后的结果(同样包装在 Result 对象中)返回给客户端,客户端可以根据返回的 Result 对象判断保存操作是否成功以及获取相应的提示信息等。
+ */
+ @RequestMapping(path = "save", method = RequestMethod.POST)
@ResponseBody
public Result save(SubjectEntity subject) {
try {
iSubjectService.save(subject);
- return Result.result(0, null, "保存分类【"+subject.getName()+"】成功");
+ return Result.result(0, null, "保存分类【" + subject.getName() + "】成功");
} catch (Exception e) {
return ExceptionSupport.resolverResult("保存分类", this.getClass(), e);
}
}
-
- @RequestMapping(path="update",method=RequestMethod.POST)
+
+ /**
+ * 处理路径为 "tiku/subject/update"(且请求方法限定为 POST)的请求方法,用于更新已存在的题库分类信息,将客户端提交的修改后的分类数据更新到数据库等存储介质中,
+ * 并返回更新操作的结果给客户端,结果以 JSON 格式响应,告知客户端更新是否成功以及相应提示信息。
+ *
+ * @param subject SubjectEntity 对象,包含了修改后的题库分类相关信息,例如分类名称、分类描述等属性信息的修改后内容,这些信息从客户端提交的数据中获取,
+ * 通过调用 iSubjectService 的 update 方法,将该分类对象中修改后的信息更新到数据库中对应的分类记录上,完成分类信息的修改操作。
+ * @return 返回一个 Result 对象,若更新操作成功,通过 Result 类的 result 方法构建一个包含成功状态码(0 表示成功)、提示信息(表明修改分类【分类名称】成功,便于客户端展示友好的提示告知用户操作结果,其中分类名称通过 subject.getName() 获取)以及空的数据部分(因为更新成功后通常不需要返回额外的数据)的 Result 对象返回给客户端;
+ * 若更新过程中出现异常,调用 ExceptionSupport 的 resolverResult 方法处理异常,并将处理后的结果(同样包装在 Result 对象中)返回给客户端,客户端可以根据返回的 Result 对象判断更新操作是否成功以及获取相应的提示信息等。
+ */
+ @RequestMapping(path = "update", method = RequestMethod.POST)
@ResponseBody
public Result update(SubjectEntity subject) {
try {
iSubjectService.update(subject);
- return Result.result(0, null, "修改分类【"+subject.getName()+"】成功");
+ return Result.result(0, null, "修改分类【" + subject.getName() + "】成功");
} catch (Exception e) {
return ExceptionSupport.resolverResult("修改分类", this.getClass(), e);
}
}
-
- @RequestMapping(path="enable",method=RequestMethod.POST)
+
+ /**
+ * 处理路径为 "tiku/subject/enable"(且请求方法限定为 POST)的请求方法,用于激活指定的题库分类,依据传入的分类编号(uid)找到对应的分类,
+ * 通过调用业务逻辑层相应方法来执行激活操作,并根据操作结果返回对应信息给客户端,告知激活操作是否成功。
+ * 结果以 JSON 格式返回给客户端,便于客户端解析和后续的展示提示信息等处理,告知用户激活分类的操作结果。
+ *
+ * @param uid 从请求中传递过来的字符串参数,用于唯一标识要激活的题库分类(例如分类编号等,具体取决于业务中分类实体类的设计),
+ * 通过这个标识去数据库等存储介质中定位到对应的分类记录,以便执行激活操作,将分类的状态修改为激活状态(具体的状态修改逻辑由业务逻辑层 iSubjectService 的 enable 方法实现)。
+ * @return 返回一个 Result 对象,若激活操作成功,通过 Result 类的 result 方法构建一个包含成功状态码(0 表示成功)、提示信息(表明激活分类成功,便于客户端向用户展示清晰的操作成功提示)以及空的数据部分(通常激活成功后不需要额外返回其他数据)的 Result 对象返回给客户端;
+ * 若激活过程中出现异常,调用 ExceptionSupport 的 resolverResult 方法来处理异常情况,该方法会进行记录异常信息、返回合适的错误提示等操作,然后返回处理后的结果(返回的也是包装在 Result 对象中),
+ * 客户端可根据接收到的返回值判断激活操作是否成功以及是否有异常发生,进而进行后续处理(例如向用户展示错误提示等)。
+ */
+ @RequestMapping(path = "enable", method = RequestMethod.POST)
@ResponseBody
public Result enable(String uid) {
try {
@@ -91,8 +172,19 @@ public class SubjectController {
return ExceptionSupport.resolverResult("激活分类", this.getClass(), e);
}
}
-
- @RequestMapping(path="disabled",method=RequestMethod.POST)
+
+ /**
+ * 处理路径为 "tiku/subject/disabled"(且请求方法限定为 POST)的请求方法,用于停用指定的题库分类,按照传入的分类编号(uid)来定位要停用的分类,
+ * 通过调用业务逻辑层相关方法执行停用操作,并依据操作结果返回相应信息给客户端,告知停用操作是否成功。
+ * 结果以 JSON 格式返回给客户端,方便客户端解析并展示相应的提示信息,告知用户停用分类的操作结果。
+ *
+ * @param uid 从请求中传递过来的字符串参数,用于唯一标识要停用的题库分类(例如分类编号等,具体取决于业务中分类实体类的设计),
+ * 通过这个标识去数据库等存储介质中找到对应的分类记录,以便执行停用操作,将分类的状态修改为停用状态(具体的状态修改逻辑由业务逻辑层 iSubjectService 的 disabled 方法实现)。
+ * @return 返回一个 Result 对象,若停用操作成功,通过 Result 类的 result 方法构建一个包含成功状态码(0 表示成功)、提示信息(表明停用分类成功,方便客户端向用户展示清晰的操作成功提示)以及空的数据部分(通常停用成功后不需要额外返回其他数据)的 Result 对象返回给客户端;
+ * 若停用过程中出现异常,调用 ExceptionSupport 的 resolverResult 方法来处理异常情况,该方法会进行记录异常信息、返回合适的错误提示等操作,然后返回处理后的结果(返回的也是包装在 Result 对象中),
+ * 客户端可根据接收到的返回值判断停用操作是否成功以及是否有异常发生,进而进行后续处理(例如向用户展示错误提示等)。
+ */
+ @RequestMapping(path = "disabled", method = RequestMethod.POST)
@ResponseBody
public Result disabled(String uid) {
try {
@@ -102,16 +194,10 @@ public class SubjectController {
return ExceptionSupport.resolverResult("停用分类", this.getClass(), e);
}
}
-
- @RequestMapping(path="delete",method=RequestMethod.POST)
- @ResponseBody
- public Result delete(String uid) {
- try {
- iSubjectService.delete(uid);
- return Result.result(0, null, "删除分类成功");
- } catch (Exception e) {
- return ExceptionSupport.resolverResult("删除分类", this.getClass(), e);
- }
- }
-
-}
+
+/**
+ * 处理路径为 "tiku/subject/delete"(且请求方法限定为 POST)的请求方法,用于删除指定的题库分类信息,根据传入的分类唯一标识(uid)从数据库等存储介质中删除对应的分类记录,
+ * 并返回删除操作的结果给客户端,结果以 JSON 格式响应,告知客户端删除是否成功以及相应提示信息。
+ *
+ * @param uid 从请求中传递过来的字符串参数,用于唯一标识要删除的题库分类(例如分类编号等,具体取决于业务中分类实体类的设计),通过这个标识定位到数据库中对应的分类记录进行删除操作。
+ * @return 返回一个 Result 对象,若删除操作成功,通过 Result 类的 result 方法构建一个包含成功
\ No newline at end of file
diff --git a/tamguo-tms/src/main/java/com/tamguo/Application.java b/tamguo-tms/src/main/java/com/tamguo/Application.java
index 46b8e8a..5c0d8dc 100644
--- a/tamguo-tms/src/main/java/com/tamguo/Application.java
+++ b/tamguo-tms/src/main/java/com/tamguo/Application.java
@@ -10,26 +10,52 @@ import com.alibaba.fastjson.serializer.SerializerFeature;
import com.alibaba.fastjson.support.config.FastJsonConfig;
import com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter;
+// @SpringBootApplication是一个组合注解,它整合了多个Spring Boot相关的注解,包括@Configuration(表明这个类是一个配置类,可用于定义Bean等配置信息)、
+// @EnableAutoConfiguration(开启Spring Boot的自动配置功能,会根据项目依赖等情况自动配置很多默认的组件和行为)、@ComponentScan(用于扫描指定包及其子包下的所有Spring组件,如@Component、@Service、@Controller等注解标记的类,使得这些类能够被Spring容器管理),
+// 这个注解标记在类上,表示这是一个Spring Boot的主应用类,启动类所在的包及其子包下的相关组件会被自动扫描并纳入Spring容器管理,同时开启自动配置等功能,整个Spring Boot应用从这个类开始启动。
@SpringBootApplication
public class Application {
+ // 应用程序的入口方法,是Java应用程序开始执行的地方,在这个方法中通过SpringApplicationBuilder来构建并启动Spring Boot应用,传入当前类(Application.class)作为参数,
+ // 告诉Spring Boot框架这个类是应用的主配置类,同时将命令行参数(args)传递给它,用于处理一些启动时可配置的相关信息(例如配置不同的运行环境等情况,具体取决于参数如何定义和使用),启动整个Spring Boot应用,初始化Spring容器、加载配置、启动相关服务等操作都会在这里开始执行。
public static void main(String[] args) {
new SpringApplicationBuilder(Application.class).run(args);
}
-
+
/**
* FastJson替代Jackson
- * @return
+ * 这个方法定义了一个Spring的Bean,用于将FastJson配置为Spring Boot应用中处理HTTP消息转换(主要是将Java对象转换为JSON格式数据发送给客户端,以及将接收到的JSON格式数据转换为Java对象)的工具,
+ * 替代默认的JSON处理框架(通常是Jackson),通过配置FastJson的相关属性(如日期格式、序列化特性等),来满足应用对于JSON数据处理的特定需求,然后将配置好的FastJsonHttpMessageConverter封装在HttpMessageConverters对象中返回,供Spring Boot应用使用。
+ *
+ * @return 返回一个HttpMessageConverters对象,其中包含了配置好的FastJsonHttpMessageConverter,这个对象会被Spring容器管理,在处理HTTP请求和响应的消息转换时会根据配置进行相应的JSON数据处理操作。
*/
@Bean
public HttpMessageConverters fastJsonHttpMessageConverters() {
+ // 创建一个FastJsonHttpMessageConverter对象,它是Spring框架中用于处理HTTP消息转换并且基于FastJson库来实现JSON数据序列化和反序列化的一个转换器,
+ // 后续会对它进行配置,设置FastJson相关的参数,使其按照应用的需求来正确地处理JSON数据,比如设置日期格式、避免循环引用等序列化特性。
FastJsonHttpMessageConverter fastConverter = new FastJsonHttpMessageConverter();
+
+ // 创建一个FastJsonConfig对象,用于配置FastJson的各种参数和特性,通过这个对象可以设置如日期格式、序列化相关的特性选项等内容,以定制FastJson在处理JSON数据时的行为,满足应用在不同场景下对JSON序列化和反序列化的要求。
FastJsonConfig fastJsonConfig = new FastJsonConfig();
+
+ // 设置FastJson在序列化日期类型数据时的格式,将日期格式设置为"yyyy-MM-dd HH:mm:ss",这样在将Java中的日期对象转换为JSON字符串时,会按照这个格式进行格式化输出,便于前端或其他客户端按照统一的格式进行解析和展示日期数据。
fastJsonConfig.setDateFormat("yyyy-MM-dd HH:mm:ss");
+
+ // 设置FastJson的序列化特性,这里使用SerializerFeature.DisableCircularReferenceDetect特性,它的作用是禁用循环引用检测,
+ // 当Java对象之间存在复杂的关联关系(比如互相引用)时,避免在序列化过程中出现循环引用导致的问题(如栈溢出等异常情况),同时也能确保序列化的JSON数据结构更符合预期,不会出现一些由于循环引用导致的不合理结构,按照设定的规则进行序列化处理。
fastJsonConfig.setSerializerFeatures(SerializerFeature.DisableCircularReferenceDetect);
+
+ // 将配置好的FastJsonConfig对象设置到FastJsonHttpMessageConverter中,使得FastJsonHttpMessageConverter在进行JSON数据的序列化和反序列化操作时,会按照FastJsonConfig中设定的参数和特性来执行,
+ // 这样就完成了对FastJson在Spring Boot应用中处理HTTP消息转换时的相关配置工作,使其能够按照应用需求来正确地转换JSON数据。
fastConverter.setFastJsonConfig(fastJsonConfig);
+
+ // 将配置好的FastJsonHttpMessageConverter对象赋值给converter变量(这里其实可以直接使用fastConverter,这个赋值操作略显多余,但可能是出于代码逻辑清晰性或者后续可能有其他修改的考虑等情况),
+ // 后续会将这个配置好的转换器封装在HttpMessageConverters对象中返回给Spring容器管理并使用。
FastJsonHttpMessageConverter converter = fastConverter;
+
+ // 创建一个HttpMessageConverters对象,并将配置好的FastJsonHttpMessageConverter作为参数传入构造函数,将其封装在HttpMessageConverters中,
+ // HttpMessageConverters是Spring框架用于管理多个HTTP消息转换器的一个类,在这里将FastJson相关的转换器添加进去后,Spring Boot应用在处理HTTP消息转换时,就会使用这个配置好的基于FastJson的转换器来处理JSON数据,实现了用FastJson替代默认的JSON处理框架(如Jackson)的功能,
+ // 最后返回这个HttpMessageConverters对象,供Spring容器管理使用,使得在整个Spring Boot应用中,涉及HTTP请求和响应的JSON数据处理都按照配置好的FastJson相关特性来执行。
return new HttpMessageConverters(converter);
}
-
-}
+}
\ No newline at end of file
diff --git a/tamguo-tms/src/main/java/com/tamguo/config/dao/MyMetaObjectHandler.java b/tamguo-tms/src/main/java/com/tamguo/config/dao/MyMetaObjectHandler.java
index 9b0c21d..8bb7f65 100644
--- a/tamguo-tms/src/main/java/com/tamguo/config/dao/MyMetaObjectHandler.java
+++ b/tamguo-tms/src/main/java/com/tamguo/config/dao/MyMetaObjectHandler.java
@@ -5,19 +5,41 @@ import org.apache.ibatis.reflection.MetaObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-/**
- * 注入公共字段自动填充,任选注入方式即可
- */
+// 以下这行被注释掉的@Component注解,如果取消注释,Spring会将这个类作为一个组件扫描并注册到Spring容器中,
+// 这样就可以自动应用它所实现的功能(在这里就是公共字段自动填充功能),不过当前代码中只是定义了类的结构和基本方法,可能并不想让Spring直接管理它,所以暂时注释掉了。
//@Component
+// 这个类继承自MetaObjectHandler类,在MyBatis Plus框架中,MetaObjectHandler用于实现对实体对象的公共字段进行自动填充的功能,
+// 比如在插入或更新数据库记录时,自动设置创建时间、更新时间、创建人、更新人等公共字段的值,通过继承该类并重写相应的方法,
+// 可以自定义这些公共字段的填充逻辑,以满足具体业务需求。这里定义的MyMetaObjectHandler类就是用于此目的,不过当前代码中尚未实现具体的填充逻辑,只是搭建了基本的方法框架。
public class MyMetaObjectHandler extends MetaObjectHandler {
+ // 创建一个静态的日志记录器对象,使用SLF4J框架的LoggerFactory来获取与当前类(MyMetaObjectHandler)对应的Logger实例,
+ // 通过这个日志记录器,可以在代码中方便地记录各种级别的日志信息(如DEBUG、INFO、WARN、ERROR等),便于在实现公共字段自动填充逻辑过程中进行调试、监控以及问题排查等操作。
protected final static Logger logger = LoggerFactory.getLogger(MyMetaObjectHandler.class);
-
+
+ /**
+ * 重写了父类MetaObjectHandler中的insertFill方法,该方法在MyBatis Plus执行插入操作(例如向数据库插入一条新记录时)时会被调用,
+ * 目的是在这里实现对插入操作时相关公共字段的自动填充逻辑。当前方法体为空,意味着还没有定义具体的填充逻辑,
+ * 实际应用中可以根据业务需求,从MetaObject参数中获取要插入的实体对象,然后设置诸如创建时间、创建人等公共字段的值,
+ * 例如可以使用Java的日期时间类获取当前时间设置为创建时间字段,从当前登录用户信息中获取用户名设置为创建人字段等操作(具体取决于业务设计)。
+ *
+ * @param metaObject MetaObject类型的参数,它是MyBatis框架中用于封装实体对象以及相关元数据的对象,通过它可以获取和操作实体对象的属性值等信息,
+ * 在这个方法中,主要通过它来获取要插入的实体对象,以便对其公共字段进行填充操作。
+ */
@Override
public void insertFill(MetaObject metaObject) {
}
+ /**
+ * 重写了父类MetaObjectHandler中的updateFill方法,该方法在MyBatis Plus执行更新操作(例如更新数据库中已存在的一条记录时)时会被调用,
+ * 用于实现对更新操作时相关公共字段的自动填充逻辑。当前方法体同样为空,尚未定义具体的填充逻辑,
+ * 在实际使用时,可以从MetaObject参数中获取要更新的实体对象,然后设置像更新时间、更新人等公共字段的值,
+ * 比如使用当前时间更新更新时间字段,根据当前登录用户信息更新更新人字段等(具体依据业务要求来定)。
+ *
+ * @param metaObject MetaObject类型的参数,通过它可以获取要更新的实体对象,进而对该对象的相关公共字段进行填充操作,
+ * 确保在更新记录时,公共字段能按照业务规则被正确地更新赋值。
+ */
@Override
public void updateFill(MetaObject metaObject) {
}
-}
+}
\ No newline at end of file
diff --git a/tamguo-tms/src/main/java/com/tamguo/config/dao/MybatisPlusConfig.java b/tamguo-tms/src/main/java/com/tamguo/config/dao/MybatisPlusConfig.java
index 47d0386..3621398 100644
--- a/tamguo-tms/src/main/java/com/tamguo/config/dao/MybatisPlusConfig.java
+++ b/tamguo-tms/src/main/java/com/tamguo/config/dao/MybatisPlusConfig.java
@@ -19,40 +19,85 @@ import com.baomidou.mybatisplus.plugins.parser.tenant.TenantSqlParser;
import net.sf.jsqlparser.expression.Expression;
import net.sf.jsqlparser.expression.LongValue;
+// @Configuration注解表明这个类是一个Spring的配置类,用于定义各种Bean以及相关的配置信息,Spring容器会在启动时读取这个类中的配置,
+// 将其中定义的Bean创建并管理起来,供其他组件进行依赖注入和使用,从而实现整个应用的各种功能配置。
@Configuration
+// @MapperScan注解用于指定MyBatis Plus的Mapper接口所在的包路径,它会自动扫描该路径下的所有Mapper接口,并创建对应的代理实现类,
+// 使得这些Mapper接口能够与数据库进行交互,这里指定扫描"com.tamguo.modules.*.dao*"路径下的Mapper接口,方便对不同模块下的数据库操作进行统一管理。
@MapperScan("com.tamguo.modules.*.dao*")
public class MybatisPlusConfig {
+ /**
+ * 创建并返回一个PerformanceInterceptor实例,将其注册为Spring容器中的一个Bean。
+ * PerformanceInterceptor是MyBatis Plus提供的一个性能分析拦截器,它可以用于统计SQL语句的执行时间等性能相关的数据,
+ * 在开发和调试阶段,有助于发现执行效率较低的SQL查询,以便进行优化。
+ *
+ * @return 返回一个新创建的PerformanceInterceptor对象,供Spring容器管理并在合适的时机应用到MyBatis Plus的SQL执行链路中进行性能分析。
+ */
@Bean
public PerformanceInterceptor performanceInterceptor() {
return new PerformanceInterceptor();
}
/**
- * mybatis-plus分页插件
- * 文档:http://mp.baomidou.com
+ * 创建并配置一个PaginationInterceptor实例,将其注册为Spring容器中的一个Bean,用于实现MyBatis Plus的分页功能,并配置相关的多租户解析逻辑等额外功能。
+ *
+ * @return 返回配置好的PaginationInterceptor对象,该对象在MyBatis Plus处理数据库查询时,会自动处理分页相关的逻辑,并根据配置进行多租户SQL解析等操作。
*/
@Bean
public PaginationInterceptor paginationInterceptor() {
+ // 创建一个PaginationInterceptor实例,它是MyBatis Plus中用于实现分页功能的核心拦截器,
+ // 通过拦截SQL语句,自动添加分页相关的语法(如 LIMIT 等,具体取决于数据库类型),实现对查询结果的分页处理。
PaginationInterceptor paginationInterceptor = new PaginationInterceptor();
- paginationInterceptor.setLocalPage(true);// 开启 PageHelper 的支持
+
+ // 设置开启PageHelper的支持,这里的PageHelper可能是指与其他分页插件兼容的一种模式或者相关功能(具体取决于项目中对分页的整体应用情况),
+ // 通过设置为true,使得PaginationInterceptor能够更好地与可能存在的PageHelper相关功能协同工作,确保分页功能的正常实现。
+ paginationInterceptor.setLocalPage(true);
+
/*
* 【测试多租户】 SQL 解析处理拦截器
* 这里固定写成住户 1 实际情况你可以从cookie读取,因此数据看不到 【 麻花藤 】 这条记录( 注意观察 SQL )
+ * 以下代码块用于配置多租户相关的SQL解析逻辑,在多租户应用场景下,不同租户的数据需要进行隔离,通过SQL解析拦截器来动态修改SQL语句,添加租户相关的筛选条件等操作,实现数据隔离。
*/
List sqlParserList = new ArrayList<>();
+
+ // 创建一个TenantSqlParser实例,它是基于MyBatis Plus的SQL解析器,专门用于处理多租户场景下的SQL语句解析和修改,
+ // 通过与TenantHandler配合,能够根据租户信息动态地在SQL中添加相应的条件,确保每个租户只能访问自己的数据。
TenantSqlParser tenantSqlParser = new TenantSqlParser();
+
+ // 为TenantSqlParser设置TenantHandler,TenantHandler用于定义获取租户ID、租户ID对应的数据库列名以及判断是否对某个表进行租户过滤等逻辑,
+ // 在这里通过匿名内部类的方式实现了TenantHandler接口,具体配置了多租户相关的核心逻辑。
tenantSqlParser.setTenantHandler(new TenantHandler() {
+ /**
+ * 获取表示租户ID的表达式,在这里返回一个LongValue类型的表达式,表示租户ID的值为1L,
+ * 在实际应用中,通常应该从更合适的地方获取(如从请求头、Cookie等中根据业务规则提取租户ID),这里只是为了测试示例固定写死为1。
+ *
+ * @return 返回表示租户ID的表达式,用于在SQL解析时添加到查询条件中,实现根据租户ID筛选数据的功能。
+ */
@Override
public Expression getTenantId() {
return new LongValue(1L);
}
+ /**
+ * 获取存储租户ID的数据库列名,在这里返回"course_id",意味着在SQL语句中,会通过这个列名来添加租户筛选条件,
+ * 例如在查询语句中添加类似"WHERE course_id = 1"(这里的1就是通过getTenantId方法获取的租户ID值)这样的条件,实现数据隔离。
+ *
+ * @return 返回存储租户ID的数据库列名,用于构建多租户相关的SQL筛选条件。
+ */
@Override
public String getTenantIdColumn() {
return "course_id";
}
+ /**
+ * 判断是否对指定的表名进行租户过滤,这里返回true,表示对所有表都应用租户过滤逻辑(具体根据业务需求,可能需要对某些表不进行租户过滤,
+ * 可以在这个方法内根据表名进行条件判断来决定是否返回true或false),
+ * 通过这个方法可以灵活控制多租户逻辑对不同表的应用情况,确保数据隔离的准确性和合理性。
+ *
+ * @param tableName 要判断的表名,根据表名来决定是否对该表应用租户过滤逻辑。
+ * @return 返回true表示对该表应用租户过滤逻辑,返回false则表示不应用,即该表的数据不受租户条件限制(所有租户都能访问该表全部数据)。
+ */
@Override
public boolean doTableFilter(String tableName) {
// 这里可以判断是否过滤表
@@ -60,9 +105,14 @@ public class MybatisPlusConfig {
}
});
-
+ // 将配置好的TenantSqlParser添加到sqlParserList中,这个列表用于存储所有需要应用的SQL解析器,
+ // 后续会将这个列表设置到PaginationInterceptor中,使得在处理分页相关的SQL语句时,同时也能应用这些解析器进行多租户相关的SQL修改等操作。
sqlParserList.add(tenantSqlParser);
+
+ // 将包含TenantSqlParser的sqlParserList设置到PaginationInterceptor中,这样在执行SQL语句时,
+ // PaginationInterceptor不仅会处理分页逻辑,还会调用列表中的各个SQL解析器对SQL进行额外的解析和修改(如添加多租户筛选条件等)。
paginationInterceptor.setSqlParserList(sqlParserList);
+
// 以下过滤方式与 @SqlParser(filter = true) 注解等效
// paginationInterceptor.setSqlParserFilter(new ISqlParserFilter() {
// @Override
@@ -75,19 +125,31 @@ public class MybatisPlusConfig {
// return false;
// }
// });
+
return paginationInterceptor;
}
+ /**
+ * 创建并返回一个MetaObjectHandler实例,将其注册为Spring容器中的一个Bean。
+ * MetaObjectHandler在MyBatis Plus中用于在插入或更新操作时,自动填充一些公共字段(如创建时间、更新时间、创建人、更新人等)的值,
+ * 通过实现该接口并自定义相关逻辑,可以方便地对实体对象的公共字段进行统一赋值,减少重复代码,提高代码的可维护性。
+ *
+ * @return 返回一个自定义的MetaObjectHandler实现类(这里返回的是MyMetaObjectHandler,应该是用户自定义的一个类,继承自MetaObjectHandler并实现了相应的填充逻辑)的实例,
+ * 供Spring容器管理并在MyBatis Plus的数据库操作中应用自动填充逻辑。
+ */
@Bean
- public MetaObjectHandler metaObjectHandler(){
+ public MetaObjectHandler metaObjectHandler() {
return new MyMetaObjectHandler();
}
/**
- * 注入sql注入器
+ * 创建并返回一个ISqlInjector实例,将其注册为Spring容器中的一个Bean,这里使用LogicSqlInjector来实现逻辑删除相关的功能注入。
+ * 在MyBatis Plus中,通过注入特定的SqlInjector,可以扩展默认的SQL注入逻辑,例如实现逻辑删除(不是真正从数据库中删除数据,而是通过更新某个字段标记数据为已删除状态)等功能。
+ *
+ * @return 返回一个LogicSqlInjector对象,用于向MyBatis Plus框架注入逻辑删除等相关的SQL生成逻辑,使得在进行数据删除操作时,按照逻辑删除的规则来生成对应的SQL语句。
*/
@Bean
- public ISqlInjector sqlInjector(){
+ public ISqlInjector sqlInjector() {
return new LogicSqlInjector();
}
-}
+}
\ No newline at end of file
diff --git a/tamguo-tms/src/main/java/com/tamguo/config/shiro/MemberRealm.java b/tamguo-tms/src/main/java/com/tamguo/config/shiro/MemberRealm.java
index 6a55f8d..40687dc 100644
--- a/tamguo-tms/src/main/java/com/tamguo/config/shiro/MemberRealm.java
+++ b/tamguo-tms/src/main/java/com/tamguo/config/shiro/MemberRealm.java
@@ -18,55 +18,95 @@ import org.springframework.beans.factory.annotation.Autowired;
import com.tamguo.modules.member.model.MemberEntity;
import com.tamguo.modules.member.service.IMemberService;
-/**
- * 认证
- *
- */
+// 该类继承自AuthorizingRealm类,在Apache Shiro框架中,AuthorizingRealm是一个用于实现认证(authentication)和授权(authorization)功能的抽象基类,
+// 自定义的Realm需要继承它并实现相关抽象方法来定义具体的认证和授权逻辑,这里的MemberRealm类就是针对会员(Member)相关业务定制的Realm,用于处理会员的认证和授权操作。
public class MemberRealm extends AuthorizingRealm {
-
+
+ // 通过@Autowired注解自动注入IMemberService接口的实现类实例,IMemberService用于处理与会员相关的业务逻辑,
+ // 例如根据用户名查询会员信息、获取会员登录失败次数、更新会员登录失败次数以及更新会员最后登录时间等操作,
+ // 在本类的认证和授权逻辑中,需要借助这些业务方法来获取会员相关数据以及更新会员状态等信息。
@Autowired
private IMemberService iMemberService;
-
- /**
- * 授权(验证权限时调用)
- */
+
+ /**
+ * 授权方法,在Shiro框架中,当需要验证用户是否具有特定权限时(例如访问某个受权限控制的资源时),会调用这个方法来获取用户的授权信息。
+ * 该方法是从父类AuthorizingRealm中继承而来的抽象方法,必须在子类中实现具体逻辑。
+ * 当前实现只是简单地创建了一个SimpleAuthorizationInfo对象,并设置了权限集合(虽然当前设置为空集合,实际应用中应该根据业务规则查询并设置用户所拥有的具体权限),然后返回该对象,
+ * 后续可以根据业务需求扩展这个方法,从数据库等数据源中查询出当前用户(通过PrincipalCollection参数可获取用户相关信息)所拥有的权限信息,并添加到SimpleAuthorizationInfo对象中,以便Shiro进行权限验证。
+ *
+ * @param principals PrincipalCollection对象,它包含了当前已认证用户的主体信息(比如用户对象、用户名等关键信息,具体取决于认证时设置的主体内容),
+ * 通过它可以获取到与当前用户相关的信息,进而根据这些信息去查询并构建该用户对应的授权信息,不过当前代码暂未充分利用它来查询权限信息,只是简单返回了一个基础的授权信息对象。
+ * @return 返回一个AuthorizationInfo接口的实现类对象(这里返回的是SimpleAuthorizationInfo实例),该对象包含了用户的授权信息,例如用户拥有的权限列表等,供Shiro框架进行权限验证使用。
+ */
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
- Set permsSet = null;
+ // 初始化一个用于存储权限字符串的集合变量,当前设置为null,实际应用中应该从数据库等数据源查询出当前用户所拥有的权限字符串,并添加到这个集合中,
+ // 权限字符串通常是一些具有特定格式的字符串,用于标识不同的操作权限(比如"user:add"表示用户添加权限,"order:delete"表示订单删除权限等,具体格式根据业务设计而定)。
+ Set permsSet = null;
+
+ // 创建一个SimpleAuthorizationInfo对象,它是Shiro框架中用于表示用户授权信息的一个简单实现类,通过调用其相关方法可以设置用户的角色、权限等信息。
SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
+
+ // 将当前为空的权限集合设置到SimpleAuthorizationInfo对象中,实际业务中应该在此处添加从数据库查询到的用户实际拥有的权限,
+ // 使得Shiro框架后续能基于这些权限信息来判断用户是否有权限访问特定资源。
info.setStringPermissions(permsSet);
-
+
return info;
}
/**
- * 认证(登录时调用)
+ * 认证方法,在Shiro框架中,当用户进行登录操作时,会调用这个方法来验证用户提供的身份信息(如用户名和密码)是否正确,以及账号是否处于可用状态等。
+ * 该方法同样是从父类AuthorizingRealm中继承而来的抽象方法,需要在子类中实现具体的认证逻辑,这里实现了根据用户名查询会员信息、验证密码、处理登录失败次数以及更新登录时间等逻辑,来完成会员登录的认证过程。
+ *
+ * @param token AuthenticationToken对象,它封装了用户在登录时提交的身份验证信息,通常包含用户名和密码(以不同的形式存储,具体取决于使用的Token实现类),
+ * 通过这个对象可以获取到用户输入的用户名和密码信息,用于与数据库中存储的用户信息进行比对验证。
+ * @return 返回一个AuthenticationInfo接口的实现类对象(这里返回的是SimpleAuthenticationInfo实例),该对象包含了已认证成功的用户相关信息(如用户对象、密码等),
+ * 告知Shiro框架认证成功,并将这些信息保存起来,以便后续在整个请求处理过程中可以获取到已认证用户的相关内容,同时也可以供其他需要验证用户身份的地方使用。
+ * @throws AuthenticationException 如果认证过程中出现异常情况(如用户名不存在、密码错误、账号被锁定等),会抛出相应的AuthenticationException及其子类异常,
+ * Shiro框架会根据抛出的异常类型进行相应的处理,比如向客户端返回对应的错误提示信息等操作。
*/
@Override
protected AuthenticationInfo doGetAuthenticationInfo(
AuthenticationToken token) throws AuthenticationException {
+ // 从AuthenticationToken对象中获取用户输入的用户名信息,由于在通常情况下,Shiro默认的Token实现类会将用户名存储在Principal位置,所以通过强制类型转换获取用户名的字符串表示形式。
String username = (String) token.getPrincipal();
- String password = new String((char[]) token.getCredentials());
-
- MemberEntity member = iMemberService.findByUsername(username);
- if(member == null) {
- throw new UnknownAccountException("用户名或密码有误,请重新输入或找回密码");
- }
- Integer loginFailureCount = iMemberService.getLoginFailureCount(member);
- if(loginFailureCount > 10) {
- throw new LockedAccountException("账号被锁定");
- }
-
- if(!new Sha256Hash(password).toHex().equals(member.getPassword())){
+
+ // 从AuthenticationToken对象中获取用户输入的密码信息,Shiro默认的Token实现类会将密码以字符数组的形式存储在Credentials位置,这里通过将字符数组转换为字符串来获取密码内容。
+ String password = new String((char[]) token.getCredentials());
+
+ // 调用iMemberService的findByUsername方法,根据获取到的用户名去数据库等数据源中查询对应的会员实体对象,用于后续验证密码以及判断账号状态等操作。
+ MemberEntity member = iMemberService.findByUsername(username);
+
+ // 如果查询到的会员对象为null,说明用户名不存在,抛出UnknownAccountException异常,Shiro框架会捕获这个异常并根据配置向客户端返回相应的错误提示信息(如提示用户名或密码有误等)。
+ if (member == null) {
+ throw new UnknownAccountException("用户名或密码有误,请重新输入或找回密码");
+ }
+
+ // 调用iMemberService的getLoginFailureCount方法,获取当前会员的登录失败次数,用于判断账号是否因为多次登录失败而被锁定。
+ Integer loginFailureCount = iMemberService.getLoginFailureCount(member);
+
+ // 如果登录失败次数大于10次,说明账号存在异常登录情况,可能被恶意攻击等,为了保证账号安全,抛出LockedAccountException异常,Shiro框架会处理这个异常并告知客户端账号被锁定,禁止登录。
+ if (loginFailureCount > 10) {
+ throw new LockedAccountException("账号被锁定");
+ }
+
+ // 使用Sha256Hash对用户输入的密码进行哈希处理(将密码转换为不可逆的哈希值形式),并与数据库中存储的会员密码(通常也是经过哈希处理后存储的)进行比对,
+ // 如果两者不一致,说明用户输入的密码错误,此时增加登录失败次数,调用iMemberService的updateLoginFailureCount方法将更新后的登录失败次数保存到数据库中,
+ // 然后抛出IncorrectCredentialsException异常,Shiro框架会根据此异常向客户端返回密码错误的提示信息,要求用户重新输入密码。
+ if (!new Sha256Hash(password).toHex().equals(member.getPassword())) {
loginFailureCount++;
- iMemberService.updateLoginFailureCount(member , loginFailureCount);
+ iMemberService.updateLoginFailureCount(member, loginFailureCount);
throw new IncorrectCredentialsException("用户名或密码有误,请重新输入或找回密码");
}
+
+ // 如果密码验证通过,说明登录认证成功,调用iMemberService的updateLastLoginTime方法,根据会员的唯一标识(member.getId())更新会员的最后登录时间,记录会员此次登录的时间信息,方便后续业务分析等使用。
// 更新登录时间
iMemberService.updateLastLoginTime(member.getId());
-
- SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(member, password, getName());
- return info;
- }
-}
+ // 创建一个SimpleAuthenticationInfo对象,将查询到的会员对象(作为已认证的主体信息)、用户输入的密码(虽然密码在实际验证后通常不再需要,但在这里按照Shiro的要求传入,Shiro内部有相应的处理机制确保安全)以及当前Realm的名称(通过getName方法获取)传入,
+ // 这个对象会告知Shiro框架认证成功,并将相关信息保存起来,供后续使用,例如在整个请求处理过程中判断用户是否已经认证等操作。
+ SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(member, password, getName());
+
+ return info;
+ }
+}
\ No newline at end of file
diff --git a/tamguo-tms/src/main/java/com/tamguo/config/shiro/ShiroConfiguration.java b/tamguo-tms/src/main/java/com/tamguo/config/shiro/ShiroConfiguration.java
index 96f9ab3..1e8f435 100644
--- a/tamguo-tms/src/main/java/com/tamguo/config/shiro/ShiroConfiguration.java
+++ b/tamguo-tms/src/main/java/com/tamguo/config/shiro/ShiroConfiguration.java
@@ -12,15 +12,35 @@ import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreato
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
+// @Configuration注解表明这个类是一个Spring的配置类,用于定义各种与Shiro框架相关的Bean以及相关的配置信息,
+// Spring容器会在启动时读取这个类中的配置,将其中定义的Bean创建并管理起来,从而实现Shiro框架在Spring应用中的集成和功能配置。
@Configuration
public class ShiroConfiguration {
+
+ // 创建一个静态的LinkedHashMap,用于存储URL路径与对应的Shiro过滤器链定义,
+ // 其中键(String类型)表示URL路径的匹配模式,值(也是String类型)表示对应的Shiro过滤器链的定义(例如需要进行什么类型的认证、授权等操作),
+ // 后续会将这个映射关系配置到ShiroFilterFactoryBean中,以实现对不同URL请求的访问控制。
private static Map filterChainDefinitionMap = new LinkedHashMap();
+ /**
+ * 创建并返回一个MemberRealm实例,将其注册为Spring容器中的一个Bean,名称为"shiroRealm"。
+ * MemberRealm是自定义的继承自Shiro的AuthorizingRealm的类,用于实现具体的用户认证和授权逻辑(如根据用户名密码验证用户身份、查询用户权限等操作),
+ * 在这里作为Shiro安全管理器(DefaultWebSecurityManager)的核心组件,提供认证和授权相关的具体实现,供Shiro框架调用。
+ *
+ * @return 返回一个新创建的MemberRealm对象,作为Shiro框架中用于处理认证和授权的关键组件,由Spring容器管理并注入到其他相关的Shiro组件中使用。
+ */
@Bean(name = "shiroRealm")
public MemberRealm getShiroRealm() {
return new MemberRealm();
}
+ /**
+ * 创建并返回一个EhCacheManager实例,将其注册为Spring容器中的一个Bean,名称为"shiroEhcacheManager"。
+ * EhCacheManager是Shiro框架用于缓存管理的一个实现类,它可以与Ehcache缓存框架集成,在这里通过设置缓存配置文件(ehcache-shiro.xml)来配置缓存相关的参数,
+ * 例如缓存的存活时间、最大缓存对象数量等,用于缓存Shiro框架运行过程中的一些数据(如用户的认证信息、授权信息等),提高系统性能,减少重复查询数据库等操作的开销。
+ *
+ * @return 返回一个配置好的EhCacheManager对象,供Shiro框架在需要进行缓存管理时使用,例如缓存用户权限信息,下次访问相同权限验证时可以直接从缓存中获取,加快验证速度。
+ */
@Bean(name = "shiroEhcacheManager")
public EhCacheManager getEhCacheManager() {
EhCacheManager em = new EhCacheManager();
@@ -28,11 +48,25 @@ public class ShiroConfiguration {
return em;
}
+ /**
+ * 创建并返回一个LifecycleBeanPostProcessor实例,将其注册为Spring容器中的一个Bean,名称为"lifecycleBeanPostProcessor"。
+ * LifecycleBeanPostProcessor是Shiro与Spring集成时用于管理Shiro组件生命周期的一个后置处理器,它可以确保Shiro的各种Bean(如Realm、SecurityManager等)在Spring容器中的生命周期方法(如初始化、销毁等方法)能够被正确调用,
+ * 保证Shiro框架相关组件能按照预期的生命周期流程进行初始化和资源释放等操作,使整个Shiro框架在Spring应用中稳定运行。
+ *
+ * @return 返回一个新创建的LifecycleBeanPostProcessor对象,用于处理Shiro组件在Spring容器中的生命周期相关逻辑。
+ */
@Bean(name = "lifecycleBeanPostProcessor")
public LifecycleBeanPostProcessor getLifecycleBeanPostProcessor() {
return new LifecycleBeanPostProcessor();
}
+ /**
+ * 创建并返回一个DefaultAdvisorAutoProxyCreator实例,用于在Spring应用中开启基于AOP(Aspect-Oriented Programming,面向切面编程)的自动代理功能,
+ * 以便能够正确地处理Shiro框架中的切面相关逻辑(如权限验证切面等),通过设置proxyTargetClass为true,强制使用基于类的代理方式(而不是基于接口的代理方式),
+ * 确保Shiro的各种通知(如权限验证的拦截逻辑等)能够准确地应用到对应的目标对象上,实现对业务方法的权限控制等功能。
+ *
+ * @return 返回一个配置好的DefaultAdvisorAutoProxyCreator对象,使得Spring能够自动创建代理对象来应用Shiro相关的切面逻辑,实现权限控制等功能。
+ */
@Bean
public DefaultAdvisorAutoProxyCreator getDefaultAdvisorAutoProxyCreator() {
DefaultAdvisorAutoProxyCreator daap = new DefaultAdvisorAutoProxyCreator();
@@ -40,6 +74,14 @@ public class ShiroConfiguration {
return daap;
}
+ /**
+ * 创建并返回一个DefaultWebSecurityManager实例,将其注册为Spring容器中的一个Bean,名称为"securityManager"。
+ * DefaultWebSecurityManager是Shiro在Web应用环境下的核心安全管理器,它负责协调Shiro的各个组件(如Realm、缓存管理器等)来完成用户认证、授权以及会话管理等安全相关的功能,
+ * 在这里将自定义的MemberRealm(通过调用getShiroRealm方法获取)和EhCacheManager(通过调用getEhCacheManager方法获取)设置到DefaultWebSecurityManager中,
+ * 使其能够使用自定义的认证授权逻辑以及缓存机制来保障系统的安全性和性能。
+ *
+ * @return 返回一个配置好的DefaultWebSecurityManager对象,作为Shiro框架在Web应用中的核心安全管理组件,供其他Shiro相关组件(如ShiroFilterFactoryBean)使用,来实现整个应用的安全控制。
+ */
@Bean(name = "securityManager")
public DefaultWebSecurityManager getDefaultWebSecurityManager() {
DefaultWebSecurityManager dwsm = new DefaultWebSecurityManager();
@@ -48,6 +90,13 @@ public class ShiroConfiguration {
return dwsm;
}
+ /**
+ * 创建并返回一个AuthorizationAttributeSourceAdvisor实例,用于为Shiro的权限验证提供基于AOP的切面配置,
+ * 它将与Spring的AOP机制结合,通过设置安全管理器(DefaultWebSecurityManager,通过调用getDefaultWebSecurityManager方法获取),
+ * 可以在业务方法执行前自动进行权限验证,拦截不符合权限要求的请求,确保只有具有相应权限的用户能够访问受保护的资源,实现基于注解或配置的权限控制功能。
+ *
+ * @return 返回一个配置好的AuthorizationAttributeSourceAdvisor对象,用于在Spring应用中基于AOP实现Shiro的权限验证切面逻辑,增强系统的权限控制能力。
+ */
@Bean
public AuthorizationAttributeSourceAdvisor getAuthorizationAttributeSourceAdvisor() {
AuthorizationAttributeSourceAdvisor aasa = new AuthorizationAttributeSourceAdvisor();
@@ -55,15 +104,30 @@ public class ShiroConfiguration {
return new AuthorizationAttributeSourceAdvisor();
}
+ /**
+ * 创建并返回一个ShiroFilterFactoryBean实例,将其注册为Spring容器中的一个Bean,名称为"shiroFilter"。
+ * ShiroFilterFactoryBean是Shiro与Spring集成用于配置Web应用中Shiro过滤器链的核心组件,它通过设置安全管理器(通过调用getDefaultWebSecurityManager方法获取)来关联整个Shiro的安全管理体系,
+ * 同时设置登录页面的URL(通过setLoginUrl方法设置为"/login",当用户未认证访问受保护资源时,会被重定向到这个登录页面进行登录操作)、登录成功后的跳转页面URL(通过setSuccessUrl方法设置为"/index",用户认证成功后会自动跳转到这个页面),
+ * 并且将之前定义的filterChainDefinitionMap(包含了URL路径与对应的Shiro过滤器链定义的映射关系)设置进去,以此来配置不同URL路径对应的访问控制规则,例如哪些路径需要进行认证("authc"表示需要认证),哪些路径可以匿名访问("anon"表示匿名访问,不需要认证)等,
+ * 最终实现对整个Web应用的URL级别的安全访问控制。
+ *
+ * @return 返回一个配置好的ShiroFilterFactoryBean对象,用于定义Web应用中Shiro的过滤器链以及相关的访问控制配置,使得Shiro框架能够根据这些配置对不同的URL请求进行相应的安全处理。
+ */
@Bean(name = "shiroFilter")
public ShiroFilterFactoryBean getShiroFilterFactoryBean() {
ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
shiroFilterFactoryBean.setSecurityManager(getDefaultWebSecurityManager());
shiroFilterFactoryBean.setLoginUrl("/login");
shiroFilterFactoryBean.setSuccessUrl("/index");
+
+ // 配置URL路径与Shiro过滤器链的映射关系,例如:
+ // "/member/**"路径下的请求都需要进行认证("authc"表示需要进行身份认证才能访问),这里的"/member/**"是一种Ant风格的路径匹配表达式,表示以"/member/"开头的所有路径。
+ // "/**"路径下的请求都允许匿名访问("anon"表示任何人都可以直接访问,不需要进行身份认证),这里的"/**"表示匹配所有的URL路径,通常用于配置一些公开的资源(如静态资源、登录页面等)可以直接访问。
filterChainDefinitionMap.put("/member/**", "authc");
filterChainDefinitionMap.put("/**", "anon");
+
shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
+
return shiroFilterFactoryBean;
}
}
\ No newline at end of file
diff --git a/tamguo-tms/src/main/java/com/tamguo/config/web/ErrorConfigurar.java b/tamguo-tms/src/main/java/com/tamguo/config/web/ErrorConfigurar.java
index 9267271..9dbac01 100644
--- a/tamguo-tms/src/main/java/com/tamguo/config/web/ErrorConfigurar.java
+++ b/tamguo-tms/src/main/java/com/tamguo/config/web/ErrorConfigurar.java
@@ -6,16 +6,36 @@ import org.springframework.boot.web.server.ErrorPageRegistry;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Component;
+// @Component注解用于将这个类标记为Spring框架中的一个组件,意味着Spring容器会在启动时扫描到这个类,并将其作为一个Bean进行管理,
+// 使得这个类可以参与到Spring应用的依赖注入以及各种组件协作的流程中,在这里它主要用于配置应用的错误页面相关逻辑。
@Component
+// 这个类实现了ErrorPageRegistrar接口,该接口用于在Spring Boot应用中注册自定义的错误页面,
+// 通过实现接口中的registerErrorPages方法,可以定义不同HTTP状态码对应的错误页面路径,当应用出现相应的错误时,会自动重定向到配置好的错误页面进行展示。
public class ErrorConfigurar implements ErrorPageRegistrar {
+ /**
+ * 实现ErrorPageRegistrar接口中定义的方法,用于向Spring Boot应用的Web服务器注册自定义的错误页面配置信息。
+ * 该方法接收一个ErrorPageRegistry类型的参数,通过这个参数可以添加不同状态码对应的错误页面映射关系,使得应用在出现对应错误时能正确地跳转到指定的错误页面进行展示,提升用户体验以及便于错误排查等操作。
+ *
+ * @param registry ErrorPageRegistry对象,它是Spring Boot提供的用于注册错误页面的接口实现类对象,通过调用其相关方法可以添加各种HTTP状态码与错误页面路径的映射关系,
+ * 从而实现对不同错误情况的页面展示配置。
+ */
@Override
public void registerErrorPages(ErrorPageRegistry registry) {
- ErrorPage[] errorPages=new ErrorPage[2];
- errorPages[0]=new ErrorPage(HttpStatus.NOT_FOUND,"/error404");
- errorPages[1]=new ErrorPage(HttpStatus.INTERNAL_SERVER_ERROR,"/error500");
+ // 创建一个ErrorPage类型的数组,用于存储要配置的不同错误页面信息,这里数组长度为2,表示要配置两种不同HTTP状态码对应的错误页面,
+ // 可以根据实际需求增加数组长度来配置更多的错误页面映射关系。
+ ErrorPage[] errorPages = new ErrorPage[2];
- registry.addErrorPages(errorPages);
+ // 配置第一个错误页面信息,对应HTTP状态码为HttpStatus.NOT_FOUND(即404状态码,表示请求的资源未找到),
+ // 当应用中出现资源未找到的错误时,会将用户重定向到"/error404"这个路径对应的页面进行展示,这里的"/error404"应该是项目中事先定义好的用于展示404错误信息的页面路径(通常是一个HTML页面等)。
+ errorPages[0] = new ErrorPage(HttpStatus.NOT_FOUND, "/error404");
+
+ // 配置第二个错误页面信息,对应HTTP状态码为HttpStatus.INTERNAL_SERVER_ERROR(即500状态码,表示服务器内部错误),
+ // 当应用在执行过程中出现服务器内部错误(比如代码抛出未捕获的异常等情况)时,会将用户重定向到"/error500"这个路径对应的页面进行展示,同样,"/error500"也是项目中用于展示500错误信息的特定页面路径。
+ errorPages[1] = new ErrorPage(HttpStatus.INTERNAL_SERVER_ERROR, "/error500");
+
+ // 通过调用ErrorPageRegistry对象的addErrorPages方法,将配置好的包含错误页面映射关系的errorPages数组添加进去,
+ // 这样Spring Boot应用的Web服务器就会根据这些配置,在相应错误发生时重定向到对应的错误页面进行展示了。
+ registry.addErrorPages(errorPages);
}
-
-}
+}
\ No newline at end of file
diff --git a/tamguo-tms/src/main/java/com/tamguo/config/web/ThymeleafConfig.java b/tamguo-tms/src/main/java/com/tamguo/config/web/ThymeleafConfig.java
index cb46b3f..7a94671 100644
--- a/tamguo-tms/src/main/java/com/tamguo/config/web/ThymeleafConfig.java
+++ b/tamguo-tms/src/main/java/com/tamguo/config/web/ThymeleafConfig.java
@@ -11,31 +11,82 @@ import org.thymeleaf.spring5.view.ThymeleafViewResolver;
import com.tamguo.common.utils.SystemConstant;
+// @Component注解用于将这个类标记为Spring框架中的一个组件,意味着Spring容器在启动时会扫描到这个类,并将其作为一个Bean进行管理,
+// 使得该类能够参与到Spring应用的依赖注入以及整个应用的配置流程中,在这里它主要负责对Thymeleaf相关的配置进行定制化设置。
@Component
-public class ThymeleafConfig implements EnvironmentAware{
+// 这个类实现了EnvironmentAware接口,通过实现该接口的setEnvironment方法,可以获取到Spring应用的运行环境配置信息(如配置文件中的各种属性值等),
+// 进而基于这些环境配置来进行相关的业务配置操作,在本类中就是利用环境配置来设置Thymeleaf视图解析器中的一些静态变量。
+public class ThymeleafConfig implements EnvironmentAware {
+ // 通过@Resource注解进行依赖注入,将Spring的Environment对象注入到当前类中。Environment对象提供了访问应用配置属性的接口,
+ // 可以通过它获取到配置文件(如application.properties或application.yml等)中定义的各种属性值,以便在代码中使用这些配置信息进行相应的逻辑处理,
+ // 例如获取服务器域名、不同模块的域名等配置信息用于后续设置到Thymeleaf的静态变量中。
@Resource
- private Environment env;
+ private Environment env;
+ /**
+ * 这个方法使用了@Resource注解,表明它是一个依赖注入相关的方法,它的参数类型是ThymeleafViewResolver,Spring会自动将对应的ThymeleafViewResolver实例注入进来。
+ * 该方法的主要功能是配置Thymeleaf视图解析器的静态变量,通过从Environment对象中获取相关的配置属性值以及从SystemConstant类中获取一些常量值,
+ * 将它们封装到一个Map中,然后设置到ThymeleafViewResolver对象里,使得在Thymeleaf模板页面中可以直接使用这些变量,方便进行页面渲染等操作,例如动态生成页面链接时使用域名变量等情况。
+ *
+ * @param viewResolver ThymeleafViewResolver类型的对象,它是Spring中用于解析Thymeleaf模板视图的核心组件,通过它可以配置视图解析相关的各种参数和属性,
+ * 在这里主要是为其设置静态变量,以便在Thymeleaf模板中能够方便地访问和使用这些变量进行页面渲染。
+ */
@Resource
private void configureThymeleafStaticVars(ThymeleafViewResolver viewResolver) {
- if(viewResolver != null) {
- Map vars = new HashMap<>();
- vars.put("domainName", env.getProperty("domain.name"));
- vars.put("adminDomain", env.getProperty("admin.domain.name"));
- vars.put("memberDomain", env.getProperty("member.domain.name"));
- vars.put("PAPER_TYPE_ZHENTI", SystemConstant.ZHENGTI_PAPER_ID);
- vars.put("PAPER_TYPE_MONI", SystemConstant.MONI_PAPER_ID);
- vars.put("PAPER_TYPE_YATI", SystemConstant.YATI_PAPER_ID);
- vars.put("PAPER_TYPE_MINGXIAO", SystemConstant.MINGXIAO_PAPER_ID);
- vars.put("BEIJING_AREA_ID", SystemConstant.BEIJING_AREA_ID);
- viewResolver.setStaticVariables(vars);
- }
+ // 判断传入的ThymeleafViewResolver对象是否为空,如果不为空,则进行后续的静态变量配置操作,避免空指针异常等情况。
+ if (viewResolver!= null) {
+ // 创建一个HashMap对象,用于存储要设置到ThymeleafViewResolver中的静态变量,键为变量名(在Thymeleaf模板中使用的名称),值为对应的变量值,
+ // 这些变量值可以是从配置文件中获取的属性值或者是代码中定义的常量值等,通过设置静态变量,方便在Thymeleaf模板中直接引用这些变量进行页面逻辑处理。
+ Map vars = new HashMap<>();
+
+ // 从Environment对象中获取名为"domain.name"的配置属性值,并将其作为"domainName"变量添加到vars集合中,
+ // 在Thymeleaf模板中可以通过${domainName}的方式来引用这个变量,可能用于生成完整的域名相关链接等操作,具体用途取决于业务需求。
+ vars.put("domainName", env.getProperty("domain.name"));
+
+ // 从Environment对象中获取名为"admin.domain.name"的配置属性值,将其作为"adminDomain"变量添加到vars集合中,
+ // 这样在Thymeleaf模板中如果涉及到与管理员相关模块的域名使用场景时,可以方便地通过${adminDomain}获取并使用这个变量,例如构建管理员模块的页面链接等情况。
+ vars.put("adminDomain", env.getProperty("admin.domain.name"));
+
+ // 类似地,从Environment对象中获取名为"member.domain.name"的配置属性值,将其作为"memberDomain"变量添加到vars集合中,
+ // 便于在Thymeleaf模板中针对会员相关模块的页面处理时,通过${memberDomain}引用这个变量来构建相关的链接或者进行其他与域名相关的操作。
+ vars.put("memberDomain", env.getProperty("member.domain.name"));
+
+ // 从SystemConstant类中获取名为ZHENGTI_PAPER_ID的常量值,并将其作为"PAPER_TYPE_ZHENTI"变量添加到vars集合中,
+ // 在Thymeleaf模板中可以通过这个变量来表示某种试卷类型(具体试卷类型含义由业务中SystemConstant类里的定义决定),例如用于页面上试卷类型的展示或者根据试卷类型进行不同的页面逻辑处理等情况。
+ vars.put("PAPER_TYPE_ZHENTI", SystemConstant.ZHENGTI_PAPER_ID);
+
+ // 从SystemConstant类中获取名为MONI_PAPER_ID的常量值,将其作为"PAPER_TYPE_MONI"变量添加到vars集合中,
+ // 同样用于在Thymeleaf模板中处理与模拟试卷类型相关的页面逻辑,比如根据模拟试卷类型展示特定的页面元素或者进行不同的交互操作等,具体取决于业务设计。
+ vars.put("PAPER_TYPE_MONI", SystemConstant.MONI_PAPER_ID);
+
+ // 从SystemConstant类中获取名为YATI_PAPER_ID的常量值,作为"PAPER_TYPE_YATI"变量添加到vars集合中,
+ // 以便在Thymeleaf模板中针对押题试卷类型相关的页面渲染和逻辑处理时能够方便地引用这个变量,例如根据是否是押题试卷类型来展示不同的提示信息等操作。
+ vars.put("PAPER_TYPE_YATI", SystemConstant.YATI_PAPER_ID);
+
+ // 从SystemConstant类中获取名为MINGXIAO_PAPER_ID的常量值,将其作为"PAPER_TYPE_MINGXIAO"变量添加到vars集合中,
+ // 在Thymeleaf模板中可以利用这个变量进行与名校试卷类型相关的页面展示和逻辑处理,比如根据名校试卷类型来展示对应的学校标识或者试卷特色等信息(具体由业务需求决定)。
+ vars.put("PAPER_TYPE_MINGXIAO", SystemConstant.MINGXIAO_PAPER_ID);
+
+ // 从SystemConstant类中获取名为BEIJING_AREA_ID的常量值,将其作为"BEIJING_AREA_ID"变量添加到vars集合中,
+ // 在Thymeleaf模板中可能用于涉及北京地区相关的页面逻辑处理,例如判断是否是北京地区试卷、展示北京地区相关的特色内容等情况(具体根据业务中对北京地区的定义和使用场景而定)。
+ vars.put("BEIJING_AREA_ID", SystemConstant.BEIJING_AREA_ID);
+
+ // 将包含了所有要设置的静态变量的vars集合,通过调用ThymeleafViewResolver的setStaticVariables方法,设置到ThymeleafViewResolver对象中,
+ // 这样在后续使用Thymeleaf解析模板进行页面渲染时,模板中就可以直接使用这些设置好的变量了,方便进行各种页面逻辑的实现以及动态内容的展示等操作。
+ viewResolver.setStaticVariables(vars);
+ }
}
+ /**
+ * 实现EnvironmentAware接口中定义的方法,该方法会在Spring容器初始化时被自动调用,用于接收Spring应用的运行环境配置信息(以Environment对象的形式传入),
+ * 在这里将传入的Environment对象赋值给类中的env成员变量,使得在类的其他方法(如configureThymeleafStaticVars方法)中可以通过这个env变量来访问和获取各种配置属性值。
+ *
+ * @param environment Spring应用的运行环境配置对象,包含了从配置文件(如application.properties、application.yml等)中读取的所有配置属性信息,
+ * 通过这个参数将环境配置信息传递到当前类中,方便后续基于这些配置进行相关的业务配置操作。
+ */
@Override
public void setEnvironment(Environment environment) {
env = environment;
}
-
-}
+}
\ No newline at end of file
diff --git a/tamguo-tms/src/main/java/com/tamguo/config/web/WebConfig.java b/tamguo-tms/src/main/java/com/tamguo/config/web/WebConfig.java
index 2b7185c..7e25122 100644
--- a/tamguo-tms/src/main/java/com/tamguo/config/web/WebConfig.java
+++ b/tamguo-tms/src/main/java/com/tamguo/config/web/WebConfig.java
@@ -13,37 +13,93 @@ import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import com.tamguo.web.interceptor.MemberInterceptor;
import com.tamguo.web.interceptor.MenuInterceptor;
-
+// @Configuration注解表明这个类是Spring框架中的一个配置类,用于定义各种Bean以及配置Spring Web MVC相关的功能,
+// Spring容器会在启动时读取这个类中的配置信息,将其中定义的Bean创建并管理起来,同时应用配置的相关规则,例如注册拦截器、配置资源处理等,来定制Web应用的行为。
@Configuration
+// 这个类实现了WebMvcConfigurer接口,该接口提供了一系列用于定制Spring Web MVC功能的方法,通过重写这些方法,
+// 可以添加拦截器、配置资源处理器、处理跨域等操作,这里重写了部分方法来实现特定的业务需求,比如添加自定义拦截器以及配置文件资源的访问路径、设置Cookie序列化相关参数等。
public class WebConfig implements WebMvcConfigurer {
-
+
+ // 通过@Value注解从配置文件(例如application.properties或application.yml等)中获取名为"file.storage.path"的属性值,并注入到当前类的fileStoragePath变量中,
+ // 这个属性值通常表示文件存储的路径,在后续配置文件资源访问时会用到,用于指定服务器上文件实际存放的位置,以便能正确地对外提供文件访问服务。
@Value("${file.storage.path}")
private String fileStoragePath;
+
+ // 同样使用@Value注解从配置文件中获取名为"cookie.domian.name"的属性值,注入到cookieDomianName变量中,
+ // 该属性值一般是Cookie的域名设置,用于确定Cookie在哪些域名下有效,在配置Cookie序列化相关参数时会用到这个值,确保Cookie的作用范围符合业务需求。
@Value("${cookie.domian.name}")
private String cookieDomianName;
+
+ // 通过@Autowired注解自动注入MemberInterceptor类型的实例,MemberInterceptor应该是一个自定义的拦截器类,
+ // 用于拦截特定路径下的请求,可能在这些请求处理前进行一些与会员相关的逻辑验证、权限判断或者预处理操作,比如检查会员是否登录等情况,在后续配置拦截器时会将其添加到拦截器链中。
@Autowired
private MemberInterceptor memberInterceptor;
+
+ // 与上面类似,通过@Autowired注解注入MenuInterceptor类型的实例,MenuInterceptor也是自定义的拦截器,
+ // 可能用于拦截所有请求(从后续添加拦截器的配置来看),并针对菜单相关的业务逻辑进行处理,例如根据用户权限动态生成菜单、验证菜单访问权限等操作,同样会在后面配置到拦截器链中发挥作用。
@Autowired
private MenuInterceptor menuInterceptor;
-
+
+ /**
+ * 重写WebMvcConfigurer接口中的addInterceptors方法,用于向Spring Web MVC的拦截器链中添加自定义的拦截器,
+ * 通过InterceptorRegistry对象可以注册多个拦截器,并指定每个拦截器要拦截的请求路径模式,从而实现对不同请求的拦截处理,满足业务中各种权限控制、前置处理等需求。
+ *
+ * @param registry InterceptorRegistry对象,它提供了添加拦截器以及配置拦截器相关参数(如拦截的路径模式)的方法,
+ * 通过调用其相关方法可以将自定义的拦截器添加到Spring Web MVC的拦截器链中,使其生效并对符合条件的请求进行拦截处理。
+ */
@Override
public void addInterceptors(InterceptorRegistry registry) {
+ // 将menuInterceptor添加到拦截器链中,并指定其拦截的路径模式为"/**",这是一种Ant风格的路径匹配表达式,表示拦截所有的请求路径,
+ // 意味着所有进入应用的请求都会先经过menuInterceptor拦截器进行处理,具体的处理逻辑在MenuInterceptor类中实现,可能涉及菜单相关的各种业务逻辑操作,比如权限验证、菜单数据准备等。
registry.addInterceptor(menuInterceptor).addPathPatterns("/**");
+
+ // 将memberInterceptor添加到拦截器链中,并设置其拦截的路径模式为"/member/**",表示拦截以"/member/"开头的所有请求路径,
+ // 通常用于处理与会员相关模块的请求,在这些请求被处理前,memberInterceptor会执行相应的会员相关逻辑,例如检查会员登录状态、会员权限验证等操作,确保只有符合条件的会员请求才能继续往下执行。
registry.addInterceptor(memberInterceptor).addPathPatterns("/member/**");
}
-
- @Override
- public void addResourceHandlers(ResourceHandlerRegistry registry) {
- registry.addResourceHandler("/files/**").addResourceLocations("file:"+fileStoragePath);
- }
-
- @Bean
- public CookieSerializer defaultCookieSerializer(){
- DefaultCookieSerializer defaultCookieSerializer = new DefaultCookieSerializer();
- defaultCookieSerializer.setCookieName("sessionId");
- defaultCookieSerializer.setDomainName(cookieDomianName);
- defaultCookieSerializer.setCookiePath("/");
- return defaultCookieSerializer;
- }
-
-}
+
+ /**
+ * 重写WebMvcConfigurer接口中的addResourceHandlers方法,用于配置Spring Web MVC中资源处理器,
+ * 可以指定对外暴露的资源路径(如图片、文件等资源的访问路径)以及对应的资源实际在服务器上的存放位置,使得客户端能够通过配置好的路径访问到相应的资源,方便应用中对静态资源或文件资源的管理和访问。
+ *
+ * @param registry ResourceHandlerRegistry对象,它提供了添加资源处理器相关配置的方法,通过调用其相关方法可以将资源的访问路径与实际存放位置进行映射配置,
+ * 让Spring Web MVC知道如何处理不同资源路径的请求,将请求正确地转发到对应的资源文件上。
+ */
+ @Override
+ public void addResourceHandlers(ResourceHandlerRegistry registry) {
+ // 配置一个资源处理器,指定对外暴露的资源访问路径为"/files/**",这也是一种Ant风格的路径匹配表达式,表示以"/files/"开头的所有路径都将被映射到对应的资源位置,
+ // 例如客户端访问"/files/image.jpg"就会去查找实际对应的资源文件(具体查找位置由后面配置的实际存放位置决定)。
+ // 同时通过addResourceLocations方法指定资源实际存放的位置,使用"file:"前缀加上之前注入的fileStoragePath变量(表示文件存储的实际路径),
+ // 这样Spring Web MVC就能根据这个配置,将对"/files/**"路径的请求转发到服务器上fileStoragePath指定的实际文件存储位置去查找并返回对应的资源文件了。
+ registry.addResourceHandler("/files/**").addResourceLocations("file:" + fileStoragePath);
+ }
+
+ /**
+ * 定义一个名为defaultCookieSerializer的方法,并使用@Bean注解将其返回的对象注册为Spring容器中的一个Bean,
+ * 该方法用于创建并配置一个DefaultCookieSerializer实例,用于对Cookie进行序列化相关的设置,比如设置Cookie的名称、域名、路径等属性,
+ * 使得在应用中使用Spring Session管理会话时,生成的Cookie能够按照配置的要求进行正确的设置和传递,保证会话相关的功能正常实现。
+ *
+ * @return 返回一个配置好的DefaultCookieSerializer对象,该对象会被Spring容器管理,在需要对Cookie进行序列化操作(例如创建、更新会话相关的Cookie)时被使用,
+ * 按照配置的参数来生成符合要求的Cookie信息,确保在客户端和服务器之间正确传递会话相关的数据。
+ */
+ @Bean
+ public CookieSerializer defaultCookieSerializer() {
+ // 创建一个DefaultCookieSerializer实例,它是Spring Session中用于对Cookie进行序列化处理的默认实现类,
+ // 通过对其属性进行设置,可以定制Cookie的各种参数,如名称、域名、路径等,以满足应用在不同环境下的需求。
+ DefaultCookieSerializer defaultCookieSerializer = new DefaultCookieSerializer();
+
+ // 设置Cookie的名称为"sessionId",在客户端浏览器中看到的Cookie的键名就会是"sessionId",用于标识会话相关的信息,
+ // 服务器通过这个名称来识别和获取对应的Cookie值,从而获取会话相关的数据,例如判断用户是否登录、获取用户会话中的其他属性等操作。
+ defaultCookieSerializer.setCookieName("sessionId");
+
+ // 设置Cookie的域名,使用之前注入的cookieDomianName变量作为域名值,确定Cookie在哪些域名下有效,
+ // 这样可以根据业务需求限制Cookie的作用范围,比如只在特定的子域名或者主域名下有效,确保会话相关的信息在合适的域名范围内传递和使用。
+ defaultCookieSerializer.setDomainName(cookieDomianName);
+
+ // 设置Cookie的路径为"/",表示这个Cookie在整个应用的所有路径下都有效,客户端在访问应用的任何页面时都会带上这个Cookie,
+ // 方便服务器根据Cookie中的会话信息来处理不同路径下的请求,维持用户的会话状态,实现诸如登录状态保持等功能。
+ defaultCookieSerializer.setCookiePath("/");
+
+ return defaultCookieSerializer;
+ }
+}
\ No newline at end of file
diff --git a/tamguo-tms/src/main/java/com/tamguo/utils/BrowserUtils.java b/tamguo-tms/src/main/java/com/tamguo/utils/BrowserUtils.java
index 0390fde..5d968c9 100644
--- a/tamguo-tms/src/main/java/com/tamguo/utils/BrowserUtils.java
+++ b/tamguo-tms/src/main/java/com/tamguo/utils/BrowserUtils.java
@@ -2,33 +2,65 @@ package com.tamguo.utils;
import java.util.regex.Pattern;
+// 这个类主要用于判断访问设备的类型,通过分析浏览器标识(User-Agent)字符串,利用正则表达式来检测是否是移动设备(包括手机和平板)进行访问,
+// 提供了一个静态方法方便外部调用,在Web应用开发中可用于根据不同的访问设备来提供适配的页面展示或者功能逻辑等情况。
public class BrowserUtils {
- // \b 是单词边界(连着的两个(字母字符 与 非字母字符) 之间的逻辑上的间隔),
- // 字符串在编译时会被转码一次,所以是 "\\b"
- // \B 是单词内部逻辑间隔(连着的两个字母字符之间的逻辑上的间隔)
- private static final String phoneReg = "\\b(ip(hone|od)|android|opera m(ob|in)i"
- +"|windows (phone|ce)|blackberry"
- +"|s(ymbian|eries60|amsung)|p(laybook|alm|rofile/midp"
- +"|laystation portable)|nokia|fennec|htc[-_]"
- +"|mobile|up.browser|[1-4][0-9]{2}x[1-4][0-9]{2})\\b";
+ // 定义一个表示手机设备的正则表达式字符串常量,用于匹配各种常见的手机操作系统、手机品牌及相关设备标识等信息,
+ // 通过这个正则表达式可以判断浏览器标识(User-Agent)中是否包含手机相关的特征字符串,从而确定是否是手机设备访问。
+ // 以下是对正则表达式各部分的详细说明:
+ // \b 是单词边界(连着的两个(字母字符 与 非字母字符)之间的逻辑上的间隔),在Java字符串中,由于反斜杠本身需要转义,所以表示为 "\\b"。
+ // 正则表达式中的 "ip(hone|od)" 用于匹配 "iphone" 或者 "ipod",表示苹果的手机或类似移动设备。
+ // "android" 用于匹配安卓操作系统相关的设备标识,常见于安卓手机等移动设备的浏览器标识中。
+ // "opera m(ob|in)i" 用于匹配 Opera 浏览器的移动版本相关标识,比如 Opera Mobile 或者 Opera Mini,也是常见的移动设备浏览器情况。
+ // "windows (phone|ce)" 用于匹配微软的 Windows Phone 或者 Windows CE 系统相关的移动设备标识,过去常用于一些微软系的手机等设备。
+ // "blackberry" 用于匹配黑莓手机的相关标识,黑莓曾经是很知名的手机品牌,有其独特的浏览器标识特征可以通过这个来匹配。
+ // "s(ymbian|eries60|amsung)" 这里可以匹配塞班系统("symbian")、诺基亚塞班 S60 系列("series60")以及三星("samsung")部分旧的移动设备相关标识,这些都是曾经在手机领域常见的系统或品牌标识情况。
+ // "p(laybook|alm|rofile/midp" 等部分用于匹配黑莓的 PlayBook、Palm 设备以及一些基于 Java ME(通过 "profile/midp" 匹配相关的配置和规范标识)的移动设备等情况,涵盖了多种不同类型的旧有移动设备特征。
+ // "laystation portable" 用于匹配索尼的 PlayStation Portable 设备,虽然它主要是游戏机,但也具备一定的浏览器功能,属于可移动使用的设备,所以也在匹配范围内。
+ // "nokia" 简单直接地匹配诺基亚手机相关标识,诺基亚曾经是全球最大的手机制造商之一,有很多不同型号手机的浏览器标识可以通过这个来识别是否是诺基亚手机访问。
+ // "fennec" 用于匹配火狐浏览器针对移动设备推出的 Fennec 版本相关标识,是移动版火狐浏览器的特征字符串。
+ // "htc[-_]" 用于匹配 HTC 品牌手机相关标识,HTC 也是知名的手机制造商,其设备在浏览器标识中通常有特定的字符串特征,这里通过包含 "htc" 以及可能的连接字符("-" 或者 "_")来匹配。
+ // "mobile" 是一个比较通用的表示移动设备的标识字符串,很多移动设备的浏览器标识中都会包含这个单词来表明其是移动设备。
+ // "up.browser" 用于匹配某些特定的移动浏览器相关标识,可能是一些不太常见但存在的移动设备浏览器情况。
+ // "[1-4][0-9]{2}x[1-4][0-9]{2}" 这部分用于匹配一些特定分辨率格式的设备标识,常见于一些较老的移动设备通过分辨率相关信息来辅助判断是否是移动设备访问,不过这种方式相对比较模糊,只是作为一种补充的匹配特征。
+ private static final String phoneReg = "\\b(ip(hone|od)|android|opera m(ob|in)i"
+ + "|windows (phone|ce)|blackberry"
+ + "|s(ymbian|eries60|amsung)|p(laybook|alm|rofile/midp"
+ + "|laystation portable)|nokia|fennec|htc[-_]"
+ + "|mobile|up.browser|[1-4][0-9]{2}x[1-4][0-9]{2})\\b";
- private static final String tabletReg = "\\b(ipad|tablet|(Nexus 7)|up.browser|[1-4][0-9]{2}x[1-4][0-9]{2})\\b";
+ // 定义一个表示平板设备的正则表达式字符串常量,用于匹配常见的平板电脑相关标识信息,
+ // 同样通过分析浏览器标识(User-Agent)中是否包含这些特征字符串来判断是否是平板设备访问,其原理和手机设备的正则表达式类似,只是匹配的具体字符串不同,更侧重于平板相关的标识。
+ // 其中 "ipad" 用于匹配苹果的 iPad 平板电脑,这是市场占有率很高的平板设备,有其独特的浏览器标识特征。
+ // "tablet" 是一个比较通用的表示平板电脑的标识字符串,很多平板设备的浏览器标识中会包含它来表明自身是平板类型的设备。
+ // "(Nexus 7)" 用于匹配谷歌的 Nexus 7 平板电脑相关标识,Nexus 系列平板曾经也比较受欢迎,有其特定的标识可以用于识别。
+ // "up.browser" 和 "[1-4][0-9]{2}x[1-4][0-9]{2}" 的含义与手机设备正则表达式中的类似,同样是作为辅助匹配一些特定情况的平板设备标识情况。
+ private static final String tabletReg = "\\b(ipad|tablet|(Nexus 7)|up.browser|[1-4][0-9]{2}x[1-4][0-9]{2})\\b";
- //移动设备正则匹配:手机端、平板
- private static Pattern phonePat = Pattern.compile(phoneReg, Pattern.CASE_INSENSITIVE);
- private static Pattern tabletPat = Pattern.compile(tabletReg, Pattern.CASE_INSENSITIVE);
+ // 使用Pattern类对phoneReg正则表达式进行编译,创建一个Pattern对象(phonePat),用于后续在匹配手机设备相关标识时使用,
+ // 通过编译后的Pattern对象可以更高效地进行正则匹配操作,并且可以设置匹配的相关参数(如这里通过第二个参数设置为 Pattern.CASE_INSENSITIVE 表示忽略大小写进行匹配),
+ // 这样在判断浏览器标识中是否包含手机设备相关特征时,就可以直接使用这个编译好的对象进行匹配操作了。
+ private static Pattern phonePat = Pattern.compile(phoneReg, Pattern.CASE_INSENSITIVE);
- /**
- * 检测是否是移动设备访问
- *
- * @param userAgent 浏览器标识
- * @return true:移动设备接入,false:pc端接入
- */
- public static boolean isMobile(String userAgent){
- if(null == userAgent){
- userAgent = "";
- }
- return phonePat.matcher(userAgent).find() || tabletPat.matcher(userAgent).find();
- }
+ // 同样地,对tabletReg正则表达式进行编译,创建一个Pattern对象(tabletPat),用于匹配平板设备相关标识,
+ // 设置匹配参数为忽略大小写(Pattern.CASE_INSENSITIVE),方便后续在分析浏览器标识时判断是否存在平板设备相关的特征字符串,进而确定是否是平板设备访问。
+ private static Pattern tabletPat = Pattern.compile(tabletReg, Pattern.CASE_INSENSITIVE);
+
+ /**
+ * 这个静态方法用于检测传入的浏览器标识(User-Agent)对应的访问设备是否是移动设备(包括手机和平板),
+ * 通过使用之前编译好的手机设备正则匹配对象(phonePat)和平板设备正则匹配对象(tabletPat)分别对浏览器标识进行正则匹配操作,
+ * 只要其中一个匹配成功(即找到了对应的手机或平板设备相关特征字符串),就返回 true,表示是移动设备接入;如果都匹配失败,则返回 false,表示是 PC 端接入。
+ *
+ * @param userAgent 浏览器标识字符串,通常是从 HTTP 请求头中的 "User-Agent" 字段获取到的值,它包含了访问设备、浏览器等相关的特征信息,
+ * 通过分析这个字符串可以判断访问来源的设备类型,以便应用可以根据不同设备类型进行相应的页面适配或者功能调整等操作。
+ * @return 返回一个布尔值,如果检测到浏览器标识中包含手机或平板设备相关的特征字符串(即通过正则匹配成功),返回 true,表示是移动设备接入;
+ * 若没有匹配到相关特征字符串,则返回 false,表示是 PC 端接入,供调用者根据返回值来进行后续不同的业务逻辑处理,比如返回不同的页面视图等情况。
+ */
+ public static boolean isMobile(String userAgent) {
+ if (null == userAgent) {
+ userAgent = "";
+ }
+ return phonePat.matcher(userAgent).find() || tabletPat.matcher(userAgent).find();
+ }
}
\ No newline at end of file
diff --git a/tamguo-tms/src/main/java/com/tamguo/utils/PageUtils.java b/tamguo-tms/src/main/java/com/tamguo/utils/PageUtils.java
index 02f511a..058003f 100644
--- a/tamguo-tms/src/main/java/com/tamguo/utils/PageUtils.java
+++ b/tamguo-tms/src/main/java/com/tamguo/utils/PageUtils.java
@@ -5,85 +5,138 @@ import java.util.List;
import com.baomidou.mybatisplus.plugins.Page;
+// 这个类主要用于对分页数据进行进一步的处理和包装,以便生成更适合前端展示分页相关交互元素(如下一页、上一页按钮显示控制以及页码列表展示等)的对象,
+// 它基于MyBatis Plus的Page对象进行相关计算和属性设置,提供了一种方便的方式将分页数据转换为前端易于处理和展示的格式。
public class PageUtils {
-
- // 是否下一页按钮
+
+ // 用于标识是否显示下一页按钮,初始化为false,表示默认不显示下一页按钮,后续会根据当前页码与总页数的关系来动态设置其值,
+ // 如果当前页小于总页数,就会将其设置为true,表示需要显示下一页按钮,方便用户点击跳转到下一页查看更多数据。
private Boolean isShowNextBtn = false;
-
- // 是否上一页按钮
+
+ // 用于标识是否显示上一页按钮,同样初始化为false,默认不显示上一页按钮,根据当前页码与总页数等情况来确定是否要显示,
+ // 当当前页码大于1时,说明不是第一页,此时会将该属性设置为true,以在前端展示上一页按钮,供用户点击返回上一页查看数据。
private Boolean isShowPreBtn = false;
-
- // 当前页
+
+ // 记录当前所在的页码,用于在生成页码列表以及判断上下页按钮显示情况等操作时作为重要依据,其值会从传入的Page对象中获取并设置。
private Integer currPageNum;
-
- // 页码列表
+
+ // 用于存储要展示给用户的页码列表,例如可能是一个包含了连续页码数字以及省略号(用于表示中间省略部分页码)的字符串列表,
+ // 通过一定的逻辑计算生成,方便在前端展示分页导航栏,让用户可以直观地点击相应页码进行页面跳转,查看不同页的数据。
private List pageNums;
-
- // 总页数
+
+ // 表示分页数据的总页数,从传入的Page对象中获取该值,用于判断是否需要生成多页的页码列表以及确定上下页按钮的显示逻辑等操作,
+ // 是整个分页逻辑处理中的一个关键数据指标。
private Integer totalPage;
-
- // 总数量
+
+ // 用于记录数据的总数量,同样从Page对象中获取,它反映了符合查询条件的所有数据的总数,有助于前端展示一些相关提示信息(如共多少条数据等)以及辅助分页相关的逻辑判断。
private Integer total;
-
- // 数据
+
+ // 存储当前页的数据列表,从Page对象中获取对应页码的数据记录,这是最终要展示给用户的数据内容,会传递给前端进行列表展示等操作。
private List> list;
-
- public static PageUtils getPage(Page> page){
+
+ /**
+ * 这是一个静态方法,用于根据传入的MyBatis Plus的Page对象创建并返回一个PageUtils对象,在这个方法中会对PageUtils对象的各个属性进行设置,
+ * 包括上下页按钮的显示控制、页码列表的生成以及将Page对象中的相关分页数据(如当前页数据、总数量、总页数等)赋值到PageUtils对象的对应属性上,
+ * 从而生成一个适合前端展示分页相关信息的对象。
+ *
+ * @param page MyBatis Plus的Page对象,它包含了分页查询的相关数据,如当前页码、每页记录数、总记录数、总页数以及当前页的数据列表等信息,
+ * 通过对这个对象进行解析和处理,来构建PageUtils对象,以便为前端提供更友好的分页展示相关数据。
+ * @return 返回一个配置好各个属性的PageUtils对象,该对象可以传递给前端,前端可以根据其属性值来展示分页导航栏(包含上下页按钮、页码列表等)以及对应页的数据列表等内容。
+ */
+ public static PageUtils getPage(Page> page) {
PageUtils pg = new PageUtils();
- if(page.getCurrent() > 1){
+
+ // 判断当前页码是否大于1,如果大于1,说明不是第一页,此时需要显示上一页按钮,将PageUtils对象的isShowPreBtn属性设置为true,
+ // 这样前端在展示分页导航栏时就会显示上一页按钮,方便用户点击返回上一页查看数据。
+ if (page.getCurrent() > 1) {
pg.setIsShowPreBtn(true);
}
- if(page.getCurrent() < page.getPages()){
+
+ // 判断当前页码是否小于总页数,如果小于总页数,意味着还有下一页数据,需要显示下一页按钮,将PageUtils对象的isShowNextBtn属性设置为true,
+ // 以便前端展示下一页按钮,供用户点击跳转到下一页查看更多数据。
+ if (page.getCurrent() < page.getPages()) {
pg.setIsShowNextBtn(true);
}
+
List pgNums = new ArrayList<>();
- if(page.getPages() > 1){
- if(page.getPages() > 10){
+
+ // 判断总页数是否大于1,如果大于1,说明有多页数据,需要生成相应的页码列表进行展示,进入下面不同情况的页码列表生成逻辑;
+ // 如果总页数等于1,说明只有一页数据,页码列表就只包含一个页码(通常就是1),后续会在循环中进行相应处理。
+ if (page.getPages() > 1) {
+ // 如果总页数大于10,说明页码较多,采用一种简化展示的方式生成页码列表,通常会显示首页、前几页、中间用省略号表示、当前页及其前后几页、尾页等关键页码信息,
+ // 方便用户在较多页码情况下能快速定位到想要查看的页面附近进行跳转操作。
+ if (page.getPages() > 10) {
+ // 添加页码1,表示首页,一般在分页导航栏中会作为第一个可点击的页码展示,方便用户快速回到第一页查看数据。
pgNums.add("1");
+ // 添加页码2,作为前面几页中的一个页码展示,让用户可以较方便地查看前面几页的数据情况。
pgNums.add("2");
+ // 添加页码3,同样是作为前面几页的页码展示,丰富前面部分页码的展示内容,便于用户操作。
pgNums.add("3");
+ // 添加省略号,表示中间省略了部分页码,因为总页数较多,全部展示会显得很冗长,通过省略号提示用户中间还有其他页码存在。
pgNums.add("...");
- if(page.getCurrent() == page.getPages()){
- pgNums.add(((Integer)(page.getCurrent() - 2)).toString());
- pgNums.add(((Integer)(page.getCurrent() - 1)).toString());
- pgNums.add(((Integer)page.getCurrent()).toString());
+
+ // 判断当前页码是否等于总页数,如果等于总页数,说明当前是最后一页,页码列表的生成逻辑稍有不同,
+ // 需要展示当前页(最后一页)及其前面紧邻的两页页码,方便用户查看临近的页面情况或者进行前后页跳转等操作。
+ if (page.getCurrent() == page.getPages()) {
+ pgNums.add(((Integer) (page.getCurrent() - 2)).toString());
+ pgNums.add(((Integer) (page.getCurrent() - 1)).toString());
+ pgNums.add(((Integer) page.getCurrent()).toString());
} else {
- pgNums.add(((Integer)(page.getCurrent() - 1)).toString());
- pgNums.add(((Integer)(page.getCurrent())).toString());
- pgNums.add(((Integer)(page.getCurrent() + 1)).toString());
+ // 如果当前页码不是总页数,说明在中间页面,此时展示当前页及其前后各一页的页码,方便用户在当前页附近进行页码跳转查看数据。
+ pgNums.add(((Integer) (page.getCurrent() - 1)).toString());
+ pgNums.add(((Integer) (page.getCurrent())).toString());
+ pgNums.add(((Integer) (page.getCurrent() + 1)).toString());
}
- }else{
+ } else {
+ // 如果总页数小于等于10,说明页码较少,可以完整地展示所有页码,通过循环依次将页码数字转换为字符串并添加到页码列表中,
+ // 方便前端展示所有可点击的页码,让用户能方便地在各页之间进行跳转查看数据。
Integer n = 1;
- if(page.getTotal() > 0){
- while(true){
+ if (page.getTotal() > 0) {
+ while (true) {
pgNums.add(n.toString());
- if(n >= page.getPages()){
+ if (n >= page.getPages()) {
break;
}
- n ++;
+ n++;
}
}
}
} else {
+ // 如果总页数等于1,同样通过循环添加唯一的页码(就是1)到页码列表中,虽然只有一页数据,但前端展示时也需要展示对应的页码信息,保持分页展示逻辑的一致性。
Integer n = 1;
- if(page.getTotal() > 0){
- while(true){
+ if (page.getTotal() > 0) {
+ while (true) {
pgNums.add(n.toString());
- if(n >= page.getPages()){
+ if (n >= page.getPages()) {
break;
}
- n ++;
+ n++;
}
}
}
+
+ // 将生成好的页码列表设置到PageUtils对象的pageNums属性中,以便前端可以获取并展示这个页码列表,实现分页导航栏中页码部分的展示功能。
pg.setPageNums(pgNums);
+
+ // 将Page对象中的当前页数据列表设置到PageUtils对象的list属性中,这些数据就是要展示给用户查看的具体内容,
+ // 前端可以根据这个属性获取数据并进行列表展示等操作,呈现当前页的详细数据信息。
pg.setList(page.getRecords());
- pg.setCurrPageNum(((Integer)page.getCurrent()));
- pg.setTotal(((Integer)page.getTotal()));
- pg.setTotalPage(((Integer)page.getPages()));
+
+ // 将Page对象中的当前页码赋值给PageUtils对象的currPageNum属性,用于前端展示当前所在页码以及在一些分页相关逻辑判断(如下一页、上一页按钮显示等)中作为依据。
+ pg.setCurrPageNum(((Integer) page.getCurrent()));
+
+ // 将Page对象中的总数据数量赋值给PageUtils对象的total属性,方便前端展示数据总量相关提示信息(如共多少条数据等),让用户对数据整体情况有直观了解。
+ pg.setTotal(((Integer) page.getTotal()));
+
+ // 将Page对象中的总页数赋值给PageUtils对象的totalPage属性,在前端分页展示逻辑中,例如判断是否显示上下页按钮、生成页码列表等操作时,会用到这个总页数信息,
+ // 确保分页相关的展示和操作符合实际的总页数情况。
+ pg.setTotalPage(((Integer) page.getPages()));
+
return pg;
}
+ // 以下是各个属性的Getter和Setter方法,用于获取和设置PageUtils对象的各个属性值,
+ // 遵循JavaBean的规范,方便在其他地方对PageUtils对象的属性进行访问和修改操作,例如在前端获取相关属性进行展示,或者在其他业务逻辑中根据需要设置属性值等情况。
public Boolean getIsShowNextBtn() {
return isShowNextBtn;
@@ -109,42 +162,34 @@ public class PageUtils {
this.list = list;
}
-
public Boolean getIsShowPreBtn() {
return isShowPreBtn;
}
-
public void setIsShowPreBtn(Boolean isShowPreBtn) {
this.isShowPreBtn = isShowPreBtn;
}
-
public Integer getCurrPageNum() {
return currPageNum;
}
-
public void setCurrPageNum(Integer currPageNum) {
this.currPageNum = currPageNum;
}
-
public Integer getTotalPage() {
return totalPage;
}
-
public void setTotalPage(Integer totalPage) {
this.totalPage = totalPage;
}
-
public Integer getTotal() {
return total;
}
-
public void setTotal(Integer total) {
this.total = total;
}
diff --git a/tamguo-tms/src/main/java/com/tamguo/utils/ShiroUtils.java b/tamguo-tms/src/main/java/com/tamguo/utils/ShiroUtils.java
index a31888d..2fabd6f 100644
--- a/tamguo-tms/src/main/java/com/tamguo/utils/ShiroUtils.java
+++ b/tamguo-tms/src/main/java/com/tamguo/utils/ShiroUtils.java
@@ -6,38 +6,91 @@ import org.apache.shiro.subject.Subject;
import com.tamguo.modules.member.model.MemberEntity;
+// 这个类是一个工具类,主要提供了一系列基于Apache Shiro框架的便捷方法,用于获取与当前用户相关的各种信息(如用户实体对象、用户ID等)、操作会话(设置和获取会话属性)以及判断用户登录状态、执行登出操作等,
+// 通过这些静态方法,可以在项目的不同地方方便地与Shiro框架进行交互,减少重复代码,使得对用户相关功能的处理更加简洁和统一。
public class ShiroUtils {
+ /**
+ * 获取当前用户的Shiro会话对象(Session)。
+ * 在Shiro框架中,会话(Session)用于在用户与服务器交互过程中保存用户相关的状态信息等,例如登录后的用户身份信息、一些临时的业务数据等,
+ * 通过调用SecurityUtils.getSubject()先获取当前的Subject对象(代表当前用户的安全主体),再调用其getSession()方法获取对应的会话对象,方便后续在会话中进行属性操作等。
+ *
+ * @return 返回当前用户的Shiro会话对象,供调用者在需要操作会话相关信息(如存储、获取会话中的属性值等)时使用。
+ */
public static Session getSession() {
return SecurityUtils.getSubject().getSession();
}
+ /**
+ * 获取当前的Subject对象,在Shiro框架中,Subject代表了当前与系统进行交互的“主体”,通常就是指当前登录的用户或者一个匿名的访问者(未登录时),
+ * 通过SecurityUtils.getSubject()方法可以获取到这个代表当前主体的对象,后续可以基于这个对象进行很多与用户安全相关的操作,比如获取用户身份信息、判断登录状态、执行认证授权相关操作等。
+ *
+ * @return 返回代表当前用户(或访问主体)的Subject对象,以便在其他地方基于这个对象进一步调用Shiro框架提供的各种方法来实现不同的功能。
+ */
public static Subject getSubject() {
return SecurityUtils.getSubject();
}
+ /**
+ * 获取当前登录用户对应的MemberEntity对象,在Shiro框架中,认证成功后会将代表用户的主体信息(通常是用户实体对象或者包含用户关键信息的对象)设置到Subject的Principal位置,
+ * 这里假设认证时将MemberEntity类型的用户对象设置为了Principal,通过调用SecurityUtils.getSubject().getPrincipal()获取到这个Principal对象,然后强制类型转换为MemberEntity类型返回,
+ * 从而获取到当前登录的会员用户的详细信息对象,方便在业务逻辑中使用会员的各种属性进行相关操作,比如获取会员的用户名、会员等级等信息。
+ *
+ * @return 返回当前登录用户对应的MemberEntity对象,如果当前用户未登录(即Principal为null),则会抛出ClassCastException异常,所以在调用该方法前通常需要先判断用户是否登录(可以使用isLogin方法判断)。
+ */
public static MemberEntity getMember() {
- return (MemberEntity)SecurityUtils.getSubject().getPrincipal();
+ return (MemberEntity) SecurityUtils.getSubject().getPrincipal();
}
+ /**
+ * 获取当前登录用户的唯一标识(ID),通过先调用getMember()方法获取到当前登录用户对应的MemberEntity对象,再调用其getId()方法获取用户的ID值,
+ * 这个ID可以用于在数据库查询、业务逻辑判断等场景中作为区分不同用户的关键依据,例如根据用户ID查询该用户的相关业务数据、判断权限等操作。
+ *
+ * @return 返回当前登录用户的ID值(以字符串形式),前提是用户已登录且MemberEntity对象中有对应的ID属性以及相应的getId()方法实现,否则可能出现空指针等异常情况(如果用户未登录,getMember方法会返回null),
+ * 所以在调用此方法前一般要先确保用户已登录(可结合isLogin方法进行判断)。
+ */
public static String getMemberId() {
return getMember().getId();
}
-
+
+ /**
+ * 在当前用户的Shiro会话中设置属性,通过先调用getSession()方法获取到当前用户的会话对象,然后调用其setAttribute方法将要存储的属性键(key)和对应的值(value)设置到会话中,
+ * 可以利用会话来临时保存一些与当前用户交互过程相关的数据,例如在一次业务操作流程中传递中间状态的数据、保存用户在某个页面的临时选择等信息,方便在后续的请求处理中获取使用。
+ *
+ * @param key 要设置的会话属性的键,通常是一个字符串或者其他可作为Map键的对象类型,用于唯一标识要存储的属性,方便后续通过相同的键来获取对应的属性值。
+ * @param value 要设置的会话属性的值,可以是任意类型的对象,它就是实际要存储到会话中的业务数据,后续通过对应的键可以获取到这个值进行相应的业务逻辑处理。
+ */
public static void setSessionAttribute(Object key, Object value) {
getSession().setAttribute(key, value);
}
+ /**
+ * 从当前用户的Shiro会话中获取指定键对应的属性值,先获取当前用户的会话对象(通过getSession方法),再调用其getAttribute方法并传入属性键(key),
+ * 可以获取到之前在会话中通过setSessionAttribute方法设置的对应属性值,方便在不同的请求处理阶段获取之前临时保存的与当前用户相关的数据,用于业务逻辑的延续和处理。
+ *
+ * @param key 要获取的会话属性的键,与设置属性时的键相对应,通过这个键来查找并获取之前存储在会话中的值,如果键不存在,会返回null,可根据业务需求进行相应的处理(如判断是否为null来决定后续操作)。
+ * @return 返回会话中指定键对应的属性值对象,如果不存在对应的属性(即键不存在),则返回null,由调用者根据返回值进行后续的业务逻辑判断和处理。
+ */
public static Object getSessionAttribute(Object key) {
return getSession().getAttribute(key);
}
+ /**
+ * 判断当前用户是否已经登录,通过获取当前用户的Subject对象,然后检查其Principal是否为null来确定用户是否登录,
+ * 如果Principal不为null,说明已经通过认证,有对应的用户主体信息存在,即用户已登录;如果Principal为null,则表示当前是匿名访问或者未进行认证操作,用户未登录。
+ * 这个方法可以在很多业务逻辑中用于前置判断,例如在需要用户登录后才能访问的功能模块入口处进行判断,根据返回值决定是否允许用户继续访问或者提示用户先登录等操作。
+ *
+ * @return 返回一个布尔值,如果用户已登录(即Subject的Principal不为null),返回true;如果用户未登录(Principal为null),则返回false,供调用者根据返回值进行相应的业务逻辑处理。
+ */
public static boolean isLogin() {
- return SecurityUtils.getSubject().getPrincipal() != null;
+ return SecurityUtils.getSubject().getPrincipal()!= null;
}
+ /**
+ * 执行用户登出操作,通过调用SecurityUtils.getSubject().logout()方法,通知Shiro框架清除当前用户的认证状态、会话信息等相关数据,
+ * 将用户的登录状态置为未登录,释放与登录相关的资源,例如清除会话中存储的临时数据、撤销权限缓存等操作,确保用户登出后系统的安全状态以及数据的一致性。
+ */
public static void logout() {
SecurityUtils.getSubject().logout();
}
-
-}
+}
\ No newline at end of file
diff --git a/tamguo-tms/src/main/java/com/tamguo/web/interceptor/MemberInterceptor.java b/tamguo-tms/src/main/java/com/tamguo/web/interceptor/MemberInterceptor.java
index 31bd248..a13ee47 100644
--- a/tamguo-tms/src/main/java/com/tamguo/web/interceptor/MemberInterceptor.java
+++ b/tamguo-tms/src/main/java/com/tamguo/web/interceptor/MemberInterceptor.java
@@ -8,53 +8,79 @@ import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
+// @Component注解用于将这个类标记为Spring框架中的一个组件,意味着Spring容器会在启动时扫描到这个类,并将其作为一个Bean进行管理,
+// 使其能够参与到Spring应用的依赖注入以及整个应用的请求处理流程中,在这里它作为一个拦截器,用于拦截特定路径下的请求并进行会员相关的验证逻辑处理。
@Component
-public class MemberInterceptor extends HandlerInterceptorAdapter{
+// 这个类继承自HandlerInterceptorAdapter类,HandlerInterceptorAdapter是Spring Web MVC中提供的一个用于方便实现拦截器功能的抽象类,
+// 通过重写其中的方法,可以在请求处理的不同阶段(如请求前、请求处理后、视图渲染后等)进行拦截并添加自定义的逻辑,这里主要重写了preHandle方法,用于在请求处理前进行会员登录状态的验证等操作。
+public class MemberInterceptor extends HandlerInterceptorAdapter {
- /** "重定向URL"参数名称 */
+ // 定义一个表示重定向URL参数名称的常量字符串,用于在重定向到登录页面时,将当前请求的URL作为参数传递过去,以便用户登录成功后可以回到原本要访问的页面,
+ // 在后续构建重定向URL的逻辑中会使用这个参数名称来添加对应的参数信息。
private static final String REDIRECT_URL_PARAMETER_NAME = "redirectUrl";
- /** 默认登录URL */
+ // 定义一个表示默认登录URL的常量字符串,初始化为"/login.html",如果没有通过配置文件指定具体的登录URL,就会使用这个默认值作为登录页面的路径,
+ // 在后续处理用户未登录需要重定向到登录页面的情况时,会参考这个默认值或者配置后的登录Url值来构建重定向的目标URL。
private static final String DEFAULT_LOGIN_URL = "/login.html";
- /** 登录URL */
+ // 用于存储登录URL的变量,初始化为默认登录URL(DEFAULT_LOGIN_URL),后续可以通过配置文件注入具体的值来覆盖默认值,
+ // 确定实际应用中用户登录页面的具体访问路径,以便在需要引导未登录用户去登录时,能够准确地重定向到正确的登录页面。
private String loginUrl = DEFAULT_LOGIN_URL;
-
+
+ // 通过@Value注解从配置文件(例如application.properties或application.yml等)中获取名为"member.domain.name"的属性值,并注入到memberDomainName变量中,
+ // 这个属性值通常表示会员相关模块所在的域名,在构建重定向到登录页面等相关的URL时会用到,用于确保重定向的URL是在正确的域名下,符合业务的域名配置要求。
@Value("${member.domain.name}")
private String memberDomainName;
-
+
/**
- * 请求前处理
- *
- * @param request
- * HttpServletRequest
- * @param response
- * HttpServletResponse
- * @param handler
- * 处理器
- * @return 是否继续执行
+ * 重写了父类HandlerInterceptorAdapter中的preHandle方法,该方法会在请求处理之前被调用,用于在请求进入实际的业务处理器之前进行拦截并执行一些前置验证逻辑,
+ * 在这里主要是验证用户是否登录(通过检查会话中是否存在"currMember"属性来判断),如果已登录则允许请求继续执行;如果未登录,则根据不同的请求情况(如是否是Ajax请求、请求方法是GET还是其他等)进行相应的重定向或错误响应处理,
+ * 以此实现对会员相关请求的登录验证功能,确保只有登录后的会员才能访问受保护的会员相关资源。
+ *
+ * @param request HttpServletRequest对象,它包含了客户端发送过来的请求相关的所有信息,如请求头、请求参数、请求路径等,
+ * 通过这个对象可以获取到判断用户登录状态所需的信息(如从会话中获取用户信息)以及构建重定向URL等操作时需要的请求相关数据。
+ * @param response HttpServletResponse对象,用于向客户端发送响应信息,在这个方法中根据不同的验证情况,通过这个对象可以进行重定向操作、设置响应头、发送错误响应等,告知客户端相应的处理结果,
+ * 例如将未登录的用户重定向到登录页面或者给Ajax请求返回禁止访问的提示信息等操作。
+ * @param handler 处理器对象,它代表了即将要处理当前请求的实际业务处理器(如某个Controller中的方法等),不过在这个方法中通常不需要直接操作这个对象,主要关注请求和响应的处理逻辑,
+ * 只有在决定是否允许请求继续执行时会间接影响到这个处理器是否会被调用(如果返回true则会调用,返回false则不会调用)。
+ * @return 返回一个布尔值,如果返回true,表示允许请求继续执行,会调用后续的业务处理器进行实际的请求处理;如果返回false,则表示拦截请求,不会调用业务处理器,直接结束当前请求的处理流程,
+ * 根据不同的业务逻辑判断情况来决定返回值,例如用户已登录就返回true,未登录且不符合其他条件时返回false等情况。
+ * @throws Exception 如果在处理过程中出现异常(如重定向过程中出现I/O异常等情况),会抛出相应的异常,Spring Web MVC框架会根据异常情况进行相应的处理,例如返回默认的错误页面等操作。
*/
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
- Object currMember = request.getSession().getAttribute("currMember");
- if (currMember != null) {
+ // 从HttpServletRequest对象的会话(Session)中获取名为"currMember"的属性值,通常假设在用户登录成功后,会将登录的会员相关信息(比如会员对象等)存储在这个会话属性中,
+ // 通过判断这个属性是否为null来确定用户是否已经登录,如果不为null,则说明用户已登录,允许请求继续执行,返回true。
+ Object currMember = request.getSession().getAttribute("currMember");
+ if (currMember!= null) {
return true;
} else {
+ // 获取请求头中名为"X-Requested-With"的字段值,这个字段常用于判断请求是否是Ajax请求(很多JavaScript框架在发送Ajax请求时会设置这个请求头),
+ // 如果该字段值不为null且等于"XMLHttpRequest"(不区分大小写),说明当前请求是Ajax请求,对于Ajax请求的处理逻辑与普通页面请求稍有不同,如下所述。
String requestType = request.getHeader("X-Requested-With");
- if (requestType != null && requestType.equalsIgnoreCase("XMLHttpRequest")) {
+ if (requestType!= null && requestType.equalsIgnoreCase("XMLHttpRequest")) {
+ // 如果是Ajax请求且用户未登录,向响应头中添加一个名为"loginStatus"的字段,值为"accessDenied",用于告知前端(JavaScript代码等)用户未登录,禁止访问,
+ // 然后通过response.sendError方法发送一个HTTP状态码为HttpServletResponse.SC_FORBIDDEN(即403状态码,表示禁止访问)的错误响应,
+ // 前端接收到这个响应后可以根据响应头中的信息以及状态码进行相应的提示或者处理(比如弹出提示框告知用户需要登录等操作),最后返回false,拦截该请求,不让其继续执行后续的业务处理器。
response.addHeader("loginStatus", "accessDenied");
response.sendError(HttpServletResponse.SC_FORBIDDEN);
return false;
} else {
+ // 如果不是Ajax请求,再根据请求的方法(如GET、POST等)进行不同的重定向处理,这里先判断请求方法是否是GET请求。
if (request.getMethod().equalsIgnoreCase("GET")) {
- String redirectUrl = request.getQueryString() != null ? request.getRequestURI() + "?" + request.getQueryString() : request.getRequestURI();
+ // 如果是GET请求,构建一个重定向的URL,用于将未登录的用户重定向到登录页面,并传递当前请求的URL作为参数(以便用户登录成功后能回到原本要访问的页面),具体构建逻辑如下:
+ // 首先判断请求中是否有查询字符串(即URL中?后面的部分),如果有,则将请求的完整路径(包括请求URI和查询字符串)作为重定向URL的一部分;
+ // 如果没有查询字符串,就只使用请求的URI作为重定向URL的一部分,然后通过URLEncoder将这个重定向URL进行UTF-8编码(防止中文等特殊字符出现编码问题),
+ // 最后将编码后的重定向URL作为参数(参数名为之前定义的REDIRECT_URL_PARAMETER_NAME)添加到登录URL后面,构建出完整的重定向URL,格式类似:memberDomainName + loginUrl + "?" + REDIRECT_URL_PARAMETER_NAME + "=" + 编码后的重定向URL。
+ String redirectUrl = request.getQueryString()!= null? request.getRequestURI() + "?" + request.getQueryString() : request.getRequestURI();
response.sendRedirect(memberDomainName + loginUrl + "?" + REDIRECT_URL_PARAMETER_NAME + "=" + URLEncoder.encode(redirectUrl, "UTF-8"));
} else {
+ // 如果请求方法不是GET请求(比如是POST等其他请求方法),则直接重定向到登录页面(不传递当前请求的URL作为参数了,因为非GET请求通常不适合这样处理,具体根据业务需求而定),
+ // 重定向的URL格式为memberDomainName + request.getContextPath() + loginUrl,其中request.getContextPath()获取的是当前应用在服务器上的上下文路径,确保重定向的登录URL是在正确的应用路径下。
response.sendRedirect(memberDomainName + request.getContextPath() + loginUrl);
}
return false;
}
}
}
-
-}
+}
\ No newline at end of file
diff --git a/tamguo-tms/src/main/java/com/tamguo/web/interceptor/MenuInterceptor.java b/tamguo-tms/src/main/java/com/tamguo/web/interceptor/MenuInterceptor.java
index b5f8660..34fd325 100644
--- a/tamguo-tms/src/main/java/com/tamguo/web/interceptor/MenuInterceptor.java
+++ b/tamguo-tms/src/main/java/com/tamguo/web/interceptor/MenuInterceptor.java
@@ -19,82 +19,149 @@ import com.tamguo.modules.tiku.service.IMenuService;
import com.tamguo.modules.tiku.service.IPaperService;
import com.tamguo.modules.tiku.service.ISchoolService;
-/**
- * 菜单拦截
- *
- */
+// @Component注解用于将这个类标记为Spring框架中的一个组件,意味着Spring容器会在启动时扫描到这个类,并将其作为一个Bean进行管理,
+// 使其能够参与到Spring应用的依赖注入以及整个Web应用的请求处理流程中,在这里它作为一个拦截器组件,用于拦截请求并处理与菜单相关的数据加载等操作。
@Component
+// 这个类实现了HandlerInterceptor接口,HandlerInterceptor接口用于在Spring Web MVC中定义拦截器,
+// 通过实现该接口的三个方法(preHandle、postHandle、afterCompletion),可以在请求处理的不同阶段(请求前、请求处理后但视图渲染前、整个请求结束后)进行拦截并执行自定义的逻辑,
+// 比如进行权限验证、数据准备、资源清理等操作,此处主要用于在请求处理过程中准备菜单相关以及其他页面展示需要的数据,并设置到请求属性中供视图渲染使用。
public class MenuInterceptor implements HandlerInterceptor {
-
+
+ // 通过@Resource注解进行依赖注入,将IMenuService接口的实现类实例注入到当前类中,IMenuService用于处理与菜单相关的业务逻辑,
+ // 例如查询不同类型的菜单数据(全部菜单、左侧菜单、底部菜单等),在后续的拦截器方法中会调用其相关方法来获取菜单数据并设置到请求属性中,方便视图渲染时展示菜单信息。
@Resource
private IMenuService iMenuService;
+
+ // 同样通过@Resource注解注入IPaperService接口的实现类实例,IPaperService用于处理与试卷相关的业务逻辑,
+ // 比如查询不同类型的试卷数据(历史试卷、模拟试卷、热门试卷等),后续会调用其方法获取试卷数据并设置到请求属性,供页面展示试卷相关内容使用。
@Resource
private IPaperService iPaperService;
+
+ // 使用@Resource注解注入ISchoolService接口的实现类实例,ISchoolService用于处理与学校相关的业务逻辑,
+ // 像查询名校试卷、名校列表等数据,在拦截器的业务逻辑中会利用它获取相应的数据并添加到请求属性里,便于在页面上展示学校相关信息。
@Resource
private ISchoolService iSchoolService;
+
+ // 通过@Resource注解注入IAdService接口的实现类实例,IAdService用于处理与广告相关的业务逻辑,
+ // 在这里用于获取所有广告数据,然后将广告数据设置到请求属性中,使得页面能够展示相应的广告内容,实现广告投放等功能。
@Resource
private IAdService iAdService;
- @Override
- public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
- throws Exception {
- //在请求处理之前进行调用(Controller方法调用之前)
- return true;
- }
-
- @Override
- public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
- ModelAndView modelAndView) throws Exception {
- //请求处理之后进行调用,但是在视图被渲染之前(Controller方法调用之后)
- List result = iMenuService.findMenus();
- request.setAttribute("menuList", result);
-
- // 获取全部菜单
- List allMenuList = iMenuService.findAllMenus();
- request.setAttribute("allMenuList", allMenuList);
-
- // 获取左侧菜单
- List leftMenuList = iMenuService.findLeftMenus();
- request.setAttribute("leftMenuList", leftMenuList);
-
- // 获取底部菜单
- List footerMenuList = iMenuService.findFooterMenus();
- request.setAttribute("footerMenuList", footerMenuList);
-
- // 获取首页专区
- List chapterMenuList = iMenuService.findChapterMenus();
- request.setAttribute("chapterMenuList", chapterMenuList);
-
- // 获取首页历年真题试卷
- List historyPaperList = iPaperService.findHistoryPaper();
- request.setAttribute("historyPaperList", historyPaperList);
-
- // 获取首页模拟试卷
- List simulationPaperList = iPaperService.findSimulationPaper();
- request.setAttribute("simulationPaperList", simulationPaperList);
-
- // 获取热门试卷
- List hotPaperList = iPaperService.findHotPaper(SystemConstant.BEIJING_AREA_ID);
- request.setAttribute("hotPaperList", hotPaperList);
-
- // 获取首页名校试卷
- List eliteSchoolPaperList = iSchoolService.findEliteSchoolPaper(SystemConstant.BEIJING_AREA_ID);
- request.setAttribute("eliteSchoolPaperList", eliteSchoolPaperList);
-
- // 获取首页名校列表
- List eliteSchoolList = iSchoolService.findEliteSchool();
- request.setAttribute("eliteSchoolList", eliteSchoolList);
-
- // 获取所有广告
- List adList = iAdService.findAll();
- request.setAttribute("adList", adList);
-
- }
-
- @Override
- public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
- throws Exception {
- //在整个请求结束之后被调用,也就是在DispatcherServlet 渲染了对应的视图之后执行(主要是用于进行资源清理工作)
- }
+ /**
+ * 这个方法是HandlerInterceptor接口中的一个方法,会在请求处理之前被调用(在具体的Controller方法被调用之前),
+ * 可以在这里进行一些前置的验证、权限判断等操作,决定是否允许请求继续执行下去。当前实现直接返回true,表示允许所有请求继续执行,
+ * 如果有特定的前置验证逻辑(比如判断用户是否登录、是否有访问权限等),可以在这里添加相应的代码进行判断,根据判断结果返回true或者false来控制请求流程。
+ *
+ * @param request HttpServletRequest对象,它包含了客户端发送过来的请求相关的所有信息,如请求头、请求参数、请求路径等,
+ * 通过这个对象可以获取到进行前置验证等操作所需的信息,例如获取用户的登录凭证等信息来判断权限情况。
+ * @param response HttpServletResponse对象,用于向客户端发送响应信息,虽然在这个方法中通常不需要直接操作它进行响应相关的操作,但在后续根据验证结果决定是否允许请求继续执行时,
+ * 可以通过它来发送相应的错误响应等信息(比如返回403禁止访问等状态码及对应提示信息)给客户端。
+ * @param handler 处理器对象,它代表了即将要处理当前请求的实际业务处理器(如某个Controller中的方法等),不过在这个方法中通常不需要直接操作这个对象,主要关注请求是否允许继续执行的判断逻辑,
+ * 如果返回true,则后续会调用这个处理器进行实际的请求处理;如果返回false,则直接拦截请求,不会调用该处理器。
+ * @return 返回一个布尔值,如果返回true,表示允许请求继续执行,会调用后续的业务处理器进行实际的请求处理;如果返回false,则表示拦截请求,不会调用业务处理器,直接结束当前请求的处理流程。
+ * @throws Exception 如果在处理过程中出现异常(比如在获取验证相关数据时出现数据库连接异常等情况),会抛出相应的异常,Spring Web MVC框架会根据异常情况进行相应的处理,例如返回默认的错误页面等操作。
+ */
+ @Override
+ public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
+ throws Exception {
+ //在请求处理之前进行调用(Controller方法调用之前)
+ return true;
+ }
+
+ /**
+ * 这个方法是HandlerInterceptor接口中的一个方法,会在请求处理之后、视图被渲染之前被调用(也就是在Controller方法执行完之后,但在返回的视图进行渲染展示给客户端之前),
+ * 可以在这里对请求处理后的结果进行一些补充操作,比如向请求属性中添加一些额外的数据,方便视图渲染时使用这些数据来展示更丰富的页面内容,
+ * 在这里主要是从各个业务服务层(通过注入的相关服务实例)获取不同类型的数据(菜单数据、试卷数据、学校数据、广告数据等),然后将这些数据设置到请求属性中,使得视图能够获取并展示这些信息。
+ *
+ * @param request HttpServletRequest对象,通过它可以获取请求相关的信息以及设置请求属性,在这里主要是利用它来设置各种数据到请求属性中,方便后续视图渲染时使用这些数据进行页面展示。
+ * @param response HttpServletResponse对象,一般在这个阶段如果需要根据请求处理结果对响应进行一些调整(比如设置响应头、添加额外的响应信息等)可以操作这个对象,不过当前代码中暂未涉及这方面操作,主要侧重于设置请求属性的操作。
+ * @param handler 处理器对象,代表了刚刚执行完的业务处理器(Controller方法等),在这里通常不需要对其进行直接操作,重点在于对请求属性的设置以及和视图渲染相关的数据准备工作。
+ * @param modelAndView ModelAndView对象,它是Spring Web MVC中用于传递数据到视图以及指定视图名称等的一个对象,虽然在这里可以通过它来操作视图相关的数据和名称等信息,
+ * 但当前代码主要是通过设置请求属性的方式来传递数据,所以并没有直接对这个对象进行过多操作,不过在一些其他场景下可以利用它来更灵活地控制视图渲染相关的内容。
+ * @throws Exception 如果在获取数据或者设置请求属性等过程中出现异常(比如数据库查询异常、设置属性时出现类型不匹配等异常情况),会抛出相应的异常,Spring Web MVC框架会根据异常情况进行相应的处理,例如返回错误页面等操作。
+ */
+ @Override
+ public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
+ ModelAndView modelAndView) throws Exception {
+ //请求处理之后进行调用,但是在视图被渲染之前(Controller方法调用之后)
+
+ // 调用iMenuService的findMenus方法,从数据库等数据源中查询出需要展示的菜单数据(具体查询逻辑由IMenuService的实现类决定),
+ // 将查询到的菜单数据(以List形式返回)设置到请求的属性中,属性名为"menuList",这样在视图(如JSP、Thymeleaf等模板页面)中就可以通过这个属性名获取到菜单数据进行展示,
+ // 例如在页面上循环展示菜单列表等操作,方便用户进行页面导航等功能。
+ List result = iMenuService.findMenus();
+ request.setAttribute("menuList", result);
+
+ // 调用iMenuService的findAllMenus方法,获取全部的菜单数据(与上面的findMenus方法可能查询条件等有所不同,这里是获取所有菜单信息),
+ // 将查询到的全部菜单数据以List形式设置到请求的属性中,属性名为"allMenuList",便于在页面上根据不同需求展示全部菜单内容,比如用于管理后台查看所有菜单情况等操作。
+ List allMenuList = iMenuService.findAllMenus();
+ request.setAttribute("allMenuList", allMenuList);
+
+ // 调用iMenuService的findLeftMenus方法,查询出要展示在页面左侧的菜单数据(通常是用于构建页面左侧导航栏等功能的菜单列表),
+ // 把查询到的左侧菜单数据以List形式添加到请求属性中,属性名为"leftMenuList",使得页面在渲染左侧导航栏时能够获取并展示这些菜单信息,方便用户进行页面操作和导航。
+ List leftMenuList = iMenuService.findLeftMenus();
+ request.setAttribute("leftMenuList", leftMenuList);
+
+ // 调用iMenuService的findFooterMenus方法,获取要展示在页面底部的菜单数据(用于构建页面底部的菜单部分,比如一些友情链接、版权信息等相关的菜单展示),
+ // 将获取到的底部菜单数据以List形式设置到请求属性中,属性名为"footerMenuList",以便页面在渲染底部部分时能够展示这些菜单内容,完善页面的整体布局和功能。
+ List footerMenuList = iMenuService.findFooterMenus();
+ request.setAttribute("footerMenuList", footerMenuList);
+
+ // 调用iMenuService的findChapterMenus方法,查询出用于首页专区展示的菜单数据(可能是首页中某个特定区域的菜单,具体功能和展示形式由业务需求决定),
+ // 将查询到的这些菜单数据以List形式添加到请求属性中,属性名为"chapterMenuList",使得首页在渲染对应专区时能够获取并展示这些菜单信息,丰富首页的展示内容和功能。
+ List chapterMenuList = iMenuService.findChapterMenus();
+ request.setAttribute("chapterMenuList", chapterMenuList);
+
+ // 调用iPaperService的findHistoryPaper方法,从数据库等数据源中查询出首页要展示的历年真题试卷数据(具体的查询逻辑根据业务中对历年真题试卷的定义和筛选条件而定),
+ // 将查询到的历年真题试卷数据(以List形式返回)设置到请求属性中,属性名为"historyPaperList",方便首页在展示试卷相关内容时获取并渲染这些真题试卷信息,供用户查看和选择。
+ List historyPaperList = iPaperService.findHistoryPaper();
+ request.setAttribute("historyPaperList", historyPaperList);
+
+ // 调用iPaperService的findSimulationPaper方法,获取首页要展示的模拟试卷数据(同样根据业务对模拟试卷的定义和筛选条件进行查询),
+ // 将查询到的模拟试卷数据以List形式设置到请求属性中,属性名为"simulationPaperList",使得首页能够展示模拟试卷相关内容,满足用户查看和练习模拟试卷的需求。
+ List simulationPaperList = iPaperService.findSimulationPaper();
+ request.setAttribute("simulationPaperList", simulationPaperList);
+
+ // 调用iPaperService的findHotPaper方法,传入SystemConstant.BEIJING_AREA_ID(可能是表示北京地区的一个常量标识,具体由业务中SystemConstant类定义),
+ // 查询出对应地区(这里是北京地区)的热门试卷数据(根据业务规则确定热门试卷的筛选条件等),将查询到的热门试卷数据以List形式设置到请求属性中,属性名为"hotPaperList",
+ // 方便在页面上展示热门试卷相关内容,吸引用户关注和选择相应的试卷进行练习等操作。
+ List hotPaperList = iPaperService.findHotPaper(SystemConstant.BEIJING_AREA_ID);
+ request.setAttribute("hotPaperList", hotPaperList);
+
+ // 调用iSchoolService的findEliteSchoolPaper方法,传入SystemConstant.BEIJING_AREA_ID,查询出北京地区的名校试卷数据(按照业务中对名校试卷的定义和筛选条件进行查询),
+ // 将查询到的名校试卷数据(以List形式返回,这里可能SchoolEntity中包含了名校以及对应的试卷相关信息,具体由业务实体类定义决定)设置到请求属性中,属性名为"eliteSchoolPaperList",
+ // 以便在首页等页面展示名校试卷相关内容,体现名校特色试卷,供用户查看和选择练习。
+ List eliteSchoolPaperList = iSchoolService.findEliteSchoolPaper(SystemConstant.BEIJING_AREA_ID);
+ request.setAttribute("eliteSchoolPaperList", eliteSchoolPaperList);
+
+ // 调用iSchoolService的findEliteSchool方法,查询出所有的名校列表数据(根据业务中对名校的定义和筛选条件从数据库等数据源获取),
+ // 将查询到的名校列表数据以List形式设置到请求属性中,属性名为"eliteSchoolList",方便在页面上展示名校相关信息,比如在选择学校的下拉框、名校推荐列表等地方展示这些名校信息。
+ List eliteSchoolList = iSchoolService.findEliteSchool();
+ request.setAttribute("eliteSchoolList", eliteSchoolList);
+
+ // 调用iAdService的findAll方法,获取所有的广告数据(具体的广告数据来源和查询逻辑由IAdService的实现类决定),
+ // 将获取到的广告数据以List形式设置到请求属性中,属性名为"adList",使得页面能够展示相应的广告内容,实现广告投放功能,提升业务宣传等效果。
+ List adList = iAdService.findAll();
+ request.setAttribute("adList", adList);
+
+ }
+ /**
+ * 这个方法是HandlerInterceptor接口中的一个方法,会在整个请求结束之后被调用,也就是在DispatcherServlet渲染了对应的视图之后执行,
+ * 主要用于进行一些资源清理工作,比如关闭数据库连接、释放一些占用的资源等操作,不过当前代码中并没有具体的资源清理相关逻辑实现,只是保留了这个方法的空实现,
+ * 如果后续有相关的资源管理需求,可以在这里添加相应的代码来进行资源清理操作,确保系统资源的合理利用和性能优化。
+ *
+ * @param request HttpServletRequest对象,虽然在这个阶段请求相关的处理基本都已完成,但通过这个对象可以获取一些请求相关的上下文信息,不过当前代码暂未利用它进行操作,
+ * 如果有需要根据请求情况进行资源清理等操作时可以考虑使用这个对象获取相关信息辅助操作。
+ * @param response HttpServletResponse对象,同样在这个阶段响应相关的操作也基本结束了,但如果有针对响应相关的资源清理(比如关闭响应相关的一些流等情况,不过比较少见)可以操作这个对象,
+ * 当前代码也没有涉及这方面操作,只是保留了这个参数位置。
+ * @param handler 处理器对象,代表了整个请求处理过程中涉及的业务处理器,在这里通常不需要对其进行直接操作,重点在于资源清理方面的操作,不过当前代码没有具体的清理逻辑实现,所以暂未涉及对这个对象的使用。
+ * @param ex Exception对象,表示在整个请求处理过程中出现的异常情况,如果在前面的处理阶段(如preHandle、postHandle或者Controller方法执行过程中)出现了异常,会将异常对象传递到这里,
+ * 可以在这里根据异常情况进行一些额外的处理(比如记录异常日志、进行一些补偿操作等),不过当前代码也没有这方面的具体实现,只是保留了这个参数接收异常情况。
+ * @throws Exception 如果在进行资源清理或者根据异常情况进行额外处理等操作过程中又出现了新的异常,会再次抛出相应的异常,Spring Web MVC框架会根据最终的异常情况进行相应的处理,例如返回错误页面等操作。
+ */
+ @Override
+ public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
+ throws Exception {
+ //在整个请求结束之后被调用,也就是在DispatcherServlet 渲染了对应的视图之后执行(主要是用于进行资源清理工作)
+ }
}
\ No newline at end of file
diff --git a/tamguo-tms/src/main/java/com/tamguo/web/member/AccountController.java b/tamguo-tms/src/main/java/com/tamguo/web/member/AccountController.java
index e4bfdd2..32f4962 100644
--- a/tamguo-tms/src/main/java/com/tamguo/web/member/AccountController.java
+++ b/tamguo-tms/src/main/java/com/tamguo/web/member/AccountController.java
@@ -34,116 +34,203 @@ import com.tamguo.modules.member.model.MemberEntity;
import com.tamguo.modules.member.service.IMemberService;
import com.tamguo.utils.ShiroUtils;
+// @Controller注解用于将这个类标记为Spring MVC框架中的一个控制器组件,意味着Spring容器会在启动时扫描到这个类,并将其管理起来,
+// 使得这个类中的方法能够处理对应的HTTP请求,根据请求的映射关系(通过@RequestMapping等注解定义)调用相应的业务逻辑方法,然后返回视图或者数据响应给客户端。
@Controller
public class AccountController {
-
+
+ // 通过@Autowired注解自动注入IMemberService接口的实现类实例,IMemberService用于处理与会员相关的各种业务逻辑,
+ // 比如查询会员信息、更新会员信息、修改会员密码等操作,在这个控制器的多个方法中会调用其相关方法来实现具体的会员业务功能。
@Autowired
public IMemberService memberService;
+
+ // 通过@Value注解从配置文件(例如application.properties或application.yml等)中获取名为"file.storage.path"的属性值,并注入到fileStoragePath变量中,
+ // 这个属性值通常表示文件存储的路径,在文件上传相关的业务逻辑中会用到,用于确定上传文件在服务器端实际保存的位置。
@Value("${file.storage.path}")
private String fileStoragePath;
+
+ // 同样使用@Value注解从配置文件中获取名为"domain.name"的属性值,注入到domainName变量中,
+ // 该属性值一般是域名相关的配置,在文件上传成功后返回文件的访问路径等场景中会用到,用于构建完整的文件访问URL,使得客户端能够通过正确的域名访问到上传的文件。
@Value("${domain.name}")
private String domainName;
+
+ // 通过@Autowired注解注入CacheService实例,CacheService应该是用于与缓存相关的操作(比如操作Redis缓存等),
+ // 在生成头像编号等逻辑中会使用它来对某个缓存键进行自增操作,以此来生成唯一的头像编号,确保头像文件命名的唯一性等情况。
@Autowired
private CacheService cacheService;
+ // 定义一个表示头像编号的无格式字符串常量,这里格式为"00000",用于在格式化生成头像编号时作为一种占位格式,
+ // 通过结合日期信息以及自增的序号等内容,生成具有特定格式的头像编号,方便对会员头像文件进行命名管理等操作。
private static final String AVATOR_NO_FORMAT = "00000";
+
+ // 定义一个头像文件名称的前缀常量,设置为"MTX",在生成头像文件完整名称时,会将这个前缀添加到前面,再结合日期、自增序号等信息,组成完整的头像文件名,便于识别和管理头像文件。
private static final String AVATOR_PREFIX = "MTX";
-
+
+ // 创建一个Logger对象,用于记录日志信息,通过LoggerFactory获取与当前类对应的Logger实例,
+ // 在代码的关键位置(如文件上传成功或出现异常等情况)可以使用这个Logger记录相应的日志,方便后续查看系统运行情况、排查问题等操作。
public Logger logger = LoggerFactory.getLogger(getClass());
+ /**
+ * 处理会员账户页面的GET请求,用于展示会员账户相关信息。
+ * 通过ModelAndView对象设置要返回的视图名称,并从会话(HttpSession)中获取当前登录会员的信息,再通过memberService查询更详细的会员信息,添加到ModelAndView对象中,
+ * 最终返回ModelAndView对象,Spring MVC框架会根据视图名称渲染对应的视图页面,并将添加的数据传递给视图进行展示,实现会员账户信息在页面上的呈现。
+ *
+ * @param model ModelAndView对象,用于设置视图名称以及向视图传递数据,在这里设置视图名称为"member/account",表示要返回的是位于"member"目录下的"account"视图页面,
+ * 同时可以通过其addObject方法向视图传递数据,方便在视图中展示会员相关信息等内容。
+ * @param session HttpSession对象,用于获取当前用户的会话信息,在这里主要是从会话中获取名为"currMember"的属性值(通常是登录会员的基本信息对象),作为后续查询详细会员信息的依据。
+ * @return 返回配置好视图名称和会员信息数据的ModelAndView对象,供Spring MVC框架进行视图渲染并展示会员账户页面内容给客户端。
+ */
@RequestMapping(value = "member/account.html", method = RequestMethod.GET)
- public ModelAndView index(ModelAndView model , HttpSession session){
+ public ModelAndView index(ModelAndView model, HttpSession session) {
model.setViewName("member/account");
MemberEntity member = (MemberEntity) session.getAttribute("currMember");
- model.addObject("member" , memberService.findByUid(member.getId()));
+ model.addObject("member", memberService.findByUid(member.getId()));
return model;
}
-
+
+ /**
+ * 处理会员信息更新的POST请求,用于接收前端传来的更新后的会员信息(以JSON格式通过请求体传递,通过@RequestBody注解解析为MemberEntity对象),
+ * 先设置会员的ID(通过ShiroUtils获取当前登录会员的ID),然后调用memberService的updateMember方法将更新后的会员信息保存到数据库等数据源中,
+ * 最后返回一个表示成功的Result对象(包含更新后的会员信息)给前端,告知前端会员信息更新成功以及更新后的具体数据情况,方便前端进行相应的提示和后续处理。
+ *
+ * @param member MemberEntity对象,通过@RequestBody注解从请求体中解析得到的包含更新后会员信息的对象,其属性值由前端传递过来的JSON数据填充,
+ * 在方法中会进一步完善其ID属性并传递给服务层进行更新操作。
+ * @return 返回一个Result对象,通过Result.successResult方法创建,表示会员信息更新成功,并携带更新后的会员信息,供前端根据返回结果进行相应的提示和页面数据更新等操作。
+ */
@RequestMapping(value = "member/account/update.html", method = RequestMethod.POST)
@ResponseBody
- public Result updateMember(@RequestBody MemberEntity member){
+ public Result updateMember(@RequestBody MemberEntity member) {
member.setId(ShiroUtils.getMemberId());
memberService.updateMember(member);
return Result.successResult(member);
}
-
+
+ /**
+ * 处理会员修改密码页面的GET请求,主要用于设置要返回的视图名称,使得Spring MVC框架能够渲染对应的修改密码页面展示给客户端,
+ * 在这里只是简单地将视图名称设置为"member/password",表示返回位于"member"目录下的"password"视图页面,供用户进行密码修改相关的操作。
+ *
+ * @param model ModelAndView对象,用于设置视图名称,在这里将视图名称设置为"member/password",指定要返回的页面视图,方便Spring MVC框架进行后续的视图渲染操作。
+ * @return 返回配置好视图名称的ModelAndView对象,供Spring MVC框架根据视图名称渲染并展示会员修改密码页面给客户端。
+ */
@RequestMapping(value = "member/password.html", method = RequestMethod.GET)
- public ModelAndView password(ModelAndView model){
+ public ModelAndView password(ModelAndView model) {
model.setViewName("member/password");
return model;
}
-
+
+ /**
+ * 处理会员修改密码的POST请求,接收前端传来的包含新密码等信息的会员对象(以JSON格式通过请求体传递,通过@RequestBody注解解析为MemberEntity对象),
+ * 先设置会员的ID(通过ShiroUtils获取当前登录会员的ID),然后调用memberService的updatePwd方法进行密码修改相关的业务逻辑处理(比如验证旧密码、更新密码到数据库等操作),
+ * 最后将memberService方法返回的Result对象直接返回给前端,Result对象中包含了密码修改是否成功等相关信息,供前端根据返回结果进行相应的提示和后续处理。
+ *
+ * @param member MemberEntity对象,通过@RequestBody注解从请求体中解析得到的包含会员密码修改相关信息的对象,其属性值由前端传递过来的JSON数据填充,
+ * 在方法中会完善其ID属性后传递给服务层进行密码修改操作。
+ * @return 返回memberService.updatePwd方法返回的Result对象,该对象包含了密码修改的结果信息(如是否成功、相关提示信息等),供前端根据结果进行相应的处理,比如提示用户密码修改成功或失败等情况。
+ */
@RequestMapping(value = "member/password/update.html", method = RequestMethod.POST)
@ResponseBody
- public Result updatePwd(@RequestBody MemberEntity member){
+ public Result updatePwd(@RequestBody MemberEntity member) {
member.setId(ShiroUtils.getMemberId());
return memberService.updatePwd(member);
}
-
+
+ /**
+ * 处理会员上传文件的POST请求,用于接收前端上传的文件(通过@RequestParam注解指定接收名为"file"的文件参数,类型为MultipartFile),
+ * 如果文件不为空,则进行文件保存相关的操作,包括创建文件存储目录、生成文件名、将文件流写入到服务器磁盘文件中,成功后返回一个包含文件上传成功信息及文件访问路径等内容的UploaderMessage对象给前端;
+ * 如果文件为空,则返回一个表示文件为空的错误信息的UploaderMessage对象给前端,告知前端文件上传失败的原因,整个过程通过日志记录关键操作信息以及进行输入输出流的正确关闭等资源管理操作。
+ *
+ * @param file MultipartFile类型的文件对象,通过@RequestParam注解从请求中获取前端上传的文件,包含了文件的内容、原始文件名等信息,用于后续的文件保存等操作。
+ * @param request HttpServletRequest对象,包含了请求相关的所有信息,在这里虽然当前代码没有直接利用它进行过多操作,但在一些扩展场景下(比如获取请求的一些其他参数、上下文信息等)可以使用这个对象,
+ * 例如根据请求中的某些参数来决定文件存储的一些额外规则等情况(不过当前代码暂未涉及这些)。
+ * @return 返回一个UploaderMessage对象,根据文件上传的情况(成功或失败以及相应的原因)设置对象的属性,包含了文件上传状态、提示信息、文件访问路径、文件所在域名等内容,供前端根据返回结果进行相应的提示和后续处理,
+ * 比如在页面上提示用户文件上传成功并展示文件访问链接,或者提示文件上传失败及失败原因等情况。
+ * @throws IOException 如果在文件流操作(如读取文件流、写入文件到磁盘等过程)中出现I/O异常情况,会抛出该异常,Spring MVC框架会根据异常情况进行相应的处理,例如返回默认的错误页面等操作。
+ */
@RequestMapping(value = "/member/uploadFile.html", method = RequestMethod.POST)
@ResponseBody
- public UploaderMessage uploadFileHandler(@RequestParam("file") MultipartFile file,HttpServletRequest request) throws IOException {
+ public UploaderMessage uploadFileHandler(@RequestParam("file") MultipartFile file, HttpServletRequest request) throws IOException {
+ // 判断上传的文件是否为空,如果不为空,说明有文件需要进行上传保存操作,进入后续的文件保存逻辑;如果为空,则直接返回表示文件为空的错误信息的UploaderMessage对象给前端。
if (!file.isEmpty()) {
InputStream in = null;
OutputStream out = null;
-
+
try {
+ // 根据文件存储路径(fileStoragePath)和当前日期(格式化为"yyyyMMdd")构建文件存储的完整目录路径,例如:fileStoragePath可能是"/data/uploads/",结合日期后可能就是"/data/uploads/20241215",
+ // 这样可以按照日期对上传文件进行分类存储,方便管理和查找文件。
String path = fileStoragePath + DateUtils.format(new Date(), "yyyyMMdd");
File dir = new File(path);
+ // 判断文件存储目录是否存在,如果不存在,则通过mkdirs方法创建多级目录(确保父目录不存在时也能创建成功),保证后续能够将文件保存到正确的目录下。
if (!dir.exists()) {
dir.mkdirs();
}
+
+ // 调用getAvatorNo方法生成一个头像编号(文件名的一部分),结合文件的原始文件名(获取后缀名部分)组成完整的头像文件名,例如生成的头像编号可能是"MTX20241200001",
+ // 如果原始文件名为"avatar.jpg",则最终的文件名就是"MTX20241200001.jpg",以此来保证文件名的唯一性以及便于识别和管理头像文件等情况。
String avatorName = this.getAvatorNo() + file.getOriginalFilename().substring(file.getOriginalFilename().lastIndexOf("."));
+
+ // 获取上传文件的输入流,用于后续读取文件内容并写入到服务器磁盘文件中,准备进行文件内容的复制操作。
in = file.getInputStream();
+ // 创建一个指向服务器磁盘文件的输出流,通过构建的文件存储路径和文件名确定要写入的目标文件位置,例如"/data/uploads/20241215/MTX20241200001.jpg",
+ // 使得后续可以将上传文件的内容通过输出流写入到这个目标文件中,完成文件的保存操作。
out = new FileOutputStream(path + "/" + avatorName);
+
+ // 创建一个字节数组作为缓冲区,大小为1024字节,用于在读取文件流和写入文件到磁盘过程中,以一定的缓冲区大小进行数据传输,提高文件读写效率,避免一次性读取或写入大量数据导致内存占用过大等问题。
byte[] b = new byte[1024];
int len = 0;
+ // 通过循环,不断从输入流中读取数据到缓冲区(每次最多读取缓冲区大小的数据量),直到读取到文件末尾(即read方法返回 -1),
+ // 然后将缓冲区中的数据通过输出流写入到服务器磁盘文件中,实现文件内容的完整复制,完成文件上传保存操作。
while ((len = in.read(b)) > 0) {
out.write(b, 0, len);
}
+
+ // 关闭输出流,释放相关的资源,确保文件写入操作完成后正确关闭流,避免资源泄露等问题,虽然在try-with-resources语句块中可以自动关闭流,但这里按照传统的方式先手动关闭,确保操作的准确性。
out.close();
+ // 关闭输入流,同样是为了释放资源,完成文件读取操作后的资源清理工作,保证整个文件上传过程中资源的合理使用和正确管理。
in.close();
+
+ // 使用Logger记录文件在服务器端保存的完整位置信息,方便后续查看文件存储情况、排查文件相关问题等操作,例如在出现文件丢失、访问异常等情况时可以通过日志查看文件实际保存的位置是否正确等信息。
logger.info("Server File Location=" + path + avatorName);
+ // 创建一个UploaderMessage对象,用于封装文件上传成功的相关信息,准备返回给前端告知文件上传成功以及提供文件的访问路径等信息,方便前端进行相应的提示和后续处理。
UploaderMessage msg = new UploaderMessage();
msg.setStatus(Status.SUCCESS);
msg.setStatusMsg("File upload success");
+ // 设置文件的访问路径,通过构建相对路径(以"/files/"开头,结合日期和文件名)的方式,方便前端根据域名(后续通过设置的fileDomain属性告知前端域名信息)来构建完整的文件访问URL,
+ // 例如前端可以根据返回的fileDomain(如"www.example.com")和filePath(如"/files/20241215/MTX20241200001.jpg")拼接出完整的文件访问链接"http://www.example.com/files/20241215/MTX20241200001.jpg"。
msg.setFilePath("/files/" + DateUtils.format(new Date(), "yyyyMMdd") + "/" + avatorName);
msg.setFileDomain(domainName);
return msg;
} catch (Exception e) {
+ // 如果在文件上传保存过程中出现异常(比如创建目录失败、文件流读写异常等情况),创建一个UploaderMessage对象,设置其状态为表示错误的Status.ERROR,
+ // 并设置错误信息为"File upload file"(这里可能是代码笔误,应该是更具体准确的错误描述会更好,不过当前就是简单设置这个通用的错误提示),然后将这个表示错误信息的对象返回给前端,告知前端文件上传失败及原因。
UploaderMessage msg = new UploaderMessage();
msg.setStatus(Status.ERROR);
msg.setError("File upload file");
return msg;
- } finally {
- if (out != null) {
- out.close();
- out = null;
- }
- if (in != null) {
- in.close();
- in = null;
+ private String getAvatorNo() {
+ // 创建一个SimpleDateFormat对象,用于将日期格式化为指定的格式,这里指定的格式是"yyyyMM",即按照四位年份和两位月份的形式来格式化日期,
+ // 例如当前日期是2024年12月,格式化后得到的字符串就是"202412",后续会基于这个格式化后的日期字符串来生成头像编号,以便在一定程度上通过日期来区分不同时间段生成的头像文件等情况。
+ SimpleDateFormat sdf = new SimpleDateFormat("yyyyMM");
+ // 使用创建好的SimpleDateFormat对象对当前日期(通过new Date()获取当前系统时间对应的Date对象)进行格式化操作,得到一个表示当前年月的字符串,
+ // 并将这个格式化后的字符串赋值给format变量,用于后续构建缓存键以及生成头像编号的相关操作,它体现了时间维度上的标识信息,方便对头像文件进行归类和管理等操作。
+ String format = sdf.format(new Date());
+
+ // 创建一个DecimalFormat对象,使用之前定义的常量AVATOR_NO_FORMAT(值为"00000")作为格式化模式,
+ // 这个DecimalFormat对象主要用于将后续生成的自增序号(数字类型)按照指定的格式进行格式化,例如将数字1格式化为"00001",保证生成的头像编号在格式上的一致性和规范性,便于识别和管理。
+ DecimalFormat df = new DecimalFormat(AVATOR_NO_FORMAT);
+
+ // 构建一个缓存键(key)字符串,通过将常量AVATOR_PREFIX(值为"MTX")和前面格式化得到的表示年月的format字符串进行拼接,
+ // 例如拼接后得到的字符串可能是"MTX202412",这个缓存键会用于在缓存中进行相关操作(这里主要是对其对应的值进行自增操作,用于生成头像编号的序号部分),通过缓存可以方便地在不同请求间对头像编号进行统一管理和递增生成,避免重复等问题。
+ String key = AVATOR_PREFIX + format;
+
+ // 调用cacheService的incr方法,传入前面构建的缓存键(key),这个incr方法应该是用于对缓存中指定键对应的值进行自增操作(假设底层使用的是类似Redis等支持自增操作的缓存实现),
+ // 例如第一次调用时,如果缓存中该键不存在,会初始化为0然后自增为1,后续每次调用都会在之前的值基础上自增1,返回自增后的结果(以Long类型返回),这个结果就作为头像编号中的序号部分,用于区分同一时间段内不同的头像文件。
+ Long incr = cacheService.incr(key);
+
+ // 使用之前创建的DecimalFormat对象(df)对自增后的序号(incr)进行格式化操作,将其格式化为符合要求的字符串形式(按照"00000"的格式进行填充,如数字1会格式化为"00001"等),
+ // 然后将常量AVATOR_PREFIX("MTX")与格式化后的序号字符串进行拼接,组成完整的头像编号字符串,例如得到的头像编号可能是"MTX20241200001",最终返回这个生成的头像编号,供其他方法使用来命名头像文件等操作。
+ String avatorNo = AVATOR_PREFIX + df.format(incr);
+ return avatorNo;
}
- }
- } else {
- UploaderMessage msg = new UploaderMessage();
- msg.setStatus(Status.ERROR);
- msg.setError("File is empty");
- return msg;
- }
- }
-
-
- private String getAvatorNo() {
- SimpleDateFormat sdf = new SimpleDateFormat("yyyyMM");
- String format = sdf.format(new Date());
- DecimalFormat df = new DecimalFormat(AVATOR_NO_FORMAT);
- String key = AVATOR_PREFIX + format;
- Long incr = cacheService.incr(key);
- String avatorNo = AVATOR_PREFIX + df.format(incr);
- return avatorNo;
- }
-}
diff --git a/tamguo-tms/src/main/java/com/tamguo/web/member/LoginController.java b/tamguo-tms/src/main/java/com/tamguo/web/member/LoginController.java
index 0896c2e..84ead48 100644
--- a/tamguo-tms/src/main/java/com/tamguo/web/member/LoginController.java
+++ b/tamguo-tms/src/main/java/com/tamguo/web/member/LoginController.java
@@ -22,94 +22,158 @@ import com.tamguo.common.utils.Result;
import com.tamguo.common.utils.SystemConstant;
import com.tamguo.utils.ShiroUtils;
+// @Controller注解用于将这个类标记为Spring MVC框架中的一个控制器组件,意味着Spring容器会在启动时扫描到这个类,并将其管理起来,
+// 使得这个类中的方法能够处理对应的HTTP请求,根据请求的映射关系(通过@RequestMapping等注解定义)调用相应的业务逻辑方法,然后返回视图或者数据响应给客户端,
+// 在这里主要用于处理与用户登录相关的各种请求,如生成验证码、登录验证、判断登录状态等操作。
@Controller
public class LoginController {
+ /**
+ * 处理生成验证码图片的请求,请求路径为"captcha.jpg",当客户端访问这个路径时,会生成一张验证码图片并返回给客户端,同时将验证码的值存储到HttpSession中,
+ * 以便后续登录等操作时进行验证码的验证对比。通过设置响应头信息来控制缓存相关行为,确保每次请求都能获取到新的验证码图片,并且设置响应的内容类型为"image/jpeg",表示返回的是JPEG格式的图片数据。
+ *
+ * @param response HttpServletResponse对象,用于设置响应的相关信息,如响应头、响应内容类型以及输出验证码图片的流等操作,通过它向客户端返回验证码图片以及控制响应的一些属性。
+ * @param session HttpSession对象,用于在服务器端存储验证码的值,通过将生成的验证码字符串以特定的键(SystemConstant.KAPTCHA_SESSION_KEY)存储到会话中,方便后续在登录验证等过程中获取并对比验证码是否正确。
+ * @throws ServletException 如果在处理Servlet相关逻辑(比如生成验证码图片过程中涉及到Servlet规范相关的操作出现问题)时出现异常,会抛出该异常,通常需要在调用该方法的上层进行相应的异常处理,比如返回错误页面等操作。
+ * @throws IOException 如果在向响应输出流写入验证码图片数据或者操作与输入输出流相关的其他环节出现I/O异常情况,会抛出该异常,同样需要在合适的地方进行异常处理,确保系统的稳定性和友好的错误提示给客户端。
+ */
@RequestMapping("captcha.jpg")
- public void captcha(HttpServletResponse response , HttpSession session) throws ServletException, IOException {
+ public void captcha(HttpServletResponse response, HttpSession session) throws ServletException, IOException {
+ // 设置响应头的"Cache-Control"字段,值为"no-store, no-cache",表示禁止浏览器缓存响应内容,这样每次客户端请求这个验证码图片时,都会获取到新生成的验证码图片,
+ // 避免因缓存导致验证码重复使用等安全问题,确保验证码的时效性和安全性。
response.setHeader("Cache-Control", "no-store, no-cache");
+ // 设置响应的内容类型为"image/jpeg",告知客户端返回的数据是JPEG格式的图片,使得客户端能够正确识别并展示接收到的验证码图片内容。
response.setContentType("image/jpeg");
-
+
+ // 调用CaptchaUtils工具类的generateCaptcha方法,传入响应的输出流(response.getOutputStream()),用于生成验证码图片并将图片数据写入到输出流中,返回生成的验证码字符串,
+ // 这个方法内部可能使用了一些图形处理库等实现了验证码图片的生成以及将验证码文本以图片形式输出到流中的功能,具体实现取决于CaptchaUtils类的代码逻辑。
String a = CaptchaUtils.generateCaptcha(response.getOutputStream());
+ // 将生成的验证码字符串存储到HttpSession中,使用SystemConstant.KAPTCHA_SESSION_KEY作为键,方便后续在登录验证等操作中从会话中获取该验证码字符串进行对比验证,确保用户输入的验证码是否正确。
session.setAttribute(SystemConstant.KAPTCHA_SESSION_KEY, a);
}
-
+
+ /**
+ * 处理登录页面的GET请求,主要用于设置要返回的视图名称以及向视图传递一些初始化的数据,使得Spring MVC框架能够渲染对应的登录页面展示给客户端,
+ * 在这里将视图名称设置为"login",表示返回名为"login"的视图页面,同时向视图添加一个名为"isVerifyCode"的属性,值为"0",具体含义可能根据前端页面的逻辑来决定,
+ * 也许是用于前端判断是否需要显示验证码输入框等相关的页面逻辑控制情况。
+ *
+ * @param model ModelAndView对象,用于设置视图名称以及向视图传递数据,在这里设置视图名称为"login",并添加了一个名为"isVerifyCode"的属性及对应的值,方便前端页面进行相应的展示和逻辑处理。
+ * @return 返回配置好视图名称和相关属性数据的ModelAndView对象,供Spring MVC框架根据视图名称渲染并展示登录页面给客户端,同时将数据传递给视图进行相应的页面逻辑处理。
+ */
@RequestMapping(value = "/login.html", method = RequestMethod.GET)
- public ModelAndView login(ModelAndView model){
+ public ModelAndView login(ModelAndView model) {
model.setViewName("login");
- model.addObject("isVerifyCode" , "0");
+ model.addObject("isVerifyCode", "0");
return model;
}
-
+
+ /**
+ * 处理用户提交登录信息的POST请求,用于验证用户输入的登录信息(用户名、密码、验证码)是否正确,根据验证结果进行不同的处理,
+ * 如果验证码错误或者用户不存在、密码错误、账号被锁定等情况,会设置相应的错误提示信息到Result对象中,并返回登录页面展示错误提示给用户;
+ * 如果登录验证通过,则将登录用户的相关信息存储到HttpSession中,并进行重定向到会员相关的首页等操作,整个过程通过Shiro框架进行用户认证相关的操作,结合自定义的Result对象来封装和返回验证结果信息。
+ *
+ * @param username 用户名,从请求参数中获取用户输入的用户名信息,用于后续在Shiro认证以及数据库验证等环节判断用户是否存在以及密码是否匹配等操作。
+ * @param password 密码,同样从请求参数中获取用户输入的密码信息,作为登录验证的关键信息之一,传递给Shiro框架进行密码验证等相关操作。
+ * @param verifyCode 验证码,从请求参数中获取用户输入的验证码信息,用于与之前生成并存储在HttpSession中的验证码进行对比验证,确保用户输入的验证码是正确的。
+ * @param model ModelAndView对象,用于根据验证结果设置要返回的视图名称以及向视图传递相关的提示信息等数据,方便在登录页面展示相应的提示内容给用户,告知登录验证的结果情况(成功或失败以及失败原因等)。
+ * @param session HttpSession对象,用于获取之前存储的验证码以及在登录成功后存储登录用户的相关信息(如将会员对象存储到"currMember"属性下),方便后续在其他请求处理中获取当前登录用户的信息进行相关业务操作。
+ * @param response HttpServletResponse对象,在登录验证通过后,用于进行重定向操作,将用户重定向到会员相关的首页(如"member/index.html"),实现登录成功后的页面跳转功能。
+ * @return 返回配置好视图名称和相关提示信息数据的ModelAndView对象,供Spring MVC框架根据视图名称渲染并展示登录页面给客户端,展示相应的提示内容给用户,或者在登录成功时直接返回null(因为已经进行了重定向操作)。
+ * @throws IOException 如果在重定向操作(通过response.sendRedirect方法)过程中出现I/O异常情况,比如网络问题导致无法发送重定向响应等,会抛出该异常,需要在合适的地方进行异常处理,确保系统的稳定性和友好的错误提示给客户端。
+ */
@RequestMapping(value = "/submitLogin.html", method = RequestMethod.POST)
- public ModelAndView submitLogin(String username , String password , String verifyCode , ModelAndView model , HttpSession session , HttpServletResponse response) throws IOException{
+ public ModelAndView submitLogin(String username, String password, String verifyCode, ModelAndView model, HttpSession session, HttpServletResponse response) throws IOException {
+ // 创建一个表示成功的Result对象,初始化为成功状态(这里虽然初始化为成功状态,但后续会根据实际验证情况进行修改),用于封装登录验证的结果信息,方便返回给前端展示相应的提示内容,
+ // 一开始假设登录验证是成功的,后续根据具体的验证逻辑来更新这个Result对象的状态、提示信息等属性。
Result result = Result.successResult(null);
- if(StringUtils.isEmpty(verifyCode)) {
+
+ // 判断用户输入的验证码是否为空,如果为空,则表示用户没有输入验证码,设置Result对象的状态码、提示信息等属性,
+ // 表示验证失败,提示用户需要输入验证码,然后将这个包含错误提示信息的Result对象相关信息设置到ModelAndView中,最终返回登录页面展示错误提示给用户。
+ if (StringUtils.isEmpty(verifyCode)) {
result = Result.result(202, null, "请输入验证码");
- } else if(StringUtils.isNotEmpty(verifyCode)){
+ } else if (StringUtils.isNotEmpty(verifyCode)) {
+ // 如果用户输入的验证码不为空,则从HttpSession中获取之前生成并存储的验证码字符串(通过SystemConstant.KAPTCHA_SESSION_KEY作为键获取),
+ // 然后将获取到的验证码字符串与用户输入的验证码进行不区分大小写的对比验证,判断验证码是否正确。
String kaptcha = session.getAttribute(SystemConstant.KAPTCHA_SESSION_KEY).toString();
if (!verifyCode.equalsIgnoreCase(kaptcha)) {
result = Result.result(205, null, "验证码错误");
} else {
+ // 如果验证码验证通过,通过ShiroUtils工具类获取当前的Subject对象,在Shiro框架中,Subject代表了当前与系统进行交互的“主体”,通常就是指当前登录的用户或者一个匿名的访问者(未登录时),
+ // 获取到Subject对象后,用于后续进行用户认证相关的操作,比如传递用户名和密码进行登录验证等操作。
Subject subject = ShiroUtils.getSubject();
+ // 创建一个UsernamePasswordToken对象,用于传递用户名和密码信息给Shiro框架进行认证操作,将用户输入的用户名和密码作为参数传入构造方法,
+ // 这个对象会作为参数传递给Subject的login方法,触发Shiro框架的认证流程,去验证用户名和密码是否匹配以及用户是否合法等情况。
UsernamePasswordToken token = new UsernamePasswordToken(username, password);
try {
+ // 调用Subject的login方法,传入前面创建的UsernamePasswordToken对象,触发Shiro框架的用户认证流程,
+ // 如果认证成功(即用户名和密码正确,且用户状态正常等情况),则继续执行后续的操作;如果认证失败,会抛出相应的异常(如UnknownAccountException、IncorrectCredentialsException等),进入对应的catch块进行相应的错误处理。
subject.login(token);
-
+
+ // 如果登录认证通过,通过ShiroUtils工具类获取当前登录用户对应的MemberEntity对象(假设认证时将MemberEntity类型的用户对象设置为了Principal),
+ // 然后将这个会员对象存储到HttpSession的"currMember"属性下,方便后续在其他请求处理中获取当前登录用户的信息进行相关业务操作,例如在页面上展示用户相关信息等情况。
session.setAttribute("currMember", ShiroUtils.getMember());
+ // 使用HttpServletResponse进行重定向操作,将用户重定向到会员相关的首页(这里是"member/index.html"),实现登录成功后的页面跳转,使得用户登录后能够进入到对应的会员页面进行操作,
+ // 重定向后方法直接返回null,因为已经完成了页面跳转操作,不需要再返回ModelAndView对象让Spring MVC进行视图渲染了(后续的请求会根据新的页面路径重新进行相应的请求处理)。
response.sendRedirect("member/index.html");
return null;
} catch (UnknownAccountException e) {
+ // 如果在Shiro认证过程中抛出UnknownAccountException异常,说明用户名不存在或者没有找到对应的用户信息,设置Result对象的状态码、提示信息等属性,
+ // 表示验证失败,提示用户用户名或密码有误,让用户重新输入或找回密码,然后将这个包含错误提示信息的Result对象相关信息设置到ModelAndView中,最终返回登录页面展示错误提示给用户。
result = Result.result(201, null, "用户名或密码有误,请重新输入或找回密码");
} catch (IncorrectCredentialsException e) {
+ // 如果抛出IncorrectCredentialsException异常,意味着密码不正确,同样设置Result对象的相应属性,提示用户用户名或密码有误,让用户重新输入或找回密码,
+ // 并将包含错误提示信息的Result对象信息设置到ModelAndView中,返回登录页面展示错误提示给用户。
result = Result.result(202, null, "用户名或密码有误,请重新输入或找回密码");
} catch (LockedAccountException e) {
+ // 如果出现LockedAccountException异常,表示用户账号被锁定了,设置Result对象的属性,提示用户账号被锁定的错误信息,
+ // 再将包含该提示信息的Result对象相关内容设置到ModelAndView中,返回登录页面展示错误提示给用户。
result = Result.result(203, null, "账号被锁定");
- }
+ }
}
- }
- model.setViewName("login");
+ }
+
+ // 如果登录验证没有通过(由于验证码错误、用户名或密码错误、账号被锁定等原因),设置ModelAndView的视图名称为"login",表示返回登录页面展示错误提示信息给用户,
+ // 然后将Result对象中的状态码、提示信息以及用户输入的用户名等信息添加到ModelAndView对象中,方便在登录页面上展示相应的提示内容以及回显用户输入的用户名等情况,方便用户重新输入登录信息进行再次尝试。
+ model.setViewName("login");
model.addObject("code", result.getCode());
- model.addObject("msg" , result.getMessage());
+ model.addObject("msg", result.getMessage());
model.addObject("username", username);
return model;
}
-
- @RequestMapping(value = "/miniLogin.html", method = RequestMethod.GET)
- @ResponseBody
- public Result miniLogin(String username , String password , String captcha, ModelAndView model , HttpSession session) {
- Result result = null;
- if(StringUtils.isEmpty(captcha)) {
- result = Result.result(204, null, "请输入验证码");
- } else if(StringUtils.isNotEmpty(captcha)){
- String kaptcha = session.getAttribute(SystemConstant.KAPTCHA_SESSION_KEY).toString();
- if (!captcha.equalsIgnoreCase(kaptcha)) {
- result = Result.result(205, null, "验证码错误");
- }else {
- Subject subject = ShiroUtils.getSubject();
- UsernamePasswordToken token = new UsernamePasswordToken(username, password);
- try {
- subject.login(token);
- session.setAttribute("currMember", ShiroUtils.getMember());
- result = Result.successResult(ShiroUtils.getMember());
- } catch (UnknownAccountException e) {
- result = Result.result(201, null, "用户名或密码有误,请重新输入或找回密码");
- } catch (IncorrectCredentialsException e) {
- result = Result.result(202, null, "用户名或密码有误,请重新输入或找回密码");
- } catch (LockedAccountException e) {
- result = Result.result(203, null, "账号被锁定");
- }
- }
- }
- return result;
- }
+ /**
+ * 处理一种可能的小型登录(也许是用于移动端或者特定场景下的登录方式,具体根据业务而定)的GET请求,与submitLogin方法类似,也是用于验证用户输入的登录信息(用户名、密码、验证码)是否正确,
+ * 根据验证结果封装成Result对象返回给前端,不同之处在于这个方法通过@ResponseBody注解直接将Result对象转换为JSON格式返回给前端(用于前端通过Ajax等方式进行异步请求登录验证的场景),
+ * 而不是像submitLogin方法那样返回视图相关的ModelAndView对象进行页面渲染展示提示信息,整体的验证逻辑(如验证码验证、Shiro认证以及不同异常情况的处理等)基本是一致的。
+ *
+ * @param username 用户名,从请求参数中获取用户输入的用户名信息,用于后续在Shiro认证以及数据库验证等环节判断用户是否存在以及密码是否匹配等操作。
+ * @param password 密码,同样从请求参数中获取用户输入的密码信息,作为登录验证的关键信息之一,传递给Shiro框架进行密码验证等相关操作。
+ * @param captcha 验证码,从请求参数中获取用户输入的验证码信息,用于与之前生成并存储在HttpSession中的验证码进行对比验证,确保用户输入的验证码是正确的。
+ * @param model ModelAndView对象,虽然在这个方法中并没有直接对其进行过多操作(因为主要是通过@ResponseBody直接返回数据),但保留了这个参数,在一些可能的扩展场景下可以利用它来进行视图相关的操作(不过当前代码暂未涉及)。
+ * @param session HttpSession对象,用于获取之前存储的验证码以及在登录成功后存储登录用户的相关信息(如将会员对象存储到"currMember"属性下),方便后续在其他请求处理中获取当前登录用户的信息进行相关业务操作。
+ * @return 返回一个Result对象,根据登录验证的结果(成功或失败以及不同的失败原因等情况)封装了相应的状态码、提示信息以及登录成功时的用户信息等内容,通过@ResponseBody注解会将这个Result对象转换为JSON格式返回给前端,
+ * 供前端根据返回结果进行相应的提示和后续处理,比如根据返回的错误提示信息展示给用户,或者在登录成功时获取用户信息进行页面局部刷新等操作。
+ */
+
+ /**
+ * 处理判断用户是否登录的GET请求,请求路径为"/isLogin.html"。
+ * 通过调用ShiroUtils工具类中的isLogin方法来检查当前用户是否处于登录状态,然后根据判断结果返回对应的Result对象给前端,
+ * 前端可以根据返回的结果(状态码及提示信息)来进行相应的页面展示或逻辑处理,例如根据是否登录来决定显示登录按钮还是用户信息等情况。
+ *
+ * @return 返回一个Result对象,若用户已登录,返回的Result对象中状态码为1,提示信息为"已经登录";若用户未登录,返回的Result对象中状态码为0,提示信息为"未登录",
+ * 通过@ResponseBody注解,该Result对象会被转换为合适的格式(如JSON格式等,具体取决于项目中的配置)返回给前端,方便前端进行后续处理。
+ */
@RequestMapping(value = "/isLogin.html", method = RequestMethod.GET)
@ResponseBody
public Result isLogin() {
- if(ShiroUtils.isLogin()) {
- return Result.result(1, null , "已经登录");
+ // 调用ShiroUtils工具类的isLogin方法,该方法会检查当前用户对应的Subject对象中的Principal是否为null,
+ // 如果不为null,则表示用户已经登录(即已通过认证,有对应的用户主体信息存在);如果为null,则表示当前是匿名访问或者未进行认证操作,用户未登录。
+ if (ShiroUtils.isLogin()) {
+ // 如果用户已登录,调用Result类的result方法创建一个Result对象,传入状态码1、提示信息"已经登录",表示登录状态为已登录,
+ // 后续这个Result对象会被返回给前端,告知前端用户当前已登录的情况,以便前端进行相应的页面展示或逻辑处理。
+ return Result.result(1, null, "已经登录");
}
+ // 如果用户未登录,同样调用Result类的result方法创建一个Result对象,传入状态码0、提示信息"未登录",表示登录状态为未登录,
+ // 最后将这个表示未登录的Result对象返回给前端,方便前端根据该结果进行相应的处理,比如显示登录按钮引导用户进行登录操作等情况。
return Result.result(0, null, "未登录");
}
-}
diff --git a/tamguo-tms/src/main/java/com/tamguo/web/member/LogoutController.java b/tamguo-tms/src/main/java/com/tamguo/web/member/LogoutController.java
index fe7a48f..b6fa235 100644
--- a/tamguo-tms/src/main/java/com/tamguo/web/member/LogoutController.java
+++ b/tamguo-tms/src/main/java/com/tamguo/web/member/LogoutController.java
@@ -10,19 +10,38 @@ import org.springframework.web.bind.annotation.RequestMethod;
import com.tamguo.utils.ShiroUtils;
+// @Controller注解用于将这个类标记为Spring MVC框架中的一个控制器组件,意味着Spring容器会在启动时扫描到这个类,并将其管理起来,
+// 使得这个类中的方法能够处理对应的HTTP请求,在这里这个控制器主要用于处理用户注销相关的请求操作,实现用户登出的功能。
@Controller
public class LogoutController {
/**
- * 注销
+ * 处理用户注销的GET请求,请求路径为"logout.html",当用户访问这个路径时,会执行用户注销相关的操作,
+ * 包括清除存储在HttpSession中的当前会员相关信息(通过移除"currMember"属性),然后调用ShiroUtils工具类的logout方法执行Shiro框架下的用户登出操作,
+ * 最后进行页面重定向,将用户重定向到网站的根路径("/"),使得用户注销后回到网站首页等相关页面,完成注销流程以及页面跳转操作。
+ *
+ * @param request HttpServletRequest对象,虽然在当前这个方法中没有直接对其进行过多操作,但它包含了客户端发送过来的请求相关的所有信息,
+ * 在一些扩展场景下(比如根据请求中的某些参数进行额外的注销相关逻辑判断等情况,不过当前代码暂未涉及)可以使用这个对象获取相关信息辅助操作。
+ * @param response HttpServletResponse对象,用于向客户端发送响应信息,在这里主要用于进行重定向操作,通过设置响应的相关属性,将用户重定向到网站根路径,实现注销后的页面跳转功能。
+ * @param session HttpSession对象,用于获取和操作当前用户的会话信息,在这里主要是先判断会话中是否存在名为"currMember"的属性(通常存储着当前登录会员的相关信息),
+ * 如果存在,则将其移除,清除当前会员在会话中的相关数据,然后再配合ShiroUtils进行Shiro框架下的登出操作,完成整个注销过程中与会话相关的清理工作。
+ * @return 返回一个字符串"redirect:/",通过Spring MVC的视图解析机制以及响应处理逻辑,这个字符串会被识别为一个重定向的指令,将用户重定向到网站的根路径(通常是网站首页等相关页面),
+ * 实现用户注销后页面跳转的功能,使得用户回到网站的初始页面或者相应的公共页面等情况,方便用户继续浏览网站或者进行其他操作(如重新登录等)。
*/
@RequestMapping(value = "logout.html", method = RequestMethod.GET)
public String logout(HttpServletRequest request, HttpServletResponse response, HttpSession session) {
- if (session.getAttribute("currMember") != null) {
+ // 判断HttpSession中是否存在名为"currMember"的属性,通常在用户登录成功后,会将会员相关信息存储在这个属性下,
+ // 如果该属性不为null,说明用户当前处于登录状态,需要进行注销相关的操作,进入下面的注销逻辑处理;如果为null,则可能用户已经处于未登录状态或者其他异常情况,不过当前代码暂不做额外处理,直接返回重定向指令。
+ if (session.getAttribute("currMember")!= null) {
+ // 从HttpSession中移除名为"currMember"的属性,清除存储在会话中的当前会员相关信息,例如清除会员对象本身以及一些基于会员登录状态存储的临时业务数据等,
+ // 完成会话层面上与当前会员相关的数据清理工作,确保注销后会话中不再保留会员相关的痕迹,保障数据的安全性和系统状态的一致性。
session.removeAttribute("currMember");
+ // 调用ShiroUtils工具类的logout方法,该方法会通知Shiro框架执行用户登出操作,清除Shiro框架中与当前用户相关的认证状态、会话信息等相关数据,
+ // 例如撤销权限缓存、清除Shiro会话中的相关属性等操作,将用户的登录状态置为未登录,释放与登录相关的资源,确保在Shiro框架层面完成用户的注销流程,保证系统的安全性和稳定性。
ShiroUtils.logout();
}
+ // 返回"redirect:/"字符串,这个字符串在Spring MVC中会被解析为一个重定向的指令,会使得客户端收到一个重定向响应,跳转到网站的根路径("/"),
+ // 一般情况下根路径对应的是网站的首页或者其他公共的起始页面,通过这样的重定向操作,让用户在注销后回到相应的页面,方便后续的浏览或者重新登录等操作。
return "redirect:/";
}
-
-}
+}
\ No newline at end of file
diff --git a/tamguo-tms/src/main/java/com/tamguo/web/member/MemberController.java b/tamguo-tms/src/main/java/com/tamguo/web/member/MemberController.java
index bbf332c..caedcb6 100644
--- a/tamguo-tms/src/main/java/com/tamguo/web/member/MemberController.java
+++ b/tamguo-tms/src/main/java/com/tamguo/web/member/MemberController.java
@@ -11,22 +11,44 @@ import com.tamguo.common.utils.Result;
import com.tamguo.modules.member.service.IMemberService;
import com.tamguo.utils.ShiroUtils;
+// @Controller注解用于将这个类标记为Spring MVC框架中的一个控制器组件,意味着Spring容器会在启动时扫描到这个类,并将其管理起来,
+// 使得这个类中的方法能够处理对应的HTTP请求,根据请求的映射关系(通过@RequestMapping等注解定义)调用相应的业务逻辑方法,然后返回视图或者数据响应给客户端,
+// 在这里主要用于处理与会员相关的页面展示及信息查询等操作。
@Controller
public class MemberController {
-
+
+ // 通过@Autowired注解自动注入IMemberService接口的实现类实例,IMemberService用于处理与会员相关的各种业务逻辑,
+ // 比如根据会员ID查询会员详细信息等操作,在这个控制器的多个方法中会调用其相关方法来实现具体的会员业务功能。
@Autowired
IMemberService iMemberService;
+ /**
+ * 处理会员首页("/member/index.html")的GET请求,用于展示会员相关的首页内容。
+ * 通过ModelAndView对象设置要返回的视图名称,并调用iMemberService的findByUid方法查询当前登录会员的详细信息(通过ShiroUtils获取当前登录会员的ID作为查询依据),
+ * 将查询到的会员信息添加到ModelAndView对象中,最终返回ModelAndView对象,Spring MVC框架会根据视图名称渲染对应的视图页面,并将添加的数据传递给视图进行展示,实现会员首页相关信息的呈现。
+ *
+ * @param model ModelAndView对象,用于设置视图名称以及向视图传递数据,在这里设置视图名称为"member/index",表示要返回的是位于"member"目录下的"index"视图页面,
+ * 同时可以通过其addObject方法向视图传递会员相关信息数据,方便在视图中展示会员的详细信息等内容。
+ * @return 返回配置好视图名称和会员信息数据的ModelAndView对象,供Spring MVC框架进行视图渲染并展示会员首页页面内容给客户端。
+ */
@RequestMapping(value = "/member/index.html", method = RequestMethod.GET)
- public ModelAndView index(ModelAndView model){
+ public ModelAndView index(ModelAndView model) {
model.setViewName("member/index");
- model.addObject("member" , iMemberService.findByUid(ShiroUtils.getMember().getId()));
+ model.addObject("member", iMemberService.findByUid(ShiroUtils.getMember().getId()));
return model;
}
-
+
+ /**
+ * 处理查询当前会员信息的GET请求,请求路径为"/member/findCurrMember.html",用于获取当前登录会员的详细信息,并将查询结果封装到Result对象中返回给前端。
+ * 通过调用iMemberService的findCurrMember方法,传入通过ShiroUtils获取的当前登录会员的ID作为参数,查询当前会员的详细信息,然后使用Result.successResult方法将查询到的会员信息封装到Result对象中,
+ * 最后通过@ResponseBody注解将Result对象转换为合适的格式(如JSON格式等,具体取决于项目配置)返回给前端,方便前端获取并展示当前会员的详细信息,或者根据返回结果进行相应的后续处理。
+ *
+ * @return 返回一个Result对象,通过Result.successResult方法创建,其中包含了通过iMemberService查询到的当前登录会员的详细信息,供前端根据返回结果进行相应的展示和后续处理操作,
+ * 比如在页面上展示会员的各项信息、根据会员信息进行权限判断等相关业务逻辑处理。
+ */
@RequestMapping(value = "/member/findCurrMember.html", method = RequestMethod.GET)
@ResponseBody
public Result findCurrMember() {
return Result.successResult(iMemberService.findCurrMember(ShiroUtils.getMemberId()));
}
-}
+}
\ No newline at end of file
diff --git a/tamguo-tms/src/main/java/com/tamguo/web/member/MemberPaperController.java b/tamguo-tms/src/main/java/com/tamguo/web/member/MemberPaperController.java
index d89925b..b911498 100644
--- a/tamguo-tms/src/main/java/com/tamguo/web/member/MemberPaperController.java
+++ b/tamguo-tms/src/main/java/com/tamguo/web/member/MemberPaperController.java
@@ -21,107 +21,157 @@ import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpSession;
import java.util.Map;
+// @Controller注解用于将这个类标记为Spring MVC框架中的一个控制器组件,意味着Spring容器会在启动时扫描到这个类,并将其管理起来,
+// 使得这个类中的方法能够处理对应的HTTP请求,根据请求的映射关系(通过@RequestMapping等注解定义)调用相应的业务逻辑方法,然后返回视图或者数据响应给客户端,
+// 在这里主要用于处理会员相关试卷的各种操作,如试卷列表展示、试卷信息查询、试卷及试卷题目信息的增删改等业务功能。
@Controller
public class MemberPaperController {
-
+
+ // 通过@Autowired注解自动注入IPaperService接口的实现类实例,IPaperService用于处理与试卷相关的各种业务逻辑,
+ // 比如查询试卷信息、添加试卷、修改试卷、删除试卷以及处理试卷题目相关信息等操作,在这个控制器的各个方法中会调用其相关方法来实现具体的试卷业务功能。
@Autowired
private IPaperService iPaperService;
-
+ /**
+ * 处理会员试卷页面("/member/paper.html")的GET请求,主要用于设置要返回的视图名称,使得Spring MVC框架能够渲染对应的试卷列表页面展示给客户端,
+ * 在这里将视图名称设置为"member/paperList",表示返回位于"member"目录下的"paperList"视图页面,供用户查看试卷相关信息等操作,该方法只是简单地进行视图名称的设置,暂未涉及其他复杂的数据传递等操作。
+ *
+ * @param model ModelAndView对象,用于设置视图名称,在这里将视图名称设置为"member/paperList",指定要返回的页面视图,方便Spring MVC框架进行后续的视图渲染操作。
+ * @return 返回配置好视图名称的ModelAndView对象,供Spring MVC框架根据视图名称渲染并展示会员试卷列表页面给客户端。
+ */
@RequestMapping(value = "/member/paper.html", method = RequestMethod.GET)
- public ModelAndView paper(ModelAndView model){
+ public ModelAndView paper(ModelAndView model) {
model.setViewName("member/paperList");
return model;
}
-
+
+ /**
+ * 处理查询单个试卷信息的GET请求,根据传入的试卷ID(paperId)查询对应的试卷详细信息,并将查询结果封装到Result对象中返回给前端。
+ * 通过调用iPaperService的selectById方法,传入试卷ID作为参数,从数据库等数据源中获取对应的试卷实体对象信息,然后使用Result.successResult方法将查询到的试卷信息封装到Result对象中,
+ * 最后通过@ResponseBody注解将Result对象转换为合适的格式(如JSON格式等,具体取决于项目配置)返回给前端,方便前端获取并展示该试卷的详细信息,或者根据返回结果进行相应的后续处理(如在页面上展示试卷详情等操作)。
+ *
+ * @param paperId 试卷的唯一标识字符串,从请求参数中获取,用于指定要查询的试卷对象,传递给iPaperService的selectById方法作为查询依据,获取对应的试卷详细信息。
+ * @return 返回一个Result对象,通过Result.successResult方法创建,其中包含了通过iPaperService查询到的指定试卷ID对应的试卷详细信息,供前端根据返回结果进行相应的展示和后续处理操作。
+ */
@RequestMapping(value = "/member/findPaper.html", method = RequestMethod.GET)
@ResponseBody
public Result findPaper(String paperId) {
return Result.successResult(iPaperService.selectById(paperId));
}
-
- @SuppressWarnings({ "unchecked"})
- @RequestMapping(value = "member/paper/list.html" , method = RequestMethod.GET)
+
+ /**
+ * 处理获取会员试卷列表的GET请求,根据传入的筛选条件(试卷名称、页码、每页数量等)查询符合条件的试卷列表信息,并将查询结果按照特定格式封装到Map中返回给前端,
+ * 用于在页面上展示试卷列表数据,支持分页功能,通过从HttpSession中获取当前登录会员的信息,作为查询条件之一(筛选出当前会员创建的试卷)来获取相应的试卷列表。
+ *
+ * @param name 试卷名称,作为筛选条件的一部分,用于模糊查询包含该名称的试卷(通过MyBatis Plus的Condition进行like查询),从请求参数中获取,传递给查询条件构建逻辑,查找匹配的试卷信息。
+ * @param page 当前页码,从请求参数中获取,用于指定要查询的页码信息,传递给Page对象来确定查询的分页情况,获取对应页码的数据记录,方便实现分页展示试卷列表的功能。
+ * @param limit 每页显示的记录数量,从请求参数中获取,同样传递给Page对象来设置每页显示的试卷数量,结合page参数实现分页查询和展示试卷列表的功能。
+ * @param session HttpSession对象,用于获取当前登录会员的信息,通过从会话中获取名为"currMember"的属性(通常是MemberEntity类型的会员对象),获取会员的ID作为查询条件之一,
+ * 构建查询条件,筛选出当前会员创建的试卷列表信息,确保返回的试卷列表是与当前登录会员相关的试卷数据。
+ * @return 返回一个Map类型的结果,其中包含了符合条件的试卷列表数据(通过Result.jqGridResult方法按照特定格式封装了试卷记录、总记录数、每页记录数、当前页码、总页数等信息),
+ * 供前端根据这个Map中的数据进行试卷列表的展示以及分页相关的操作处理,例如在页面上循环展示试卷列表信息,并根据总页数等信息实现分页导航等功能。
+ */
+ @SuppressWarnings({ "unchecked" })
+ @RequestMapping(value = "member/paper/list.html", method = RequestMethod.GET)
@ResponseBody
- public Map paperList(String name , Integer page , Integer limit , HttpSession session){
- MemberEntity member = ((MemberEntity)session.getAttribute("currMember"));
- Page list = iPaperService.selectPage(new Page(page , limit) , Condition.create().like("name", name).eq("creater_id", member.getId()));
+ public Map paperList(String name, Integer page, Integer limit, HttpSession session) {
+ // 从HttpSession中获取当前登录会员的信息,通过将名为"currMember"的属性强制转换为MemberEntity类型获取会员对象,用于后续获取会员ID作为查询条件,
+ // 筛选出当前会员创建的试卷列表信息,确保数据的关联性和权限控制(只展示当前会员创建的试卷)。
+ MemberEntity member = ((MemberEntity) session.getAttribute("currMember"));
+ // 创建一个Page对象,用于进行分页查询操作,传入当前页码(page)和每页显示的记录数量(limit)作为分页参数,指定要查询的分页情况,
+ // 同时通过Condition.create().like("name", name).eq("creater_id", member.getId())构建查询条件,使用MyBatis Plus的条件构造器,
+ // like("name", name)表示按照试卷名称进行模糊查询,包含传入的name参数值的试卷;eq("creater_id", member.getId())表示筛选出创建者ID等于当前会员ID的试卷,
+ // 最终通过iPaperService的selectPage方法进行分页查询,获取符合条件的试卷列表信息(以Page形式返回,包含了分页相关的数据以及试卷记录列表等内容)。
+ Page list = iPaperService.selectPage(new Page(page, limit),
+ Condition.create().like("name", name).eq("creater_id", member.getId()));
+ // 使用Result.jqGridResult方法将分页查询得到的试卷列表相关信息(试卷记录、总记录数、每页记录数、当前页码、总页数等)按照特定格式封装到一个Map中返回给前端,
+ // 方便前端根据这个Map中的数据进行试卷列表的展示以及分页相关的操作处理,例如在页面上循环展示试卷列表信息,并根据总页数等信息实现分页导航等功能。
return Result.jqGridResult(list.getRecords(), list.getTotal(), limit, page, list.getPages());
}
-
- @RequestMapping(value="member/paperList/addPaperQuestionInfo.html",method=RequestMethod.POST)
+
+ /**
+ * 处理添加试卷题目信息的POST请求,接收前端传来的包含试卷题目相关信息的JSON数据(通过@RequestBody注解解析为JSONObject对象),
+ * 从JSON数据中提取出关键信息(试卷ID、题目标题、题目类型等),根据题目类型获取对应的描述信息,然后调用iPaperService的addPaperQuestionInfo方法将题目信息添加到对应的试卷中,
+ * 如果操作成功,返回表示成功的Result对象;如果出现异常,通过ExceptionSupport工具类处理异常并返回相应的包含错误信息的Result对象给前端,告知前端添加操作的结果情况。
+ *
+ * @param data JSONObject对象,通过@RequestBody注解从请求体中解析得到的包含试卷题目相关信息的JSON数据对象,其包含了如试卷ID、题目标题、题目类型等关键信息,
+ * 需要从这个对象中提取出相应的属性值传递给服务层进行添加题目信息的操作。
+ * @return 返回一个Result对象,如果添加试卷题目信息操作成功,返回的Result对象中状态码为0,提示信息为"修改成功"(这里可能表述不太准确,应该是"添加成功"更合适,不过按代码原文来注释);
+ * 如果在操作过程中出现异常,通过ExceptionSupport工具类的resolverResult方法处理异常并返回相应的包含错误信息的Result对象给前端,供前端根据返回结果进行相应的提示和后续处理操作。
+ */
+ @RequestMapping(value = "member/paperList/addPaperQuestionInfo.html", method = RequestMethod.POST)
@ResponseBody
- public Result addPaperQuestionInfo(@RequestBody JSONObject data){
+ public Result addPaperQuestionInfo(@RequestBody JSONObject data) {
try {
- String paperId ; String title ; String name ;String type;
+ // 从传入的JSONObject数据中获取试卷ID字符串,用于指定要添加题目信息的目标试卷,该ID对应数据库中试卷表的唯一标识字段,确保题目信息添加到正确的试卷上。
+ String paperId;
+ String title;
+ String name;
+ String type;
paperId = data.getString("id");
+ // 获取题目标题字符串,作为题目信息的关键内容之一,传递给服务层用于添加到试卷题目相关的表中,展示题目的具体内容。
title = data.getString("title");
+ // 获取题目类型字符串,用于后续根据题目类型获取对应的描述信息以及区分不同类型的题目进行不同的处理逻辑(比如不同类型题目可能在数据库中的存储结构等有所不同)。
type = data.getString("type");
+ // 根据获取到的题目类型(type),通过QuestionTypeEnum枚举类的getQuestionType方法获取对应的枚举实例,再调用其getDesc方法获取该类型题目的描述信息,
+ // 例如将题目类型代码转换为对应的中文描述等情况,方便在试卷题目展示等方面提供更友好的信息,然后将这个描述信息赋值给name变量,用于后续添加题目信息操作中传递给服务层。
name = QuestionTypeEnum.getQuestionType(type).getDesc();
- iPaperService.addPaperQuestionInfo(paperId , title , name , type);
+ // 调用iPaperService的addPaperQuestionInfo方法,传入试卷ID、题目标题、题目描述信息、题目类型等参数,将题目信息添加到对应的试卷中,实现添加试卷题目信息的业务逻辑操作。
+ iPaperService.addPaperQuestionInfo(paperId, title, name, type);
return Result.result(0, null, "修改成功");
} catch (Exception e) {
+ // 如果在添加试卷题目信息过程中出现异常,通过ExceptionSupport工具类的resolverResult方法处理异常,传入操作名称("添加questionInfo",用于在异常信息中标识是哪个操作出现了问题)、
+ // 当前类的Class对象(用于定位异常出现的位置等信息)以及捕获到的异常对象(e),该方法会根据异常情况生成一个包含相应错误信息的Result对象返回给前端,告知前端添加操作失败及失败原因等情况,方便前端进行相应的提示和后续处理操作。
return ExceptionSupport.resolverResult("添加questionInfo", this.getClass(), e);
}
}
-
+
+ /**
+ * 处理修改试卷题目信息的POST请求,与addPaperQuestionInfo方法类似,接收前端传来的包含试卷题目修改相关信息的JSON数据(通过@RequestBody注解解析为JSONObject对象),
+ * 从中提取关键信息(试卷ID、题目标题、题目类型、题目信息的唯一标识等),根据题目类型获取描述信息,然后调用iPaperService的updatePaperQuestionInfo方法更新对应的试卷题目信息,
+ * 如果操作成功,返回表示成功的Result对象;若出现异常,借助ExceptionSupport工具类处理异常并返回相应的包含错误信息的Result对象给前端,告知前端修改操作的结果情况。
+ *
+ * @param data JSONObject对象,通过@RequestBody注解从请求体中解析得到的包含试卷题目修改相关信息的JSON数据对象,包含了如试卷ID、题目标题、题目类型、题目信息唯一标识等关键信息,
+ * 从中提取相应的值传递给服务层进行题目信息更新操作。
+ * @return 返回一个Result对象,若修改试卷题目信息操作成功,返回的Result对象中状态码为0,提示信息为"修改成功";
+ * 如果在操作过程中出现异常,通过ExceptionSupport工具类的resolverResult方法处理异常并返回相应的包含错误信息的Result对象给前端,供前端根据返回结果进行相应的提示和后续处理操作。
+ */
@RequestMapping("member/paperList/updatePaperQuestionInfo.html")
@ResponseBody
- public Result updatePaperQuestionInfo(@RequestBody JSONObject data){
+ public Result updatePaperQuestionInfo(@RequestBody JSONObject data) {
try {
- String paperId ; String title ; String name ; String type ; String uid;
+ // 从传入的JSONObject数据中获取试卷ID字符串,用于指定要修改题目信息的目标试卷,确保更新操作作用在正确的试卷对应的题目上。
+ String paperId;
+ String title;
+ String name;
+ String type;
+ String uid;
paperId = data.getString("uid");
+ // 获取题目标题字符串,作为要修改的题目关键内容之一,传递给服务层用于更新数据库中对应的题目记录的标题字段等内容。
title = data.getString("title");
+ // 获取题目类型字符串,用于后续根据题目类型获取对应的描述信息以及按照不同类型题目进行相应的更新逻辑处理(比如不同类型题目可能更新的字段等有所不同)。
type = data.getString("type");
+ // 根据获取到的题目类型(type),通过QuestionTypeEnum枚举类的getQuestionType方法获取对应的枚举实例,再调用其getDesc方法获取该类型题目的描述信息,
+ // 以便在更新题目信息时使用更友好的描述内容替换原有的信息等情况,然后将这个描述信息赋值给name变量,传递给服务层进行更新操作。
name = QuestionTypeEnum.getQuestionType(type).getDesc();
+ // 获取题目信息的唯一标识字符串(可能用于在数据库中精准定位要更新的具体题目记录,比如是数据库表中的主键等唯一标识字段),传递给服务层在更新操作中确定具体要修改的题目记录。
uid = data.getString("infoUid");
- iPaperService.updatePaperQuestionInfo(paperId , title , name , type , uid);
+ // 调用iPaperService的updatePaperQuestionInfo方法,传入试卷ID、题目标题、题目描述信息、题目类型、题目信息唯一标识等参数,更新对应的试卷题目信息,实现修改试卷题目信息的业务逻辑操作。
+ iPaperService.updatePaperQuestionInfo(paperId, title, name, type, uid);
return Result.result(0, null, "修改成功");
} catch (Exception e) {
+ // 如果在修改试卷题目信息过程中出现异常,通过ExceptionSupport工具类的resolverResult方法处理异常,传入操作名称("修改questionInfo",用于在异常信息中标识是哪个操作出现了问题)、
+ // 当前类的Class对象(用于定位异常出现的位置等信息)以及捕获到的异常对象(e),该方法会根据异常情况生成一个包含相应错误信息的Result对象返回给前端,告知前端修改操作失败及失败原因等情况,方便前端进行相应的提示和后续处理操作。
return ExceptionSupport.resolverResult("修改questionInfo", this.getClass(), e);
}
}
-
- @RequestMapping("member/paperList/deletePaper")
- @ResponseBody
- public Result deletePaper(String paperId){
- try {
- return iPaperService.deletePaper(ShiroUtils.getMemberId() , paperId);
- } catch (Exception e) {
- return ExceptionSupport.resolverResult("删除试卷", this.getClass(), e);
- }
- }
-
- @RequestMapping("member/paperList/deletePaperQuestionInfoBtn.html")
- @ResponseBody
- public Result deletePaperQuestionInfoBtn(String paperId , String uid){
- try {
- return iPaperService.deletePaperQuestionInfoBtn(ShiroUtils.getMemberId() , paperId , uid);
- } catch (Exception e) {
- return ExceptionSupport.resolverResult("删除子卷", this.getClass(), e);
- }
- }
-
- @RequestMapping(value="member/paperList/addPaper.html",method=RequestMethod.POST)
- @ResponseBody
- public Result addPaper(@RequestBody PaperEntity paper,HttpSession session){
- try {
- MemberEntity member = (MemberEntity) session.getAttribute("currMember");
- paper.setCreaterId(member.getId());
- iPaperService.addPaper(paper);
- return Result.result(Result.SUCCESS_CODE, paper, "添加成功");
- } catch (Exception e) {
- return ExceptionSupport.resolverResult("添加试卷", this.getClass(), e);
- }
- }
-
- @RequestMapping(value="member/paperList/updatePaper.html",method=RequestMethod.POST)
- @ResponseBody
- public Result updatePaper(@RequestBody PaperEntity paper){
- try {
- return iPaperService.updatePaper(paper , ShiroUtils.getMemberId());
- } catch (Exception e) {
- return ExceptionSupport.resolverResult("修改试卷", this.getClass(), e);
- }
- }
-}
+
+ /**
+ * 处理删除试卷的请求,根据传入的试卷ID(paperId)以及当前登录会员的ID(通过ShiroUtils获取)调用iPaperService的deletePaper方法来删除对应的试卷信息,
+ * 如果操作成功,直接返回iPaperService方法返回的Result对象给前端(其中包含了删除操作的结果信息,如是否成功等情况);若出现异常,通过ExceptionSupport工具类处理异常并返回相应的Result对象给前端,告知前端删除操作的结果情况。
+ *
+ * @param paperId 试卷的唯一标识字符串,从请求参数中获取,用于指定要删除的试卷对象,传递给iPaperService的deletePaper方法作为删除操作的依据,确定要从数据库等数据源中删除的试卷记录。
+ * @return 返回一个Result对象,如果删除试卷操作成功,返回的就是iPaperService.deletePaper方法返回的Result对象,其中包含了删除操作是否成功等相关信息;
+ * 如果在操作过程中出现异常,通过ExceptionSupport工具类的resolverResult方法处理异常并返回相应的包含错误信息的Result对象给前端,供前端根据返回结果进行相应的提示和后续处理操作。
+ */
+ @RequestMapping("member/paperList/deletePaper
\ No newline at end of file
diff --git a/tamguo-tms/src/main/java/com/tamguo/web/member/PasswordController.java b/tamguo-tms/src/main/java/com/tamguo/web/member/PasswordController.java
index 85d923b..ee288dc 100644
--- a/tamguo-tms/src/main/java/com/tamguo/web/member/PasswordController.java
+++ b/tamguo-tms/src/main/java/com/tamguo/web/member/PasswordController.java
@@ -12,70 +12,146 @@ import com.tamguo.common.utils.Result;
import com.tamguo.common.utils.SystemConstant;
import com.tamguo.modules.member.service.IMemberService;
+// @Controller注解用于将这个类标记为Spring MVC框架中的一个控制器组件,意味着Spring容器会在启动时扫描到这个类,并将其管理起来,
+// 使得这个类中的方法能够处理对应的HTTP请求,根据请求的映射关系(通过@RequestMapping等注解定义)调用相应的业务逻辑方法,然后返回视图或者数据响应给客户端,
+// 在这里主要用于处理与用户密码相关的各种操作,比如密码找回过程中涉及的账户确认、安全验证、密码重置等业务功能对应的页面请求及处理逻辑。
@Controller
public class PasswordController {
-
+
+ // 通过@Autowired注解自动注入IMemberService接口的实现类实例,IMemberService用于处理与会员相关的各种业务逻辑,
+ // 在密码相关操作中,比如确认账户是否存在、进行安全验证、重置密码等操作时,会调用其相关方法来实现具体的业务功能,根据不同的业务逻辑返回相应的Result对象来表示操作结果情况。
@Autowired
private IMemberService iMemberService;
-
+
+ /**
+ * 处理密码找回中确认账户页面("password/find.html")的GET请求,主要用于设置要返回的视图名称,使得Spring MVC框架能够渲染对应的确认账户页面展示给客户端,
+ * 在这里将视图名称设置为"password/confirmAccount",表示返回位于"password"目录下的"confirmAccount"视图页面,供用户输入账户信息等操作,该方法只是简单地进行视图名称的设置,暂未涉及其他复杂的数据传递等操作。
+ *
+ * @param model ModelAndView对象,用于设置视图名称,在这里将视图名称设置为"password/confirmAccount",指定要返回的页面视图,方便Spring MVC框架进行后续的视图渲染操作。
+ * @return 返回配置好视图名称的ModelAndView对象,供Spring MVC框架根据视图名称渲染并展示密码找回的确认账户页面给客户端。
+ */
@RequestMapping(value = "password/find.html", method = RequestMethod.GET)
- public ModelAndView confirmAccount(ModelAndView model){
+ public ModelAndView confirmAccount(ModelAndView model) {
model.setViewName("password/confirmAccount");
return model;
}
-
+
+ /**
+ * 处理提交确认账户信息的POST请求,用于验证用户输入的账户(username)和验证码(veritycode)信息是否有效,根据验证结果进行不同的页面跳转和数据传递操作。
+ * 首先调用iMemberService的confirmAccount方法验证账户信息,然后对比用户输入的验证码与存储在HttpSession中的验证码是否一致,根据这些验证情况设置ModelAndView对象的视图名称以及向其添加相应的数据,
+ * 最终返回ModelAndView对象,Spring MVC框架会根据视图名称渲染对应的视图页面,并将添加的数据传递给视图进行展示,实现根据验证结果展示不同页面及提示信息给用户的功能。
+ *
+ * @param username 用户输入的账户信息(可能是用户名或者邮箱等用于标识用户的信息),从请求参数中获取,传递给iMemberService的confirmAccount方法用于验证账户是否存在以及是否符合相关规则等情况。
+ * @param veritycode 用户输入的验证码信息,同样从请求参数中获取,一方面用于与服务层验证账户时返回的验证码进行对比(如果服务层有相应验证逻辑),另一方面与存储在HttpSession中的验证码进行对比,确保验证码的正确性。
+ * @param model ModelAndView对象,用于根据验证结果设置要返回的视图名称以及向视图传递相关的数据,比如验证结果信息、用户输入的账户信息等,方便在不同页面展示相应的提示内容给用户,告知验证的结果情况(成功或失败以及失败原因等)。
+ * @param session HttpSession对象,用于获取之前存储的验证码(通过SystemConstant.KAPTCHA_SESSION_KEY作为键获取),与用户输入的验证码进行对比验证,确保用户输入的验证码是正确的,保证验证流程的完整性和安全性。
+ * @return 返回配置好视图名称和相关数据的ModelAndView对象,供Spring MVC框架根据视图名称渲染并展示相应的页面给客户端,展示相应的提示内容给用户,例如在验证成功时跳转到安全验证页面,失败时返回确认账户页面并展示错误提示信息等情况。
+ */
@RequestMapping(value = "password/confirmAccount.html", method = RequestMethod.POST)
- public ModelAndView submitConfirmAccount(String username , String veritycode , ModelAndView model , HttpSession session){
+ public ModelAndView submitConfirmAccount(String username, String veritycode, ModelAndView model, HttpSession session) {
+ // 调用iMemberService的confirmAccount方法,传入用户输入的用户名和验证码信息,该方法会根据业务逻辑验证账户是否存在、验证码是否匹配等情况(具体验证逻辑由IMemberService的实现类决定),
+ // 返回一个Result对象,其中包含了验证结果的相关信息,如状态码(表示验证是否成功等情况)、提示信息等内容,后续会根据这个Result对象以及验证码的对比情况来进一步处理页面跳转和数据传递等操作。
Result result = iMemberService.confirmAccount(username, veritycode);
+
+ // 从HttpSession中获取之前存储的验证码字符串(通过SystemConstant.KAPTCHA_SESSION_KEY作为键获取),将获取到的验证码字符串与用户输入的验证码进行不区分大小写的对比验证,判断验证码是否正确。
String kaptcha = session.getAttribute(SystemConstant.KAPTCHA_SESSION_KEY).toString();
if (!veritycode.equalsIgnoreCase(kaptcha)) {
+ // 如果验证码对比不一致,说明验证码错误,创建一个Result对象并设置其状态码为202,提示信息为"验证码错误",表示验证失败,
+ // 后续会根据这个表示验证码错误的Result对象来设置ModelAndView相关信息,最终返回确认账户页面展示错误提示给用户。
result = Result.result(202, null, "验证码错误");
}
- if(result.getCode() == 200){
+
+ // 判断Result对象中的状态码是否为200(通常表示验证成功等情况,具体含义由业务中Result类的定义以及服务层返回逻辑决定),
+ // 如果状态码为200,说明账户验证通过(包括验证码也正确等情况),则设置ModelAndView的视图名称为"password/securityCheck",表示要跳转到密码找回的安全验证页面,
+ // 同时将Result对象以及根据用户名判断是否为邮箱得到的标识信息("1"表示是邮箱,"0"表示不是邮箱)添加到ModelAndView对象中,方便在安全验证页面展示相应的验证结果以及相关提示信息给用户。
+ if (result.getCode() == 200) {
model.setViewName("password/securityCheck");
model.addObject("result", result);
- model.addObject("isEmail", username.contains("@") ? "1" : "0");
- }else{
+ model.addObject("isEmail", username.contains("@")? "1" : "0");
+ } else {
+ // 如果Result对象的状态码不是200,说明账户验证失败(可能是账户不存在、其他验证规则不满足等原因),设置ModelAndView的视图名称为"password/confirmAccount",表示返回确认账户页面展示错误提示信息给用户,
+ // 然后将用户输入的账户信息、用户名、验证码以及Result对象中的状态码等相关信息添加到ModelAndView对象中,方便在确认账户页面上展示相应的提示内容以及回显用户输入的信息等情况,方便用户重新输入进行再次尝试。
model.setViewName("password/confirmAccount");
model.addObject("account", username);
- model.addObject("username",username);
+ model.addObject("username", username);
model.addObject("veritycode", veritycode);
model.addObject("code", result.getCode());
}
+
return model;
}
-
+
+ /**
+ * 处理密码找回中安全验证页面("password/securityCheck.html")的POST请求,用于进一步验证用户的安全信息(如通过手机验证码等方式,具体根据业务逻辑而定),根据验证结果进行不同的页面跳转和数据传递操作。
+ * 调用iMemberService的securityCheck方法进行安全验证,根据返回的Result对象中的状态码判断验证是否成功,若成功则跳转到密码重置页面并传递相关数据,若失败则返回安全验证页面展示错误提示信息等情况。
+ *
+ * @param username 用户输入的账户信息(通常是前面确认账户步骤中验证通过的用户名或者邮箱等),从请求参数中获取,传递给iMemberService的securityCheck方法用于进一步的安全验证操作,结合其他参数(如手机验证码等)判断用户是否通过安全验证。
+ * @param isEmail 表示账户是否为邮箱的标识信息("1"表示是邮箱,"0"表示不是邮箱),从请求参数中获取,传递给iMemberService的securityCheck方法以及用于在页面展示等环节根据是否为邮箱进行不同的逻辑处理(比如邮箱验证和手机号验证可能有不同的提示信息等情况)。
+ * @param mobileVcode 用户输入的手机验证码信息(如果安全验证涉及手机验证码的情况),从请求参数中获取,作为安全验证的关键信息之一传递给iMemberService的securityCheck方法,与其他信息一起判断用户是否通过安全验证流程。
+ * @param model ModelAndView对象,用于根据安全验证结果设置要返回的视图名称以及向视图传递相关的数据,比如验证结果信息、用户名等,方便在不同页面展示相应的提示内容给用户,告知验证的结果情况(成功或失败以及失败原因等)。
+ * @return 返回配置好视图名称和相关数据的ModelAndView对象,供Spring MVC框架根据视图名称渲染并展示相应的页面给客户端,展示相应的提示内容给用户,例如在验证成功时跳转到密码重置页面,失败时返回安全验证页面并展示错误提示信息等情况。
+ */
@RequestMapping(value = "password/securityCheck.html", method = RequestMethod.POST)
- public ModelAndView securityCheck(String username , String isEmail , String mobileVcode , ModelAndView model){
- Result result = iMemberService.securityCheck(username , isEmail , mobileVcode);
- if(result.getCode() == 200){
+ public ModelAndView securityCheck(String username, String isEmail, String mobileVcode, ModelAndView model) {
+ // 调用iMemberService的securityCheck方法,传入用户名、是否为邮箱标识信息以及手机验证码等参数,该方法会根据业务逻辑进行安全验证操作(比如验证手机验证码是否正确、结合账户信息判断是否符合安全要求等情况),
+ // 返回一个Result对象,其中包含了安全验证结果的相关信息,如状态码(表示验证是否成功等情况)、提示信息以及可能的其他验证相关结果数据等内容,后续会根据这个Result对象来进一步处理页面跳转和数据传递等操作。
+ Result result = iMemberService.securityCheck(username, isEmail, mobileVcode);
+
+ // 判断Result对象中的状态码是否为200(通常表示安全验证成功等情况,具体含义由业务中Result类的定义以及服务层返回逻辑决定),
+ // 如果状态码为200,说明安全验证通过,将用户名以及iMemberService的securityCheck方法返回的用于密码重置的关键信息(通过result.getResult()获取,可能是一个重置密码的令牌等关键数据)添加到ModelAndView对象中,
+ // 同时设置ModelAndView的视图名称为"password/resetPassword",表示要跳转到密码重置页面,方便用户在该页面进行密码重置操作,使用获取到的关键信息来完成重置流程。
+ if (result.getCode() == 200) {
model.addObject("username", username);
- model.addObject("resetPasswordKey" , result.getResult());
+ model.addObject("resetPasswordKey", result.getResult());
model.setViewName("password/resetPassword");
- }else{
+ } else {
+ // 如果Result对象的状态码不是200,说明安全验证失败,将Result对象、是否为邮箱标识信息以及一个表示验证码错误的标识("1",这里可能根据具体业务逻辑有更准确的含义,比如表示验证失败相关情况)添加到ModelAndView对象中,
+ // 同时设置ModelAndView的视图名称为"password/securityCheck",表示返回安全验证页面展示错误提示信息给用户,方便用户查看错误原因并重新进行安全验证操作等情况。
model.addObject("result", result);
model.addObject("isEmail", isEmail);
model.addObject("codeError", "1");
model.setViewName("password/securityCheck");
}
+
return model;
}
-
+
+ /**
+ * 处理密码重置页面("password/resetPassword.html")的POST请求,用于接收用户输入的新密码以及相关验证信息,调用iMemberService的resetPassword方法进行密码重置操作,根据返回的Result对象中的状态码判断重置是否成功,
+ * 若成功则跳转到密码重置成功页面,若失败则返回密码重置页面,方便用户根据提示信息重新进行密码重置操作。
+ *
+ * @param resetPasswordKey 用于密码重置的关键信息(可能是前面安全验证通过后获取到的重置密码令牌等),从请求参数中获取,传递给iMemberService的resetPassword方法作为密码重置操作的重要依据,确保只有通过安全验证的用户才能进行密码重置。
+ * @param username 用户输入的账户信息(通常是经过前面确认账户、安全验证等步骤的用户名或者邮箱等),从请求参数中获取,传递给iMemberService的resetPassword方法用于确定要重置密码的具体用户账户,保证密码重置操作对应正确的用户。
+ * @param password 用户输入的新密码信息,作为密码重置的关键内容之一,从请求参数中获取,传递给iMemberService的resetPassword方法用于更新用户账户对应的密码信息,设置新的密码值。
+ * @param verifypwd 用户输入的用于验证新密码的信息(比如再次输入新密码进行一致性验证等情况),从请求参数中获取,同样传递给iMemberService的resetPassword方法,用于验证新密码输入的一致性等情况,确保密码重置操作的准确性和安全性。
+ * @param model ModelAndView对象,用于根据密码重置结果设置要返回的视图名称,比如重置成功跳转到密码重置成功页面,失败则返回密码重置页面,方便用户根据页面展示的提示信息进行相应的后续操作。
+ * @return 返回配置好视图名称的ModelAndView对象,供Spring MVC框架根据视图名称渲染并展示相应的页面给客户端,展示相应的提示内容给用户,例如在密码重置成功时展示成功提示页面,失败时返回密码重置页面并可能展示错误提示信息等情况。
+ */
@RequestMapping(value = "password/resetPassword.html", method = RequestMethod.POST)
- public ModelAndView resetPassword(String resetPasswordKey , String username , String password , String verifypwd , ModelAndView model){
- Result result = iMemberService.resetPassword(resetPasswordKey , username , password , verifypwd);
- if(result.getCode() == 200){
+ public ModelAndView resetPassword(String resetPasswordKey, String username, String password, String verifypwd, ModelAndView model) {
+ // 调用iMemberService的resetPassword方法,传入重置密码关键信息、用户名、新密码以及验证新密码的信息等参数,该方法会根据业务逻辑进行密码重置操作(比如验证关键信息是否有效、新密码格式是否正确、两次输入密码是否一致等情况),
+ // 返回一个Result对象,其中包含了密码重置结果的相关信息,如状态码(表示重置是否成功等情况)、提示信息等内容,后续会根据这个Result对象来进一步处理页面跳转和数据传递等操作。
+ Result result = iMemberService.resetPassword(resetPasswordKey, username, password, verifypwd);
+
+ // 判断Result对象中的状态码是否为200(通常表示密码重置成功等情况,具体含义由业务中Result类的定义以及服务层返回逻辑决定),
+ // 如果状态码为200,说明密码重置成功,设置ModelAndView的视图名称为"password/resetPwSuccess",表示要跳转到密码重置成功页面,展示相应的成功提示信息给用户,告知用户密码重置操作已顺利完成。
+ if (result.getCode() == 200) {
model.setViewName("password/resetPwSuccess");
- }else{
+ } else {
+ // 如果Result对象的状态码不是200,说明密码重置失败,设置ModelAndView的视图名称为"password/resetPassword",表示返回密码重置页面,方便用户查看可能的错误提示信息(由服务层返回的Result对象中的提示信息决定),
+ // 然后重新输入密码等信息进行再次尝试密码重置操作。
model.setViewName("password/resetPassword");
}
+
return model;
}
-
- @RequestMapping(value = "password/checkAccount.html", method = RequestMethod.GET)
- @ResponseBody
- public Result checkAccount(String account){
- return iMemberService.checkAccount(account);
- }
-
-}
+
+ /**
+ * 处理检查账户是否存在的GET请求,请求路径为"password/checkAccount.html",用于验证输入的账户(account)是否存在,通过调用iMemberService的checkAccount方法进行验证,
+ * 并将验证结果(以Result对象形式返回)直接返回给前端,前端可以根据返回的Result对象中的状态码、提示信息等内容来进行相应的提示和后续处理,比如提示用户账户不存在或者已存在等情况。
+ *
+ * @param account 用户输入的账户信息(可能是用户名或者邮箱等用于标识用户的信息),从请求参数中获取,传递给iMemberService的checkAccount方法用于验证账户是否存在,该方法会根据业务逻辑进行相应的查询和判断操作,返回对应的Result对象表示验证结果。
+ * @return 返回一个Result对象,即iMemberService的checkAccount方法返回的Result对象,其中包含了账户是否存在的验证结果相关信息(如状态码、提示信息等内容),通过@ResponseBody注解将Result对象转换为合适的格式(如JSON格式等,具体取决于项目配置)返回给前端,
+ * 供前端根据返回结果进行相应的提示和后续处理操作,比如根据状态码判断账户是否存在,然后在页面上展示相应的提示信息给用户。
+ */
+ @RequestMapping(value = "password/checkAccount.html", method = RequestMethod
\ No newline at end of file
diff --git a/tamguo-tms/src/main/java/com/tamguo/web/member/QuestionAnswerController.java b/tamguo-tms/src/main/java/com/tamguo/web/member/QuestionAnswerController.java
index abf25ad..1bf6013 100644
--- a/tamguo-tms/src/main/java/com/tamguo/web/member/QuestionAnswerController.java
+++ b/tamguo-tms/src/main/java/com/tamguo/web/member/QuestionAnswerController.java
@@ -11,20 +11,46 @@ import com.tamguo.modules.tiku.model.QuestionAnswerEntity;
import com.tamguo.modules.tiku.service.IQuestionAnswerService;
import com.tamguo.utils.ShiroUtils;
+// @Controller注解用于将这个类标记为Spring MVC框架中的一个控制器组件,意味着Spring容器会在启动时扫描到这个类,并将其管理起来,
+// 使得这个类中的方法能够处理对应的HTTP请求,根据请求的映射关系(通过@RequestMapping等注解定义)调用相应的业务逻辑方法,然后返回视图或者数据响应给客户端,
+// 在这里主要用于处理与会员答题相关的业务操作,具体为保存会员答题信息的功能。
@Controller
public class QuestionAnswerController {
-
+
+ // 通过@Autowired注解自动注入IQuestionAnswerService接口的实现类实例,IQuestionAnswerService用于处理与题目答案相关的各种业务逻辑,
+ // 比如保存用户提交的答题信息到数据库等操作,在这个控制器的sendAnswer方法中会调用其相关方法来实现具体的保存答题信息的业务功能。
@Autowired
private IQuestionAnswerService iQuestionAnswerService;
+ /**
+ * 处理会员发送答题信息的POST请求,请求路径为"member/sendAnswer.html",用于接收前端传来的包含答题信息的QuestionAnswerEntity对象(通过@RequestBody注解解析请求体中的JSON数据为实体对象),
+ * 在将答题信息保存到数据库等数据源之前,先设置答题信息对应的会员相关属性(头像、会员ID、会员昵称),通过ShiroUtils工具类获取当前登录会员的相关信息进行赋值,然后调用iQuestionAnswerService的sendAnswer方法保存答题信息,
+ * 最后返回一个表示保存成功的Result对象给前端,告知前端答题信息保存成功的情况,方便前端进行相应的提示和后续处理。
+ *
+ * @param entity QuestionAnswerEntity对象,通过@RequestBody注解从请求体中解析得到的包含答题信息的实体对象,其属性包含了题目答案相关的各种内容(如答案内容、题目ID等,具体取决于QuestionAnswerEntity类的定义),
+ * 在方法中会进一步完善其会员相关的属性(头像、会员ID、会员昵称)后传递给服务层进行保存操作。
+ * @return 返回一个Result对象,通过Result.result方法创建,其中状态码设置为0,表示操作成功,提示信息为"保存成功",用于告知前端答题信息已经成功保存到后端,供前端根据返回结果进行相应的提示和后续处理操作,
+ * 比如在页面上提示用户答题已成功提交等情况。
+ */
@RequestMapping(value = "member/sendAnswer.html", method = RequestMethod.POST)
@ResponseBody
- public Result sendAnswer(@RequestBody QuestionAnswerEntity entity){
+ public Result sendAnswer(@RequestBody QuestionAnswerEntity entity) {
+ // 通过ShiroUtils工具类获取当前登录会员对应的实体对象,并从中获取会员头像信息,赋值给传入的QuestionAnswerEntity对象的memberAvatar属性,
+ // 这样在保存答题信息时,能够关联上当前答题会员的头像信息,方便后续在展示答题记录等场景中显示答题会员的头像情况。
entity.setMemberAvatar(ShiroUtils.getMember().getAvatar());
+ // 通过ShiroUtils工具类获取当前登录会员的ID,并赋值给QuestionAnswerEntity对象的memberId属性,用于明确答题信息所属的会员,
+ // 使得数据库等数据源中能够准确记录是哪个会员提交的该答题信息,方便进行数据关联查询以及权限管理等相关业务操作(例如只有会员本人或特定权限角色才能查看、修改其答题信息等情况)。
entity.setMemberId(ShiroUtils.getMemberId());
+ // 通过ShiroUtils工具类获取当前登录会员对应的实体对象,并从中获取会员昵称信息,赋值给QuestionAnswerEntity对象的memberName属性,
+ // 同样在保存答题信息时关联上会员昵称,便于后续展示答题记录等场景中更友好地显示答题会员的相关信息,提高信息展示的可读性和用户体验。
entity.setMemberName(ShiroUtils.getMember().getNickName());
+
+ // 调用iQuestionAnswerService的sendAnswer方法,传入完善了会员相关属性的QuestionAnswerEntity对象,将答题信息保存到数据库等数据源中,执行具体的答题信息保存业务逻辑操作,
+ // 比如将答题信息插入到对应的答题记录表中,同时可能还涉及到一些关联表的更新操作(如更新会员答题次数统计等相关表,具体取决于业务逻辑设计)。
iQuestionAnswerService.sendAnswer(entity);
+
+ // 返回一个Result对象,通过Result.result方法创建,传入状态码0、提示信息"保存成功"以及null(表示无其他额外返回数据,不过这里可根据业务需求调整),
+ // 告知前端答题信息保存操作已成功完成,方便前端根据这个返回结果进行相应的提示和后续处理,例如在页面上显示答题成功的提示信息给用户,或者根据业务逻辑进行页面跳转等操作。
return Result.result(0, null, "保存成功");
}
-
-}
+}
\ No newline at end of file
diff --git a/tamguo-tms/src/main/java/com/tamguo/web/member/QuestionController.java b/tamguo-tms/src/main/java/com/tamguo/web/member/QuestionController.java
index 7fd9afc..65c3daa 100644
--- a/tamguo-tms/src/main/java/com/tamguo/web/member/QuestionController.java
+++ b/tamguo-tms/src/main/java/com/tamguo/web/member/QuestionController.java
@@ -18,80 +18,164 @@ import com.tamguo.modules.tiku.service.IPaperService;
import com.tamguo.modules.tiku.service.IQuestionService;
import com.tamguo.utils.ShiroUtils;
-@Controller(value="memberQuestionController")
+// @Controller注解用于将这个类标记为Spring MVC框架中的一个控制器组件,并且指定了组件的名称为"memberQuestionController",
+// Spring容器会在启动时扫描到这个类并进行管理,使得类中的方法能够处理对应的HTTP请求,根据请求的映射关系调用相应的业务逻辑方法,然后返回视图或者数据响应给客户端,
+// 在这里主要用于处理会员相关试题的各种操作,例如添加试题、查询试题列表、编辑和更新试题以及删除试题等业务功能对应的页面请求及处理逻辑。
+@Controller(value = "memberQuestionController")
public class QuestionController {
-
+
+ // 通过@Autowired注解自动注入IQuestionService接口的实现类实例,IQuestionService用于处理与试题相关的各种业务逻辑,
+ // 比如添加试题、查询试题、更新试题、删除试题等具体操作,在这个控制器的多个方法中会调用其相关方法来实现具体的试题业务功能。
@Autowired
private IQuestionService iQuestionService;
+
+ // 通过@Autowired注解自动注入IPaperService接口的实现类实例,IPaperService主要用于处理与试卷相关的业务逻辑,
+ // 在涉及试题与试卷关联的操作中(例如根据试卷ID查询试卷信息、获取属于某个试卷的试题列表等情况)会调用其相关方法来获取试卷相关的数据,辅助试题相关业务操作的完成。
@Autowired
private IPaperService iPaperService;
-
+
+ /**
+ * 处理会员添加试题页面("/member/addQuestion.html")的GET请求,用于展示添加试题的页面,并根据传入的试卷ID(paperId)查询对应的试卷信息,添加到ModelAndView对象中传递给页面进行展示,
+ * 使得用户在添加试题时能够知晓该试题所属的试卷情况,方便后续关联操作,最后返回配置好的ModelAndView对象供Spring MVC框架渲染并展示添加试题页面给客户端。
+ *
+ * @param paperId 试卷的唯一标识字符串,从请求参数中获取,用于指定要添加试题所属的试卷,通过调用iPaperService的selectById方法查询该试卷的详细信息,传递给页面展示相关信息,
+ * 例如试卷名称、试卷其他属性等内容,方便用户在添加试题时了解其所属试卷的情况。
+ * @param model ModelAndView对象,用于设置视图名称以及向视图传递数据,在这里设置视图名称为"member/addQuestion",表示要返回的是位于"member"目录下的"addQuestion"视图页面,
+ * 同时将查询到的试卷信息添加到该对象中,方便在视图中展示试卷相关信息,辅助用户进行试题添加操作。
+ * @return 返回配置好视图名称和试卷信息数据的ModelAndView对象,供Spring MVC框架进行视图渲染并展示会员添加试题页面内容给客户端,使得用户能看到添加试题的页面以及对应的试卷相关信息。
+ */
@RequestMapping(value = "/member/addQuestion.html", method = RequestMethod.GET)
- public ModelAndView index(String paperId , ModelAndView model){
+ public ModelAndView index(String paperId, ModelAndView model) {
model.setViewName("member/addQuestion");
model.addObject("paper", iPaperService.selectById(paperId));
return model;
}
-
+
+ /**
+ * 处理会员提交试题的POST请求,接收前端传来的包含试题信息的QuestionEntity对象,尝试调用iQuestionService的addQuestion方法将试题信息添加到数据库等数据源中,
+ * 如果操作成功,直接返回iQuestionService方法返回的Result对象给前端(其中包含了添加操作的结果信息,如是否成功等情况);若出现异常,通过ExceptionSupport工具类处理异常并返回相应的Result对象给前端,告知前端添加操作的结果情况。
+ *
+ * @param question QuestionEntity对象,从请求参数中获取,包含了前端传来的试题相关信息(如题目内容、题目类型等,具体取决于QuestionEntity类的定义),传递给iQuestionService的addQuestion方法作为要添加的试题数据,
+ * 在添加过程中会关联当前登录会员的ID(通过ShiroUtils获取),以确定试题的创建者等相关信息,确保数据的完整性和关联性。
+ * @return 返回一个Result对象,如果添加试题操作成功,返回的就是iQuestionService.addQuestion方法返回的Result对象,其中包含了添加操作是否成功等相关信息;
+ * 如果在操作过程中出现异常,通过ExceptionSupport工具类的resolverResult方法处理异常并返回相应的包含错误信息的Result对象给前端,供前端根据返回结果进行相应的提示和后续处理操作。
+ */
@RequestMapping(value = "/member/submitQuestion.html", method = RequestMethod.POST)
@ResponseBody
- public Result submitQuestion(QuestionEntity question){
+ public Result submitQuestion(QuestionEntity question) {
try {
- return iQuestionService.addQuestion(question , ShiroUtils.getMemberId());
+ return iQuestionService.addQuestion(question, ShiroUtils.getMemberId());
} catch (Exception e) {
return ExceptionSupport.resolverResult("添加试题", this.getClass(), e);
}
}
-
+
+ /**
+ * 处理会员试题列表页面("/member/questionList.html")的GET请求,根据传入的试卷ID(paperId)查询对应的试卷信息,添加到ModelAndView对象中,然后设置要返回的视图名称为"member/questionList",
+ * 使得Spring MVC框架能够渲染对应的试题列表页面展示给客户端,在页面上展示该试卷对应的试题列表相关信息(虽然当前代码只是传递了试卷信息,可能后续在页面渲染时会进一步获取试题列表数据进行展示,具体取决于页面的逻辑),
+ * 最后返回配置好的ModelAndView对象供框架进行视图渲染并展示页面给客户端。
+ *
+ * @param paperId 试卷的唯一标识字符串,从请求参数中获取,用于指定要展示试题列表所属的试卷,通过调用iPaperService的selectById方法查询该试卷的详细信息,传递给ModelAndView对象,
+ * 方便在试题列表页面展示试卷相关信息(例如试卷名称等),让用户知晓当前展示的试题是属于哪个试卷的情况。
+ * @param model ModelAndView对象,用于设置视图名称以及向视图传递数据,在这里先将查询到的试卷信息添加到该对象中,然后设置视图名称为"member/questionList",指定要返回的页面视图,
+ * 方便Spring MVC框架进行后续的视图渲染操作,使得页面能够展示试卷信息以及后续可能的试题列表等相关内容。
+ * @return 返回配置好视图名称和试卷信息数据的ModelAndView对象,供Spring MVC框架根据视图名称渲染并展示会员试题列表页面内容给客户端,方便用户查看特定试卷下的试题相关情况。
+ */
@RequestMapping(value = "/member/questionList.html", method = RequestMethod.GET)
- public ModelAndView questionList(String paperId , ModelAndView model){
+ public ModelAndView questionList(String paperId, ModelAndView model) {
model.addObject("paper", iPaperService.selectById(paperId));
model.setViewName("member/questionList");
return model;
}
-
- @RequestMapping(value = "/member/queryQuestionList.html" , method=RequestMethod.POST)
+
+ /**
+ * 处理会员查询试题列表的POST请求,接收前端传来的包含查询条件的JSONObject对象(通过@RequestBody注解解析请求体中的JSON数据),从JSON数据中提取出试题类型、试题唯一标识、试题内容、试卷ID、页码、每页数量等关键信息,
+ * 根据这些信息构建分页查询条件,调用iQuestionService的queryQuestionList方法进行分页查询符合条件的试题列表信息,将查询结果按照特定格式封装到Map中返回给前端,用于在页面上展示试题列表数据,支持分页功能。
+ *
+ * @param data JSONObject对象,通过@RequestBody注解从请求体中解析得到的包含试题列表查询条件的JSON数据对象,其包含了如试题类型、试题唯一标识、试题内容、试卷ID、页码、每页数量等关键信息,
+ * 需要从这个对象中提取出相应的属性值传递给服务层进行查询操作。
+ * @return 返回一个Map类型的结果,其中包含了符合条件的试题列表数据(通过Result.jqGridResult方法按照特定格式封装了试题记录、总记录数、每页记录数、当前页码、总页数等信息),
+ * 供前端根据这个Map中的数据进行试题列表的展示以及分页相关的操作处理,例如在页面上循环展示试题列表信息,并根据总页数等信息实现分页导航等功能。
+ */
+ @RequestMapping(value = "/member/queryQuestionList.html", method = RequestMethod.POST)
@ResponseBody
- public Map queryQuestionList(@RequestBody JSONObject data){
- String questionType ; String uid ; String content ; String paperId ;
- Integer page ; Integer limit;
+ public Map queryQuestionList(@RequestBody JSONObject data) {
+ // 从传入的JSONObject数据中获取试题类型字符串,用于筛选特定类型的试题,作为查询条件之一传递给iQuestionService的queryQuestionList方法,
+ // 以便获取符合该类型要求的试题列表信息,例如只查询选择题、填空题等不同类型的试题,具体取决于业务中对试题类型的分类和使用方式。
+ String questionType;
+ String uid;
+ String content;
+ String paperId;
+ Integer page;
+ Integer limit;
questionType = data.getString("questionType");
+ // 获取试题的唯一标识字符串,可用于精准定位特定的试题(比如在更新、删除或者更精确的查询场景下作为筛选条件),传递给查询方法用于在查询过程中进一步筛选或关联特定试题记录。
uid = data.getString("uid");
- content = data.getString("content");
+ // 获取试题内容字符串,作为模糊查询的条件之一,用于查找包含该内容的试题(例如通过题目中包含的关键字进行搜索等情况),传递给服务层在查询操作中进行相应的模糊查询逻辑处理。
+ content = data.getString("questionType");
+ // 获取试卷ID字符串,用于筛选属于该试卷的试题,确保查询到的试题列表是与指定试卷相关的,传递给服务层结合其他条件进行试题的筛选查询操作,获取对应试卷下的试题信息。
paperId = data.getString("paperId");
+ // 获取当前页码整数,用于指定要查询的页码信息,传递给Page对象来确定查询的分页情况,获取对应页码的数据记录,方便实现分页展示试题列表的功能。
page = data.getInteger("page");
+ // 获取每页显示的记录数量整数,同样传递给Page对象来设置每页显示的试题数量,结合page参数实现分页查询和展示试题列表的功能。
limit = data.getInteger("limit");
+
+ // 创建一个Page对象,用于进行分页查询操作,通过设置当前页码(page)和每页显示的记录数量(limit)来确定分页情况,
+ // 后续将这个Page对象以及其他查询条件一起传递给iQuestionService的queryQuestionList方法进行分页查询符合条件的试题列表信息。
Page p = new Page<>();
p.setCurrent(page);
p.setSize(limit);
- Page list = iQuestionService.queryQuestionList(questionType , uid , content , paperId , ShiroUtils.getMemberId() , p);
+
+ // 调用iQuestionService的queryQuestionList方法,传入试题类型、试题唯一标识、试题内容、试卷ID、当前登录会员的ID(通过ShiroUtils获取,可能用于权限控制等情况,确保会员只能查询自己有权限查看的试题)以及构建好的Page对象作为参数,
+ // 进行分页查询操作,获取符合条件的试题列表信息(以Page形式返回,包含了分页相关的数据以及试题记录列表等内容)。
+ Page list = iQuestionService.queryQuestionList(questionType, uid, content, paperId, ShiroUtils.getMemberId(), p);
+
+ // 使用Result.jqGridResult方法将分页查询得到的试题列表相关信息(试题记录、总记录数、每页记录数、当前页码、总页数等)按照特定格式封装到一个Map中返回给前端,
+ // 方便前端根据这个Map中的数据进行试题列表的展示以及分页相关的操作处理,例如在页面上循环展示试题列表信息,并根据总页数等信息实现分页导航等功能。
return Result.jqGridResult(list.getRecords(), list.getTotal(), limit, page, list.getPages());
}
-
+
+ /**
+ * 处理会员编辑试题页面("/member/editQuestion.html")的GET请求,用于展示编辑试题的页面,根据传入的试卷ID(paperId)和试题ID(questionId)分别查询对应的试卷信息和设置试题ID相关属性,添加到ModelAndView对象中传递给页面进行展示,
+ * 使得用户在编辑试题时能够知晓该试题所属的试卷情况以及明确要编辑的是哪个试题,最后返回配置好的ModelAndView对象供Spring MVC框架渲染并展示编辑试题页面给客户端。
+ *
+ * @param paperId 试卷的唯一标识字符串,从请求参数中获取,用于指定要编辑试题所属的试卷,通过调用iPaperService的selectById方法查询该试卷的详细信息,传递给页面展示相关信息,
+ * 例如试卷名称、试卷其他属性等内容,方便用户在编辑试题时了解其所属试卷的情况。
+ * @param questionId 试题的唯一标识字符串,从请求参数中获取,用于明确要编辑的具体试题,添加到ModelAndView对象中传递给页面,方便页面在渲染时能够确定要展示和编辑的是哪个试题记录,
+ * 例如通过该ID从数据库获取试题的原始内容等信息展示在编辑页面上供用户修改。
+ * @param model ModelAndView对象,用于设置视图名称以及向视图传递数据,在这里设置视图名称为"member/editQuestion",表示要返回的是位于"member"目录下的"editQuestion"视图页面,
+ * 同时将查询到的试卷信息和试题ID相关属性添加到该对象中,方便在视图中展示试卷及试题相关信息,辅助用户进行试题编辑操作。
+ * @return 返回配置好视图名称、试卷信息和试题ID相关属性数据的ModelAndView对象,供Spring MVC框架进行视图渲染并展示会员编辑试题页面内容给客户端,使得用户能看到编辑试题的页面以及对应的试卷和试题相关信息。
+ */
@RequestMapping(value = "/member/editQuestion.html", method = RequestMethod.GET)
- public ModelAndView editQuestion(String paperId , String questionId , ModelAndView model){
+ public ModelAndView editQuestion(String paperId, String questionId, ModelAndView model) {
model.setViewName("member/editQuestion");
model.addObject("paper", iPaperService.selectById(paperId));
- model.addObject("questionId" , questionId);
+ model.addObject("questionId", questionId);
return model;
}
-
+
+ /**
+ * 处理获取单个试题信息的GET请求,根据传入的试题ID(questionId)查询对应的试题详细信息,并将查询结果封装到Result对象中返回给前端,
+ * 通过调用iQuestionService的selectById方法,传入试题ID作为参数,从数据库等数据源中获取对应的试题实体对象信息,然后使用Result.successResult方法将查询到的试题信息封装到Result对象中,
+ * 最后通过@ResponseBody注解将Result对象转换为合适的格式(如JSON格式等,具体取决于项目配置)返回给前端,方便前端获取并展示该试题的详细信息,或者根据返回结果进行相应的后续处理(如在页面上展示试题详情等操作)。
+ *
+ * @param questionId 试题的唯一标识字符串,从请求参数中获取,用于指定要查询的试题对象,传递给iQuestionService的selectById方法作为查询依据,获取对应的试题详细信息。
+ * @return 返回一个Result对象,通过Result.successResult方法创建,其中包含了通过iQuestionService查询到的指定试题ID对应的试题详细信息,供前端根据返回结果进行相应的展示和后续处理操作。
+ */
@RequestMapping(value = "/member/getQuestion.html", method = RequestMethod.GET)
@ResponseBody
public Result getQuestion(String questionId) {
return Result.successResult(iQuestionService.selectById(questionId));
}
-
- @RequestMapping(value = "/member/updateQuestion.html", method = RequestMethod.POST)
- @ResponseBody
- public Result updateQuestion(QuestionEntity question) {
- return iQuestionService.updateQuestion(question , ShiroUtils.getMemberId());
- }
-
-
- @RequestMapping(value = "/member/deleteQuestion.html", method = RequestMethod.GET)
- @ResponseBody
- public Result deleteQuestion(@RequestBody String uid) {
- return iQuestionService.delete(uid , ShiroUtils.getMemberId());
- }
-}
+
+ /**
+ * 处理会员更新试题信息的POST请求,接收前端传来的包含更新后试题信息的QuestionEntity对象,调用iQuestionService的updateQuestion方法更新对应的试题信息,
+ * 直接返回iQuestionService方法返回的Result对象给前端(其中包含了更新操作的结果信息,如是否成功等情况),前端可以根据返回结果进行相应的提示和后续处理(比如提示用户试题更新成功或失败等情况)。
+ *
+ * @param question QuestionEntity对象,从请求参数中获取,包含了前端传来的更新后的试题相关信息(如修改后的题目内容、题目类型等),传递给iQuestionService的updateQuestion方法作为要更新的试题数据,
+ * 在更新过程中会关联当前登录会员的ID(通过ShiroUtils获取),以确定试题的更新者等相关信息,确保数据的完整性和关联性,同时进行相应的权限控制等业务逻辑操作(例如只有创建者或特定权限角色才能更新试题等情况)。
+ * @return 返回一个Result对象,即iQuestionService.updateQuestion方法返回的Result对象,其中包含了试题更新操作是否成功等相关信息,供前端根据返回结果进行相应的提示和后续处理操作,
+ * 比如根据返回的状态码判断更新是否成功,然后在页面上展示相应的提示信息给用户,告知试题更新的结果情况。
+ */
+ @RequestMapping(value = "/member/updateQuestion.html", method = RequestMethod.POST)
\ No newline at end of file
diff --git a/tamguo-tms/src/main/java/com/tamguo/web/member/RegisterController.java b/tamguo-tms/src/main/java/com/tamguo/web/member/RegisterController.java
index 5bea46e..b0d09cd 100644
--- a/tamguo-tms/src/main/java/com/tamguo/web/member/RegisterController.java
+++ b/tamguo-tms/src/main/java/com/tamguo/web/member/RegisterController.java
@@ -19,51 +19,116 @@ import com.tamguo.modules.member.model.MemberEntity;
import com.tamguo.modules.member.service.IMemberService;
import com.tamguo.utils.ShiroUtils;
+// @Controller注解用于将这个类标记为Spring MVC框架中的一个控制器组件,意味着Spring容器会在启动时扫描到这个类,并将其管理起来,
+// 使得这个类中的方法能够处理对应的HTTP请求,根据请求的映射关系(通过@RequestMapping等注解定义)调用相应的业务逻辑方法,然后返回视图或者数据响应给客户端,
+// 在这里主要用于处理与用户注册相关的各种操作,比如注册页面展示、注册信息验证以及实际的用户注册和注册后尝试登录等业务功能。
@Controller
public class RegisterController {
-
+
+ // 通过@Autowired注解自动注入IMemberService接口的实现类实例,IMemberService用于处理与会员相关的各种业务逻辑,
+ // 在注册相关操作中,比如验证用户名是否可用、验证手机号是否可用、进行用户注册等操作时,会调用其相关方法来实现具体的业务功能,根据不同的业务逻辑返回相应的Result对象来表示操作结果情况。
@Autowired
private IMemberService iMemberService;
+ /**
+ * 处理用户注册页面("/register.html")的GET请求,主要用于设置要返回的视图名称,使得Spring MVC框架能够渲染对应的注册页面展示给客户端,
+ * 在这里将视图名称设置为"register",表示返回名为"register"的视图页面,供用户填写注册信息等操作,该方法只是简单地进行视图名称的设置,暂未涉及其他复杂的数据传递等操作。
+ *
+ * @param model ModelAndView对象,用于设置视图名称,在这里将视图名称设置为"register",指定要返回的页面视图,方便Spring MVC框架进行后续的视图渲染操作。
+ * @param session HttpSession对象,虽然在当前这个方法中没有直接对其进行过多操作,但在后续的注册相关逻辑(比如注册成功后存储用户信息到会话等情况,不过当前代码暂未体现完整逻辑)中可能会用到,
+ * 它可以用于在服务器端存储与当前用户会话相关的数据,辅助完成注册以及后续的业务流程操作。
+ * @return 返回配置好视图名称的ModelAndView对象,供Spring MVC框架根据视图名称渲染并展示用户注册页面给客户端。
+ */
@RequestMapping(value = "/register.html", method = RequestMethod.GET)
- public ModelAndView register(ModelAndView model , HttpSession session) {
+ public ModelAndView register(ModelAndView model, HttpSession session) {
model.setViewName("register");
return model;
- }
-
+ }
+
+ /**
+ * 处理检查用户名是否可用的GET请求,请求路径为"/checkUsername.html",用于验证输入的用户名(username)是否已经被其他用户使用,通过调用iMemberService的checkUsername方法进行验证,
+ * 并将验证结果(以Result对象形式返回)直接返回给前端,前端可以根据返回的Result对象中的状态码、提示信息等内容来进行相应的提示和后续处理,比如提示用户用户名可用或者已被占用等情况。
+ *
+ * @param username 用户输入的用户名信息,从请求参数中获取,传递给iMemberService的checkUsername方法用于验证用户名是否存在(通常是在数据库中查询是否有相同用户名的记录),该方法会根据业务逻辑进行相应的查询和判断操作,返回对应的Result对象表示验证结果。
+ * @return 返回一个Result对象,即iMemberService的checkUsername方法返回的Result对象,其中包含了用户名是否可用的验证结果相关信息(如状态码、提示信息等内容),通过@ResponseBody注解将Result对象转换为合适的格式(如JSON格式等,具体取决于项目配置)返回给前端,
+ * 供前端根据返回结果进行相应的提示和后续处理操作,比如根据状态码判断用户名是否可用,然后在页面上展示相应的提示信息给用户。
+ */
@RequestMapping(value = "/checkUsername.html", method = RequestMethod.GET)
@ResponseBody
- public Result checkUsername(String username){
+ public Result checkUsername(String username) {
return iMemberService.checkUsername(username);
}
-
+
+ /**
+ * 处理检查手机号是否可用的GET请求,请求路径为"/checkMobile.html",用于验证输入的手机号(mobile)是否已经被其他用户绑定,通过调用iMemberService的checkMobile方法进行验证,
+ * 并将验证结果(以Result对象形式返回)直接返回给前端,前端可以根据返回的Result对象中的状态码、提示信息等内容来进行相应的提示和后续处理,比如提示用户手机号可用或者已被绑定等情况。
+ *
+ * @param mobile 用户输入的手机号信息,从请求参数中获取,传递给iMemberService的checkMobile方法用于验证手机号是否存在绑定记录(通常是在数据库中查询是否有相同手机号的记录),该方法会根据业务逻辑进行相应的查询和判断操作,返回对应的Result对象表示验证结果。
+ * @return 返回一个Result对象,即iMemberService的checkMobile方法返回的Result对象,其中包含了手机号是否可用的验证结果相关信息(如状态码、提示信息等内容),通过@ResponseBody注解将Result对象转换为合适的格式(如JSON格式等,具体取决于项目配置)返回给前端,
+ * 供前端根据返回结果进行相应的提示和后续处理操作,比如根据状态码判断手机号是否可用,然后在页面上展示相应的提示信息给用户。
+ */
@RequestMapping(value = "/checkMobile.html", method = RequestMethod.GET)
@ResponseBody
- public Result checkMobile(String mobile){
+ public Result checkMobile(String mobile) {
return iMemberService.checkMobile(mobile);
}
-
+
+ /**
+ * 处理用户提交注册信息的POST请求,接收前端传来的包含用户注册信息的MemberEntity对象(通过@RequestBody注解解析请求体中的JSON数据为实体对象),
+ * 首先调用iMemberService的register方法进行用户注册操作,若注册成功(返回的Result对象状态码为200),则尝试使用注册时填写的用户名和密码进行登录操作(通过Shiro框架实现),
+ * 根据登录过程中可能出现的异常情况(如用户名不存在、密码错误、账号被锁定等)返回相应的Result对象告知前端;若注册不成功(返回的Result对象状态码不为200),则直接将注册操作返回的Result对象返回给前端,告知前端注册失败及失败原因等情况。
+ *
+ * @param member MemberEntity对象,通过@RequestBody注解从请求体中解析得到的包含用户注册信息的实体对象,其属性包含了用户名、密码、手机号、邮箱等各种注册相关的信息(具体取决于MemberEntity类的定义),
+ * 传递给iMemberService的register方法用于将用户信息保存到数据库等数据源中,完成用户注册的业务逻辑操作。
+ * @param session HttpSession对象,用于在注册成功且登录成功后,存储当前登录用户的相关信息(通过将用户信息存储到"currMember"属性下),方便后续在其他请求处理中获取当前登录用户的信息进行相关业务操作,例如在页面上展示用户相关信息等情况。
+ * @return 返回一个Result对象,如果注册操作成功且登录操作也成功,最终返回的Result对象中包含了注册成功以及登录成功的相关信息(具体由iMemberService的register方法以及登录成功后的相关逻辑决定);
+ * 如果注册操作不成功,直接返回iMemberService的register方法返回的Result对象,其中包含了注册失败的原因等相关信息;如果注册成功但登录过程中出现异常(如用户名或密码错误、账号被锁定等情况),
+ * 则根据不同的异常情况返回相应的Result对象,告知前端登录失败及失败原因等情况,方便前端根据返回结果进行相应的提示和后续处理操作。
+ */
@RequestMapping(value = "/subRegister.html", method = RequestMethod.POST)
@ResponseBody
- public Result subRegister(@RequestBody MemberEntity member , HttpSession session){
+ public Result subRegister(@RequestBody MemberEntity member, HttpSession session) {
+ // 调用iMemberService的register方法,传入包含用户注册信息的MemberEntity对象,该方法会根据业务逻辑进行用户注册操作,比如将用户信息插入到数据库的用户表中,进行合法性验证、唯一性验证等相关操作,
+ // 返回一个Result对象,其中包含了注册操作的结果相关信息,如状态码(表示注册是否成功等情况)、提示信息以及可能的注册成功后返回的用户相关数据等内容,后续会根据这个Result对象的状态码来进一步处理登录相关逻辑以及最终返回结果给前端的操作。
Result result = iMemberService.register(member);
- if(result.getCode() == 200) {
+
+ // 判断Result对象中的状态码是否为200(通常表示注册成功等情况,具体含义由业务中Result类的定义以及服务层返回逻辑决定),
+ // 如果状态码为200,说明注册成功,接下来尝试进行登录操作,以下是登录相关的逻辑处理。
+ if (result.getCode() == 200) {
+ // 通过ShiroUtils工具类获取当前的Subject对象,在Shiro框架中,Subject代表了当前与系统进行交互的“主体”,通常就是指当前登录的用户或者一个匿名的访问者(未登录时),
+ // 获取到Subject对象后,用于后续进行用户认证相关的操作,也就是使用刚注册的用户信息进行登录验证操作。
Subject subject = ShiroUtils.getSubject();
+ // 从注册操作返回的Result对象中获取注册成功后的用户实体对象(通过强制转换为MemberEntity类型获取,假设注册成功时会将创建的用户对象作为结果返回在Result中),
+ // 用于后续创建UsernamePasswordToken对象传递用户名和密码信息进行登录操作。
MemberEntity memberEntity = (MemberEntity) result.getResult();
+ // 创建一个UsernamePasswordToken对象,用于传递用户名和密码信息给Shiro框架进行认证操作,将注册成功的用户的用户名(memberEntity.getUsername())和注册时填写的密码(member.getPassword())作为参数传入构造方法,
+ // 这个对象会作为参数传递给Subject的login方法,触发Shiro框架的认证流程,去验证用户名和密码是否匹配以及用户是否合法等情况。
UsernamePasswordToken token = new UsernamePasswordToken(memberEntity.getUsername(), member.getPassword());
try {
+ // 调用Subject的login方法,传入前面创建的UsernamePasswordToken对象,触发Shiro框架的用户认证流程,
+ // 如果认证成功(即用户名和密码正确,且用户状态正常等情况),则继续执行后续的操作;如果认证失败,会抛出相应的异常(如UnknownAccountException、IncorrectCredentialsException等),进入对应的catch块进行相应的错误处理。
subject.login(token);
-
+
+ // 如果登录认证通过,通过ShiroUtils工具类获取当前登录用户对应的MemberEntity对象(假设认证时将MemberEntity类型的用户对象设置为了Principal),
+ // 然后将这个会员对象存储到HttpSession的"currMember"属性下,方便后续在其他请求处理中获取当前登录用户的信息进行相关业务操作,例如在页面上展示用户相关信息等情况。
session.setAttribute("currMember", ShiroUtils.getMember());
} catch (UnknownAccountException e) {
+ // 如果在Shiro认证过程中抛出UnknownAccountException异常,说明用户名不存在或者没有找到对应的用户信息,返回一个Result对象,设置其状态码为201,提示信息为"用户名或密码有误,请重新输入或找回密码",
+ // 表示登录失败,将这个Result对象返回给前端,告知前端登录失败的原因,方便前端进行相应的提示和后续处理操作。
return Result.result(201, null, "用户名或密码有误,请重新输入或找回密码");
} catch (IncorrectCredentialsException e) {
+ // 如果抛出IncorrectCredentialsException异常,意味着密码不正确,返回一个Result对象,设置其状态码为202,提示信息为"用户名或密码有误,请重新输入或找回密码",
+ // 同样将这个Result对象返回给前端,告知前端登录失败是因为密码错误,方便前端进行相应的提示和后续处理操作。
return Result.result(202, null, "用户名或密码有误,请重新输入或找回密码");
} catch (LockedAccountException e) {
+ // 如果出现LockedAccountException异常,表示用户账号被锁定了,返回一个Result对象,设置其状态码为203,提示信息为"账号被锁定",
+ // 并将这个Result对象返回给前端,告知前端登录失败是因为账号被锁定的原因,方便前端进行相应的提示和后续处理操作。
return Result.result(203, null, "账号被锁定");
- }
+ }
}
+
+ // 如果注册操作不成功(Result对象的状态码不为200),或者注册成功但登录过程中出现异常(在对应的catch块中已经返回相应的Result对象),直接将最初注册操作返回的Result对象返回给前端,
+ // 这个Result对象中包含了注册失败的原因等相关信息,方便前端根据返回结果进行相应的提示和后续处理操作,比如提示用户注册失败的具体原因(如用户名已存在、手机号格式错误等情况)。
return result;
}
-
-}
+}
\ No newline at end of file
diff --git a/tamguo-tms/src/main/java/com/tamguo/web/sys/JoinusController.java b/tamguo-tms/src/main/java/com/tamguo/web/sys/JoinusController.java
index 4b76361..4b41897 100644
--- a/tamguo-tms/src/main/java/com/tamguo/web/sys/JoinusController.java
+++ b/tamguo-tms/src/main/java/com/tamguo/web/sys/JoinusController.java
@@ -15,31 +15,77 @@ import com.tamguo.common.utils.Result;
import com.tamguo.modules.sys.model.TeacherEntity;
import com.tamguo.modules.sys.service.ITeacherService;
+// @Controller注解用于将这个类标记为Spring MVC框架中的一个控制器组件,意味着Spring容器会在启动时扫描到这个类,并将其管理起来,
+// 使得这个类中的方法能够处理对应的HTTP请求,根据请求的映射关系(通过@RequestMapping等注解定义)调用相应的业务逻辑方法,然后返回视图或者数据响应给客户端,
+// 在这里主要用于处理与教师应聘相关的各种操作,比如应聘页面展示、获取教师信息以及提交教师应聘信息等业务功能。
@Controller
public class JoinusController {
-
+
+ // 通过@Autowired注解自动注入ITeacherService接口的实现类实例,ITeacherService用于处理与教师相关的各种业务逻辑,
+ // 在教师应聘相关操作中,比如根据手机号获取教师信息、保存教师应聘信息等操作时,会调用其相关方法来实现具体的业务功能,根据不同的业务逻辑返回相应的Result对象来表示操作结果情况。
@Autowired
private ITeacherService iTeacherService;
+ /**
+ * 处理教师应聘页面("teacher/joinus.html")的GET请求,主要用于设置要返回的视图名称,使得Spring MVC框架能够渲染对应的应聘页面展示给客户端,
+ * 在这里将视图名称设置为"teacher/joinus",表示返回位于"teacher"目录下的"joinus"视图页面,供教师填写应聘信息等操作,该方法只是简单地进行视图名称的设置,暂未涉及其他复杂的数据传递等操作。
+ *
+ * @param model ModelAndView对象,用于设置视图名称,在这里将视图名称设置为"teacher/joinus",指定要返回的页面视图,方便Spring MVC框架进行后续的视图渲染操作。
+ * @param session HttpSession对象,虽然在当前这个方法中没有直接对其进行过多操作,但在一些扩展的业务逻辑中(比如记录应聘教师的访问会话信息等情况,不过当前代码暂未体现相关完整逻辑)可能会用到,
+ * 它可以用于在服务器端存储与当前用户会话相关的数据,辅助完成教师应聘以及后续可能的业务流程操作。
+ * @return 返回配置好视图名称的ModelAndView对象,供Spring MVC框架根据视图名称渲染并展示教师应聘页面给客户端。
+ */
@RequestMapping(value = "teacher/joinus.html", method = RequestMethod.GET)
- public ModelAndView register(ModelAndView model , HttpSession session) {
+ public ModelAndView register(ModelAndView model, HttpSession session) {
model.setViewName("teacher/joinus");
return model;
- }
-
+ }
+
+ /**
+ * 处理获取教师信息的POST请求,请求路径为"teacher/info.html",接收前端传来的包含查询条件的Map对象(通过@RequestBody注解解析请求体中的JSON数据为Map类型,假设数据格式为JSON格式且能转换为Map),
+ * 从Map中获取手机号(mobile)和验证码(verifyCode)信息,调用iTeacherService的getTeacherByMobile方法根据手机号和验证码获取对应的教师信息,然后将获取到的结果(以Result对象形式返回)直接返回给前端,
+ * 前端可以根据返回的Result对象中的状态码、提示信息等内容来进行相应的提示和后续处理,比如提示教师信息获取成功或者验证失败等情况。
+ *
+ * @param param Map对象,通过@RequestBody注解从请求体中解析得到的包含查询教师信息相关条件的Map类型数据对象,其键值对包含了如手机号、验证码等关键信息(具体键名由前端传递的数据格式决定),
+ * 需要从这个Map中提取出相应的信息传递给服务层进行教师信息查询操作。
+ * @return 返回一个Result对象,即iTeacherService的getTeacherByMobile方法返回的Result对象,其中包含了根据手机号和验证码查询教师信息的结果相关信息(如状态码、提示信息等内容),通过@ResponseBody注解将Result对象转换为合适的格式(如JSON格式等,具体取决于项目配置)返回给前端,
+ * 供前端根据返回结果进行相应的提示和后续处理操作,比如根据状态码判断教师信息是否获取成功,然后在页面上展示相应的提示信息给教师。
+ */
@RequestMapping(value = "teacher/info.html", method = RequestMethod.POST)
@ResponseBody
public Result getTeacher(@RequestBody Map param) {
+ // 从传入的Map参数中获取手机号字符串,作为查询教师信息的关键条件之一,传递给iTeacherService的getTeacherByMobile方法用于在数据库等数据源中查找对应的教师记录,
+ // 例如通过手机号来精准定位特定教师的相关信息,判断是否存在该手机号对应的教师以及验证手机号与验证码是否匹配等情况(具体逻辑由ITeacherService的实现类决定)。
String mobile = (String) param.get("mobile");
+ // 从Map参数中获取验证码字符串,同样作为重要的查询验证条件,与手机号一起传递给iTeacherService的getTeacherByMobile方法,用于验证教师的合法性或者确认当前操作的有效性等情况,
+ // 确保只有输入正确验证码的情况下才能获取相应教师的信息,保证信息获取的安全性和准确性。
String verifyCode = (String) param.get("verifyCode");
+
+ // 调用iTeacherService的getTeacherByMobile方法,传入手机号和验证码作为参数,该方法会根据业务逻辑进行教师信息查询以及相关验证操作,返回一个Result对象,
+ // 其中包含了查询及验证结果的相关信息,如状态码(表示是否查询到教师信息、验证是否通过等情况)、提示信息以及可能的查询到的教师实体对象等内容,后续会将这个Result对象直接返回给前端,告知前端教师信息获取的结果情况。
Result result = iTeacherService.getTeacherByMobile(mobile, verifyCode);
+
return result;
}
-
+
+ /**
+ * 处理教师应聘提交信息的POST请求,接收前端传来的包含教师应聘信息的TeacherEntity对象(通过@RequestBody注解解析请求体中的JSON数据为实体对象),
+ * 调用iTeacherService的joinus方法将教师应聘信息保存到数据库等数据源中,然后返回一个表示操作成功的Result对象(通过Result.successResult方法创建)给前端,告知前端应聘信息提交成功的情况,方便前端进行相应的提示和后续处理。
+ *
+ * @param teacher TeacherEntity对象,通过@RequestBody注解从请求体中解析得到的包含教师应聘信息的实体对象,其属性包含了教师的个人基本信息(如姓名、学历、教学经验等,具体取决于TeacherEntity类的定义)、应聘岗位相关信息等各种应聘相关的内容,
+ * 传递给iTeacherService的joinus方法用于将教师应聘信息保存到数据库等数据源中,完成教师应聘信息提交的业务逻辑操作。
+ * @return 返回一个Result对象,通过Result.successResult方法创建,其中传入null表示无其他额外返回数据(不过这里可根据业务需求调整),用于告知前端教师应聘信息已经成功提交到后端,供前端根据返回结果进行相应的提示和后续处理操作,
+ * 比如在页面上提示教师应聘已成功提交等情况。
+ */
@RequestMapping(value = "teacher/joinus.html", method = RequestMethod.POST)
@ResponseBody
public Result teacherJoinus(@RequestBody TeacherEntity teacher) {
+ // 调用iTeacherService的joinus方法,传入包含教师应聘信息的TeacherEntity对象,该方法会根据业务逻辑进行教师应聘信息的保存操作,比如将教师信息插入到数据库的教师应聘表或者相关关联表中,进行合法性验证等相关操作,
+ // 完成将教师应聘信息持久化的业务逻辑,确保信息被正确保存到后端存储中,方便后续的审核等业务流程处理。
iTeacherService.joinus(teacher);
+
+ // 返回一个Result对象,通过Result.successResult方法创建,传入null参数(表示无额外需要返回的数据,不过可以根据实际业务需求进行调整,比如返回保存后的教师信息ID等内容),
+ // 告知前端教师应聘信息提交操作已成功完成,方便前端根据这个返回结果进行相应的提示和后续处理,例如在页面上显示应聘成功提交的提示信息给教师,或者根据业务逻辑进行页面跳转等操作。
return Result.successResult(null);
}
-}
+}
\ No newline at end of file
diff --git a/tamguo-tms/src/main/java/com/tamguo/web/tiku/AreaController.java b/tamguo-tms/src/main/java/com/tamguo/web/tiku/AreaController.java
index e2521bf..b3ac8dc 100644
--- a/tamguo-tms/src/main/java/com/tamguo/web/tiku/AreaController.java
+++ b/tamguo-tms/src/main/java/com/tamguo/web/tiku/AreaController.java
@@ -9,17 +9,28 @@ import org.springframework.web.bind.annotation.ResponseBody;
import com.tamguo.common.utils.Result;
import com.tamguo.modules.sys.service.ISysAreaService;
+// @Controller注解用于将这个类标记为Spring MVC框架中的一个控制器组件,意味着Spring容器会在启动时扫描到这个类,并将其管理起来,
+// 使得这个类中的方法能够处理对应的HTTP请求,根据请求的映射关系(通过@RequestMapping等注解定义)调用相应的业务逻辑方法,然后返回视图或者数据响应给客户端,
+// 在这里主要用于处理与区域相关的业务操作,当前类中仅实现了查询区域树信息这一功能对应的请求处理逻辑。
@Controller
public class AreaController {
+ // 通过@Autowired注解自动注入ISysAreaService接口的实现类实例,ISysAreaService用于处理与系统区域相关的各种业务逻辑,
+ // 比如查询区域树结构数据等操作,在这个控制器的findAreaTree方法中会调用其相关方法来实现具体的查询区域树信息的业务功能。
@Autowired
private ISysAreaService iSysAreaService;
+ /**
+ * 处理查询区域树信息的GET请求,请求路径为"area/findAreaTree.html",用于获取区域的树形结构数据(通常用于在前端页面以树状结构展示区域的层级关系等情况),
+ * 通过调用iSysAreaService的findAreaTree方法进行查询操作,然后将查询结果(以Result对象形式返回)直接返回给前端,前端可以根据返回的Result对象中的数据、状态码、提示信息等内容来进行相应的展示和后续处理,
+ * 比如在页面上展示区域树结构,或者根据返回的状态码判断查询是否成功等情况。
+ *
+ * @return 返回一个Result对象,即iSysAreaService的findAreaTree方法返回的Result对象,其中包含了查询区域树信息的结果相关信息(如状态码、提示信息以及查询到的区域树结构数据等内容),通过@ResponseBody注解将Result对象转换为合适的格式(如JSON格式等,具体取决于项目配置)返回给前端,
+ * 供前端根据返回结果进行相应的展示和后续处理操作,比如根据状态码判断查询是否成功,然后利用返回的数据在页面上渲染展示区域树结构给用户查看。
+ */
@RequestMapping(value = {"area/findAreaTree.html"}, method = RequestMethod.GET)
@ResponseBody
public Result findAreaTree() {
return iSysAreaService.findAreaTree();
}
-
-
-}
+}
\ No newline at end of file
diff --git a/tamguo-tms/src/main/java/com/tamguo/web/tiku/CourseController.java b/tamguo-tms/src/main/java/com/tamguo/web/tiku/CourseController.java
index bc6a36c..9fa1e33 100644
--- a/tamguo-tms/src/main/java/com/tamguo/web/tiku/CourseController.java
+++ b/tamguo-tms/src/main/java/com/tamguo/web/tiku/CourseController.java
@@ -27,57 +27,129 @@ import com.tamguo.utils.BrowserUtils;
/**
* Controller - 科目
- *
+ * 这个类主要作为Spring MVC的控制器,用于处理与课程相关的各种HTTP请求,
+ * 通过调用不同的业务服务层接口来获取相应的数据,并根据请求的情况返回视图或者数据响应给客户端,
+ * 例如展示课程相关页面以及查询课程对应的章节信息等功能。
+ *
* @author tamguo
*
*/
@Controller
public class CourseController {
-
+
+ // 创建一个日志记录器对象,用于记录在这个控制器类中发生的一些关键操作、调试信息或者错误信息等,
+ // 通过LoggerFactory根据当前类的Class对象获取对应的Logger实例,方便后续在代码中进行日志输出操作,便于调试和查看运行情况。
private Logger logger = LoggerFactory.getLogger(getClass());
+
+ // 通过@Autowired注解自动注入IChapterService接口的实现类实例,IChapterService用于处理与章节相关的各种业务逻辑,
+ // 比如查询章节树结构、根据课程ID获取章节信息等操作,在这个控制器的相关方法中会调用其相关方法来实现具体的章节相关业务功能。
@Autowired
IChapterService iChapterService;
+
+ // 自动注入ICourseService接口的实现类实例,ICourseService主要负责处理与课程相关的业务逻辑,
+ // 像根据课程ID查询课程信息、获取某个学科下的课程列表等操作都会调用它的相应方法来完成。
@Autowired
ICourseService iCourseService;
+
+ // 注入ISubjectService接口的实现类实例,ISubjectService用于处理与学科(科目)相关的业务逻辑,
+ // 例如根据学科ID查询学科详细信息等操作,在课程相关操作中,可能需要获取所属学科的相关信息来完善页面展示等功能,会用到该服务层接口的方法。
@Autowired
ISubjectService iSubjectService;
+
+ // 注入IKnowPointService接口的实现类实例,IKnowPointService用于处理知识点相关的业务逻辑,
+ // 比如根据课程ID查询对应的知识点列表等操作,在构建课程相关页面数据时,会涉及到知识点相关信息的获取与处理,会调用其相应方法。
@Autowired
IKnowPointService knowPointService;
+ /**
+ * 处理课程详情页面的GET请求,请求路径为"course/{uid}.html",其中{uid}是一个路径变量,表示课程的唯一标识,
+ * 该方法用于获取课程相关的详细信息以及与之关联的其他数据(如知识点列表、章节列表、所属学科信息、同学科下的课程列表等),
+ * 根据请求头中用户代理信息判断是否是移动端访问,来设置不同的视图名称,最后将获取到的数据添加到ModelAndView对象中返回,供Spring MVC框架渲染相应的视图展示给客户端。
+ *
+ * @param request HttpServletRequest对象,用于获取请求相关的各种信息,在这里主要是获取请求的URI(通过request.getRequestURI()方法)记录日志,
+ * 以及获取请求头中的"user-agent"信息传递给BrowserUtils工具类判断是否是移动端访问,从而决定返回的视图名称等操作。
+ * @param uid 课程的唯一标识字符串,通过@PathVariable注解从请求路径中获取,用于指定要查询详细信息的具体课程,传递给相关服务层方法作为查询依据,获取课程及其关联的数据信息。
+ * @param model ModelAndView对象,用于设置视图名称以及向视图传递数据,在这里会将查询到的课程相关的各种数据(章节列表、课程列表、课程本身、所属学科、知识点列表、知识点等)添加到该对象中,
+ * 然后根据设备类型设置合适的视图名称,最后返回该对象供Spring MVC框架进行视图渲染并展示课程详情页面给客户端。
+ * @return 返回配置好视图名称和课程相关数据的ModelAndView对象,供Spring MVC框架根据视图名称渲染并展示课程详情页面给客户端,展示相应的课程信息以及关联数据给用户查看。
+ */
@SuppressWarnings("unchecked")
@RequestMapping(value = {"course/{uid}.html"}, method = RequestMethod.GET)
- public ModelAndView index(HttpServletRequest request , @PathVariable String uid , ModelAndView model) {
- // request url
- logger.info("request url :{}" , request.getRequestURI());
+ public ModelAndView index(HttpServletRequest request, @PathVariable String uid, ModelAndView model) {
+ // 使用日志记录器记录请求的URL信息,方便后续查看请求访问情况以及进行调试等操作,通过格式化输出的方式将请求的URI信息记录到日志中,
+ // 输出的日志级别为INFO,通常用于记录一些重要的运行时信息,方便运维人员或者开发人员了解系统的访问情况。
+ logger.info("request url :{}", request.getRequestURI());
+
+ // 调用iCourseService的selectById方法,传入课程的唯一标识(uid)作为参数,从数据库等数据源中查询对应的课程详细信息(以CourseEntity对象形式返回),
+ // 获取到的课程信息后续会添加到ModelAndView对象中传递给视图进行展示,例如展示课程名称、课程简介等相关内容。
CourseEntity course = iCourseService.selectById(uid);
+
+ // 调用knowPointService的selectList方法,通过MyBatis Plus的条件构造器Condition创建查询条件,
+ // 使用eq("course_id", uid)表示筛选出课程ID等于当前传入课程唯一标识(uid)的知识点列表,获取与该课程相关的所有知识点信息(以List形式返回),
+ // 这些知识点信息同样会添加到ModelAndView对象中,方便在视图中展示课程包含的知识点情况,比如在页面上列出知识点名称等相关内容。
List knowPointList = knowPointService.selectList(Condition.create().eq("course_id", uid));
+
+ // 初始化章节列表为null,后续会根据知识点情况来确定章节列表的值,如果有对应的知识点存在,会进一步查询相关章节信息进行赋值。
List chapterList = null;
KnowPointEntity knowPoint = null;
- if(knowPointList.size() > 0) {
+
+ // 判断知识点列表的大小是否大于0,即是否存在与当前课程相关的知识点,
+ // 如果存在知识点,说明可以基于知识点进一步获取与之关联的章节信息等内容,进行后续的数据准备操作。
+ if (knowPointList.size() > 0) {
+ // 从知识点列表中获取第一个知识点对象(这里假设可以基于第一个知识点来获取相关章节信息,具体业务逻辑可能根据实际情况而定),
+ // 获取这个知识点对象主要是为了获取其ID,作为查询章节树结构的依据,获取与该知识点相关联的章节信息。
knowPoint = knowPointList.get(0);
+ // 调用iChapterService的findChapterTree方法,传入获取到的知识点的ID作为参数,查询与该知识点相关的章节树结构信息(以List形式返回),
+ // 章节树结构信息可能是一种层级嵌套的数据结构,方便在页面上以树状形式展示章节的层级关系等情况,获取到的章节列表信息会赋值给chapterList变量,后续添加到ModelAndView对象中用于视图展示。
chapterList = iChapterService.findChapterTree(knowPoint.getId());
}
+
+ // 调用iSubjectService的selectById方法,传入课程对象中的学科ID(course.getSubjectId())作为参数,从数据库等数据源中查询对应的学科详细信息(以SubjectEntity对象形式返回),
+ // 获取学科信息是为了在课程详情页面展示该课程所属的学科相关情况,例如学科名称等内容,将学科信息添加到ModelAndView对象中传递给视图进行展示。
SubjectEntity subject = iSubjectService.selectById(course.getSubjectId());
+
+ // 调用iCourseService的selectList方法,通过MyBatis Plus的条件构造器构建查询条件,
+ // 使用eq("subject_id", course.getSubjectId())表示筛选出学科ID等于当前课程所属学科ID的课程列表,再通过orderAsc(Arrays.asList("sort"))按照"sort"字段升序排序课程列表,
+ // 获取与当前课程同属一个学科的其他课程列表信息(以List形式返回),用于在课程详情页面展示同学科下的其他课程情况,比如在页面上提供相关课程的导航链接等情况,将课程列表信息添加到ModelAndView对象中。
List courseList = iCourseService.selectList(Condition.create().eq("subject_id", course.getSubjectId()).orderAsc(Arrays.asList("sort")));
-
+
+ // 将查询到的章节列表信息添加到ModelAndView对象中,设置属性名为"chapterList",方便在视图中通过这个属性名获取章节列表数据进行展示,例如循环展示章节名称等相关内容。
model.addObject("chapterList", chapterList);
+ // 同样将同学科下的课程列表信息添加到ModelAndView对象中,属性名为"courseList",以便在视图中展示相关课程信息,为用户提供更多课程相关的导航或参考信息。
model.addObject("courseList", courseList);
+ // 将查询到的当前课程的详细信息添加到ModelAndView对象中,属性名为"course",方便在视图中展示课程的各种详细内容,如课程名称、简介等信息。
model.addObject("course", course);
+ // 把查询到的课程所属学科的详细信息添加到ModelAndView对象中,属性名为"subject",用于在视图中展示学科相关情况,例如学科名称等内容,让用户了解课程所属的学科背景。
model.addObject("subject", subject);
+ // 将获取到的与当前课程相关的知识点列表信息添加到ModelAndView对象中,属性名为"knowPointList",方便在视图中展示课程包含的知识点情况,例如列出知识点名称等内容。
model.addObject("knowPointList", knowPointList);
- model.addObject("knowPoint" , knowPoint);
- if(BrowserUtils.isMobile(request.getHeader("user-agent"))) {
- model.setViewName("mobile/chapter");
- }else {
- model.setViewName("chapter");
- }
+ // 把前面获取到的知识点对象(如果存在的话)添加到ModelAndView对象中,属性名为"knowPoint",在视图中可能用于展示某个特定知识点相关的详细信息或者作为关联其他数据的依据等情况(具体取决于视图的业务逻辑设计)。
+ model.addObject("knowPoint", knowPoint);
+
+ // 通过BrowserUtils工具类的isMobile方法判断请求头中的"user-agent"信息是否表示当前访问是来自移动端设备,
+ // 如果是移动端访问,设置ModelAndView的视图名称为"mobile/chapter",表示返回移动端对应的章节相关视图页面(具体视图页面的内容和样式由对应的前端页面模板决定);
+ // 如果不是移动端访问,设置视图名称为"chapter",表示返回普通桌面端等设备对应的章节相关视图页面,根据不同设备类型展示合适的页面给用户查看。
+ if (BrowserUtils.isMobile(request.getHeader("user-agent"))) {
+ model.setViewName("mobile/chapter");
+ } else {
+ model.setViewName("chapter");
+ }
+
return model;
}
-
+
+ /**
+ * 处理根据课程ID查询章节信息的GET请求,请求路径为"course/findChapter.html",用于获取指定课程下的章节信息,
+ * 通过调用iChapterService的findCourseChapter方法,传入课程ID(courseId)作为参数进行查询操作,然后将查询到的章节信息(以List形式返回)直接返回给前端,
+ * 前端可以根据返回的章节列表数据进行相应的展示和后续处理,比如在页面上展示课程章节列表等情况。
+ *
+ * @param courseId 课程的唯一标识字符串,从请求参数中获取,用于指定要查询章节信息所属的课程,传递给iChapterService的findCourseChapter方法作为查询依据,获取对应的章节信息。
+ * @return 返回一个List类型的结果,即iChapterService的findCourseChapter方法返回的章节信息列表,包含了指定课程下的所有章节实体对象,
+ * 通过@ResponseBody注解将这个列表转换为合适的格式(如JSON格式等,具体取决于项目配置)返回给前端,供前端根据返回结果进行相应的展示和后续处理操作,例如在页面上循环展示章节名称等相关内容。
+ */
@RequestMapping(value = {"course/findChapter.html"}, method = RequestMethod.GET)
@ResponseBody
- public List findChapterByCourseId(String courseId){
+ public List findChapterByCourseId(String courseId) {
return iChapterService.findCourseChapter(courseId);
}
-
-}
+}
\ No newline at end of file
diff --git a/tamguo-tms/src/main/java/com/tamguo/web/tiku/IndexController.java b/tamguo-tms/src/main/java/com/tamguo/web/tiku/IndexController.java
index 8fa6997..556cf74 100644
--- a/tamguo-tms/src/main/java/com/tamguo/web/tiku/IndexController.java
+++ b/tamguo-tms/src/main/java/com/tamguo/web/tiku/IndexController.java
@@ -11,57 +11,117 @@ import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.servlet.ModelAndView;
import com.tamguo.modules.tiku.model.ChapterEntity;
-
import com.tamguo.modules.tiku.model.queue.LearnChapterQueue;
import com.tamguo.utils.BrowserUtils;
+// @Controller注解用于将这个类标记为Spring MVC框架中的一个控制器组件,意味着Spring容器会在启动时扫描到这个类,并将其管理起来,
+// 使得这个类中的方法能够处理对应的HTTP请求,根据请求的映射关系(通过@RequestMapping等注解定义)调用相应的业务逻辑方法,然后返回视图或者数据响应给客户端,
+// 在这里主要用于处理多个不同页面相关的请求,包括首页、第三方验证页面以及错误页面等的展示逻辑。
@Controller
public class IndexController {
-
- private Logger logger = LoggerFactory.getLogger(getClass());
-
- @RequestMapping(value = {"/","index"}, method = RequestMethod.GET)
- public ModelAndView indexAction(ModelAndView model , HttpServletRequest request) {
- // request url
- logger.info("request url :{}" , request.getRequestURI());
- BlockingQueue chapterQueue = LearnChapterQueue.getChapterQueue();
- model.addObject("chapterList", chapterQueue.toArray());
- if(BrowserUtils.isMobile(request.getHeader("user-agent"))) {
- model.setViewName("mobile/index");
- }else {
- model.setViewName("index");
- }
+
+ // 创建一个日志记录器对象,用于记录在这个控制器类中发生的一些关键操作、调试信息或者错误信息等,
+ // 通过LoggerFactory根据当前类的Class对象获取对应的Logger实例,方便后续在代码中进行日志输出操作,便于调试和查看运行情况。
+ private Logger logger = LoggerFactory.getLogger(getClass());
+
+ /**
+ * 处理网站首页(根路径"/"或者"index")的GET请求,用于展示网站的首页内容,
+ * 该方法会获取一个章节队列(BlockingQueue)中的数据,添加到ModelAndView对象中作为页面展示的数据,
+ * 同时根据请求头中用户代理信息判断是否是移动端访问,来设置不同的视图名称,最后返回ModelAndView对象供Spring MVC框架渲染相应的视图展示给客户端。
+ *
+ * @param model ModelAndView对象,用于设置视图名称以及向视图传递数据,在这里会将章节队列中的数据添加到该对象中,然后根据设备类型设置合适的视图名称,最后返回该对象供Spring MVC框架进行视图渲染并展示首页给客户端。
+ * @param request HttpServletRequest对象,用于获取请求相关的各种信息,在这里主要是获取请求的URI(通过request.getRequestURI()方法)记录日志,
+ * 以及获取请求头中的"user-agent"信息传递给BrowserUtils工具类判断是否是移动端访问,从而决定返回的视图名称等操作。
+ * @return 返回配置好视图名称和章节队列数据(转换为数组形式)的ModelAndView对象,供Spring MVC框架根据视图名称渲染并展示首页给客户端,展示相应的章节相关信息(具体展示内容取决于前端页面如何处理该数据)给用户查看。
+ */
+ @RequestMapping(value = {"/", "index"}, method = RequestMethod.GET)
+ public ModelAndView indexAction(ModelAndView model, HttpServletRequest request) {
+ // 使用日志记录器记录请求的URL信息,方便后续查看请求访问情况以及进行调试等操作,通过格式化输出的方式将请求的URI信息记录到日志中,
+ // 输出的日志级别为INFO,通常用于记录一些重要的运行时信息,方便运维人员或者开发人员了解系统的访问情况。
+ logger.info("request url :{}", request.getRequestURI());
+
+ // 从LearnChapterQueue类中获取章节队列对象(BlockingQueue),这个队列可能是用于存储学习相关章节信息的一种数据结构,
+ // 后续会将队列中的数据添加到ModelAndView对象中传递给视图进行展示,具体展示方式取决于前端页面如何处理这些章节数据(例如可能展示章节列表等情况)。
+ BlockingQueue chapterQueue = LearnChapterQueue.getChapterQueue();
+
+ // 将章节队列中的数据转换为数组形式,添加到ModelAndView对象中,设置属性名为"chapterList",方便在视图中通过这个属性名获取章节相关数据进行展示,
+ // 例如在首页上循环展示章节名称等相关内容(具体展示逻辑由前端页面模板决定)。
+ model.addObject("chapterList", chapterQueue.toArray());
+
+ // 通过BrowserUtils工具类的isMobile方法判断请求头中的"user-agent"信息是否表示当前访问是来自移动端设备,
+ // 如果是移动端访问,设置ModelAndView的视图名称为"mobile/index",表示返回移动端对应的首页视图页面(具体视图页面的内容和样式由对应的前端页面模板决定);
+ // 如果不是移动端访问,设置视图名称为"index",表示返回普通桌面端等设备对应的首页视图页面,根据不同设备类型展示合适的首页内容给用户查看。
+ if (BrowserUtils.isMobile(request.getHeader("user-agent"))) {
+ model.setViewName("mobile/index");
+ } else {
+ model.setViewName("index");
+ }
+
return model;
}
-
+
+ /**
+ * 处理百度验证页面("baidu_verify_5agfTbCO3Q")的GET请求,该页面可能是用于百度搜索引擎对网站进行验证等相关操作的特定页面,
+ * 此方法仅简单地设置要返回的视图名称为"thirdparty/baidu_verify_5agfTbCO3Q",使得Spring MVC框架能够渲染对应的验证页面展示给客户端,暂未涉及其他复杂的数据传递等操作。
+ *
+ * @param model ModelAndView对象,用于设置视图名称,在这里将视图名称设置为"thirdparty/baidu_verify_5agfTbCO3Q",指定要返回的页面视图,方便Spring MVC框架进行后续的视图渲染操作。
+ * @return 返回配置好视图名称的ModelAndView对象,供Spring MVC框架根据视图名称渲染并展示百度验证页面("baidu_verify_5agfTbCO3Q")给客户端。
+ */
@RequestMapping(value = "/baidu_verify_5agfTbCO3Q", method = RequestMethod.GET)
public ModelAndView baidu_verify_5agfTbCO3Q(ModelAndView model) {
- model.setViewName("thirdparty/baidu_verify_5agfTbCO3Q");
+ model.setViewName("thirdparty/baidu_verify_5agfTbCO3Q");
return model;
}
-
+
+ /**
+ * 处理另一个百度验证页面("baidu_verify_iAm7387J0l")的GET请求,与上一个百度验证页面类似,也是用于百度搜索引擎相关验证操作的特定页面,
+ * 同样只是设置视图名称为"thirdparty/baidu_verify_iAm7387J0l",以便Spring MVC框架渲染对应的页面展示给客户端,没有其他复杂的数据处理逻辑。
+ *
+ * @param model ModelAndView对象,用于设置视图名称,在这里将视图名称设置为"thirdparty/baidu_verify_iAm7387J0l",指定要返回的页面视图,方便Spring MVC框架进行后续的视图渲染操作。
+ * @return 返回配置好视图名称的ModelAndView对象,供Spring MVC框架根据视图名称渲染并展示百度验证页面("baidu_verify_iAm7387J0l")给客户端。
+ */
@RequestMapping(value = "/baidu_verify_iAm7387J0l", method = RequestMethod.GET)
public ModelAndView baidu_verify_iAm7387J0l(ModelAndView model) {
- model.setViewName("thirdparty/baidu_verify_iAm7387J0l");
+ model.setViewName("thirdparty/baidu_verify_iAm7387J0l");
return model;
}
-
+
+ /**
+ * 处理搜狗网站验证页面("sogousiteverification")的GET请求,该页面大概率是用于搜狗搜索引擎对网站进行验证等相关操作的特定页面,
+ * 方法中仅设置视图名称为"thirdparty/sogousiteverification",供Spring MVC框架渲染对应的页面展示给客户端,不涉及复杂的数据传递与处理操作。
+ *
+ * @param model ModelAndView对象,用于设置视图名称,在这里将视图名称设置为"thirdparty/sogousiteverification",指定要返回的页面视图,方便Spring MVC框架进行后续的视图渲染操作。
+ * @return 返回配置好视图名称的ModelAndView对象,供Spring MVC框架根据视图名称渲染并展示搜狗网站验证页面给客户端。
+ */
@RequestMapping(value = "/sogousiteverification", method = RequestMethod.GET)
public ModelAndView sogousiteverification(ModelAndView model) {
- model.setViewName("thirdparty/sogousiteverification");
+ model.setViewName("thirdparty/sogousiteverification");
return model;
}
-
- @RequestMapping(value = "error404", method = RequestMethod.GET)
+
+ /**
+ * 处理404错误页面的GET请求,用于展示当用户访问不存在的页面等情况时的404错误提示页面,
+ * 此方法简单地设置要返回的视图名称为"404",使得Spring MVC框架能够渲染对应的错误页面展示给客户端,告知用户请求的页面不存在。
+ *
+ * @param model ModelAndView对象,用于设置视图名称,在这里将视图名称设置为"404",指定要返回的页面视图,方便Spring MVC框架进行后续的视图渲染操作。
+ * @return 返回配置好视图名称的ModelAndView对象,供Spring MVC框架根据视图名称渲染并展示404错误页面给客户端,提示用户所访问的页面不存在。
+ */
+ @RequestMapping(value = "error404", method = RequestMethod.GET)
public ModelAndView error404(ModelAndView model) {
- model.setViewName("404");
+ model.setViewName("404");
return model;
}
- @RequestMapping(value = "error500", method = RequestMethod.GET)
+ /**
+ * 处理500错误页面的GET请求,用于展示当服务器内部出现错误等情况时的500错误提示页面,
+ * 该方法仅仅设置视图名称为"500",让Spring MVC框架渲染对应的错误页面展示给客户端,告知用户服务器出现了内部错误情况。
+ *
+ * @param model ModelAndView对象,用于设置视图名称,在这里将视图名称设置为"500",指定要返回的页面视图,方便Spring MVC框架进行后续的视图渲染操作。
+ * @return 返回配置好视图名称的ModelAndView对象,供Spring MVC框架根据视图名称渲染并展示500错误页面给客户端,提示用户服务器发生了内部错误。
+ */
+ @RequestMapping(value = "error500", method = RequestMethod.GET)
public ModelAndView error500(ModelAndView model) {
- model.setViewName("500");
+ model.setViewName("500");
return model;
}
-
-}
+}
\ No newline at end of file
diff --git a/tamguo-tms/src/main/java/com/tamguo/web/tiku/KnowPointController.java b/tamguo-tms/src/main/java/com/tamguo/web/tiku/KnowPointController.java
index 5767a38..7083a96 100644
--- a/tamguo-tms/src/main/java/com/tamguo/web/tiku/KnowPointController.java
+++ b/tamguo-tms/src/main/java/com/tamguo/web/tiku/KnowPointController.java
@@ -24,38 +24,96 @@ import com.tamguo.modules.tiku.service.IChapterService;
import com.tamguo.modules.tiku.service.ICourseService;
import com.tamguo.modules.tiku.service.ISubjectService;
+// @Controller注解用于将这个类标记为Spring MVC框架中的一个控制器组件,意味着Spring容器会在启动时扫描到这个类,并将其管理起来,
+// 使得这个类中的方法能够处理对应的HTTP请求,根据请求的映射关系(通过@RequestMapping等注解定义)调用相应的业务逻辑方法,然后返回视图或者数据响应给客户端,
+// 在这里主要用于处理与知识点相关的业务操作,具体为展示知识点详情页面以及获取相关联的数据信息等功能对应的请求处理逻辑。
@Controller
public class KnowPointController {
+ // 创建一个日志记录器对象,用于记录在这个控制器类中发生的一些关键操作、调试信息或者错误信息等,
+ // 通过LoggerFactory根据当前类的Class对象获取对应的Logger实例,方便后续在代码中进行日志输出操作,便于调试和查看运行情况。
private Logger logger = LoggerFactory.getLogger(getClass());
+
+ // 通过@Autowired注解自动注入IKnowPointService接口的实现类实例,IKnowPointService用于处理与知识点相关的各种业务逻辑,
+ // 比如根据知识点ID查询知识点详细信息、获取某个课程下的知识点列表等操作,在这个控制器的index方法中会调用其相关方法来实现具体的知识点相关业务功能。
@Autowired
IKnowPointService iKnowPointService;
+
+ // 自动注入IChapterService接口的实现类实例,IChapterService用于处理与章节相关的各种业务逻辑,
+ // 例如查询章节树结构等操作,在知识点详情页面展示时,可能需要获取与知识点相关联的章节信息进行展示,会调用其相应方法来获取相关章节数据。
@Autowired
IChapterService iChapterService;
+
+ // 注入ISubjectService接口的实现类实例,ISubjectService用于处理与学科(科目)相关的业务逻辑,
+ // 像根据学科ID查询学科详细信息等操作,在知识点详情页面展示时,会获取知识点所属学科的相关信息进行展示,需要调用该服务层接口的方法来获取学科数据。
@Autowired
ISubjectService iSubjectService;
+
+ // 注入ICourseService接口的实现类实例,ICourseService主要负责处理与课程相关的业务逻辑,
+ // 比如根据课程ID查询课程信息、获取某个学科下的课程列表等操作,在知识点详情页面展示相关数据时,也会涉及到课程相关信息的获取与展示,会调用它的相应方法来完成。
@Autowired
ICourseService iCourseService;
-
+
+ /**
+ * 处理知识点详情页面的GET请求,请求路径为"knowpoint/{uid}.html",其中{uid}是一个路径变量,表示知识点的唯一标识,
+ * 该方法用于获取知识点相关的详细信息以及与之关联的其他数据(如所属学科、相关课程、同课程下的其他知识点、相关章节等),
+ * 将获取到的数据添加到ModelAndView对象中,并设置相应的视图名称为"knowpoint",最后返回ModelAndView对象供Spring MVC框架渲染视图展示给客户端,展示知识点详情及其关联数据给用户查看。
+ *
+ * @param uid 知识点的唯一标识字符串,通过@PathVariable注解从请求路径中获取,用于指定要查询详细信息的具体知识点,传递给相关服务层方法作为查询依据,获取知识点及其关联的数据信息。
+ * @param model ModelAndView对象,用于设置视图名称以及向视图传递数据,在这里会将查询到的知识点相关的各种数据(知识点本身、所属学科、相关课程、章节列表、同课程下的知识点列表等)添加到该对象中,
+ * 然后设置视图名称为"knowpoint",最后返回该对象供Spring MVC框架进行视图渲染并展示知识点详情页面给客户端。
+ * @param request HttpServletRequest对象,用于获取请求相关的各种信息,在这里主要是获取请求的URI(通过request.getRequestURI()方法)记录日志,方便后续查看请求访问情况以及进行调试等操作。
+ * @return 返回配置好视图名称和知识点相关数据的ModelAndView对象,供Spring MVC框架根据视图名称渲染并展示知识点详情页面给客户端,展示相应的知识点信息以及关联数据给用户查看。
+ */
@SuppressWarnings("unchecked")
@RequestMapping(value = {"knowpoint/{uid}.html"}, method = RequestMethod.GET)
- public ModelAndView index(@PathVariable String uid , ModelAndView model , HttpServletRequest request) {
- // request url
- logger.info("request url :{} " , request.getRequestURI());
+ public ModelAndView index(@PathVariable String uid, ModelAndView model, HttpServletRequest request) {
+ // 使用日志记录器记录请求的URL信息,方便后续查看请求访问情况以及进行调试等操作,通过格式化输出的方式将请求的URI信息记录到日志中,
+ // 输出的日志级别为INFO,通常用于记录一些重要的运行时信息,方便运维人员或者开发人员了解系统的访问情况。
+ logger.info("request url :{} ", request.getRequestURI());
+
+ // 调用iKnowPointService的selectById方法,传入知识点的唯一标识(uid)作为参数,从数据库等数据源中查询对应的知识点详细信息(以KnowPointEntity对象形式返回),
+ // 获取到的知识点信息后续会添加到ModelAndView对象中传递给视图进行展示,例如展示知识点名称、描述等相关内容。
KnowPointEntity knowpoint = iKnowPointService.selectById(uid);
+
+ // 调用iSubjectService的selectById方法,传入知识点对象中的学科ID(knowpoint.getSubjectId())作为参数,从数据库等数据源中查询对应的学科详细信息(以SubjectEntity对象形式返回),
+ // 获取学科信息是为了在知识点详情页面展示该知识点所属的学科相关情况,例如学科名称等内容,将学科信息添加到ModelAndView对象中传递给视图进行展示。
SubjectEntity subject = iSubjectService.selectById(knowpoint.getSubjectId());
+
+ // 调用iCourseService的selectList方法,通过MyBatis Plus的条件构造器Condition创建查询条件,
+ // 使用eq("subject_id", subject.getId())表示筛选出学科ID等于当前知识点所属学科ID的课程列表,再通过orderAsc(Arrays.asList("sort"))按照"sort"字段升序排序课程列表,
+ // 获取与该知识点所属学科相关的课程列表信息(以List形式返回),用于在知识点详情页面展示同属一个学科下的其他课程情况,比如在页面上提供相关课程的导航链接等情况,将课程列表信息添加到ModelAndView对象中。
List courseList = iCourseService.selectList(Condition.create().eq("subject_id", subject.getId()).orderAsc(Arrays.asList("sort")));
+
+ // 调用iKnowPointService的selectList方法,通过条件构造器构建查询条件,
+ // 使用eq("course_id", knowpoint.getCourseId())表示筛选出课程ID等于当前知识点所属课程ID的知识点列表,获取与该知识点同属一个课程的其他知识点信息(以List形式返回),
+ // 这些知识点信息会添加到ModelAndView对象中,方便在知识点详情页面展示同课程下的其他知识点情况,例如在页面上列出其他知识点名称等相关内容。
List knowPointList = iKnowPointService.selectList(Condition.create().eq("course_id", knowpoint.getCourseId()));
+
+ // 调用iCourseService的selectById方法,传入知识点对象中的课程ID(knowpoint.getCourseId())作为参数,从数据库等数据源中查询对应的课程详细信息(以CourseEntity对象形式返回),
+ // 获取课程信息是为了在知识点详情页面展示该知识点所属的课程相关情况,例如课程名称等内容,将课程信息添加到ModelAndView对象中传递给视图进行展示。
CourseEntity course = iCourseService.selectById(knowpoint.getCourseId());
+
+ // 调用iChapterService的findChapterTree方法,传入知识点的ID(knowpoint.getId())作为参数,查询与该知识点相关的章节树结构信息(以List形式返回),
+ // 章节树结构信息可能是一种层级嵌套的数据结构,方便在页面上以树状形式展示章节的层级关系等情况,获取到的章节列表信息会添加到ModelAndView对象中用于视图展示。
List chapterList = iChapterService.findChapterTree(knowpoint.getId());
+
+ // 将查询到的知识点详细信息添加到ModelAndView对象中,设置属性名为"knowpoint",方便在视图中通过这个属性名获取知识点的各种详细内容进行展示,如知识点名称、描述等信息。
model.addObject("knowpoint", knowpoint);
+ // 把查询到的知识点所属学科的详细信息添加到ModelAndView对象中,属性名为"subject",用于在视图中展示学科相关情况,例如学科名称等内容,让用户了解知识点所属的学科背景。
model.addObject("subject", subject);
+ // 将获取到的知识点所属课程的详细信息添加到ModelAndView对象中,属性名为"course",方便在视图中展示课程相关情况,例如课程名称等信息。
model.addObject("course", course);
- model.addObject("chapterList" , chapterList);
+ // 把查询到的与知识点相关的章节列表信息添加到ModelAndView对象中,属性名为"chapterList",方便在视图中展示章节相关信息,例如以树状结构展示章节层级关系等情况。
+ model.addObject("chapterList", chapterList);
+ // 将同属一个学科下的课程列表信息添加到ModelAndView对象中,属性名为"courseList",以便在视图中展示相关课程信息,为用户提供更多课程相关的导航或参考信息。
model.addObject("courseList", courseList);
+ // 把获取到的同课程下的其他知识点列表信息添加到ModelAndView对象中,属性名为"knowPointList",方便在视图中展示其他知识点情况,例如列出知识点名称等内容。
model.addObject("knowPointList", knowPointList);
+
+ // 设置ModelAndView的视图名称为"knowpoint",表示返回名为"knowpoint"的视图页面,供Spring MVC框架根据这个视图名称进行视图渲染并展示知识点详情页面给客户端,展示相应的知识点及其关联数据给用户查看。
model.setViewName("knowpoint");
+
return model;
}
-
-}
+}
\ No newline at end of file
diff --git a/tamguo-tms/src/main/java/com/tamguo/web/tiku/PaperController.java b/tamguo-tms/src/main/java/com/tamguo/web/tiku/PaperController.java
index 2b7472f..4809f69 100644
--- a/tamguo-tms/src/main/java/com/tamguo/web/tiku/PaperController.java
+++ b/tamguo-tms/src/main/java/com/tamguo/web/tiku/PaperController.java
@@ -30,113 +30,156 @@ import java.util.List;
/**
* Controller - 试卷
- *
+ * 这个类主要作为Spring MVC的控制器,用于处理与试卷相关的各种HTTP请求,
+ * 通过调用不同的业务服务层接口来获取相应的数据,进行分页处理、条件筛选等操作,
+ * 并根据请求的情况返回视图或者数据响应给客户端,例如展示试卷列表页面以及试卷详情页面等功能。
+ *
* @author candy.tam
*
*/
@Controller
public class PaperController {
-
+
+ // 创建一个日志记录器对象,用于记录在这个控制器类中发生的一些关键操作、调试信息或者错误信息等,
+ // 通过LoggerFactory根据当前类的Class对象获取对应的Logger实例,方便后续在代码中进行日志输出操作,便于调试和查看运行情况。
private Logger logger = LoggerFactory.getLogger(getClass());
-
+
+ // 通过@Autowired注解自动注入ICourseService接口的实现类实例,ICourseService用于处理与课程相关的各种业务逻辑,
+ // 比如根据课程ID查询课程信息、获取某个学科下的课程列表等操作,在试卷相关操作中(如试卷列表页面展示时关联课程信息等情况)会调用其相关方法来实现具体的课程相关业务功能。
@Autowired
private ICourseService iCourseService;
+
+ // 注入ISysAreaService接口的实现类实例,ISysAreaService用于处理与系统区域相关的业务逻辑,
+ // 例如根据区域ID查询区域信息、获取特定层级的区域列表等操作,在试卷相关业务中(可能涉及按区域筛选试卷等情况)会用到该服务层接口的方法来获取区域相关数据。
@Autowired
private ISysAreaService iSysAreaService;
+
+ // 自动注入IPaperService接口的实现类实例,IPaperService主要负责处理与试卷相关的业务逻辑,
+ // 像根据试卷ID查询试卷信息、获取符合特定条件的试卷列表(分页查询并结合各种筛选条件)、查找试卷包含的题目信息等操作都会调用它的相应方法来完成。
@Autowired
private IPaperService iPaperService;
+
+ // 注入IQuestionService接口的实现类实例,IQuestionService用于处理与题目相关的业务逻辑,
+ // 在试卷详情页面展示时,需要获取试卷包含的题目列表进行展示,会调用其相关方法来获取题目相关数据。
@Autowired
private IQuestionService iQuestionService;
+
+ // 注入ISubjectService接口的实现类实例,ISubjectService用于处理与学科(科目)相关的业务逻辑,
+ // 例如根据学科ID查询学科详细信息等操作,在试卷相关操作中(如试卷列表页面展示所属学科信息、试卷详情页面关联学科信息等情况)会调用该服务层接口的方法来获取学科数据。
@Autowired
private ISubjectService iSubjectService;
+ /**
+ * 处理试卷列表页面的GET请求,请求路径格式为"paperlist/{subjectId}-{courseId}-{paperType}-{year}-{area}-{pageNum}.html",
+ * 其中各个{ }内的参数是路径变量,分别代表学科ID、课程ID、试卷类型、年份、区域、页码,
+ * 该方法用于获取试卷列表相关的各种数据(如课程信息、区域信息、学科信息、符合条件的试卷分页数据等),
+ * 根据请求头中用户代理信息判断是否是移动端访问,来设置不同的视图名称,最后将获取到的数据添加到ModelAndView对象中返回,供Spring MVC框架渲染相应的视图展示给客户端。
+ *
+ * @param request HttpServletRequest对象,用于获取请求相关的各种信息,在这里主要是获取请求的URI(通过request.getRequestURI()方法)记录日志,
+ * 以及获取请求头中的"user-agent"信息传递给BrowserUtils工具类判断是否是移动端访问,从而决定返回的视图名称等操作。
+ * @param subjectId 学科的唯一标识字符串,通过@PathVariable注解从请求路径中获取,用于指定要查询试卷列表所属的学科,传递给相关服务层方法作为查询依据,获取学科及其关联的数据信息,例如筛选该学科下的试卷等操作。
+ * @param courseId 课程的唯一标识字符串,同样是路径变量,用于指定要查询试卷列表相关的课程,传递给服务层方法查询课程信息以及筛选该课程相关的试卷等操作,获取相应的课程数据以及符合课程关联条件的试卷信息。
+ * @param paperType 试卷类型的标识字符串,从请求路径中获取,用于筛选特定类型的试卷,传递给条件构造器来构建查询条件,获取符合该类型要求的试卷列表信息,例如只查询真题、模拟题等不同类型的试卷,具体取决于业务中对试卷类型的分类和使用方式。
+ * @param year 年份字符串,用于筛选特定年份的试卷,作为查询条件之一传递给服务层构建查询条件,以便获取对应年份的试卷列表信息,例如查询2023年的试卷等情况。
+ * @param area 区域的标识字符串,从请求路径中获取,用于指定区域相关的筛选条件,传递给服务层方法查询对应区域信息以及筛选该区域相关的试卷等操作,获取相应的区域数据以及符合区域关联条件的试卷信息。
+ * @param pageNum 页码整数,通过路径变量获取,表示要查询的试卷列表的页码信息,用于创建Page对象来确定分页查询情况,获取对应页码的数据记录,方便实现试卷列表的分页展示功能。
+ * @param model ModelAndView对象,用于设置视图名称以及向视图传递数据,在这里会将查询到的课程列表、学科信息、当前课程、区域列表、试卷分页数据、试卷总数等各种试卷相关的数据添加到该对象中,
+ * 然后根据设备类型设置合适的视图名称,最后返回该对象供Spring MVC框架进行视图渲染并展示试卷列表页面给客户端。
+ * @return 返回配置好视图名称和试卷相关数据的ModelAndView对象,供Spring MVC框架根据视图名称渲染并展示试卷列表页面给客户端,展示相应的试卷信息以及关联数据给用户查看。
+ */
@SuppressWarnings("unchecked")
@RequestMapping(value = {"paperlist/{subjectId}-{courseId}-{paperType}-{year}-{area}-{pageNum}.html"}, method = RequestMethod.GET)
- public ModelAndView indexAction(HttpServletRequest request , @PathVariable String subjectId , @PathVariable String courseId , @PathVariable String paperType,
- @PathVariable String year , @PathVariable String area , @PathVariable Integer pageNum, ModelAndView model) {
- // request url
- logger.info("request url :{}" , request.getRequestURI());
- CourseEntity course = iCourseService.selectById(courseId);
- SysAreaEntity currArea = iSysAreaService.selectById(area);
+ public ModelAndView indexAction(HttpServletRequest request, @PathVariable String subjectId, @PathVariable String courseId, @PathVariable String paperType,
+ @PathVariable String year, @PathVariable String area, @PathVariable Integer pageNum, ModelAndView model) {
+ // 使用日志记录器记录请求的URL信息,方便后续查看请求访问情况以及进行调试等操作,通过格式化输出的方式将请求的URI信息记录到日志中,
+ // 输出的日志级别为INFO,通常用于记录一些重要的运行时信息,方便运维人员或者开发人员了解系统的访问情况。
+ logger.info("request url :{}", request.getRequestURI());
+
+ // 调用iCourseService的selectById方法,传入课程的唯一标识(courseId)作为参数,从数据库等数据源中查询对应的课程详细信息(以CourseEntity对象形式返回),
+ // 获取到的课程信息后续会添加到ModelAndView对象中传递给视图进行展示,例如展示课程名称、课程简介等相关内容,同时也可能用于其他关联查询或筛选操作(如筛选该课程下的试卷等情况)。
+ CourseEntity course = iCourseService.selectById(courseId);
+
+ // 调用iSysAreaService的selectById方法,传入区域的标识(area)作为参数,从数据库等数据源中查询对应的区域详细信息(以SysAreaEntity对象形式返回),
+ // 获取到的区域信息(在这里命名为currArea,表示当前筛选的区域)会添加到ModelAndView对象中,方便在试卷列表页面展示区域相关情况,例如区域名称等内容,也可能用于后续的筛选或关联操作。
+ SysAreaEntity currArea = iSysAreaService.selectById(area);
+
+ // 调用iCourseService的selectList方法,通过MyBatis Plus的条件构造器Condition创建查询条件,
+ // 使用eq("subject_id", subjectId)表示筛选出学科ID等于当前传入学科ID(subjectId)的课程列表,再通过orderBy("sort", true)按照"sort"字段升序排序课程列表,
+ // 获取与该学科相关的课程列表信息(以List形式返回),用于在试卷列表页面展示同属一个学科下的其他课程情况,比如在页面上提供相关课程的导航链接等情况,将课程列表信息添加到ModelAndView对象中。
List courseList = iCourseService.selectList(Condition.create().eq("subject_id", subjectId).orderBy("sort", true));
- SubjectEntity subject = iSubjectService.selectById(subjectId);
- List areaList = iSysAreaService.selectList(Condition.create().eq("tree_level", "0"));
-
- Page page = new Page<>(pageNum , 10);
- Condition condition = Condition.create();
- if(!StringUtils.isEmpty(subjectId) && !"0".equals(subjectId)) {
- condition.eq("subject_id", subjectId);
- }
- if(!StringUtils.isEmpty(paperType) && !"0".equals(paperType)) {
- condition.eq("type", paperType);
- }
- if(!StringUtils.isEmpty(courseId) && !"0".equals(courseId)) {
- condition.eq("course_id", courseId);
- }
- if(!StringUtils.isEmpty(year) && !"0".equals(year)) {
- condition.eq("year", year);
- }
- if(!StringUtils.isEmpty(area) && !"0".equals(area)) {
- condition.eq("area_id", area);
- }
- PageUtils result = PageUtils.getPage(iPaperService.selectPage(page , condition));
- if(courseList.size() > 0 && course == null) {
- course = courseList.get(0);
- }
- Integer total = iPaperService.selectCount(Condition.EMPTY);
- model.addObject("courseList", courseList);
- model.addObject("subject", subject);
- model.addObject("course", course);
- model.addObject("areaList", areaList);
- model.addObject("paperPage" , result);
- model.addObject("total" , total);
- model.addObject("courseId", courseId);
- model.addObject("paperType", paperType);
- model.addObject("year", year);
- model.addObject("area", area);
- model.addObject("currArea", currArea);
-
-
- if(BrowserUtils.isMobile(request.getHeader("user-agent"))) {
- model.setViewName("mobile/paperlist");
- }else {
- model.setViewName("paperlist");
- }
- return model;
- }
-
- @SuppressWarnings("unchecked")
- @RequestMapping(value = {"/paper/{paperId}.html"}, method = RequestMethod.GET)
- public ModelAndView indexAction(HttpServletRequest request , @PathVariable String paperId , ModelAndView model){
- try {
- // request url
- logger.info("request url :{}" , request.getRequestURI());
- model.setViewName("paper");
- PaperEntity paper = iPaperService.selectById(paperId);
- model.addObject("paper", paper);
- model.addObject("subject", StringUtils.isEmpty(paper.getSubjectId()) ? null : iSubjectService.selectById(paper.getSubjectId()));
- model.addObject("course", StringUtils.isEmpty(paper.getCourseId()) ? null : iCourseService.selectById(paper.getCourseId()));
-
- // 查询试卷题目
- model.addObject("questionList", iPaperService.findQuestionList(paperId));
- // 获取推荐试卷
- model.addObject("zhentiPaperList", iPaperService.selectPage(new Page(1, 5) , Condition.create().eq("subject_id", paper.getSubjectId()).eq("type",SystemConstant.ZHENGTI_PAPER_ID)).getRecords());
- model.addObject("moniPaperList", iPaperService.selectPage(new Page(1, 5) , Condition.create().eq("subject_id", paper.getSubjectId()).eq("type",SystemConstant.MONI_PAPER_ID)).getRecords());
- model.addObject("yatiPaperList", iPaperService.selectPage(new Page(1, 5) , Condition.create().eq("subject_id", paper.getSubjectId()).eq("type",SystemConstant.YATI_PAPER_ID)).getRecords());
- model.addObject("hotPaperList", iPaperService.selectPage(new Page(1, 5) , Condition.create().eq("subject_id", paper.getSubjectId()).eq("course_id", paper.getCourseId())).getRecords());
-
-
- if(BrowserUtils.isMobile(request.getHeader("user-agent"))) {
- model.setViewName("mobile/paper");
- }else {
- model.setViewName("paper");
- }
- return model;
- } catch (Exception e) {
- model.setViewName("404");
- return model;
+
+ // 调用iSubjectService的selectById方法,传入学科的唯一标识(subjectId)作为参数,从数据库等数据源中查询对应的学科详细信息(以SubjectEntity对象形式返回),
+ // 获取学科信息是为了在试卷列表页面展示该试卷列表所属的学科相关情况,例如学科名称等内容,将学科信息添加到ModelAndView对象中传递给视图进行展示。
+ SubjectEntity subject = iSubjectService.selectById(subjectId);
+
+ // 调用iSysAreaService的selectList方法,通过条件构造器构建查询条件,
+ // 使用eq("tree_level", "0")表示筛选出层级为0的区域列表(可能表示顶级区域或者根区域等情况,具体含义由业务中区域层级的定义决定),获取区域列表信息(以List形式返回),
+ // 这些区域列表信息会添加到ModelAndView对象中,方便在试卷列表页面展示可筛选的区域情况,例如提供区域下拉框供用户选择等情况。
+ List areaList = iSysAreaService.selectList(Condition.create().eq("tree_level", "0"));
+
+ // 创建一个Page对象,用于进行分页查询操作,传入当前页码(pageNum)和每页显示的记录数量(这里固定为10)来确定分页情况,
+ // 后续将这个Page对象以及其他构建的查询条件一起传递给iPaperService的selectPage方法进行分页查询符合条件的试卷列表信息。
+ Page page = new Page<>(pageNum, 10);
+
+ // 创建一个Condition对象,用于构建MyBatis Plus的查询条件,后续根据传入的各个参数情况,往这个条件对象中添加相应的条件,用于筛选符合要求的试卷列表信息。
+ Condition condition = Condition.create();
+
+ // 判断学科ID是否不为空且不等于"0"(可能"0"表示不进行学科筛选等特殊情况,具体由业务逻辑决定),
+ // 如果满足条件,使用eq("subject_id", subjectId)向条件对象中添加学科ID的筛选条件,即筛选出学科ID等于传入学科ID的试卷列表信息。
+ if (!StringUtils.isEmpty(subjectId) &&!"0".equals(subjectId)) {
+ condition.eq("subject_id", subjectId);
+ }
+
+ // 类似地,判断试卷类型是否不为空且不等于"0",如果是,则添加试卷类型的筛选条件,筛选出符合该类型要求的试卷列表信息,例如只查询真题、模拟题等不同类型的试卷。
+ if (!StringUtils.isEmpty(paperType) &&!"0".equals(paperType)) {
+ condition.eq("type", paperType);
+ }
+
+ // 判断课程ID是否满足相应条件,若满足则添加课程ID的筛选条件,用于获取该课程相关的试卷信息,例如筛选出属于某个具体课程的试卷列表。
+ if (!StringUtils.isEmpty(courseId) &&!"0".equals(courseId)) {
+ condition.eq("course_id", courseId);
+ }
+
+ // 对年份参数进行类似的判断和条件添加操作,筛选出对应年份的试卷列表信息,比如只展示2023年的试卷等情况。
+ if (!StringUtils.isEmpty(year) &&!"0".equals(year)) {
+ condition.eq("year", year);
}
-
- }
-
-}
+
+ // 根据区域ID参数情况添加区域筛选条件,获取该区域相关的试卷信息,确保查询到的试卷列表是与指定区域相关的。
+ if (!StringUtils.isEmpty(area) &&!"0".equals(area)) {
+ condition.eq("area_id", area);
+ }
+
+ // 调用PageUtils工具类的getPage方法,传入iPaperService的selectPage方法返回的结果(即分页查询到的试卷列表信息),进行一些分页相关的处理(具体处理逻辑由PageUtils类决定),
+ // 获取处理后的分页数据结果(以PageUtils对象形式返回),包含了分页相关的数据(如总记录数、当前页码、每页记录数等信息以及试卷记录列表等内容),将其添加到ModelAndView对象中,用于在视图中展示试卷列表以及分页相关的情况。
+ PageUtils result = PageUtils.getPage(iPaperService.selectPage(page, condition));
+
+ // 判断课程列表的大小是否大于0且当前课程对象为null(可能存在传入的课程ID对应的课程不存在,但有同学科下的其他课程情况),
+ // 如果满足条件,说明可以从课程列表中取第一个课程作为默认展示的课程(具体业务逻辑可能根据实际情况而定),将其赋值给course变量,后续添加到ModelAndView对象中用于视图展示。
+ if (courseList.size() > 0 && course == null) {
+ course = courseList.get(0);
+ }
+
+ // 调用iPaperService的selectCount方法,传入空的Condition对象(表示不添加额外筛选条件,可能用于获取全部试卷的总数等情况,具体取决于业务逻辑),
+ // 查询试卷的总数量(以整数形式返回),将试卷总数添加到ModelAndView对象中,方便在页面上展示试卷的总数量等相关信息,例如提示用户共有多少份试卷等情况。
+ Integer total = iPaperService.selectCount(Condition.EMPTY);
+
+ // 将查询到的课程列表信息添加到ModelAndView对象中,设置属性名为"courseList",方便在视图中通过这个属性名获取课程列表数据进行展示,例如循环展示课程名称等相关内容。
+ model.addObject("courseList", courseList);
+ // 把学科信息添加到ModelAndView对象中,属性名为"subject",用于在视图中展示学科相关情况,例如学科名称等内容,让用户了解试卷所属的学科背景。
+ model.addObject("subject", subject);
+ // 将当前课程的详细信息添加到ModelAndView对象中,属性名为"course",方便在视图中展示课程的各种详细内容,如课程名称、简介等信息。
+ model.addObject("course", course);
+ // 把区域列表信息添加到ModelAndView对象中,属性名为"areaList",以便在视图中展示可筛选的区域情况,例如以下拉框形式展示区域选项等情况。
+ model.addObject("areaList", areaList);
+ // 将处理后的试卷分页数据添加到ModelAndView对象中,属性名为"paperPage",方便在视图中展示试卷列表以及分页相关的信息,例如展示试卷标题、分页导航条等内容。
+ model.addObject("paperPage", result);
+ // 把试卷总数添加到ModelAndView对象中,属性名为"total",用于在视图中展示试卷的总数量相关信息,给用户一个整体的试卷数量提示。
+ model.addObject("total", total);
+ // 将课程ID添加到ModelAndView对象中,属性名为"courseId",可能在页面上用于一些与课程相关的操作或者链接生成等情况(具体取决于前端页面的业务逻辑设计)。
+ model.addObject("courseId", courseId);
+ // 同样把试卷类型添加到ModelAndView对象中,属性名为"paperType",方便在页面上展示当前筛选的试卷类型情况,或者用于根据类型进行其他相关操作等情况。
+ model.addObject("paperType", paperType);
+ // 将年份信息添加到ModelAndView对象中,属性名为"year",用于在视图中展示当前筛选的年份情况,例如提示用户当前展示的是哪一年的试卷等情况。
+ model.addObject("year", year);
+ // 把区域标识添加到ModelAndView对象中,属性名为"area",可能在页面上用于显示当前筛选的区域情况或者进行区域相关的操作等情况。
\ No newline at end of file
diff --git a/tamguo-tms/src/main/java/com/tamguo/web/tiku/QuestionContrller.java b/tamguo-tms/src/main/java/com/tamguo/web/tiku/QuestionContrller.java
index cf8922d..c02c368 100644
--- a/tamguo-tms/src/main/java/com/tamguo/web/tiku/QuestionContrller.java
+++ b/tamguo-tms/src/main/java/com/tamguo/web/tiku/QuestionContrller.java
@@ -26,95 +26,157 @@ import com.tamguo.modules.tiku.model.enums.QuestionTypeEnum;
import com.tamguo.modules.tiku.model.queue.LearnChapterQueue;
import com.tamguo.utils.BrowserUtils;
+// @Controller注解用于将这个类标记为Spring MVC框架中的一个控制器组件,意味着Spring容器会在启动时扫描到这个类,并将其管理起来,
+// 使得这个类中的方法能够处理对应的HTTP请求,根据请求的映射关系(通过@RequestMapping等注解定义)调用相应的业务逻辑方法,然后返回视图或者数据响应给客户端,
+// 在这里主要用于处理与题目相关的各种业务操作,例如展示题目列表页面、单个题目详情页面以及提供获取题目信息的接口等功能。
@Controller
public class QuestionContrller {
-
+
+ // 创建一个日志记录器对象,用于记录在这个控制器类中发生的一些关键操作、调试信息或者错误信息等,
+ // 通过LoggerFactory根据当前类的Class对象获取对应的Logger实例,方便后续在代码中进行日志输出操作,便于调试和查看运行情况。
private Logger logger = LoggerFactory.getLogger(getClass());
+ // 通过@Autowired注解自动注入IQuestionService接口的实现类实例,IQuestionService用于处理与题目相关的各种业务逻辑,
+ // 比如根据题目ID查询题目详细信息、进行题目列表的分页查询等操作,在这个控制器的各个方法中会调用其相关方法来实现具体的题目相关业务功能。
@Autowired
private IQuestionService iQuestionService;
+
+ // 自动注入IChapterService接口的实现类实例,IChapterService用于处理与章节相关的各种业务逻辑,
+ // 例如根据章节ID查询章节信息、获取章节相关的下一章信息等操作,在题目相关操作中(如题目列表按章节筛选、题目关联所属章节等情况)会调用其相关方法来获取章节相关数据。
@Autowired
private IChapterService iChapterService;
+
+ // 注入ISubjectService接口的实现类实例,ISubjectService用于处理与学科(科目)相关的业务逻辑,
+ // 像根据学科ID查询学科详细信息等操作,在题目相关操作中(如题目列表展示所属学科信息、题目关联所属学科等情况)会调用该服务层接口的方法来获取学科数据。
@Autowired
private ISubjectService iSubjectService;
+
+ // 注入ICourseService接口的实现类实例,ICourseService主要负责处理与课程相关的业务逻辑,
+ // 比如根据课程ID查询课程信息、题目关联所属课程等操作,在题目相关业务中会调用它的相应方法来获取课程相关数据以及进行关联查询等操作。
@Autowired
private ICourseService iCourseService;
+
+ // 注入IQuestionAnswerService接口的实现类实例,IQuestionAnswerService用于处理与题目答案相关的业务逻辑,
+ // 在展示题目详情页面时,需要获取题目对应的答案列表进行展示,会调用其相关方法来获取答案相关数据。
@Autowired
private IQuestionAnswerService iQuestionAnswerService;
+
+ // 注入IQuestionOptionsService接口的实现类实例,IQuestionOptionsService用于处理与题目选项相关的业务逻辑,
+ // 例如获取题目包含的选项列表等操作,在展示题目详情以及题目列表时,需要为题目设置对应的选项信息,会调用其相关方法来获取选项数据并进行相应设置。
@Autowired
private IQuestionOptionsService iQuestionOptionsService;
- // 章节
+ // 创建一个阻塞队列(BlockingQueue)用于存储章节实体对象(ChapterEntity),队列容量设置为10,
+ // 可能用于在某些业务逻辑中对章节信息进行缓存、排队处理或者传递章节相关数据(从当前代码来看,在questionList方法中有向这个队列添加章节信息的操作),具体作用取决于整体业务需求。
BlockingQueue chapterQueue = new LinkedBlockingQueue(10);
-
+
+ /**
+ * 处理题目列表页面的GET请求,请求路径格式为"questionlist/{chapterId}-{current}-{size}.html",
+ * 其中{chapterId}是章节的唯一标识、{current}表示当前页码、{size}表示每页显示的题目数量,这些都是路径变量,
+ * 该方法用于获取题目列表相关的各种数据(如所属章节、课程、学科信息、题目分页数据以及为题目设置选项和类型描述等),
+ * 根据请求头中用户代理信息判断是否是移动端访问,来设置不同的视图名称,最后将获取到的数据添加到ModelAndView对象中返回,供Spring MVC框架渲染相应的视图展示给客户端,同时还会将章节信息添加到特定的队列中。
+ *
+ * @param chapterId 章节的唯一标识字符串,通过@PathVariable注解从请求路径中获取,用于指定要查询题目列表所属的章节,传递给相关服务层方法作为查询依据,获取章节及其关联的数据信息,例如筛选该章节下的题目等操作。
+ * @param current 表示当前页码的整数,通过路径变量获取,用于创建Page对象来确定分页查询情况,获取对应页码的数据记录,方便实现题目列表的分页展示功能,告诉服务层要获取第几页的题目数据。
+ * @param size 表示每页显示题目数量的整数,同样是路径变量,用于设置Page对象中每页的记录数,确定分页查询时每页显示的题目数量,以便获取符合要求的题目分页列表信息。
+ * @param model ModelAndView对象,用于设置视图名称以及向视图传递数据,在这里会将查询到的学科信息、课程信息、章节信息、父章节信息、下一章信息、题目分页列表等各种题目相关的数据添加到该对象中,
+ * 然后根据设备类型设置合适的视图名称,最后返回该对象供Spring MVC框架进行视图渲染并展示题目列表页面给客户端,同时还会向章节队列中添加章节信息。
+ * @param request HttpServletRequest对象,用于获取请求相关的各种信息,在这里主要是获取请求的URI(通过request.getRequestURI()方法)记录日志,
+ * 以及获取请求头中的"user-agent"信息传递给BrowserUtils工具类判断是否是移动端访问,从而决定返回的视图名称等操作。
+ * @return 返回配置好视图名称和题目相关数据的ModelAndView对象,供Spring MVC框架根据视图名称渲染并展示题目列表页面给客户端,展示相应的题目信息以及关联数据给用户查看,同时章节信息会被添加到章节队列中用于可能的后续业务处理。
+ * @throws InterruptedException 因为使用了阻塞队列(BlockingQueue),在向队列添加元素(LearnChapterQueue.add(chapter)操作)时可能会抛出此异常,需要在调用该方法的地方进行处理,
+ * 例如在当前方法签名中声明抛出该异常,由上层调用者决定如何处理这种线程被中断的情况(通常在多线程环境下可能出现)。
+ */
@SuppressWarnings("unchecked")
@RequestMapping(value = {"questionlist/{chapterId}-{current}-{size}.html"}, method = RequestMethod.GET)
- public ModelAndView questionList(@PathVariable String chapterId , @PathVariable Integer current ,
- @PathVariable Integer size , ModelAndView model , HttpServletRequest request) throws InterruptedException{
- // request url
- logger.info("request url :{} " , request.getRequestURI());
+ public ModelAndView questionList(@PathVariable String chapterId, @PathVariable Integer current,
+ @PathVariable Integer size, ModelAndView model, HttpServletRequest request) throws InterruptedException {
+ // 使用日志记录器记录请求的URL信息,方便后续查看请求访问情况以及进行调试等操作,通过格式化输出的方式将请求的URI信息记录到日志中,
+ // 输出的日志级别为INFO,通常用于记录一些重要的运行时信息,方便运维人员或者开发人员了解系统的访问情况。
+ logger.info("request url :{} ", request.getRequestURI());
+ // 调用iChapterService的selectById方法,传入章节的唯一标识(chapterId)作为参数,从数据库等数据源中查询对应的章节详细信息(以ChapterEntity对象形式返回),
+ // 获取到的章节信息后续会用于关联查询其他相关数据(如所属课程等情况),也会添加到ModelAndView对象中传递给视图进行展示,例如展示章节名称等相关内容。
ChapterEntity chapter = iChapterService.selectById(chapterId);
+
+ // 调用iCourseService的selectById方法,传入章节对象中的课程ID(chapter.getCourseId())作为参数,从数据库等数据源中查询对应的课程详细信息(以CourseEntity对象形式返回),
+ // 获取课程信息是为了在题目列表页面展示题目所属的课程相关情况,例如课程名称等内容,将课程信息添加到ModelAndView对象中传递给视图进行展示,同时也用于后续关联查询所属学科信息等操作。
CourseEntity course = iCourseService.selectById(chapter.getCourseId());
+
+ // 调用iSubjectService的selectById方法,传入课程对象中的学科ID(course.getSubjectId())作为参数,从数据库等数据源中查询对应的学科详细信息(以SubjectEntity对象形式返回),
+ // 获取学科信息用于在题目列表页面展示该题目列表所属的学科相关情况,例如学科名称等内容,将学科信息添加到ModelAndView对象中传递给视图进行展示。
SubjectEntity subject = iSubjectService.selectById(course.getSubjectId());
+
+ // 调用iChapterService的selectById方法,传入章节对象中的父章节代码(chapter.getParentCode())作为参数,从数据库等数据源中查询对应的父章节详细信息(以ChapterEntity对象形式返回),
+ // 获取父章节信息可能用于在题目列表页面展示章节的层级关系等情况,例如显示当前章节的上级章节名称等内容,将父章节信息添加到ModelAndView对象中传递给视图进行展示。
ChapterEntity parentChapter = iChapterService.selectById(chapter.getParentCode());
- ChapterEntity nextChapter = iChapterService.selectNextChapter(chapter.getParentCode() , chapter.getId());
-
+
+ // 调用iChapterService的selectNextChapter方法,传入章节的父章节代码(chapter.getParentCode())和当前章节的ID(chapter.getId())作为参数,查询当前章节的下一章信息(以ChapterEntity对象形式返回),
+ // 获取下一章信息可以用于在题目列表页面提供章节导航功能等情况,例如提示用户下一章的相关信息或者提供跳转到下一章的链接等,将下一章信息添加到ModelAndView对象中传递给视图进行展示。
+ ChapterEntity nextChapter = iChapterService.selectNextChapter(chapter.getParentCode(), chapter.getId());
+
+ // 创建一个Page对象,用于进行分页查询操作,先实例化一个空的Page对象,后续会设置当前页码和每页记录数等属性来确定具体的分页情况。
Page page = new Page<>();
+ // 设置Page对象的当前页码属性,传入从请求路径中获取的当前页码(current)参数,告诉服务层要获取第几页的题目数据,以便进行分页查询操作。
page.setCurrent(current);
+ // 设置Page对象的每页记录数属性,传入从请求路径中获取的每页题目数量(size)参数,确定分页查询时每页显示的题目数量,使得查询返回符合要求的题目分页列表信息。
page.setSize(size);
- Page questionList = iQuestionService.selectPage(page , Condition.create().eq("chapter_id", chapterId).orderDesc(Arrays.asList("id")));
- for(int i=0 ;i对象形式返回),其中包含了题目记录列表以及分页相关的信息(如总记录数、当前页码、每页记录数等)。
+ Page questionList = iQuestionService.selectPage(page, Condition.create().eq("chapter_id", chapterId).orderDesc(Arrays.asList("id")));
+
+ // 循环遍历题目分页列表中的每一条题目记录,对每个题目进行相关数据设置操作,主要是设置题目选项和题目类型描述信息。
+ for (int i = 0; i < questionList.getRecords().size(); i++) {
+ // 从题目分页列表中获取当前遍历到的题目实体对象,用于后续设置其选项和类型描述等相关信息。
QuestionEntity question = questionList.getRecords().get(i);
- List questionOptions = iQuestionOptionsService.selectList(Condition.create().eq("question_id" , question.getId()));
+ // 调用iQuestionOptionsService的selectList方法,通过条件构造器构建查询条件,
+ // 使用eq("question_id", question.getId())表示筛选出题目ID等于当前题目ID的选项列表,获取该题目包含的所有选项信息(以List形式返回),
+ // 然后将获取到的选项列表设置到题目对象的questionOptions属性中,方便在视图中展示题目对应的选项内容,例如选择题的各个选项等情况。
+ List questionOptions = iQuestionOptionsService.selectList(Condition.create().eq("question_id", question.getId()));
question.setQuestionOptions(questionOptions);
+ // 通过QuestionTypeEnum枚举类的getQuestionType方法,传入题目对象中的题目类型字段(question.getQuestionType())获取对应的题目类型枚举对象,
+ // 再调用该枚举对象的getDesc方法获取题目类型的描述信息(例如将题目类型代码转换为具体的文字描述,如"单选题"、"多选题"等情况),将题目类型描述设置到题目对象的questionType属性中,
+ // 以便在视图中展示题目类型的详细描述信息,让用户更清晰地了解题目的类型情况。
question.setQuestionType(QuestionTypeEnum.getQuestionType(question.getQuestionType()).getDesc());
}
+
+ // 将查询到的学科信息添加到ModelAndView对象中,设置属性名为"subject",方便在视图中通过这个属性名获取学科列表数据进行展示,例如展示学科名称等相关内容,让用户了解题目所属的学科背景。
model.addObject("subject", subject);
+ // 把课程信息添加到ModelAndView对象中,属性名为"course",用于在视图中展示课程相关情况,例如课程名称等内容,让用户知道题目所属的课程信息。
model.addObject("course", course);
+ // 将章节信息添加到ModelAndView对象中,属性名为"chapter",方便在视图中展示章节相关情况,例如章节名称、章节顺序等内容,让用户明确题目所属的章节情况。
model.addObject("chapter", chapter);
- model.addObject("parentChapter" , parentChapter);
- model.addObject("nextChapter" , nextChapter);
+ // 把父章节信息添加到ModelAndView对象中,属性名为"parentChapter",用于在视图中展示章节的层级关系情况,例如显示当前章节的上级章节名称等内容。
+ model.addObject("parentChapter", parentChapter);
+ // 将下一章信息添加到ModelAndView对象中,属性名为"nextChapter",方便在视图中展示章节导航相关情况,例如提示用户下一章的相关信息或者提供跳转到下一章的链接等。
+ model.addObject("nextChapter", nextChapter);
+ // 把处理好的题目分页列表信息添加到ModelAndView对象中,属性名为"questionList",以便在视图中展示题目列表以及分页相关的信息,例如展示题目标题、分页导航条等内容。
model.addObject("questionList", questionList);
+ // 将课程的学科ID添加到ModelAndView对象中,属性名为"subjectId",可能在页面上用于一些与学科相关的操作或者链接生成等情况(具体取决于前端页面的业务逻辑设计)。
model.addObject("subjectId", course.getSubjectId());
+ // 同样把课程的唯一标识添加到ModelAndView对象中,属性名为"courseId",方便在页面上进行一些与课程相关的操作,例如根据课程ID查询其他课程相关信息等情况。
model.addObject("courseId", course.getId());
-
+
+ // 将当前章节信息添加到LearnChapterQueue队列中(假设LearnChapterQueue是一个用于管理章节信息的自定义队列类),
+ // 具体作用可能是用于缓存章节信息、后续进行章节相关的统计或其他业务逻辑处理等情况,这里将章节添加到队列中,方便在其他地方使用该章节数据(具体取决于LearnChapterQueue类的具体实现和业务用途)。
LearnChapterQueue.add(chapter);
-
- if(BrowserUtils.isMobile(request.getHeader("user-agent"))) {
- model.setViewName("mobile/questionList");
- }else {
- model.setViewName("questionList");
- }
- return model;
- }
-
- /**
- * 直接访问题目
- * @param uid
- * @param model
- * @return
- */
- @SuppressWarnings("unchecked")
- @RequestMapping(value = {"/question/{uid}.html"}, method = RequestMethod.GET)
- public ModelAndView question(@PathVariable String uid , ModelAndView model , HttpServletRequest request){
- // request url
- logger.info("request url :{}" , request.getRequestURI());
- model.setViewName("question");
- QuestionEntity question = iQuestionService.selectById(uid);
- List questionOptions = iQuestionOptionsService.selectList(Condition.create().eq("question_id" , question.getId()));
- question.setQuestionOptions(questionOptions);
- question.setQuestionType(QuestionTypeEnum.getQuestionType(question.getQuestionType()).getDesc());
- model.addObject("question", question);
- model.addObject("course", iCourseService.selectById(question.getCourseId()));
- model.addObject("answerList", iQuestionAnswerService.selectList(Condition.create().eq("question_id", uid).orderDesc(Arrays.asList("create_date"))));
- if(BrowserUtils.isMobile(request.getHeader("user-agent"))) {
- model.setViewName("mobile/question");
- }else {
- model.setViewName("question");
- }
+
+ // 通过BrowserUtils工具类的isMobile方法判断请求头中的"user-agent"信息是否表示当前访问是来自移动端设备,
+ // 如果是移动端访问,设置ModelAndView的视图名称为"mobile/questionList",表示返回移动端对应的题目列表视图页面(具体视图页面的内容和样式由对应的前端页面模板决定);
+ // 如果不是移动端访问,设置视图名称为"questionList",表示返回普通桌面端等设备对应的题目列表视图页面,根据不同设备类型展示合适的题目列表内容给用户查看。
+ if (BrowserUtils.isMobile(request.getHeader("user-agent"))) {
+ model.setViewName("mobile/questionList");
+ } else {
+ model.setViewName("questionList");
+ }
+
return model;
}
+
+/**
+ * 处理直接访问题目详情页面的GET请求
@RequestMapping(value = {"question/getQuestion/{uid}.html"}, method = RequestMethod.GET)
@ResponseBody
diff --git a/tamguo-tms/src/main/java/com/tamguo/web/tiku/SmsController.java b/tamguo-tms/src/main/java/com/tamguo/web/tiku/SmsController.java
index 795def2..9684315 100644
--- a/tamguo-tms/src/main/java/com/tamguo/web/tiku/SmsController.java
+++ b/tamguo-tms/src/main/java/com/tamguo/web/tiku/SmsController.java
@@ -10,21 +10,38 @@ import com.aliyuncs.exceptions.ClientException;
import com.tamguo.common.utils.Result;
import com.tamguo.modules.sys.service.ISmsService;
+// @Controller注解用于将这个类标记为Spring MVC框架中的一个控制器组件,意味着Spring容器会在启动时扫描到这个类,并将其管理起来,
+// 使得这个类中的方法能够处理对应的HTTP请求,根据请求的映射关系(通过@RequestMapping等注解定义)调用相应的业务逻辑方法,然后返回视图或者数据响应给客户端,
+// 在这里主要用于处理与短信发送(具体为发送找回密码相关短信)的业务操作,即接收前端请求并调用相关服务层方法来尝试发送短信,然后将结果返回给前端。
@Controller
public class SmsController {
-
+
+ // 通过@Autowired注解自动注入ISmsService接口的实现类实例,ISmsService用于处理与短信发送相关的各种业务逻辑,
+ // 比如在这里具体用于发送找回密码的短信,在sendFindPasswordSms方法中会调用其对应的发送短信方法来实现具体的短信发送功能。
@Autowired
ISmsService iSmsService;
+ /**
+ * 处理发送找回密码短信的GET请求,请求路径为"sms/sendFindPasswordSms.html",该方法接收一个手机号码(mobile)作为参数,
+ * 用于调用iSmsService的sendFindPasswordSms方法来尝试发送找回密码相关的短信,若发送成功则将服务层返回的结果(以Result对象形式)直接返回给前端,
+ * 若发送过程中出现异常(具体为阿里云客户端异常ClientException,可能是短信服务配置问题、网络问题等导致与阿里云短信服务通信异常等情况),则打印异常堆栈信息,并返回一个表示失败的Result对象(状态码为500)给前端告知发送失败。
+ *
+ * @param mobile 表示要接收找回密码短信的手机号码的字符串参数,从请求中获取,传递给iSmsService的sendFindPasswordSms方法作为短信发送的目标手机号,确定短信要发送到哪个手机号上。
+ * @return 返回一个Result对象,正常情况下返回iSmsService的sendFindPasswordSms方法返回的Result对象,其中包含了短信发送的结果相关信息(如状态码表示发送是否成功、提示信息等内容),通过@ResponseBody注解将Result对象转换为合适的格式(如JSON格式等,具体取决于项目配置)返回给前端,
+ * 供前端根据返回结果进行相应的提示和后续处理操作,比如提示用户短信已发送成功或者发送失败等情况;若发送过程中出现异常,则返回一个表示失败的Result对象(状态码为500,无具体数据,提示信息为空字符串)告知前端短信发送出现问题。
+ */
@RequestMapping(value = {"sms/sendFindPasswordSms.html"}, method = RequestMethod.GET)
@ResponseBody
- public Result sendFindPasswordSms(String mobile){
+ public Result sendFindPasswordSms(String mobile) {
try {
+ // 调用iSmsService的sendFindPasswordSms方法,传入要接收短信的手机号码(mobile)作为参数,尝试发送找回密码相关的短信,该方法会根据业务逻辑与短信服务提供商(如阿里云短信服务等,具体取决于ISmsService的实现)进行交互,
+ // 进行短信内容组装、发送等操作,并返回一个Result对象,其中包含了短信发送的结果相关信息(如状态码表示发送是否成功、提示信息等内容),后续会将这个Result对象返回给前端,告知前端短信发送的情况。
return iSmsService.sendFindPasswordSms(mobile);
} catch (ClientException e) {
+ // 若在调用iSmsService的sendFindPasswordSms方法发送短信过程中出现ClientException异常(可能是短信服务配置问题、网络问题等导致与阿里云短信服务通信异常等情况),
+ // 则通过e.printStackTrace()打印异常的堆栈信息,方便开发人员进行调试和定位问题所在,然后返回一个表示失败的Result对象(状态码为500,无具体数据,提示信息为空字符串)给前端,告知前端短信发送出现了问题,发送失败。
e.printStackTrace();
}
return Result.result(500, null, "");
}
-
-}
+}
\ No newline at end of file
diff --git a/tamguo-tms/src/main/java/com/tamguo/web/tiku/SubjectController.java b/tamguo-tms/src/main/java/com/tamguo/web/tiku/SubjectController.java
index c5fd4b2..fe710ab 100644
--- a/tamguo-tms/src/main/java/com/tamguo/web/tiku/SubjectController.java
+++ b/tamguo-tms/src/main/java/com/tamguo/web/tiku/SubjectController.java
@@ -24,74 +24,168 @@ import java.util.List;
/**
* Controller - 考试(高考,建造师,医药师)
- *
+ * 这个类作为Spring MVC的控制器,主要用于处理与各类考试(像高考、建造师考试、医药师考试等)相关的不同业务操作对应的HTTP请求,
+ * 通过调用相应的业务服务层接口来获取数据,进行数据组装、分页处理等操作,然后根据请求情况返回视图或者数据响应给客户端,例如展示考试科目相关页面以及提供课程、学科相关树形结构数据获取的接口等功能。
+ *
* @author candy.tam
*
*/
@Controller
public class SubjectController {
-
+
+ // 创建一个日志记录器对象,用于记录在这个控制器类中发生的一些关键操作、调试信息或者错误信息等,
+ // 通过LoggerFactory根据当前类的Class对象获取对应的Logger实例,方便后续在代码中进行日志输出操作,便于调试和查看运行情况。
private Logger logger = LoggerFactory.getLogger(getClass());
-
+
+ // 通过@Autowired注解自动注入IChapterService接口的实现类实例,IChapterService用于处理与章节相关的各种业务逻辑,
+ // 比如根据章节相关条件查询章节列表、通过书籍ID获取章节列表等操作,在考试科目相关页面展示中,可能需要获取章节信息进行展示,会调用其相关方法来获取章节数据。
@Autowired
private IChapterService iChapterService;
+
+ // 注入ISysAreaService接口的实现类实例,ISysAreaService用于处理与系统区域相关的业务逻辑,
+ // 例如获取特定层级(如层级为0的顶级区域等情况)的区域列表等操作,在考试科目相关页面展示时,可能会展示区域相关信息(比如用于筛选试卷等情况,虽然当前代码中未明确体现完整相关逻辑),会用到该服务层接口的方法来获取区域数据。
@Autowired
private ISysAreaService iSysAreaService;
+
+ // 自动注入ISubjectService接口的实现类实例,ISubjectService主要负责处理与学科(科目)相关的业务逻辑,
+ // 像根据学科ID查询学科详细信息、获取课程级联树数据、获取学科树数据等操作都会调用它的相应方法来完成,是处理考试科目相关业务的核心服务层接口之一。
@Autowired
private ISubjectService iSubjectService;
+
+ // 注入ICourseService接口的实现类实例,ICourseService用于处理与课程相关的业务逻辑,
+ // 例如根据学科ID查询该学科下的课程列表、获取课程相关信息等操作,在考试科目相关页面展示以及其他业务逻辑中(如获取课程级联树数据等情况)会调用其相应方法来获取课程相关数据。
@Autowired
private ICourseService iCourseService;
+
+ // 注入IKnowPointService接口的实现类实例,IKnowPointService用于处理知识点相关的业务逻辑(在这里代码中变量命名为iBookService,可能知识点与书籍有一定关联或者从业务角度将知识点当作书籍看待等情况,具体取决于业务含义),
+ // 比如根据课程ID查询对应的知识点列表等操作,在构建考试科目相关页面数据时,会涉及到知识点(书籍)相关信息的获取与处理,会调用其相应方法。
@Autowired
private IKnowPointService iBookService;
+
+ // 注入IPaperService接口的实现类实例,IPaperService用于处理与试卷相关的业务逻辑,
+ // 例如根据学科ID分页查询最新的试卷列表等操作,在考试科目相关页面展示时,会获取该学科相关的试卷信息进行展示,需要调用它的相应方法来获取试卷数据。
@Autowired
private IPaperService iPaperService;
+ /**
+ * 处理考试科目详情页面的GET请求,请求路径为"subject/{subjectId}.html",其中{subjectId}是一个路径变量,表示考试科目的唯一标识,
+ * 该方法用于获取考试科目相关的详细信息以及与之关联的其他数据(如所属课程列表、课程对应的知识点相关章节列表、区域列表、最新试卷列表等),
+ * 根据请求头中用户代理信息判断是否是移动端访问,来设置不同的视图名称,最后将获取到的数据添加到ModelAndView对象中返回,供Spring MVC框架渲染相应的视图展示给客户端。
+ *
+ * @param subjectId 考试科目的唯一标识字符串,通过@PathVariable注解从请求路径中获取,用于指定要查询详细信息的具体考试科目,传递给相关服务层方法作为查询依据,获取科目及其关联的数据信息。
+ * @param request HttpServletRequest对象,用于获取请求相关的各种信息,在这里主要是获取请求的URI(通过request.getRequestURI()方法)记录日志,
+ * 以及获取请求头中的"user-agent"信息传递给BrowserUtils工具类判断是否是移动端访问,从而决定返回的视图名称等操作。
+ * @param model ModelAndView对象,用于设置视图名称以及向视图传递数据,在这里会将查询到的考试科目相关的各种数据(科目本身、课程列表、章节列表、区域列表、试卷列表等)添加到该对象中,
+ * 然后根据设备类型设置合适的视图名称,最后返回该对象供Spring MVC框架进行视图渲染并展示考试科目详情页面给客户端。
+ * @return 返回配置好视图名称和考试科目相关数据的ModelAndView对象,供Spring MVC框架根据视图名称渲染并展示考试科目详情页面给客户端,展示相应的考试科目信息以及关联数据给用户查看。
+ */
@SuppressWarnings("unchecked")
@RequestMapping(value = {"subject/{subjectId}.html"}, method = RequestMethod.GET)
- public ModelAndView indexAction(@PathVariable String subjectId , HttpServletRequest request , ModelAndView model) {
- // request url
- logger.info("request url :{} " , request.getRequestURI() );
+ public ModelAndView indexAction(@PathVariable String subjectId, HttpServletRequest request, ModelAndView model) {
+ // 使用日志记录器记录请求的URL信息,方便后续查看请求访问情况以及进行调试等操作,通过格式化输出的方式将请求的URI信息记录到日志中,
+ // 输出的日志级别为INFO,通常用于记录一些重要的运行时信息,方便运维人员或者开发人员了解系统的访问情况。
+ logger.info("request url :{} ", request.getRequestURI());
+
+ // 调用iSubjectService的selectById方法,传入考试科目的唯一标识(subjectId)作为参数,从数据库等数据源中查询对应的考试科目详细信息(以SubjectEntity对象形式返回),
+ // 获取到的考试科目信息后续会添加到ModelAndView对象中传递给视图进行展示,例如展示科目名称、科目简介等相关内容。
SubjectEntity subject = iSubjectService.selectById(subjectId);
+
+ // 调用iCourseService的selectList方法,通过MyBatis Plus的条件构造器Condition创建查询条件,
+ // 使用eq("subject_id", subjectId)表示筛选出学科ID等于当前传入考试科目ID(subjectId)的课程列表,再通过orderAsc(Arrays.asList("sort"))按照"sort"字段升序排序课程列表,
+ // 获取与该考试科目相关的课程列表信息(以List形式返回),用于在考试科目详情页面展示同属一个科目的课程情况,比如在页面上列出课程名称等相关内容,将课程列表信息添加到ModelAndView对象中。
List courseList = iCourseService.selectList(Condition.create().eq("subject_id", subjectId).orderAsc(Arrays.asList("sort")));
- // 获取第一个科目
+
+ // 从获取到的课程列表中获取第一个课程对象(这里假设可以基于第一个课程来获取相关知识点、章节等信息,具体业务逻辑可能根据实际情况而定),
+ // 获取这个课程对象主要是为了后续基于它来获取相关的知识点、章节等数据,进行页面数据的进一步组装和展示操作。
CourseEntity course = courseList.get(0);
- // 获取第一本书
+
+ // 调用iBookService(实际为IKnowPointService)的selectList方法,通过条件构造器构建查询条件,
+ // 使用eq("course_id", course.getId())表示筛选出课程ID等于当前获取到的课程ID(course.getId())的知识点列表(这里看作书籍列表,具体取决于业务含义),获取与该课程相关的所有知识点(书籍)信息(以List形式返回),
+ // 这些知识点(书籍)信息后续可能用于获取与之关联的章节信息等操作,也会添加到ModelAndView对象中(虽然当前代码中未明确在视图中如何展示,可能根据业务需求有相应的处理逻辑)。
List bookList = iBookService.selectList(Condition.create().eq("course_id", course.getId()));
+
+ // 初始化章节列表为null,后续会根据知识点(书籍)情况来确定章节列表的值,如果有对应的知识点(书籍)存在,会进一步查询相关章节信息进行赋值。
List chapterList = null;
- if(bookList.size() > 0) {
+
+ // 判断知识点(书籍)列表的大小是否大于0,即是否存在与当前课程相关的知识点(书籍),
+ // 如果存在知识点(书籍),说明可以基于它们进一步获取与之关联的章节信息等内容,进行后续的数据准备操作。
+ if (bookList.size() > 0) {
+ // 从知识点(书籍)列表中获取第一个知识点(书籍)对象(同样假设基于第一个对象来获取章节信息,具体业务逻辑依实际情况而定),
+ // 获取这个知识点(书籍)对象主要是为了获取其ID,作为查询章节列表的依据,获取与该知识点(书籍)相关联的章节信息。
KnowPointEntity book = bookList.get(0);
+ // 调用iChapterService的selectList方法,传入通过条件构造器构建的查询条件,
+ // 使用eq("book_id", book.getId())表示筛选出书籍ID等于当前获取到的知识点(书籍)ID(book.getId())的章节列表,获取与该知识点(书籍)相关的章节列表信息(以List形式返回),
+ // 章节列表信息可能用于在考试科目详情页面展示课程对应的章节情况(例如章节名称等内容,具体展示逻辑由前端页面模板决定),获取到的章节列表信息会赋值给chapterList变量,后续添加到ModelAndView对象中用于视图展示。
chapterList = iChapterService.selectList(Condition.create().eq("book_id", book.getId()));
}
- // 获取最新的试卷
- Page paperPage = iPaperService.selectPage(new Page(1, 15) , Condition.create().eq("subject_id", subjectId).orderDesc(Arrays.asList("id")));
- model.addObject("subject", subject);
- model.addObject("course" , course);
- model.addObject("courseList", courseList);
- model.addObject("chapterList" , chapterList);
- model.addObject("areaList", iSysAreaService.selectList(Condition.create().eq("tree_level", "0")));
- model.addObject("paperList", paperPage.getRecords());
- if(BrowserUtils.isMobile(request.getHeader("user-agent"))) {
- model.setViewName("mobile/subject");
- }else {
- model.setViewName("subject");
- }
- return model;
- }
-
- // [{"value":"11","label":"北京市","children":[{"value":"1101","label":"市辖区"}]}]
+
+ // 调用iPaperService的selectPage方法,创建一个Page对象用于分页查询,传入当前页码为1和每页显示记录数为15,表示获取第一页且每页显示15条记录,
+ // 通过条件构造器构建查询条件,使用eq("subject_id", subjectId)表示筛选出学科ID等于当前考试科目ID(subjectId)的试卷列表,再通过orderDesc(Arrays.asList("id"))按照试卷ID降序排序试卷列表,
+ // 进行分页查询操作,获取符合学科筛选条件且按要求排序的试卷分页数据(以Page对象形式返回),这里只取第一页的试卷记录(即最新的试卷列表,假设ID越大越新等情况,具体取决于业务中试卷ID的定义和排序规则),
+ // 获取到的试卷列表信息会添加到ModelAndView对象中,用于在考试科目详情页面展示该科目相关的试卷情况,例如展示试卷标题等相关内容。
+ Page paperPage = iPaperService.selectPage(new Page(1, 15), Condition.create().eq("subject_id", subjectId).orderDesc(Arrays.asList("id")));
+
+ // 将查询到的考试科目详细信息添加到ModelAndView对象中,设置属性名为"subject",方便在视图中通过这个属性名获取科目详细内容进行展示,如科目名称、简介等信息。
+ model.addObject("subject", subject);
+ // 把获取到的当前课程信息添加到ModelAndView对象中,属性名为"course",用于在视图中展示课程相关情况,例如课程名称等内容,让用户了解考试科目下的具体课程情况。
+ model.addObject("course", course);
+ // 将同属一个科目的课程列表信息添加到ModelAndView对象中,属性名为"courseList",以便在视图中展示课程列表相关信息,例如循环展示课程名称等情况,为用户提供更多课程相关的参考信息。
+ model.addObject("courseList", courseList);
+ // 把获取到的章节列表信息添加到ModelAndView对象中,属性名为"chapterList",方便在视图中展示章节相关信息,例如展示章节名称等内容,体现课程对应的章节情况。
+ model.addObject("chapterList", chapterList);
+ // 将区域列表信息添加到ModelAndView对象中,属性名为"areaList",通过调用iSysAreaService的selectList方法获取层级为0的区域列表(可能表示顶级区域等情况,具体含义由业务中区域层级的定义决定),
+ // 方便在视图中展示可筛选的区域情况(虽然当前代码未明确体现完整筛选逻辑,可能后续有相关扩展功能),例如以下拉框形式展示区域选项等情况。
+ model.addObject("areaList", iSysAreaService.selectList(Condition.create().eq("tree_level", "0")));
+ // 把获取到的试卷列表信息(具体为第一页的试卷记录)添加到ModelAndView对象中,属性名为"paperList",以便在视图中展示试卷相关信息,例如展示试卷标题等内容,让用户了解该科目相关的试卷情况。
+ model.addObject("paperList", paperPage.getRecords());
+
+ // 通过BrowserUtils工具类的isMobile方法判断请求头中的"user-agent"信息是否表示当前访问是来自移动端设备,
+ // 如果是移动端访问,设置ModelAndView的视图名称为"mobile/subject",表示返回移动端对应的考试科目详情视图页面(具体视图页面的内容和样式由对应的前端页面模板决定);
+ // 如果不是移动端访问,设置视图名称为"subject",表示返回普通桌面端等设备对应的考试科目详情视图页面,根据不同设备类型展示合适的考试科目详情内容给用户查看。
+ if (BrowserUtils.isMobile(request.getHeader("user-agent"))) {
+ model.setViewName("mobile/subject");
+ } else {
+ model.setViewName("subject");
+ }
+
+ return model;
+ }
+
+ /**
+ * 处理获取课程级联树数据的GET请求,请求路径为"subject/getCourseCascaderTree.html",
+ * 该方法用于调用iSubjectService的getCourseCascaderTree方法获取课程级联树数据(以JSONArray形式返回,可能是一种树形结构的数据,用于前端以级联选择等形式展示课程相关的层级关系等情况),
+ * 将获取到的数据包装在Result对象中(通过Result.successResult方法),然后返回给前端,前端可以根据返回的Result对象中的数据进行相应的展示和后续处理,比如展示课程的层级选择框等情况。
+ *
+ * @return 返回一个Result对象,通过调用Result.successResult方法将iSubjectService的getCourseCascaderTree方法返回的JSONArray数据(课程级联树数据)包装起来,其中包含了表示成功的状态码以及课程级联树相关的数据信息,
+ * 通过@ResponseBody注解将Result对象转换为合适的格式(如JSON格式等,具体取决于项目配置)返回给前端,供前端根据返回结果进行相应的展示和后续处理操作,例如在页面上展示课程的层级选择框等情况,方便用户选择课程。
+ */
@RequestMapping(value = {"subject/getCourseCascaderTree.html"}, method = RequestMethod.GET)
@ResponseBody
public Result getCourseCascaderTree() {
JSONArray list = iSubjectService.getCourseCascaderTree();
return Result.successResult(list);
}
-
- // [{"value":"11","label":"北京市"}]
+
+ /**
+ * 处理获取学科树数据的GET请求,请求路径为"subject/getSubjectTree.html",
+ * 该方法调用iSubjectService的getSubjectTree方法获取学科树数据(同样以JSONArray形式返回,是一种树形结构的数据,用于前端展示学科的层级关系等情况),
+ * 将获取到的数据包装在Result对象中(通过Result.successResult方法),再返回给前端,供前端根据返回的数据进行相应的展示和后续处理,比如展示学科的层级结构等情况。
+ *
+ * @return 返回一个Result对象,通过调用Result.successResult方法将iSubjectService的getSubjectTree方法返回的JSONArray数据(学科树数据)包装起来,其中包含了表示成功的状态码以及学科树相关的数据信息,
+ * 通过@ResponseBody注解将Result对象转换为合适的格式(如JSON格式等,具体取决于项目配置)返回给前端,供前端根据返回结果进行相应的展示和后续处理操作,例如在页面上展示学科的层级结构等情况,方便用户查看学科的分类和层级关系。
+ */
+// 处理获取学科树数据的GET请求,请求路径为"subject/getSubjectTree.html",意味着当客户端发起一个GET请求到该路径时,此方法会被触发执行。
+// 通过这个方法可以获取学科相关的树形结构数据,一般用于在前端页面以树形结构展示学科的层级关系等情况,方便用户直观地查看和操作学科分类信息。
@RequestMapping(value = {"subject/getSubjectTree.html"}, method = RequestMethod.GET)
+// @ResponseBody注解用于将方法的返回值直接作为响应体返回给客户端,而不是去寻找对应的视图进行渲染。
+// 在这里,会将获取到的学科树数据(以JSONArray形式)包装在Result对象中,然后以合适的格式(如JSON格式,取决于项目配置)返回给前端,供前端进行后续处理和展示。
@ResponseBody
public Result getSubjectTree() {
+ // 调用iSubjectService(应该是注入的处理学科相关业务逻辑的服务层接口实现类)的getSubjectTree方法,
+ // 该方法的作用是从数据源(如数据库等)中获取学科的树形结构数据,返回的数据格式为JSONArray,它可以方便地表示具有层级关系的数据结构,适合用于前端展示树形结构的场景。
JSONArray list = iSubjectService.getSubjectTree();
+ // 将获取到的JSONArray格式的学科树数据list,通过Result.successResult方法进行包装,Result对象通常用于统一封装返回给前端的数据格式,
+ // 它里面包含了表示请求是否成功的状态码(这里调用successResult方法表示成功状态)以及实际的数据内容(即学科树数据list),然后将这个包装好的Result对象返回给前端,
+ // 前端可以根据Result对象中的状态码判断请求是否成功,并提取其中的学科树数据进行相应的展示和处理,比如在页面上以树形菜单等形式展示学科的层级结构等情况。
return Result.successResult(list);
}
-
-}