当前位置: 首页 > news >正文

SpringMVC(后)SSM整合

10、文件上传和下载

10.1、文件下载

ResponseEntity用于控制器方法的返回值类型,该控制器方法的返回值就是响应到浏览器的响应报文

使用ResponseEntity实现下载文件的功能

@RequestMapping("/testDown")
public ResponseEntity<byte[]> testResponseEntity(HttpSession session) throwsIOException {//获取ServletContext对象ServletContext servletContext = session.getServletContext();//获取服务器中文件的真实路径String realPath = servletContext.getRealPath("/static/img/1.jpg");//创建输入流InputStream is = new FileInputStream(realPath);//创建字节数组byte[] bytes = new byte[is.available()];//将流读到字节数组中is.read(bytes);//创建HttpHeaders对象设置响应头信息MultiValueMap<String, String> headers = new HttpHeaders();//设置要下载方式以及下载文件的名字headers.add("Content-Disposition", "attachment;filename=1.jpg");//设置响应状态码HttpStatus statusCode = HttpStatus.OK;//创建ResponseEntity对象ResponseEntity<byte[]> responseEntity = new ResponseEntity<>(bytes, headers,statusCode);//关闭输入流is.close();return responseEntity;
}

10.2、文件上传

文件上传要求form表单的请求方式必须为post,并且添加属性enctype=“multipart/form-data”

SpringMVC中将上传的文件封装到MultipartFile对象中,通过此对象可以获取文件相关信息

上传步骤:

①添加依赖:

<!-- https://mvnrepository.com/artifact/commons-fileupload/commons-fileupload -->
<dependency><groupId>commons-fileupload</groupId><artifactId>commons-fileupload</artifactId><version>1.3.1</version>
</dependency>

②在SpringMVC的配置文件中添加配置:

<!--必须通过文件解析器的解析才能将文件转换为MultipartFile对象-->
<bean id="multipartResolver"
class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
</bean>

③控制器方法:

@RequestMapping("/testUp")
public String testUp(MultipartFile photo, HttpSession session) throws IOException {//获取上传的文件的文件名String fileName = photo.getOriginalFilename();//处理文件重名问题String hzName = fileName.substring(fileName.lastIndexOf("."));fileName = UUID.randomUUID().toString() + hzName;//获取服务器中photo目录的路径ServletContext servletContext = session.getServletContext();String photoPath = servletContext.getRealPath("photo");File file = new File(photoPath);if(!file.exists()){file.mkdir();}String finalPath = photoPath + File.separator + fileName;//实现上传功能photo.transferTo(new File(finalPath));return "success";
}

11、拦截器

11.1、拦截器的配置

SpringMVC中的拦截器用于拦截控制器方法的执行

SpringMVC中的拦截器需要实现HandlerInterceptor

SpringMVC的拦截器必须在SpringMVC的配置文件中进行配置:

<bean class="com.atguigu.interceptor.FirstInterceptor"></bean>
<ref bean="firstInterceptor"></ref>
<!-- 以上两种配置方式都是对DispatcherServlet所处理的所有的请求进行拦截 -->
<mvc:interceptor><mvc:mapping path="/**"/><mvc:exclude-mapping path="/testRequestEntity"/><ref bean="firstInterceptor"></ref>
</mvc:interceptor>
<!--以上配置方式可以通过ref或bean标签设置拦截器,通过mvc:mapping设置需要拦截的请求,通过mvc:exclude-mapping设置需要排除的请求,即不需要拦截的请求
-->

11.2、拦截器的三个抽象方法

SpringMVC中的拦截器有三个抽象方法:

preHandle:控制器方法执行之前执行preHandle(),其boolean类型的返回值表示是否拦截或放行,返回true为放行,即调用控制器方法;返回false表示拦截,即不调用控制器方法

postHandle:控制器方法执行之后执行postHandle()

afterCompletion:处理完视图和模型数据,渲染视图完毕之后执行afterCompletion()

11.3、多个拦截器的执行顺序

①若每个拦截器的preHandle()都返回true

此时多个拦截器的执行顺序和拦截器在SpringMVC的配置文件的配置顺序有关:

preHandle()会按照配置的顺序执行,而postHandle()和afterCompletion()会按照配置的反序执行

②若某个拦截器的preHandle()返回了false

preHandle()返回false和它之前的拦截器的preHandle()都会执行,postHandle()都不执行,返回false的拦截器之前的拦截器的afterCompletion()会执行

12、异常处理器

12.1、基于配置的异常处理

SpringMVC提供了一个处理控制器方法执行过程中所出现的异常的接口:HandlerExceptionResolver

HandlerExceptionResolver接口的实现类有:DefaultHandlerExceptionResolver和

SimpleMappingExceptionResolver

SpringMVC提供了自定义的异常处理器SimpleMappingExceptionResolver,使用方式:

<beanclass="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver"><property name="exceptionMappings"><props><!--properties的键表示处理器方法执行过程中出现的异常properties的值表示若出现指定异常时,设置一个新的视图名称,跳转到指定页面--><prop key="java.lang.ArithmeticException">error</prop></props></property><!--exceptionAttribute属性设置一个属性名,将出现的异常信息在请求域中进行共享--><property name="exceptionAttribute" value="ex"></property>
</bean>

12.2、基于注解的异常处理

//@ControllerAdvice将当前类标识为异常处理的组件
@ControllerAdvice
public class ExceptionController {//@ExceptionHandler用于设置所标识方法处理的异常@ExceptionHandler(ArithmeticException.class)//ex表示当前请求处理中出现的异常对象public String handleArithmeticException(Exception ex, Model model){model.addAttribute("ex", ex);return "error";}
}

13、注解配置SpringMVC

使用配置类和注解代替web.xml和SpringMVC配置文件的功能

13.1、创建初始化类,代替web.xml

在Servlet3.0环境中,容器会在类路径中查找实javax.servlet.ServletContainerInitializer接口的类,

如果找到的话就用它来配置Servlet容器。 Spring提供了这个接口的实现,名为
SpringServletContainerInitializer,这个类反过来又会查找实WebApplicationInitializer的类并将配置的任务交给它们来完成。Spring3.2引入了一个便利的
WebApplicationInitializer基础实现,名为AbstractAnnotationConfigDispatcherServletInitializer,当我们的类扩展了

AbstractAnnotationConfigDispatcherServletInitializer并将其部署到Servlet3.0容器的时候,容器会自动发现它,并用它来配置Servlet上下文。

