SpringMVC 进阶

SpringMVC 进阶

一、拦截器

SpringMVC 中 Interceptor 拦截器的主要作⽤是拦截⽤⼾的请求并进⾏相应的处理。⽐如通过它来进⾏权限验证,或者是来判断⽤⼾是否登陆等操作。对于 SpringMVC 拦截器的定义⽅式有两种:

实现接⼝:org.springframework.web.servlet.HandlerInterceptor

继承适配器:org.springframework.web.servlet.handler.HandlerInterceptorAdapter

1.拦截器实现

实现 HandlerInterceptor 接⼝
/*** 拦截器的实现*  实现 HandlerInterceptor 接口*/
public class MyInterceptor01 implements HandlerInterceptor {/*** 在目标Handler(方法)执行前执行*      返回true:执行Handler方法*      返回false:阻止目标Handler执行* @param request* @param response* @param handler* @return* @throws Exception*/@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {System.out.println("目标Handler执行前执行MyInterceptor01 --> preHandle方法...");/*** 返回true:执行Handler方法* 返回false:阻止目标Handler执行*/return true;}/*** 在 目标Handler(方法)执行后,视图生成前 执行* @param request* @param response* @param handler* @param modelAndView* @throws Exception*/@Overridepublic void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {System.out.println("目标Handler执行后,视图生成前执行MyInterceptor01 --> postHandle方法...");}/*** 在 目标Handler(方法)执行后,视图生成后 执行* @param request* @param response* @param handler* @param ex* @throws Exception*/@Overridepublic void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {System.out.println("目标Handler执行后,视图生成后执行MyInterceptor01 --> afterCompletion方法...");}
}
拦截器xml配置
<!-- 拦截器配置:方式一 --><mvc:interceptors><!--使用bean标签定义一个Interceptor直接定义在mvc:interceptors标签中,表示拦截器会拦截所有的请求--><bean class="com.xxxx.springmvc.interceptor.MyInterceptor01"/></mvc:interceptors>
<!-- 拦截器配置:方式二 (推荐使用) --><mvc:interceptors><!--定义在 mvc:interceptor 标签中,可以自定义需要被拦截的请求。可以定义多个拦截器。如果有多个拦截器,则会根据配置的先后顺序来执行--><mvc:interceptor><!-- 通过 mvc:mapping 配置需要被拦截的资源。支持通配符。可配置多个。 --><!-- "/**"表示拦截所有的请求 --><mvc:mapping path="/**"/><!-- 通过 mvc:exclude-mapping 标签配置不需要拦截的资源。支持通配符。可配置多个。--><!--"/url/"表示url路径下的所有资源 --><mvc:exclude-mapping path="/url/*"/><bean class="com.xxxx.springmvc.interceptor.MyInterceptor01"/></mvc:interceptor></mvc:interceptors>
继承 HandlerInterceptorAdapter

实际上最终还是 HandlerInterceptor 接⼝实现。

子类实现类
/*** 拦截器实现*      继承 HandlerInterceptorAdapter 适配器*/
public class MyInterceptor02 extends HandlerInterceptorAdapter {/*** 在 目标Handler(方法)执行前 执行*      返回true:执行Handler方法*      返回false:阻止目标Handler执行* @param request* @param response* @param handler* @return* @throws Exception*/@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {System.out.println("目标Handler执行前执行MyInterceptor02 --> preHandle方法...");return true;}/*** 在 目标Handler(方法)执行后,视图生成前 执行* @param request* @param response* @param handler* @param modelAndView* @throws Exception*/@Overridepublic void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {System.out.println("目标Handler执行后,视图生成前执行MyInterceptor02 --> postHandle方法...");}/*** 在 目标Handler(方法)执行后,视图生成后 执行* @param request* @param response* @param handler* @param ex* @throws Exception*/@Overridepublic void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {System.out.println("目标Handler执行后,视图生成后执行MyInterceptor02 --> afterCompletion方法...");}
}
拦截器xml配置
<mvc:interceptors><mvc:interceptor><!-- 拦截的资源 --><mvc:mapping path="/**"/><!-- 放行的资源 --><mvc:exclude-mapping path="/url/test01"/><mvc:exclude-mapping path="/url/test02"/><bean class="com.xxxx.springmvc.interceptor.MyInterceptor02"/></mvc:interceptor>
</mvc:interceptors>
多个拦截器实现

SpringMVC 框架⽀持多个拦截器配置,从⽽构成拦截器链,对客⼾端请求进⾏多次拦截操作。

拦截器代码实现

这⾥参考MyInterceptor01、MyInterceptor02代码

拦截器xml配置
<mvc:interceptors><!--拦截器链(多个拦截器)如果有多个拦截满足拦截的要求,则会根据配置的先后顺序执行先配置的拦截器的 preHandle方法,先执行先配置的拦截器的 postHandle、afterCompletion方法,后执行--><mvc:interceptor><mvc:mapping path="/**"/><bean class="com.xxxx.springmvc.interceptor.MyInterceptor02"/></mvc:interceptor><mvc:interceptor><mvc:mapping path="/**"/><bean class="com.xxxx.springmvc.interceptor.MyInterceptor01"/></mvc:interceptor></mvc:interceptors>

2.拦截器应用 - 非法请求拦截

使⽤拦截器完成⽤⼾是否登录请求验证功能

用户控制器

UserInfoController 定义

/*** 用户模块*      用户登录 (不需要拦截)*      用户添加 (需要拦截)*      用户更新 (需要拦截)*      用户删除 (需要拦截)*/
@Controller
@RequestMapping("/userInfo")
public class UserInfoController {/*** 用户登录* @return*/@RequestMapping("/login")public ModelAndView userLogin(HttpSession session){System.out.println("用户登录...");ModelAndView modelAndView = new ModelAndView();// 设置视图modelAndView.setViewName("success");// 如果用户登录,则设置用户对象到session作用域中User user = new User();user.setId(1);user.setUserName("admin");user.setUserPwd("123456");session.setAttribute("user", user);return modelAndView;}/*** 用户添加* @return*/@RequestMapping("/add")public ModelAndView userAdd(){System.out.println("用户添加...");ModelAndView modelAndView = new ModelAndView();// 设置视图modelAndView.setViewName("success");return modelAndView;}/*** 用户更新* @return*/@RequestMapping("/update")public ModelAndView userupdate(){System.out.println("用户更新...");ModelAndView modelAndView = new ModelAndView();// 设置视图modelAndView.setViewName("success");return modelAndView;}/*** 用户删除* @return*/@RequestMapping("/delete")public ModelAndView userDelete(){System.out.println("用户删除...");ModelAndView modelAndView = new ModelAndView();// 设置视图modelAndView.setViewName("success");return modelAndView;}
}
页面定义

success.jsp 定义

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head><title>Title</title>
</head>
<body><h3>登录页面</h3>
</body>
</html>
非法请求拦截器定义

LoginInterceptor 定义

public class LoginInterceptor extends HandlerInterceptorAdapter {/*** 在 目标方法执行前 执行* @param request* @param response* @param handler* @return* @throws Exception*/@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {// 获取session作用域中的user对象User user = (User) request.getSession().getAttribute("user");// 判断session作用域的user对象是否为空if (user == null){ // 如果为空,表示用户未登录// 拦截请求并跳转到登录页面response.sendRedirect(request.getContextPath() + "/login.jsp");// 不执行目标方法return false;}// 执行目标方法return true;}
}
拦截器xml配置

servlet-context.xml 配置

<!-- 非法访问拦截 拦截器 -->
<mvc:interceptors><mvc:interceptor><!-- 拦截所有请求 --><mvc:mapping path="/**"/><mvc:exclude-mapping path="/userInfo/login"/><mvc:exclude-mapping path="/uploadFile"/><mvc:exclude-mapping path="/uploadFiles"/><bean class="com.xxxx.springmvc.interceptor.LoginInterceptor"/></mvc:interceptor>
</mvc:interceptors>

二、文件上传

1.环境配置

pom.xml文件修改
    <!-- 添加 commons-fileupload 依赖 --><dependency><groupId>commons-fileupload</groupId><artifactId>commons-fileupload</artifactId><version>1.3.2</version></dependency>
servlet-context.xml修改
<!-- 文件上传 --><bean id="multipartResolver"class="org.springframework.web.multipart.commons.CommonsMultipartResolver"><!-- 允许文件上传的最大尺寸 --><property name="maxUploadSize"><value>104857600</value></property><!--设置文件放入临时文件夹的最大大小限制。此值是阈值,低于此值,则保存在内存中,如高于此值,则生成硬盘上的临时文件。--><property name="maxInMemorySize"><value>4096</value></property></bean>

2.代码实现

单文件上传
页面表单

input 的type设置为file

form 表单的method设为post

form 表单的enctype设置为multipart/form-data,以⼆进制的形式传输数据

<form method="post" action="uploadFile" enctype="multipart/form-data"><input type="file" name="file"/><button>上传</button>
</form>
代码实现
/*** 单文件上传** @return*/
@Controller
public class FileController {@RequestMapping("/uploadFile")public String uploadFile(HttpServletRequest request, @RequestParam("file") MultipartFile file) {// 判断文件是否为空,如果不为空则进行对应的文件上传操作if (!file.isEmpty()) {try {// 获取项目所在的路径 (绝对路径)String path = request.getServletContext().getRealPath("/");// 设置上传文件存放的目录File uploadFile = new File(path + "/upload");// 判断文件目录是否存在,如果不存在则新建对应的目录if (!uploadFile.exists()) {// 新建目录uploadFile.mkdir();}// 获取上传文件的文件名String originalName = file.getOriginalFilename();// 获取上传文件的后缀名String suffix = originalName.substring(originalName.lastIndexOf("."));// 通过系统当前时间的毫秒数,生成随机的文件名String fileName = System.currentTimeMillis() + suffix;// 上传文件 (转存文件到指定目录)file.transferTo(new File(uploadFile, fileName));// 如果上传成功,设置作用域request.setAttribute("msg", "文件上传成功!");} catch (IOException e) {e.printStackTrace();// 如果上传失败,设置作用域request.setAttribute("msg", "文件上传失败!");}} else {// 如果上传文件不存在,设置作用域request.setAttribute("msg", "文件不存在!");}return "result";}
}
多文件件上传
页面表单
    <form method="post" action="uploadFiles" enctype="multipart/form-data"><input type="file" name="files"/><input type="file" name="files"/><button>上传</button></form>
代码实现
 @RequestMapping("/uploadFiles")public String uploadFiles(HttpServletRequest request, @RequestParam("files") List<MultipartFile> files){// 判断文件集合是否为空if (files != null && files.size() > 0) {for (MultipartFile file : files ) {// 上传文件saveFile(file, request);}}return "result";}/*** 上传文件* @param file* @param request*/public void saveFile(MultipartFile file, HttpServletRequest request) {// 判断文件是否为空,如果不为空则进行对应的文件上传操作if (!file.isEmpty()) {try {// 获取项目所在的路径 (绝对路径)String path = request.getServletContext().getRealPath("/");// 设置上传文件存放的目录File uploadFile = new File(path + "/upload");// 判断文件目录是否存在,如果不存在则新建对应的目录if (!uploadFile.exists()) {// 新建目录uploadFile.mkdir();}// 获取上传文件的文件名String originalName = file.getOriginalFilename();// 获取上传文件的后缀名String suffix = originalName.substring(originalName.lastIndexOf("."));// 通过系统当前时间的毫秒数,生成随机的文件名String fileName = System.currentTimeMillis() + suffix;// 上传文件 (转存文件到指定目录)file.transferTo(new File(uploadFile, fileName));// 如果上传成功,设置作用域request.setAttribute("msg","文件上传成功!");} catch (IOException e) {e.printStackTrace();// 如果上传失败,设置作用域request.setAttribute("msg","文件上传失败!");}} else {// 如果上传文件不存在,设置作用域request.setAttribute("msg","文件不存在!");}}

三、SSM 框架集成与测试

1.环境配置

配置 pom.xml
修改 JDK 版本
  <properties><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding><maven.compiler.source>1.8</maven.compiler.source><maven.compiler.target>1.8</maven.compiler.target></properties>
添加坐标依赖
<dependencies><!-- junit 测试 --><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.12</version><scope>test</scope></dependency><!-- spring 核心jar --><dependency><groupId>org.springframework</groupId><artifactId>spring-context</artifactId><version>5.2.4.RELEASE</version></dependency><!-- spring 测试jar --><dependency><groupId>org.springframework</groupId><artifactId>spring-test</artifactId><version>5.2.4.RELEASE</version></dependency><!-- spring jdbc --><dependency><groupId>org.springframework</groupId><artifactId>spring-jdbc</artifactId><version>5.2.4.RELEASE</version></dependency><!-- spring事物 --><dependency><groupId>org.springframework</groupId><artifactId>spring-tx</artifactId><version>5.2.4.RELEASE</version></dependency><!-- aspectj切面编程的jar --><dependency><groupId>org.aspectj</groupId><artifactId>aspectjweaver</artifactId><version>1.9.5</version></dependency><!-- c3p0 连接池 --><dependency><groupId>com.mchange</groupId><artifactId>c3p0</artifactId><version>0.9.5.2</version></dependency><!-- mybatis --><dependency><groupId>org.mybatis</groupId><artifactId>mybatis</artifactId><version>3.5.3</version></dependency><!-- 添加mybatis与Spring整合的核心包 --><dependency><groupId>org.mybatis</groupId><artifactId>mybatis-spring</artifactId><version>2.0.3</version></dependency><!-- mysql 驱动包 --><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>8.0.19</version></dependency><!-- 日志打印相关的jar --><dependency><groupId>org.slf4j</groupId><artifactId>slf4j-log4j12</artifactId><version>1.7.2</version></dependency><dependency><groupId>org.slf4j</groupId><artifactId>slf4j-api</artifactId><version>1.7.2</version></dependency><!-- 分页插件 --><dependency><groupId>com.github.pagehelper</groupId><artifactId>pagehelper</artifactId><version>5.1.10</version></dependency><!-- spring web --><dependency><groupId>org.springframework</groupId><artifactId>spring-web</artifactId><version>5.2.4.RELEASE</version></dependency><!-- spring mvc --><dependency><groupId>org.springframework</groupId><artifactId>spring-webmvc</artifactId><version>5.2.4.RELEASE</version></dependency><!-- web servlet --><dependency><groupId>javax.servlet</groupId><artifactId>javax.servlet-api</artifactId><version>3.0.1</version></dependency><!-- 添加json 依赖jar包(注意版本问题) --><dependency><groupId>com.fasterxml.jackson.core</groupId><artifactId>jackson-core</artifactId><version>2.10.0</version></dependency><dependency><groupId>com.fasterxml.jackson.core</groupId><artifactId>jackson-databind</artifactId><version>2.10.0</version></dependency><dependency><groupId>com.fasterxml.jackson.core</groupId><artifactId>jackson-annotations</artifactId><version>2.10.0</version></dependency><!-- commons-fileupload --><dependency><groupId>commons-fileupload</groupId><artifactId>commons-fileupload</artifactId><version>1.3.2</version></dependency></dependencies>
设置资源目录和插件
<build><finalName>ssm</finalName><!--Maven 项目:如果源代码(src/main/java)存在xml、properties、tld 等文件Maven 默认不会自动编译该文件到输出目录,如果要编译源代码中xml properties tld 等文件需要显式配置 resources 标签--><resources><resource><directory>src/main/resources</directory></resource><resource><directory>src/main/java</directory><includes><include>**/*.xml</include><include>**/*.properties</include><include>**/*.tld</include></includes><filtering>false</filtering></resource></resources><plugins><!-- 编译环境插件 --><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-compiler-plugin</artifactId><version>2.3.2</version><configuration><source>1.8</source><target>1.8</target><encoding>UTF-8</encoding></configuration></plugin><!-- jetty插件 --><plugin><groupId>org.eclipse.jetty</groupId><artifactId>jetty-maven-plugin</artifactId><version>9.4.27.v20200227</version><configuration><scanIntervalSeconds>10</scanIntervalSeconds><!-- 设置端口 --><httpConnector><port>8080</port></httpConnector><!-- 设置项目路径 --><webAppConfig><contextPath>/ssm</contextPath></webAppConfig></configuration></plugin></plugins></build>
配置 web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app id="WebApp_ID" version="3.0"xmlns="http://java.sun.com/xml/ns/javaee"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://java.sun.com/xml/ns/javaeehttp://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"><!-- 启动spring容器--><context-param><param-name>contextConfigLocation</param-name><param-value>classpath:spring.xml</param-value></context-param><!-- 设置监听器 --><listener><listener-class>org.springframework.web.context.ContextLoaderListener</listener-class></listener><!-- 编码过滤 utf-8 --><filter><description>char encoding filter</description><filter-name>encodingFilter</filter-name><filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class><init-param><param-name>encoding</param-name><param-value>UTF-8</param-value></init-param></filter><filter-mapping><filter-name>encodingFilter</filter-name><url-pattern>/*</url-pattern></filter-mapping><!-- servlet请求分发器 --><servlet><servlet-name>springMvc</servlet-name><servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class><init-param><param-name>contextConfigLocation</param-name><param-value>classpath:servlet-context.xml</param-value></init-param><!-- 表示启动容器时初始化该Servlet --><load-on-startup>1</load-on-startup></servlet><servlet-mapping><servlet-name>springMvc</servlet-name><!-- 这是拦截请求, "/"代表拦截所有请求,"*.do"拦截所有.do请求 --><url-pattern>/</url-pattern><!--<url-pattern>*.do</url-pattern>--></servlet-mapping></web-app>
配置 servlet-context.xml
<beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:mvc="http://www.springframework.org/schema/mvc"xmlns:context="http://www.springframework.org/schema/context"xsi:schemaLocation="http://www.springframework.org/schema/mvchttp://www.springframework.org/schema/mvc/spring-mvc.xsdhttp://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context.xsd"><!-- 开启扫描器 --><context:component-scan base-package="com.xxxx.ssm.controller" /><!-- mvc 注解驱动 并添加json 支持 --><mvc:annotation-driven><mvc:message-converters><!-- 返回信息为字符串时 处理 --><bean class="org.springframework.http.converter.StringHttpMessageConverter"/><!-- 将对象转换为json 对象 --><bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter"/></mvc:message-converters></mvc:annotation-driven><!-- 使用默认的 Servlet 来响应静态文件 --><mvc:default-servlet-handler/><!-- 配置视图解析器 --><bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"id="internalResourceViewResolver"><!-- 前缀:在WEB-INF目录下的jsp目录下 --><property name="prefix" value="/WEB-INF/jsp/"/><!-- 后缀:以.jsp结尾的资源 --><property name="suffix" value=".jsp"/></bean><!-- 文件上传 --><bean id="multipartResolver"class="org.springframework.web.multipart.commons.CommonsMultipartResolver"><!-- 允许文件上传的最大尺寸 --><property name="maxUploadSize"><value>104857600</value></property><!--设置文件放入临时文件夹的最大大小限制。此值是阈值,低于此值,则保存在内存中,如高于此值,则生成硬盘上的临时文件。--><property name="maxInMemorySize"><value>4096</value></property></bean></beans>
配置 spring.xml

在项⽬的 src/main/resources 下创建 spring.xml ⽂件, 内容如下

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context.xsdhttp://www.springframework.org/schema/aophttp://www.springframework.org/schema/aop/spring-aop.xsdhttp://www.springframework.org/schema/txhttp://www.springframework.org/schema/tx/spring-tx.xsd"><!-- 扫描基本包 --><context:component-scan base-package="com.xxxx.ssm" ><!--  context:exclude-filter标签:排除对某个注解的扫描 (过滤controller层) --><context:exclude-filter type="annotation"expression="org.springframework.stereotype.Controller" /></context:component-scan><!-- 加载properties 配置文件 --><context:property-placeholder location="classpath:db.properties" /><!-- aop --><aop:aspectj-autoproxy /><!-- 配置c3p0 数据源 --><bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"><property name="driverClass" value="${jdbc.driver}"></property><property name="jdbcUrl" value="${jdbc.url}"></property><property name="user" value="${jdbc.username}"></property><property name="password" value="${jdbc.password}"></property></bean><!-- 配置事务管理器 --><bean id="txManager"class="org.springframework.jdbc.datasource.DataSourceTransactionManager"><property name="dataSource" ref="dataSource"></property></bean><!-- 设置事物增强 --><tx:advice id="txAdvice" transaction-manager="txManager"><tx:attributes><tx:method name="add*" propagation="REQUIRED" /><tx:method name="insert*" propagation="REQUIRED" /><tx:method name="update*" propagation="REQUIRED" /><tx:method name="delete*" propagation="REQUIRED" /></tx:attributes></tx:advice><!-- aop 切面配置 --><aop:config><aop:pointcut id="servicePointcut"expression="execution(* com.xxxx.ssm.service..*.*(..))" /><aop:advisor advice-ref="txAdvice" pointcut-ref="servicePointcut" /></aop:config><!-- 配置 sqlSessionFactory --><bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"><property name="dataSource" ref="dataSource"></property><property name="configLocation" value="classpath:mybatis.xml" /><property name="mapperLocations" value="classpath:com/xxxx/ssm/mapper/*.xml" /></bean><!-- 配置扫描器 --><bean id="mapperScanner" class="org.mybatis.spring.mapper.MapperScannerConfigurer"><!-- 扫描com.xxxx.ssm.dao这个包以及它的子包下的所有映射接口类 --><property name="basePackage" value="com.xxxx.ssm.dao" /><property name="sqlSessionFactoryBeanName" value="sqlSessionFactory" /></bean>
</beans>
配置 mybatis.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configurationPUBLIC "-//mybatis.org//DTD Config 3.0//EN""http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration><typeAliases><package name="com.xxxx.ssm.po"/></typeAliases><plugins><plugin interceptor="com.github.pagehelper.PageInterceptor"></plugin></plugins>
</configuration>
配置 db.properties

在项⽬的 src/main/resources 下创建 db.properties ⽂件,内容如下(mysql 创建数据库ssm)

jdbc.driver=com.mysql.cj.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/ssm?useUnicode=true&characterEncoding=utf8&serverTimezone=GMT%2B8&useSSL=false
jdbc.username=root
jdbc.password=root
添加 log4j.properties

在项⽬的 src/main/resources 下创建 log4j.properties ⽂件,内容如下

log4j.rootLogger=DEBUG, Console
# Console
log4j.appender.Console=org.apache.log4j.ConsoleAppender
log4j.appender.Console.layout=org.apache.log4j.PatternLayout
log4j.appender.Console.layout.ConversionPattern=%d [%t] %-5p [%c] - %m%n
log4j.logger.java.sql.ResultSet=INFO
log4j.logger.org.apache=INFO
log4j.logger.java.sql.Connection=DEBUG
log4j.logger.java.sql.Statement=DEBUG
log4j.logger.java.sql.PreparedStatement=DEBUG

2.添加源代码

添加包

在项⽬的 src/main/java 下创建对应的包结构

com.xxxx.ssm.controller

com.xxxx.ssm.service

com.xxxx.ssm.mapper

com.xxxx.ssm.dao

com.xxxx.ssm.po

添加 User.java

在 com.xxxx.ssm.po 包下创建 JavaBean ⽂件 User.java (数据库字段对应如下)

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

public class User {private Integer userId;private String userName;private String userPwd;private String userEmail;private Date createDate;private Date updateDate;
}
添加UserDao.java 接口

com.xxxx.ssm.dao 包下创建 UserDao.java ⽂件,提供对应的⽤⼾详情查询功能

public interface UserDao {User queryUserByUserId(Integer userId);
}
添加UserMapper.xml 映射文件

com.xxxx.ssm.mapper 包下创建 UserMapper.xml ⽂件,提供select 查询标签配置

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.xxxx.ssm.dao.UserDao"><select id="queryUserByUserId" parameterType="int" resultType="com.xxxx.ssm.po.User">select user_id as userId,user_name as userName,user_pwd as userPwdfrom tb_userwhere user_id = #{userId}</select>
</mapper>
添加 UserService.java

com.xxxx.ssm.service 包下创建UserService.java ⽂件,提供⽤⼾详情查询⽅法

@Service
public class UserService {// 注入userDao@Autowiredprivate UserDao userDao;public User queryUserByUserId(Integer userId){User user = userDao.queryUserByUserId(userId);return user;}}
添加 HelloController.java

在 com.xxxx.ssm.controller 包下创建 HelloController.java ⽂件

@Controller
public class UserController extends BaseController {// 注入userService@Autowiredprivate UserService userService;@RequestMapping("/hello")public String hello (Model model){// 调用UserService层的方法User user = userService.queryUserByUserId(1);// 将数据存到model对象中model.addAttribute("user",user);return "hello";}}
添加 hello.jsp 视图⽂件

在src/main/webapp/WEB-INF 创建jsp ⽬录,并在该⽬下创建hello.jsp ,展⽰查询的⽤⼾信息

<body>欢迎你,${user.userName}
</body>

四、RestFul URL

模型 - 视图 - 控制器(MVC)是⼀个以设计界⾯应⽤程序为基础的设计思想。

Restful ⻛格的 API 是⼀种软件架构⻛格,设计⻛格⽽不是标准,只是提供了⼀组设计原则和约束条件。它主要⽤于客⼾端和服务器交互类的软件。基于这个⻛格设计的软件可以更简洁,更有层次,更易于实现缓存等机制。

在Restful ⻛格中,⽤⼾请求的 url 使⽤同⼀个 url,⽤请求⽅式:get,post,delete,put…等⽅式对请求的处理⽅法进⾏区分,这样可以在前后台分离式的开发中使得前端开发⼈员不会对请求的资源地址产⽣混淆和⼤量的检查⽅法名的⿇烦,形成⼀个统⼀的接⼝。

GET(SELECT):从服务器查询,可以在服务器通过请求的参数区分查询的⽅式。

POST(CREATE):在服务器端新建⼀个资源,调⽤ insert 操作。

PUT(UPDATE):在服务器端更新资源,调⽤ update 操作。

PATCH(UPDATE):在服务器端更新资源(客⼾端提供改变的属性)。(⽬前 jdk7 未实现,tomcat7 不⽀持)。

DELETE(DELETE):从服务器端删除资源,调⽤ delete 语句。

1.SpringMVC 支持 RestFul URL 风格设计

如何使用 Java 构造没有扩展名的RestFul URL ,如 /forms/1?

SpringMVC 是通过 @RequestMapping 及 @PathVariable 注解提供的。

通过如@RequestMapping(value=“/blog /{id}”, method = RequestMethod.DELETE),即可处理 /blog/1 的 delete请求。

2.RestFul URL 映射地址配置

准备环境
添加 Account

在 src/resources/java 对应的 com.xxxx.ssm.po ⽬录下新建 Account.java 实体类

public class Account {private Integer id;private String aname;private String type;private Double money;private Integer userId;private Date createTime;private Date updateTime;private String remark;}
添加 AccountDao

在 src/resources/java 对应的 com.xxxx.ssm.dao ⽬录下新建 AccountDao.java 接⼝类

public interface AccountDao {public Account selectById(Integer id);public int save(Account account);public int update(Account account);public int delete(Integer id);
}
添加 AccountMapper

在 src/resources/java 对应的 com.xxxx.ssm.mapper ⽬录下新建 AccountMapper.xml 映射⽂件

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="com.xxxx.ssm.dao.AccountDao" ><resultMap id="BaseResultMap" type="com.xxxx.ssm.po.Account" ><id column="id" property="id" jdbcType="INTEGER" /><result column="aname" property="aname" jdbcType="VARCHAR" /><result column="type" property="type" jdbcType="VARCHAR" /><result column="money" property="money" jdbcType="DOUBLE" /><result column="user_id" property="userId" jdbcType="INTEGER" /><result column="create_time" property="createTime" jdbcType="DATE" /><result column="update_time" property="updateTime" jdbcType="DATE" /><result column="remark" property="remark" jdbcType="VARCHAR" /></resultMap><sql id="Base_Column_List" >id, aname, type, money, user_id, create_time, update_time, remark</sql><!-- 查询操作 --><select id="selectById" resultMap="BaseResultMap" parameterType="java.lang.Integer" >select<include refid="Base_Column_List" />from tb_accountwhere id = #{id,jdbcType=INTEGER}</select><!-- 删除操作 --><delete id="delete" parameterType="java.lang.Integer" >delete from tb_accountwhere id = #{id,jdbcType=INTEGER}</delete><!-- 添加操作 --><insert id="save" parameterType="com.xxxx.ssm.po.Account" >insert into tb_account<trim prefix="(" suffix=")" suffixOverrides="," ><if test="id != null" >id,</if><if test="aname != null" >aname,</if><if test="type != null" >type,</if><if test="money != null" >money,</if><if test="userId != null" >user_id,</if><if test="createTime != null" >create_time,</if><if test="updateTime != null" >update_time,</if><if test="remark != null" >remark,</if></trim><trim prefix="values (" suffix=")" suffixOverrides="," ><if test="id != null" >#{id,jdbcType=INTEGER},</if><if test="aname != null" >#{aname,jdbcType=VARCHAR},</if><if test="type != null" >#{type,jdbcType=VARCHAR},</if><if test="money != null" >#{money,jdbcType=DOUBLE},</if><if test="userId != null" >#{userId,jdbcType=INTEGER},</if><if test="createTime != null" >#{createTime,jdbcType=DATE},</if><if test="updateTime != null" >#{updateTime,jdbcType=DATE},</if><if test="remark != null" >#{remark,jdbcType=VARCHAR},</if></trim></insert><!-- 更新操作 --><update id="update" parameterType="com.xxxx.ssm.po.Account" >update tb_account<set ><if test="aname != null" >aname = #{aname,jdbcType=VARCHAR},</if><if test="type != null" >type = #{type,jdbcType=VARCHAR},</if><if test="money != null" >money = #{money,jdbcType=DOUBLE},</if><if test="userId != null" >user_id = #{userId,jdbcType=INTEGER},</if><if test="createTime != null" >create_time = #{createTime,jdbcType=DATE},</if><if test="updateTime != null" >update_time = #{updateTime,jdbcType=DATE},</if><if test="remark != null" >remark = #{remark,jdbcType=VARCHAR},</if></set>where id = #{id,jdbcType=INTEGER}</update>
</mapper>
添加 AccountService
@Service
public class AccountService {@Autowiredprivate AccountDao accountDao;public Account selectById(Integer id){return accountDao.selectById(id);}public int saveAccount(Account account){return accountDao.save(account);}public int updateAccount(Account account){return accountDao.update(account);}public int delAccount(Integer id){return accountDao.delete(id);}}
URL 映射地址配置
/*** RestFul URL 配置*      1. 设置请求类型*          GET(查询)     @GetMapping*          DELETE(删除)  @DeleteMapping*          POST(添加)    @PostMapping*          PUT(更新)     @PutMapping*      2. URL设置时,不体现动作行为 (没有动词)*          例如:/account/1、/account/2、/account*      3. 定义参数格式*          1. 路径参数 ( @PathVariable )*          2. json格式 ( @RequestBody )*          3. 普通表单参数*      4. 设置响应数据*          json格式 ( @ResponseBody )*/
@Controller
public class AccountController extends BaseController {@Autowiredprivate AccountService accountService;/*** 查询操作*      传统的 URL 访问:*          http://localhost:8080/ssm/account/queryAccountById?id=1*      RestFul URL 访问:*          @GetMapping("/account/{id}")*          http://localhost:8080/ssm/account/1*      @PathVariable 将形参设置为参数路径,声明在形参前面* @param id* @return*/// @RequestMapping("/account/queryAccountById")@GetMapping("/account/{id}")@ResponseBodypublic Account queryAccountById(@PathVariable  Integer id) {// 设置异常return accountService.selectById(id);}/*** 删除操作* @param id* @return*/@DeleteMapping("/account/{id}")@ResponseBodypublic Map<String,String> deleteAccountById(@PathVariable Integer id) {// 调用service层的删除方法,返回受影响的行数int row = accountService.delAccount(id);// 判断受影响的行数是否大于0Map<String ,String> map = new HashMap<>();if (row > 0) {// 删除成功map.put("code","200");map.put("msg","删除成功!");} else {// 删除失败map.put("code","500");map.put("msg","删除失败!");}return  map;}/*** 添加操作* @param account* @return*/@PostMapping("/account")@ResponseBodypublic Map<String,String> addAccount(@RequestBody Account account) {Map<String ,String> map = new HashMap<>();// 调用service层的添加方法,返回受影响的行数int row = accountService.saveAccount(account);// 判断受影响的行数是否大于0if (row > 0) {// 删除成功map.put("code","200");map.put("msg","添加成功!");} else {// 删除失败map.put("code","500");map.put("msg","添加失败!");}return map;}/*** 更新操作* @param account* @return*/@PutMapping("/account")@ResponseBodypublic Map<String,String> updateAccount(@RequestBody Account account) {Map<String ,String> map = new HashMap<>();// 调用service层的添加方法,返回受影响的行数int row = accountService.updateAccount(account);// 判断受影响的行数是否大于0if (row > 0) {// 删除成功map.put("code","200");map.put("msg","更新成功!");} else {// 删除失败map.put("code","500");map.put("msg","更新失败!");}return map;}
}

五、全局异常统⼀处理

SpringMVC 对于异常处理这块提供了⽀持,通过 SpringMVC 提供的全局异常处理机制,能够将所有类型的异常处理从各处理过程解耦出来,既保证了相关处理过程的功能较单⼀,也实现了异常信息的统⼀处理和维护

全局异常实现⽅式 Spring MVC 处理异常有 3 种⽅式:

  1. 使⽤ Spring MVC 提供的简单异常处理器 SimpleMappingExceptionResolver

  2. 实现 Spring 的异常处理接⼝ HandlerExceptionResolver ⾃定义⾃⼰的异常处理器

  3. 使⽤ @ExceptionHandler 注解实现异常处理

1.异常处理实现

全局异常处理方式一
配置简单异常处理器

配置 SimpleMappingExceptionResolver 对象

<!-- 配置全局异常统⼀处理的 Bean (简单异常处理器) -->
<bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
<!-- ⻚⾯在转发时出现异常,设置默认的错误⻚⾯ (error代表的是⼀个视图) -->
<property name="defaultErrorView" value="error"></property>
<!-- 异常发⽣时,设置异常的变量名 -->
<property name="exceptionAttribute" value="ex"></property>
</bean>

可以在处理异常的⻚⾯获取异常信息

${ex}
使自定定义异常

参数异常

package com.xxxx.ssm.exception;/*** 自定义异常:参数异常*/
public class ParamsException extends RuntimeException {private Integer code = 300;private String msg = "参数异常!";public ParamsException() {super("参数异常!");}public ParamsException(String msg) {super(msg);this.msg = msg;}public ParamsException(Integer code) {super("参数异常!");this.code = code;}public ParamsException(Integer code, String msg) {super(msg);this.code = code;this.msg = msg;}public Integer getCode() {return code;}public void setCode(Integer code) {this.code = code;}public String getMsg() {return msg;}public void setMsg(String msg) {this.msg = msg;}
}

业务异常

package com.xxxx.ssm.exception;/*** 自定义异常:业务异常*/
public class BusinessException extends RuntimeException {private Integer code=400;private String msg="业务异常!";public BusinessException() {super("业务异常!");}public BusinessException(String msg) {super(msg);this.msg = msg;}public BusinessException(Integer code) {super("业务异常!");this.code = code;}public BusinessException(Integer code, String msg) {super(msg);this.code = code;this.msg = msg;}public Integer getCode() {return code;}public void setCode(Integer code) {this.code = code;}public String getMsg() {return msg;}public void setMsg(String msg) {this.msg = msg;}
}
设置⾃定义异常与⻚⾯的映射
<!-- 设置⾃定义异常与⻚⾯的映射 -->
<property name="exceptionMappings">
<props>
<!-- key:⾃定义异常对象的路径; 标签中设置具体的处理⻚⾯的视图名-->
<prop key="com.xxxx.ssm.exception.BusinessException">error</prop>
<prop key="com.xxxx.ssm.exception.ParamsException">error</prop>
</props>
</property>

使⽤ SimpleMappingExceptionResolver 进⾏异常处理,具有集成简单、有良好的扩展性、对已有代码没有⼊侵性等优点,但该⽅法仅能获取到异常信息,若在出现异常时,对需要获取除异常以外的数据的情况不适⽤。

全局异常处理方式二(推荐)
实现 HandlerExceptionResolver 接⼝
/**
* 全局异常统⼀处理
*/
@Component
public class GlobalExceptionResolver implements HandlerExceptionResolver {
@Override
public ModelAndView resolveException(HttpServletRequest httpServletRequest,
HttpServletResponse httpServletResponse, Object handler, Exception ex) {
ModelAndView mv = new ModelAndView("error");
mv.addObject("ex","默认错误信息");
return mv;
}
}
⾃定义异常处理
/**
* 全局异常统⼀处理
*/
@Component
public class GlobalExceptionResolver implements HandlerExceptionResolver {
@Override
public ModelAndView resolveException(HttpServletRequest httpServletRequest,
HttpServletResponse httpServletResponse, Object handler, Exception ex) {
ModelAndView mv = new ModelAndView("error");
mv.addObject("ex","默认错误信息");
// 判断是否是⾃定义异常
if (ex instanceof ParamsException) {
mv.setViewName("params_error");
ParamsException e = (ParamsException) ex;
mv.addObject("ex", e.getMsg());
}
if (ex instanceof BusinessException) {
mv.setViewName("business_error");
BusinessException e = (BusinessException) ex;
mv.addObject("ex", e.getMsg());
}
return mv;
}

使⽤实现 HandlerExceptionResolver 接⼝的异常处理器进⾏异常处理,具有集成简单、有良好的扩展性、对已有代码没有⼊侵性等优点,同时,在异常处理时能获取导致出现异常的对象,有利于提供更详细的异常处理信息。

全局异常处理方式三

⻚⾯处理器继承 BaseController

public class BaseController {
@ExceptionHandler
public String exc(HttpServletRequest request,HttpServletResponse response,Exception ex){
request.setAttribute("ex", ex);
if(ex instanceof ParamsException){
return "error_param";
}
if(ex instanceof BusinessException){
return "error_business";
}
return "error";
}
}

使⽤ @ExceptionHandler 注解实现异常处理,具有集成简单、有扩展性好(只需要将要异常处理的 Controller 类继承于 BaseController 即可)、不需要附加Spring 配置等优点,但该⽅法对已有代码存在⼊侵性(需要修改已有代码,使相关类继承于 BaseController),在异常处理时不能获取除异常以外的数据。

2.未捕获异常的处理

在 web.xml 中通过(Websphere/Weblogic)或者(Tomcat)节点配置特定异常情况的显⽰⻚⾯。

  <!-- 出错页面定义 --><error-page><exception-type>java.lang.Throwable</exception-type><location>/500.jsp</location></error-page><error-page><error-code>404</error-code><location>/404.jsp</location></error-page><error-page><error-code>500</error-code><location>/500.jsp</location></error-page>

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

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

相关文章

如何在3DMax中使用超过16个材质ID通道?

3DMAX效果通道扩展插件EffectsChannelEx教程 3DMax的材质ID通道允许我们生成渲染元素&#xff0c;这些元素可用于在合成或其他软件中产生处理或特殊效果。如对渲染或动画进行颜色校正。你可以在Photoshop中为你的静态3D渲染图像做这件事。或者使用After Effects、Blackmagic Fu…

竞赛选题 目标检测-行人车辆检测流量计数

文章目录 前言1\. 目标检测概况1.1 什么是目标检测&#xff1f;1.2 发展阶段 2\. 行人检测2.1 行人检测简介2.2 行人检测技术难点2.3 行人检测实现效果2.4 关键代码-训练过程 最后 前言 &#x1f525; 优质竞赛项目系列&#xff0c;今天要分享的是 行人车辆目标检测计数系统 …

JAVA小游戏 “拼图”

第一步是创建项目 项目名自拟 第二部创建个包名 来规范class 然后是创建类 创建一个代码类 和一个运行类 代码如下&#xff1a; package heima;import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.KeyEvent; import jav…

企业微信机器人定时发送图文信息,后续无需人工操作

企业微信群机器人是企业微信的内置功能&#xff0c;可以理解为是一个群提醒通知工具&#xff0c;接收数据并自动发送信息到企业微信群中。 数环通实现打通定时器和企业微信机器人的对接&#xff0c;定时执行自动化流程&#xff0c;无需人工干预&#xff0c;实现工作流程自动化&…

【EI会议征稿】2024年电气技术与自动化工程国际学术会议 (ETAE 2024)

2024年电气技术与自动化工程国际学术会议 (ETAE 2024) 2024 International Conference on Electrical Technology and Automation Engineering 2024年电气技术与自动化工程国际学术会议 (ETAE 2024) 将于2024年3月8-10日在中国杭州召开。电气工程及其自动化和人们的日常生活…

电磁场与电磁波part5--均匀平面波在无界空间的传播

目录 1、相位速度 2、波阻抗 3、理想介质中均匀平面波的传播特点 4、色散现象 5、导电媒质中均匀平面波的传播特点 6、趋肤效应 7、电磁波的极化 1、相位速度 电磁波的等相位面在空间中的移动速度&#xff08;相速&#xff09; 在自由空间&#xff08;自由空间的光速&a…

SpringBoot——入门及原理

SpringBoot用来简化Spring应用开发&#xff0c;约定大于配置&#xff0c;去繁从简&#xff0c;是由Pivotal团队提供的全新框架。其设计目的是用来简化新Spring应用的初始搭建以及开发过程。该框架使用了特定的方式来进行配置&#xff08;有特殊需求可以添加自己的配置覆盖默认配…

linux上交叉编译qt库

linux上交叉编译qt库 Qt程序从X86平台Linux移植到ARM平台Linux需要做什么 1.在ubuntu上使用qt的源码交叉编译出Qt库 2.将编译好的库拷贝到开发板上并设置相应的环境变量&#xff08;库路径啥的&#xff09; 前两步一劳永逸&#xff0c;做一次就行 3.X86上写好程序代码&…

浅谈多回路电表在荷兰光伏系统配电项目中的应用

1.背景信息 Background&#xff1a; 随着全球化石能源&#xff08;石油&#xff0c;煤炭&#xff09;越来越接近枯竭&#xff0c;污染日趋严重&#xff0c;气候日益变暖等问题&#xff0c;全球多个国家和地区相继出台了法规政策&#xff0c;推动了光伏产业的发展。但是现有的光…

UE5 - ArchvizExplorer - 数字孪生城市模板 - 功能修改

数字孪生项目&#xff0c;大多是双屏互动&#xff0c;而非下方菜单点击&#xff0c;所以要做一番改造 参考&#xff1a;https://blog.csdn.net/qq_17523181/article/details/133853099 1. 去掉提示框 打开BP_MasterMenu_Widget&#xff0c;进入EventGraph&#xff0c;断开Open…

给折腿的罗技G512键盘换键帽

文章目录 1\. 引言2\. 操作2.1. 用打火机烤2.2. 用钳子拔出来2.2.1. 拔出成功2.2.2. 放大细看2.3. 更换键帽 1. 引言 G512的轴采用的是塑料连接&#xff0c;特别容易腿折在里面&#xff0c;换着的时候&#xff0c;得先把这个卡在里面的塑料腿拿出来才行 放大效果图 2. 操作 可…

Spring Boot中使用Redis进行大数据缓存

Spring Boot中使用Redis进行大数据缓存 在Spring Boot中使用Redis进行大数据缓存是一种常见的做法&#xff0c;因为Redis是一种高性能的内存数据库&#xff0c;适用于缓存大量数据。以下是说明和示例代码&#xff0c;演示如何在Spring Boot项目中使用Redis进行大数据缓存。 步…

龙讯旷腾PWmat发PRL:多k点计算的NAMD方法应用于小型超胞与在等效的大型超胞中进行的单个Γ点模拟之间的一致性

文章信息 作者信息&#xff1a;郑帆&#xff0c;汪林望 通信单位&#xff1a;上海科技大学 中国科学院半导体所 背景导读 固态材料中的超快载流子动力学在能源材料、光电子学、传感器和量子材料等领域起着关键作用。随着超快实验技术在固态系统中载流子动力学研究中的快速发…

纯CSS动态渐变文本特效

如图所示&#xff0c;这是一个炫酷的文本渐变效果&#xff0c;如同冰岛的极光一般。本次的文章让我们逐步分解代码&#xff0c;了解其实现原理。 基于以上动图效果可以分析以下是本次动效实现的主要几点&#xff1a; 文本中有多个颜色的动画每个颜色显示的半径不同&#xff0…

MCU内存基础知识

文章目录 一、存储器分类二、C语言内存分区内存区三、STM32启动文件分析四、应用分析 一、存储器分类 RAM&#xff08;Random Access Memory) &#xff1a;掉电之后就丢失数据&#xff0c;读写速度块 ROM (Read Only Memory) &#xff1a;掉电之后仍然可以保持数据 单片机的RA…

Springboot 项目启动类放置位置

文章目录 Springboot 项目启动类放置位置springboot 默认包扫描机制启动类放在特定位置springboot 启动注解理解配置启动类扫描特定的包1、 ComponentScan2、利用 SpringBootApplication 注解的 scanBasePackages 属性 Springboot 项目启动类放置位置 如果我们使用 IDEA 或者 …

将Agent技术的灵活性引入RPA,清华等发布自动化智能体ProAgent

近日&#xff0c;来自清华大学的研究人员联合面壁智能、中国人民大学、MIT、CMU 等机构共同发布了新一代流程自动化范式 “智能体流程自动化” Agentic Process Automation&#xff08;APA&#xff09;&#xff0c;结合大模型智能体帮助人类进行工作流构建&#xff0c;并让智能…

Openlayer【二】—— 绘制不同的点、线以及给其添加监听事件

Openlayer【二】—— 绘制不同的点、线以及给其添加监听事件 接上篇&#xff1a;OpenLayer初始化 在openlayer当中&#xff0c;图层Layer与地图源Source是一对一的关系。当创建了一个图层Layer&#xff0c;相应的需要给图层添加地图源Source&#xff0c;然后将图层Layer添加到…

浅谈无线测温产品在菲律宾某工厂配电项目的应用

摘要&#xff1a;配电系统是由多种配电设备和配电设施所组成的变换电压和直接向终端用户分配电能的一个电力网络系统。由于配电系统作为电力系统的一个环节直接面向终端用户&#xff0c;它的完善与否直接关系着广大用户的用电可靠性和用电质量&#xff0c;因而在电力系统中具有…

第14届蓝桥杯青少组python试题解析:23年5月省赛

选择题 T1. 执行以下代码&#xff0c;输出结果是&#xff08;&#xff09;。 lst "abc" print(lstlst)abcabc abc lstlst abcabc T2. 执行以下代码&#xff0c;输出的结果是&#xff08;&#xff09;。 age {16,18,17} print(type(sorted(age)))<class set&…