public class WebInit extendsAbstractAnnotationConfigDispatcherServletInitializer {/*** 指定spring的配置类* @return*/@Overrideprotected Class<?>[] getRootConfigClasses() {return new Class[]{SpringConfig.class};}/*** 指定SpringMVC的配置类* @return*/@Overrideprotected Class<?>[] getServletConfigClasses() {return new Class[]{WebConfig.class};}/*** 指定DispatcherServlet的映射规则,即url-pattern* @return*/@Overrideprotected String[] getServletMappings() {return new String[]{"/"};}/*** 添加过滤器* @return*/@Overrideprotected Filter[] getServletFilters() {CharacterEncodingFilter encodingFilter = new CharacterEncodingFilter();encodingFilter.setEncoding("UTF-8");encodingFilter.setForceRequestEncoding(true);HiddenHttpMethodFilter hiddenHttpMethodFilter = newHiddenHttpMethodFilter();return new Filter[]{encodingFilter, hiddenHttpMethodFilter};}
}

13.2、创建SpringConfig配置类,代替spring的配置文件

@Configuration
public class SpringConfig {//ssm整合之后,spring的配置信息写在此类中
}

13.3、创建WebConfig配置类,代替SpringMVC的配置文件

@Configuration
//扫描组件
@ComponentScan("com.atguigu.mvc.controller")
//开启MVC注解驱动
@EnableWebMvc
public class WebConfig implements WebMvcConfigurer {//使用默认的servlet处理静态资源@Overridepublic void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {configurer.enable();}//配置文件上传解析器@Beanpublic CommonsMultipartResolver multipartResolver(){return new CommonsMultipartResolver();}//配置拦截器@Overridepublic void addInterceptors(InterceptorRegistry registry) {FirstInterceptor firstInterceptor = new FirstInterceptor();registry.addInterceptor(firstInterceptor).addPathPatterns("/**");}//配置视图控制/*@Overridepublic void addViewControllers(ViewControllerRegistry registry) {registry.addViewController("/").setViewName("index");}*///配置异常映射/*@Overridepublic void configureHandlerExceptionResolvers(List<HandlerExceptionResolver> resolvers) {SimpleMappingExceptionResolver exceptionResolver = new SimpleMappingExceptionResolver();Properties prop = new Properties();prop.setProperty("java.lang.ArithmeticException", "error");//设置异常映射exceptionResolver.setExceptionMappings(prop);//设置共享异常信息的键exceptionResolver.setExceptionAttribute("ex");resolvers.add(exceptionResolver);}*///配置生成模板解析器@Beanpublic ITemplateResolver templateResolver() {WebApplicationContext webApplicationContext =ContextLoader.getCurrentWebApplicationContext();// ServletContextTemplateResolver需要一个ServletContext作为构造参数,可通过WebApplicationContext 的方法获得ServletContextTemplateResolver templateResolver = newServletContextTemplateResolver(webApplicationContext.getServletContext());templateResolver.setPrefix("/WEB-INF/templates/");templateResolver.setSuffix(".html");templateResolver.setCharacterEncoding("UTF-8");templateResolver.setTemplateMode(TemplateMode.HTML);return templateResolver;}//生成模板引擎并为模板引擎注入模板解析器@Beanpublic SpringTemplateEngine templateEngine(ITemplateResolver templateResolver) {SpringTemplateEngine templateEngine = new SpringTemplateEngine();templateEngine.setTemplateResolver(templateResolver);return templateEngine;}//生成视图解析器并未解析器注入模板引擎@Beanpublic ViewResolver viewResolver(SpringTemplateEngine templateEngine) {ThymeleafViewResolver viewResolver = new ThymeleafViewResolver();viewResolver.setCharacterEncoding("UTF-8");viewResolver.setTemplateEngine(templateEngine);return viewResolver;}
}

13.4、测试功能

@RequestMapping("/")
public String index(){return "index";
}

14、SpringMVC执行流程

14.1、SpringMVC常用组件

  • DispatcherServlet:前端控制器,不需要工程师开发,由框架提供

作用:统一处理请求和响应,整个流程控制的中心,由它调用其它组件处理用户的请求

  • HandlerMapping:处理器映射器,不需要工程师开发,由框架提供

作用:根据请求的url、method等信息查找Handler,即控制器方法

  • Handler:处理器,需要工程师开发

作用:在DispatcherServlet的控制下Handler对具体的用户请求进行处理

  • HandlerAdapter:处理器适配器,不需要工程师开发,由框架提供

作用:通过HandlerAdapter对处理器(控制器方法)进行执行

  • ViewResolver:视图解析器,不需要工程师开发,由框架提供

作用:进行视图解析,得到相应的视图,例如:ThymeleafView、InternalResourceView、

RedirectView

  • View:视图

作用:将模型数据通过页面展示给用户

14.2、DispatcherServlet初始化过程

DispatcherServlet 本质上是一个 Servlet,所以天然的遵循 Servlet 的生命周期。所以宏观上是 Servlet生命周期来进行调度。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-XvXtAWNl-1682844225842)(img\33.png)]

①初始化WebApplicationContext

所在类:org.springframework.web.servlet.FrameworkServlet

protected WebApplicationContext initWebApplicationContext() {WebApplicationContext rootContext = WebApplicationContextUtils.getWebApplicationContext(getServletContext());WebApplicationContext wac = null;if (this.webApplicationContext != null) {// A context instance was injected at construction time -> use itwac = this.webApplicationContext;if (wac instanceof ConfigurableWebApplicationContext) {ConfigurableWebApplicationContext cwac =(ConfigurableWebApplicationContext) wac;if (!cwac.isActive()) {// The context has not yet been refreshed -> provide services such as// setting the parent context, setting the application context id, etcif (cwac.getParent() == null) {// The context instance was injected without an explicit parent -> set// the root application context (if any; may be null) as the parentcwac.setParent(rootContext);}configureAndRefreshWebApplicationContext(cwac);}}}if (wac == null) {// No context instance was injected at construction time -> see if one// has been registered in the servlet context. If one exists, it is assumed// that the parent context (if any) has already been set and that the// user has performed any initialization such as setting the context idwac = findWebApplicationContext();}if (wac == null) {// No context instance is defined for this servlet -> create a local one// 创建WebApplicationContextwac = createWebApplicationContext(rootContext);}if (!this.refreshEventReceived) {// Either the context is not a ConfigurableApplicationContext with refresh// support or the context injected at construction time had already been// refreshed -> trigger initial onRefresh manually here.synchronized (this.onRefreshMonitor) {// 刷新WebApplicationContextonRefresh(wac);}}if (this.publishContext) {// Publish the context as a servlet context attribute.// 将IOC容器在应用域共享String attrName = getServletContextAttributeName();getServletContext().setAttribute(attrName, wac);}return wac;
}

②创建WebApplicationContext

所在类:org.springframework.web.servlet.FrameworkServlet

protected WebApplicationContext createWebApplicationContext(@Nullable ApplicationContext parent) {Class<?> contextClass = getContextClass();if (!ConfigurableWebApplicationContext.class.isAssignableFrom(contextClass)){throw new ApplicationContextException("Fatal initialization error in servlet with name '" +getServletName() +"': custom WebApplicationContext class [" + contextClass.getName() +"] is not of type ConfigurableWebApplicationContext");}// 通过反射创建 IOC 容器对象ConfigurableWebApplicationContext wac = (ConfigurableWebApplicationContext)BeanUtils.instantiateClass(contextClass);wac.setEnvironment(getEnvironment());// 设置父容器wac.setParent(parent);String configLocation = getContextConfigLocation();if (configLocation != null) {wac.setConfigLocation(configLocation);}configureAndRefreshWebApplicationContext(wac);return wac;
}

③DispatcherServlet初始化策略

FrameworkServlet创建WebApplicationContext后,刷新容器,调用onRefresh(wac),此方法在

DispatcherServlet中进行了重写,调用了initStrategies(context)方法,初始化策略,即初始化

DispatcherServlet的各个组件

所在类:org.springframework.web.servlet.DispatcherServlet

protected void initStrategies(ApplicationContext context) {initMultipartResolver(context);initLocaleResolver(context);initThemeResolver(context);initHandlerMappings(context);initHandlerAdapters(context);initHandlerExceptionResolvers(context);initRequestToViewNameTranslator(context);initViewResolvers(context);initFlashMapManager(context);
}

14.3、DispatcherServlet调用组件处理请求

①processRequest()

FrameworkServlet重写HttpServlet中的service()和doXxx(),这些方法中调用了

processRequest(request, response)

所在类:org.springframework.web.servlet.FrameworkServlet

protected final void processRequest(HttpServletRequest request,HttpServletResponse response)throws ServletException, IOException
{long startTime = System.currentTimeMillis();Throwable failureCause = null;LocaleContext previousLocaleContext = LocaleContextHolder.getLocaleContext();LocaleContext localeContext = buildLocaleContext(request);RequestAttributes previousAttributes = RequestContextHolder.getRequestAttributes();ServletRequestAttributes requestAttributes = buildRequestAttributes(request,response, previousAttributes);WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);asyncManager.registerCallableInterceptor(FrameworkServlet.class.getName(),new RequestBindingInterceptor());initContextHolders(request, localeContext, requestAttributes);try {// 执行服务,doService()是一个抽象方法,在DispatcherServlet中进行了重写doService(request, response);}catch (ServletException | IOException ex) {failureCause = ex;throw ex;}catch (Throwable ex) {failureCause = ex;throw new NestedServletException("Request processing failed", ex);}finally {resetContextHolders(request, previousLocaleContext, previousAttributes);if (requestAttributes != null) {requestAttributes.requestCompleted();}logResult(request, response, failureCause, asyncManager);publishRequestHandledEvent(request, response, startTime, failureCause);}
}

②doService()

所在类:org.springframework.web.servlet.DispatcherServlet

@Override
protected void doService(HttpServletRequest request, HttpServletResponse response) throws Exception {logRequest(request);// Keep a snapshot of the request attributes in case of an include,// to be able to restore the original attributes after the include.Map<String, Object> attributesSnapshot = null;if (WebUtils.isIncludeRequest(request)) {attributesSnapshot = new HashMap<>();Enumeration<?> attrNames = request.getAttributeNames();while (attrNames.hasMoreElements()) {String attrName = (String) attrNames.nextElement();if (this.cleanupAfterInclude || attrName.startsWith(DEFAULT_STRATEGIES_PREFIX)) {attributesSnapshot.put(attrName,request.getAttribute(attrName));}}}// Make framework objects available to handlers and view objects.request.setAttribute(WEB_APPLICATION_CONTEXT_ATTRIBUTE,getWebApplicationContext());request.setAttribute(LOCALE_RESOLVER_ATTRIBUTE, this.localeResolver);request.setAttribute(THEME_RESOLVER_ATTRIBUTE, this.themeResolver);request.setAttribute(THEME_SOURCE_ATTRIBUTE, getThemeSource());if (this.flashMapManager != null) {FlashMap inputFlashMap = this.flashMapManager.retrieveAndUpdate(request,response);if (inputFlashMap != null) {request.setAttribute(INPUT_FLASH_MAP_ATTRIBUTE,Collections.unmodifiableMap(inputFlashMap));}request.setAttribute(OUTPUT_FLASH_MAP_ATTRIBUTE, new FlashMap());request.setAttribute(FLASH_MAP_MANAGER_ATTRIBUTE, this.flashMapManager);}RequestPath requestPath = null;if (this.parseRequestPath && !ServletRequestPathUtils.hasParsedRequestPath(request)) {requestPath = ServletRequestPathUtils.parseAndCache(request);}try {// 处理请求和响应doDispatch(request, response);}finally {if(!WebAsyncUtils.getAsyncManager(request).isConcurrentHandlingStarted()) {// Restore the original attribute snapshot, in case of an include.if (attributesSnapshot != null) {restoreAttributesAfterInclude(request, attributesSnapshot);}}if (requestPath != null) {ServletRequestPathUtils.clearParsedRequestPath(request);}}
}

③doDispatch()

所在类:org.springframework.web.servlet.DispatcherServlet

protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {HttpServletRequest processedRequest = request;HandlerExecutionChain mappedHandler = null;boolean multipartRequestParsed = false;WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);try {ModelAndView mv = null;Exception dispatchException = null;try {processedRequest = checkMultipart(request);multipartRequestParsed = (processedRequest != request);// Determine handler for the current request./*mappedHandler:调用链包含handler、interceptorList、interceptorIndexhandler:浏览器发送的请求所匹配的控制器方法interceptorList:处理控制器方法的所有拦截器集合interceptorIndex:拦截器索引,控制拦截器afterCompletion()的执行*/mappedHandler = getHandler(processedRequest);if (mappedHandler == null) {noHandlerFound(processedRequest, response);return;}// Determine handler adapter for the current request.// 通过控制器方法创建相应的处理器适配器,调用所对应的控制器方法HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());// Process last-modified header, if supported by the handler.String method = request.getMethod();boolean isGet = "GET".equals(method);if (isGet || "HEAD".equals(method)) {long lastModified = ha.getLastModified(request,mappedHandler.getHandler());if (new ServletWebRequest(request,response).checkNotModified(lastModified) && isGet) {return;}}// 调用拦截器的preHandle()if (!mappedHandler.applyPreHandle(processedRequest, response)) {return;}// Actually invoke the handler.// 由处理器适配器调用具体的控制器方法,最终获得ModelAndView对象mv = ha.handle(processedRequest, response,mappedHandler.getHandler());if (asyncManager.isConcurrentHandlingStarted()) {return;}applyDefaultViewName(processedRequest, mv);// 调用拦截器的postHandle()mappedHandler.applyPostHandle(processedRequest, response, mv);}catch (Exception ex) {dispatchException = ex;}catch (Throwable err) {// As of 4.3, we're processing Errors thrown from handler methods as well,// making them available for @ExceptionHandler methods and otherscenarios.dispatchException = new NestedServletException("Handler dispatchfailed", err);}// 后续处理:处理模型数据和渲染视图 processDispatchResult(processedRequest, response, mappedHandler, mv,dispatchException);}catch (Exception ex) {triggerAfterCompletion(processedRequest, response, mappedHandler, ex);}catch (Throwable err) {triggerAfterCompletion(processedRequest, response, mappedHandler,new NestedServletException("Handler processingfailed",err));}finally {if (asyncManager.isConcurrentHandlingStarted()) {// Instead of postHandle and afterCompletionif (mappedHandler != null) {mappedHandler.applyAfterConcurrentHandlingStarted(processedRequest, response);}}else {// Clean up any resources used by a multipart request.if (multipartRequestParsed) {cleanupMultipart(processedRequest);}}}
}                                                          

④processDispatchResult()

private void processDispatchResult(HttpServletRequest request,HttpServletResponse response,@Nullable HandlerExecutionChainmappedHandler, @Nullable ModelAndView mv,@Nullable Exception exception) throws Exception {boolean errorView = false;if (exception != null) {if (exception instanceof ModelAndViewDefiningException) {logger.debug("ModelAndViewDefiningException encountered",exception);mv = ((ModelAndViewDefiningException) exception).getModelAndView();}else {Object handler = (mappedHandler != null ? mappedHandler.getHandler(): null);mv = processHandlerException(request, response, handler, exception);errorView = (mv != null);}}// Did the handler return a view to render?if (mv != null && !mv.wasCleared()) {// 处理模型数据和渲染视图render(mv, request, response);if (errorView) {WebUtils.clearErrorRequestAttributes(request);}}else {if (logger.isTraceEnabled()) {logger.trace("No view rendering, null ModelAndView returned.");}}if (WebAsyncUtils.getAsyncManager(request).isConcurrentHandlingStarted()) {// Concurrent handling started during a forwardreturn;}if (mappedHandler != null) {// Exception (if any) is already handled..// 调用拦截器的afterCompletion()mappedHandler.triggerAfterCompletion(request, response, null);}
}                                   

14.4、SpringMVC的执行流程

1.) 用户向服务器发送请求,请求被SpringMVC 前端控制器 DispatcherServlet捕获。

  1. DispatcherServlet对请求URL进行解析,得到请求资源标识符(URI),判断请求URI对应的映射:

a) 不存在

i. 再判断是否配置了mvc:default-servlet-handler

ii. 如果没配置,则控制台报映射查找不到,客户端展示404错误

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-bhG3KPLT-1682844225842)(img\34.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-366On5zk-1682844225842)(img\35.png)]

iii. 如果有配置,则访问目标资源(一般为静态资源,如:JS,CSS,HTML),找不到客户端也会展示404

错误

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-CPk083iM-1682844225843)(img\36.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-FnkXTGRh-1682844225843)(img\37.png)]

b) 存在则执行下面的流程

3.) 根据该URI,调用HandlerMapping获得该Handler配置的所有相关的对象(包括Handler对象以及Handler对象对应的拦截器),最后以HandlerExecutionChain执行链对象的形式返回。

4.) DispatcherServlet 根据获得的Handler,选择一个合适的HandlerAdapter。

5.) 如果成功获得HandlerAdapter,此时将开始执行拦截器的preHandler(…)方法【正向】

6.) 提取Request中的模型数据,填充Handler入参,开始执行Handler(Controller)方法,处理请求。

在填充Handler的入参过程中,根据你的配置,Spring将帮你做一些额外的工作:

a) HttpMessageConveter: 将请求消息(如Json、xml等数据)转换成一个对象,将对象转换为指定的响应信息

b) 数据转换:对请求消息进行数据转换。如String转换成Integer、Double等

c) 数据格式化:对请求消息进行数据格式化。 如将字符串转换成格式化数字或格式化日期等

d) 数据验证: 验证数据的有效性(长度、格式等),验证结果存储到BindingResult或Error中

7.) Handler执行完成后,向DispatcherServlet 返回一个ModelAndView对象。

8.) 此时将开始执行拦截器的postHandle(…)方法【逆向】。

9.) 根据返回的ModelAndView(此时会判断是否存在异常:如果存在异常,则执行

HandlerExceptionResolver进行异常处理)选择一个适合的ViewResolver进行视图解析,根据Model和View,来渲染视图。

10.) 渲染视图完毕执行拦截器的afterCompletion(…)方法【逆向】。

11.) 将渲染结果返回给客户端。

四、SSM整合

4.1、ContextLoaderListener

Spring提供了监听器ContextLoaderListener,实现ServletContextListener接口,可监听

ServletContext的状态,在web服务器的启动,读取Spring的配置文件,创建Spring的IOC容器。web应用中必须在web.xml中配置

<listener><!--配置Spring的监听器,在服务器启动时加载Spring的配置文件Spring配置文件默认位置和名称:/WEB-INF/applicationContext.xml可通过上下文参数自定义Spring配置文件的位置和名称--><listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<!--自定义Spring配置文件的位置和名称-->
<context-param><param-name>contextConfigLocation</param-name><param-value>classpath:spring.xml</param-value>
</context-param>

4.2、准备工作

①创建Maven Module

②导入依赖

<packaging>war</packaging>
<properties><spring.version>5.3.1</spring.version>
</properties>
<dependencies><dependency><groupId>org.springframework</groupId><artifactId>spring-context</artifactId><version>${spring.version}</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-beans</artifactId><version>${spring.version}</version></dependency><!--springmvc--><dependency><groupId>org.springframework</groupId><artifactId>spring-web</artifactId><version>${spring.version}</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-webmvc</artifactId><version>${spring.version}</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-jdbc</artifactId><version>${spring.version}</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-aspects</artifactId><version>${spring.version}</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-test</artifactId><version>${spring.version}</version></dependency><!-- Mybatis核心 --><dependency><groupId>org.mybatis</groupId><artifactId>mybatis</artifactId><version>3.5.7</version></dependency><!--mybatis和spring的整合包--><dependency><groupId>org.mybatis</groupId><artifactId>mybatis-spring</artifactId><version>2.0.6</version></dependency><!-- 连接池 --><dependency><groupId>com.alibaba</groupId><artifactId>druid</artifactId><version>1.0.9</version></dependency><!-- junit测试 --><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.12</version><scope>test</scope></dependency><!-- MySQL驱动 --><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>8.0.16</version></dependency><!-- log4j日志 --><dependency><groupId>log4j</groupId><artifactId>log4j</artifactId><version>1.2.17</version></dependency><!-- https://mvnrepository.com/artifact/com.github.pagehelper/pagehelper -->   <dependency><groupId>com.github.pagehelper</groupId><artifactId>pagehelper</artifactId><version>5.2.0</version></dependency><!-- 日志 --><dependency><groupId>ch.qos.logback</groupId><artifactId>logback-classic</artifactId><version>1.2.3</version></dependency><!-- ServletAPI --><dependency><groupId>javax.servlet</groupId><artifactId>javax.servlet-api</artifactId><version>3.1.0</version><scope>provided</scope></dependency><dependency><groupId>com.fasterxml.jackson.core</groupId><artifactId>jackson-databind</artifactId><version>2.12.1</version></dependency><dependency><groupId>commons-fileupload</groupId><artifactId>commons-fileupload</artifactId><version>1.3.1</version></dependency><!-- Spring5和Thymeleaf整合包 --><dependency><groupId>org.thymeleaf</groupId><artifactId>thymeleaf-spring5</artifactId><version>3.0.12.RELEASE</version></dependency>
</dependencies> 

③创建表

CREATE TABLE `t_emp` (`emp_id` int(11) NOT NULL AUTO_INCREMENT,`emp_name` varchar(20) DEFAULT NULL,`age` int(11) DEFAULT NULL,`sex` char(1) DEFAULT NULL,`email` varchar(50) DEFAULT NULL,PRIMARY KEY (`emp_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8

4.3、配置web.xml

<!-- 配置Spring的编码过滤器 -->
<filter><filter-name>CharacterEncodingFilter</filter-name><filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class><init-param><param-name>encoding</param-name><param-value>UTF-8</param-value></init-param><init-param><param-name>forceEncoding</param-name><param-value>true</param-value></init-param>
</filter>
<filter-mapping><filter-name>CharacterEncodingFilter</filter-name><url-pattern>/*</url-pattern>
</filter-mapping>
<!-- 配置处理请求方式PUT和DELETE的过滤器 -->
<filter><filter-name>HiddenHttpMethodFilter</filter-name><filter-class>org.springframework.web.filter.HiddenHttpMethodFilter</filterclass>
</filter>
<filter-mapping><filter-name>HiddenHttpMethodFilter</filter-name><url-pattern>/*</url-pattern>
</filter-mapping>
<!-- 配置SpringMVC的前端控制器 -->
<servlet><servlet-name>DispatcherServlet</servlet-name><servlet-class>org.springframework.web.servlet.DispatcherServlet</servletclass><!-- 设置SpringMVC的配置文件的位置和名称 --><init-param><param-name>contextConfigLocation</param-name><param-value>classpath:SpringMVC.xml</param-value></init-param><load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping><servlet-name>DispatcherServlet</servlet-name><url-pattern>/</url-pattern>
</servlet-mapping>
<!-- 设置Spring的配置文件的位置和名称 -->
<context-param><param-name>contextConfigLocation</param-name><param-value>classpath:Spring.xml</param-value>
</context-param>
<!-- 配置Spring的监听器 -->
<listener><listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>

4.4、创建SpringMVC的配置文件并配置

<!--扫描组件-->
<context:component-scan base-package="com.atguigu.ssm.controller">
</context:component-scan>
<!--配置视图解析器-->
<bean id="viewResolver"class="org.thymeleaf.spring5.view.ThymeleafViewResolver"><property name="order" value="1"/><property name="characterEncoding" value="UTF-8"/><property name="templateEngine"><bean class="org.thymeleaf.spring5.SpringTemplateEngine"><property name="templateResolver"><beanclass="org.thymeleaf.spring5.templateresolver.SpringResourceTemplateResolver"><!-- 视图前缀 --><property name="prefix" value="/WEB-INF/templates/"/><!-- 视图后缀 --><property name="suffix" value=".html"/><property name="templateMode" value="HTML5"/><property name="characterEncoding" value="UTF-8" /></bean></property></bean></property>
</bean>
<!-- 配置访问首页的视图控制 -->
<mvc:view-controller path="/" view-name="index"></mvc:view-controller>
<!-- 配置默认的servlet处理静态资源 -->
<mvc:default-servlet-handler />
<!-- 开启MVC的注解驱动 -->
<mvc:annotation-driven />

4.5、搭建MyBatis环境

①创建属性文件jdbc.properties

jdbc.user=root
jdbc.password=atguigu
jdbc.url=jdbc:mysql://localhost:3306/ssm?serverTimezone=UTC
jdbc.driver=com.mysql.cj.jdbc.Driver

②创建MyBatis的核心配置文件mybatis-config.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration><settings><!--将下划线映射为驼峰--><setting name="mapUnderscoreToCamelCase" value="true"/></settings><plugins><!--配置分页插件--><plugin interceptor="com.github.pagehelper.PageInterceptor"></plugin></plugins>
</configuration>

③创建Mapper接口和映射文件

public interface EmployeeMapper {
List<Employee> getEmployeeList();
}
<?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.atguigu.ssm.mapper.EmployeeMapper"><select id="getEmployeeList" resultType="Employee">select * from t_emp</select>
</mapper>

④创建日志文件log4j.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/"><appender name="STDOUT" class="org.apache.log4j.ConsoleAppender"><param name="Encoding" value="UTF-8" /><layout class="org.apache.log4j.PatternLayout"><param name="ConversionPattern" value="%-5p %d{MM-dd HH:mm:ss,SSS} %m (%F:%L) \n" /></layout></appender><logger name="java.sql"><level value="debug" /></logger><logger name="org.apache.ibatis"><level value="info" /></logger><root><level value="debug" /><appender-ref ref="STDOUT" /></root>
</log4j:configuration>

4.6、创建Spring的配置文件并配置

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:context="http://www.springframework.org/schema/context"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/contexthttps://www.springframework.org/schema/context/spring-context.xsd"><!--扫描组件--><context:component-scan base-package="com.atguigu.ssm"><context:exclude-filter type="annotation"expression="org.springframework.stereotype.Controller"/></context:component-scan><!-- 引入jdbc.properties --><context:property-placeholder location="classpath:jdbc.properties"></context:property-placeholder><!-- 配置Druid数据源 --><bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource"><property name="driverClassName" value="${jdbc.driver}"></property><property name="url" value="${jdbc.url}"></property><property name="username" value="${jdbc.username}"></property><property name="password" value="${jdbc.password}"></property></bean><!-- 配置用于创建SqlSessionFactory的工厂bean --><bean class="org.mybatis.spring.SqlSessionFactoryBean"><!-- 设置MyBatis配置文件的路径(可以不设置) --><property name="configLocation" value="classpath:mybatis-config.xml"></property><!-- 设置数据源 --><property name="dataSource" ref="dataSource"></property><!-- 设置类型别名所对应的包 --><property name="typeAliasesPackage" value="com.atguigu.ssm.pojo"></property><!--设置映射文件的路径若映射文件所在路径和mapper接口所在路径一致,则不需要设置--><!--<property name="mapperLocations" value="classpath:mapper/*.xml"></property>--></bean><!--配置mapper接口的扫描配置由mybatis-spring提供,可以将指定包下所有的mapper接口创建动态代理并将这些动态代理作为IOC容器的bean管理--><bean class="org.mybatis.spring.mapper.MapperScannerConfigurer"><property name="basePackage" value="com.atguigu.ssm.mapper"></property></bean>
</beans>

4.7、测试功能

①创建组件

实体类Employee

public class Employee {private Integer empId;private String empName;private Integer age;private String sex;private String email;public Employee() {}public Employee(Integer empId, String empName, Integer age, String sex,String email) {this.empId = empId;this.empName = empName;this.age = age;this.sex = sex;this.email = email;}public Integer getEmpId() {return empId;}public void setEmpId(Integer empId) {this.empId = empId;}public String getEmpName() {return empName;}public void setEmpName(String empName) {this.empName = empName;}public Integer getAge() {return age;}public void setAge(Integer age) {this.age = age;}public String getSex() {return sex;}public void setSex(String sex) {this.sex = sex;}public String getEmail() {return email;}public void setEmail(String email) {this.email = email;}
}

创建控制层组件EmployeeController

@Controller
public class EmployeeController {@Autowiredprivate EmployeeService employeeService;@RequestMapping(value = "/employee/page/{pageNum}", method = RequestMethod.GET)public String getEmployeeList(Model model, @PathVariable("pageNum") Integer pageNum){PageInfo<Employee> page = employeeService.getEmployeeList(pageNum);model.addAttribute("page", page);return "employee_list";}
}

创建接口EmployeeService

public interface EmployeeService {PageInfo<Employee> getEmployeeList(Integer pageNum);
}

创建实现类EmployeeServiceImpl

@Service
public class EmployeeServiceImpl implements EmployeeService {@Autowiredprivate EmployeeMapper employeeMapper;@Overridepublic PageInfo<Employee> getEmployeeList(Integer pageNum) {PageHelper.startPage(pageNum, 4);List<Employee> list = employeeMapper.getEmployeeList();PageInfo<Employee> page = new PageInfo<>(list, 5);return page;}
}

②创建页面

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org"><head><meta charset="UTF-8"><title>Employee Info</title><link rel="stylesheet" th:href="@{/static/css/index_work.css}"></head><body><table><tr><th colspan="6">Employee Info</th></tr><tr><th>emp_id</th><th>emp_name</th><th>age</th><th>sex</th><th>email</th><th>options</th></tr><tr th:each="employee : ${page.list}"><td th:text="${employee.empId}"></td><td th:text="${employee.empName}"></td><td th:text="${employee.age}"></td><td th:text="${employee.sex}"></td><td th:text="${employee.email}"></td><td><a href="">delete</a><a href="">update</a></td></tr><tr><td colspan="6"><span th:if="${page.hasPreviousPage}"><a th:href="@{/employee/page/1}">首页</a><a th:href="@{'/employee/page/'+${page.prePage}}">上一页</a></span><span th:each="num : ${page.navigatepageNums}"><a th:if="${page.pageNum==num}"th:href="@{'/employee/page/'+${num}}" th:text="'['+${num}+']'" style="color:red;"></a><a th:if="${page.pageNum!=num}"th:href="@{'/employee/page/'+${num}}" th:text="${num} "></a></span><span th:if="${page.hasNextPage}"><a th:href="@{'/employee/page/'+${page.nextPage}}">下一页</a><a th:href="@{'/employee/page/'+${page.pages}}">末页</a></span></td></tr></table></body>
</html>

③访问测试分页功能


创建接口EmployeeService```java
public interface EmployeeService {PageInfo<Employee> getEmployeeList(Integer pageNum);
}

创建实现类EmployeeServiceImpl

@Service
public class EmployeeServiceImpl implements EmployeeService {@Autowiredprivate EmployeeMapper employeeMapper;@Overridepublic PageInfo<Employee> getEmployeeList(Integer pageNum) {PageHelper.startPage(pageNum, 4);List<Employee> list = employeeMapper.getEmployeeList();PageInfo<Employee> page = new PageInfo<>(list, 5);return page;}
}

②创建页面

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org"><head><meta charset="UTF-8"><title>Employee Info</title><link rel="stylesheet" th:href="@{/static/css/index_work.css}"></head><body><table><tr><th colspan="6">Employee Info</th></tr><tr><th>emp_id</th><th>emp_name</th><th>age</th><th>sex</th><th>email</th><th>options</th></tr><tr th:each="employee : ${page.list}"><td th:text="${employee.empId}"></td><td th:text="${employee.empName}"></td><td th:text="${employee.age}"></td><td th:text="${employee.sex}"></td><td th:text="${employee.email}"></td><td><a href="">delete</a><a href="">update</a></td></tr><tr><td colspan="6"><span th:if="${page.hasPreviousPage}"><a th:href="@{/employee/page/1}">首页</a><a th:href="@{'/employee/page/'+${page.prePage}}">上一页</a></span><span th:each="num : ${page.navigatepageNums}"><a th:if="${page.pageNum==num}"th:href="@{'/employee/page/'+${num}}" th:text="'['+${num}+']'" style="color:red;"></a><a th:if="${page.pageNum!=num}"th:href="@{'/employee/page/'+${num}}" th:text="${num} "></a></span><span th:if="${page.hasNextPage}"><a th:href="@{'/employee/page/'+${page.nextPage}}">下一页</a><a th:href="@{'/employee/page/'+${page.pages}}">末页</a></span></td></tr></table></body>
</html>

③访问测试分页功能

localhost:8080/employee/page/1

相关文章:

SpringMVC(后)SSM整合

10、文件上传和下载 10.1、文件下载 ResponseEntity用于控制器方法的返回值类型&#xff0c;该控制器方法的返回值就是响应到浏览器的响应报文 使用ResponseEntity实现下载文件的功能 RequestMapping("/testDown") public ResponseEntity<byte[]> testResp…...

【博弈论】【第一章】博弈论导论

博弈论导论 【例题】选择数字【例题】巴什博弈【例题】射手博弈博弈论的基本概念&#xff1a;参与人战略行动信息支付函数【例题】分100元 课程概述&#xff1a; 【例题】选择数字 两个参与人A和B&#xff0c;轮流选择[3,4,5,6,7,8,9]中的一个整数&#xff08;可重复)。当累计…...

keil移植linux(makefile)

文章目录 运行环境&#xff1a;1.1 freeRTOS_LED工程移植1)修改cubeMX配置2)setting设置3)launch设置4)修改makefile5)修改代码6)实验效果 运行环境&#xff1a; ubuntu18.04.melodic 宏基暗影骑士笔记本 stm32f427IIH6 stlink 9-24v可调电源 robomaster A 板 1.1 freeRTOS_L…...

C++——类和对象(3)

作者&#xff1a;几冬雪来 时间&#xff1a;2023年5月6日 内容&#xff1a;C类和对象内容讲解 目录 前言&#xff1a; 1.运算符重载&#xff08;续&#xff09;&#xff1a; 2.赋值重载&#xff1a; 结尾&#xff1a; 前言&#xff1a; 在上一篇博客中我们再一次讲解了…...

itop-3568开发板驱动学习笔记(24)设备树(三)时钟实例分析

《【北京迅为】itop-3568开发板驱动开发指南.pdf》 学习笔记 文章目录 生产者属性#clock-cells 属性clock-output-namesclock-frequencyassigned-clockclock-indicesassigned-clock-parents 消费者属性 设备树中的时钟信息以时钟树形式体现&#xff0c;时钟树包括时钟的属性和结…...

linux中使用docker部署微服务

目录 一、制作jar包&#xff08;如果看一眼很简单&#xff0c;可以直接使用结尾的jar&#xff09; 1.首先创建一个微服务 demo2 2.启动微服务&#xff08;在DemoApplication上右键执行启动就行&#xff09; 注意&#xff1a;其他操作导致的 可能遇到的报错 3.修改端口 4.新…...

操作系统考试复习—第三章 优先级倒置 死锁问题

当前OS广泛采用优先级调度算法和抢占方式&#xff0c;然而在系统中存在着影响进程运行的资源从而可能产生"优先级倒置"现象 具体解释为&#xff1a;在原本的调度算法设计中&#xff0c;高优先级进程可以抢占低优先级的CPU资源&#xff0c;先执行高优先级任务。但是存…...

OpenHarmony送显流程分析

OpenHarmony送显流程分析 引言 本文档主要记录OpenHarmony在渲染完成之后如何进行合成和送显流程的。这个过程牵涉的代码很多&#xff0c;而且流程也是比较繁琐的。所以我一定要坚持下来。千万不能半途而废&#xff0c;也不要想着一口气吃出一个胖子&#xff0c;路漫漫其修远兮…...

Java面试题字节流字符流

String 编码UTF-8 和GBK的区别 GBK编码&#xff1a;是指中国的中文字符&#xff0c;其实它包含了简体中文与繁体中文字符&#xff0c;另外还有一种字符 “gb2312”&#xff0c;这种字符仅能存储简体中文字符。 UTF-8编码&#xff1a;它是一种全国家通过的一种编码&#x…...

Self-Attention结构细节及计算过程

一、结构 上面那个图其实不是那么重要&#xff0c;只要知道将输入的x矩阵转换成三个矩阵进行计算即可。自注意力结构的输入为 输入矩阵的三个变形 Q&#xff08;query矩阵&#xff09;、K&#xff08;key矩阵&#xff09;、V&#xff08;value矩阵&#xff09;构成&#xff0c;…...

在Ubuntu18.04中安装uWebSockets库

目录 1.下载uWebSockets库2.下载uSockets3.安装openssl开发包4.编译首先说明这里使用的Ubuntu版本为18.04。 1.下载uWebSockets库 下载uWebSockets库有两种方式,一是终端,从Github中克隆uWebSockets库到Ubuntu本地文件夹,二是打开uWebSockets库下载链接自己下载到Windows,然…...

【Fluent】接着上一次计算的结果继续计算,利用计算过程中得到的物理场(温度、速度、压力等)插值Interpolate文件初始化模型的方法

一、问题背景 因为fluent中支持的初始化无非三种类型。 1、Standard initialization 标准初始化 2、Hybridinitialization 混合初始化 3、FMG initialization FMG初始化 另外&#xff0c;还可以用UDF通过坐标判断的方式予以初始化。 但是这些初始化方法都没办法利用以前计算过…...

第二十九章 使用消息订阅发布实现组件通信

PubSubJS库介绍 如果你想在React中使用第三方库来实现Pub/Sub机制&#xff0c;PubSubJS是一个不错的选择。它是一个轻量级的库&#xff0c;可以在浏览器和Node.js环境中使用。 PubSubJS提供了一个简单的API&#xff0c;可以让你在应用程序中订阅和发布消息。你可以使用npm来安…...

Transformer的位置编码

1. 什么是位置编码&#xff0c;为什么要使用位置编码 简单来说位置编码就是给一个句子中的每个token一个位置信息&#xff0c;通过位置编码可以明确token的前后顺序关系。 对任何语言来说&#xff0c;句子中词汇的顺序和位置都是非常重要的。它们定义了语法&#xff0c;从而定…...

Python学习简记

做题时遇到的不知道的知识点会更新在此&#xff1a; python中的int()函数可以用于进制转换 该函数最为常见的使用是用于强制类型转换&#xff0c;实际上&#xff0c;它可以有两个参数 值得强调的是当传入两个参数时第一个参数一定要是字符串类型 字符串方法&#xff1a; lower(…...

windows搭建一个FTP服务器超详细

一.场景&#xff1a; 在开发过程中需要FTP文件上传下载功能&#xff0c;需要在本地或者服务器上搭建一个FTP服务器。 二.详细步骤&#xff1a; 1. 安装FTP服务器支持和配置IIS web服务器 打卡“启动关闭Window功能” 控制面板>程序>启动或关闭Windows功能 或者选择快…...

u01使用率100%报错归档满的问题

今天下午客户报数据库无法连接了&#xff0c;我也立刻登录查看 因为显示orcl1归档满了&#xff0c;我就登录查看磁盘组的空间&#xff0c;发现空间空余很多 就sqlpus登录了&#xff0c;发现u01使用率满了 [oracledb1 ~]$ sqlplus / as sysdba SQL*Plus: Release 11.2.0.4.0 …...

Packet Tracer - 配置扩展 ACL - 场景 2

Packet Tracer - 配置扩展 ACL - 场景 2 拓扑图 地址分配表 设备 接口 IP 地址 子网掩码 默认网关 RTA G0/0 10.101.117.49 255.255.255.248 不适用 G0/1 10.101.117.33 255.255.255.240 不适用 G0/2 10.101.117.1 255.255.255.224 不适用 PCA NIC 10.101…...

最近面了12个人,发现这个测试基础题都答不上来...

一般面试我都会问一两道很基础的题目&#xff0c;来考察候选人的“地基”是否扎实&#xff0c;有些是操作系统层面的&#xff0c;有些是 python语言方面的&#xff0c;还有些… 深耕IT行业多年&#xff0c;我们发现&#xff0c;对于一个程序员而言&#xff0c;能去到一线互联网…...

JAVA基于Springboot框架的停车场管理系统开发实践和实现【附源码】

运行环境: jdk1.8idea/eclipsemaven3mysql5.6 项目技术: Java,Springboot,mybatis,mysql,jquery,html 该系统为停车场管理人员提供了对停车场中车辆&#xff0c;车位和财务的管理。操作员可以灵活地使用相关权限开展工作。在车位管理&#xff0c;车辆的停放和驶离、缴费&a…...

[230501] 4月29日考试真题第一篇|Temporary Pools

题目来源&#xff1a;http://t.csdn.cn/goCDT 正确率&#xff1a;6/10 目录​​​​​​​ Temporary Pools 题目 Temporary Pools Paragraph 1: Temporary pools are freshwater habitats that retain water for only three to four months of the year or even shorter pe…...

Qt中QString, int等数据转换以及Qt与Halcon联编程序打包

一、Qt中QString, int等数据转换 在QT中,数值类型转为字符串类型,一般是可以使用 QString::number(); 示例: int num = 65; QString ab = QString::number(num); 其实还可以转为不同的进制字符串,比如 int num = 65; QString ab = QString::number(num,10); //十进…...

Android FlexboxLayout布局

FlexboxLayout 布局 一、简介二、使用三、功能详解FlexboxLayout属性flexWrapflexDirectionalignItemsjustifyContentalignContentdividerDrawableHorizontal、showDividerHorizontaldividerDrawableVertical、showDividerVerticaldividerDrawable、showDividermaxLine Flexbox…...

GNU编码标准(七)发布过程 相关内容摘录

仅对第7章The Release Process的内容进行摘录。 文章目录 7 发布过程7.1 configure应该如何工作7.2Makefile公约7.2.1 Makefile的一般公约7.2.2 Makefiles中的实用程序7.2.3 指定命令的变量7.2.4 DESTDIR&#xff1a;支持分阶段安装7.2.5 安装目录的变量7.2.6 用户标准目标7.2…...

DX算法还原

早在之前作者就写过一篇关于顶象的滑块验证&#xff0c;潦潦草草几句话就带过了。 出于互相学习的想法&#xff0c;给了一个大学生&#xff0c;奈何不讲武德把源码甩群里了&#xff0c;虽然在大佬们眼里不难&#xff0c; 不过拿着别人的东西乱传还是不太好。自认倒霉&#xf…...

多媒体API

私人博客 许小墨のBlog —— 菜鸡博客直通车 系列文章完整版&#xff0c;配图更多&#xff0c;CSDN博文图片需要手动上传&#xff0c;因此文章配图较少&#xff0c;看不懂的可以去菜鸡博客参考一下配图&#xff01; 系列文章目录 前端系列文章——传送门 后端系列文章——传送…...

免费矢量图标网站有哪些?

图标作为UI设计的必要元素&#xff0c;矢量图标是质量的保证。据说完美的用户体验应该从灵活性开始 。在响应设计盛行的当下&#xff0c;灵活矢量图标的重要性不言而喻。在这种情况下&#xff0c;风格齐全、质量上乘的矢量图标网站堪称设计宝藏。在这篇文章中&#xff0c;我们…...

基于Redis的分布式限流详解

前言 Redis除了能用作缓存外&#xff0c;还有很多其他用途&#xff0c;比如分布式锁&#xff0c;分布式限流&#xff0c;分布式唯一主键等&#xff0c;本文将和大家分享下基于Redis分布式限流的各种实现方案。 一、为什么需要限流 用最简单的话来说&#xff1a;外部请求是不可…...

权限提升:漏洞探针.(Linux系统)

权限提升&#xff1a;漏洞探针. 权限提升简称提权&#xff0c;由于操作系统都是多用户操作系统&#xff0c;用户之间都有权限控制&#xff0c;比如通过 Web 漏洞拿到的是 Web 进程的权限&#xff0c;往往 Web 服务都是以一个权限很低的账号启动的&#xff0c;因此通过 Webshel…...

python-11-多线程模块threading

python使用多线程实例讲解 1 进程和线程 1.1 进程和线程的概念 进程(process)和线程(thread)是操作系统的基本概念。 进程是资源分配的最小单位&#xff0c;线程是CPU调度的最小单位。 线程是程序中一个单一的顺序控制流程&#xff0c;进程内一个相对独立的、可调度的执行单…...

俄罗斯乌克兰克里米亚/荆州seo推广

网上找的资料&#xff0c;然后加以自己的实践和总结。 FCKeditor2.63下载 官方网站http://www.fckeditor.net/ dll控件&#xff1a;http://jaist.dl.sourceforge.net/project/fckeditor/FCKeditor.Net/2.6.3/FCKeditor.Net_2.6.3.zip 图片JS文件&#xff1a;http://jaist.dl.so…...

国外网站发展建设/优化师

/***************************************************************************** #define | enum(enumerator)* 声明&#xff1a;* 今天突然在Linux内核看到枚举和宏&#xff0c;感觉是一样的功能&#xff0c;于是找了一下他们* 之间差异。** …...

pytson做网站安全吗/seo外链工具

一、昨天干了什么&#xff1f; 对我们最后要发布的版本不断修复&#xff0c;将软件发布到蒲公英开放平台&#xff0c;集成蒲公英SDK&#xff0c;新增摇一摇反馈的功能和版本更新功能。 二、今天准备做什么&#xff1f; 向同学们宣传我们的软件&#xff0c;然后给我们提供反馈&a…...

wordpress主题添加评论框/aso优化什么意思是

刚开始用的是where进行多表关联查询&#xff0c;但是最终发现当中奖表中么有数据的时候是查找不到任何信息的&#xff0c;改用LEFT JOIN 用这个就很简单了&#xff0c;代码如下DESC SELECT * FROM enet_wall_list AS lLEFT JOIN enet_wall_lottery AS lottery ON l.openid l…...

注册网站云空间/建站系统推荐

1、数据字典怎么理解&#xff1f;数据字典是指对数据的数据项、数据结构、数据流、数据存储、处理逻辑、外部实体等进行定义和描述&#xff0c;其目的是对数据流程图中的各个元素做出详细的说明。数据字典(Data dictionary)是一种用户可以访问的记录数据库和应用程序源数据的目…...

城乡建设部网官方网站/市场推广方案ppt

我的环境 f.lux 我的使用感受是让屏幕看起来舒服一些&#xff0c;因为我有近视&#xff0c;所以需要保护眼睛。 f.lux官网&#xff1a;https://justgetflux.com/ f.lux v4.47 windows 10 x64 显示器&#xff1a;戴尔(DELL) P2414H 我最常用的色温值&#xff1a;5200 f.lux zipc…...