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
     */
    @Override
    public 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
     */
    @Override
    public 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
     */
    @Override
    public 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
     */
    @Override
    public 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
     */
    @Override
    public 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
     */
    @Override
    public 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
     */
    @Override
    public 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/javaee
    http://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/mvc
        http://www.springframework.org/schema/mvc/spring-mvc.xsd
        http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context.xsd">

    <!-- 开启扫描器 -->
    <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/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context.xsd
        http://www.springframework.org/schema/aop
        http://www.springframework.org/schema/aop/spring-aop.xsd
        http://www.springframework.org/schema/tx
        http://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 configuration
        PUBLIC "-//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 mapper
        PUBLIC "-//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 userPwd
           from tb_user
           where user_id = #{userId}
      </select>
</mapper>
添加 UserService.java

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

@Service
public class UserService {

    // 注入userDao
    @Autowired
    private 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
    @Autowired
    private 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_account
        where id = #{id,jdbcType=INTEGER}
    </select>

    <!-- 删除操作 -->
    <delete id="delete" parameterType="java.lang.Integer" >
    delete from tb_account
    where 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 {

    @Autowired
    private 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 {

    @Autowired
    private 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}")
    @ResponseBody
    public Account queryAccountById(@PathVariable  Integer id) {
        // 设置异常
        return accountService.selectById(id);
    }


    /**
     * 删除操作
     * @param id
     * @return
     */
    @DeleteMapping("/account/{id}")
    @ResponseBody
    public Map<String,String> deleteAccountById(@PathVariable Integer id) {

        // 调用service层的删除方法,返回受影响的行数
        int row = accountService.delAccount(id);
        // 判断受影响的行数是否大于0
        Map<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")
    @ResponseBody
    public Map<String,String> addAccount(@RequestBody Account account) {
        Map<String ,String> map = new HashMap<>();

        // 调用service层的添加方法,返回受影响的行数
        int row = accountService.saveAccount(account);

        // 判断受影响的行数是否大于0
        if (row > 0) {
            // 删除成功
            map.put("code","200");
            map.put("msg","添加成功!");
        } else {
            // 删除失败
            map.put("code","500");
            map.put("msg","添加失败!");
        }
        return map;
    }


    /**
     * 更新操作
     * @param account
     * @return
     */
    @PutMapping("/account")
    @ResponseBody
    public Map<String,String> updateAccount(@RequestBody Account account) {
        Map<String ,String> map = new HashMap<>();

        // 调用service层的添加方法,返回受影响的行数
        int row = accountService.updateAccount(account);

        // 判断受影响的行数是否大于0
        if (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>

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

C语言——冒泡排序

一、冒泡排序是什么 冒泡排序&#xff1a; 冒泡排序(Bubble Sort)&#xff0c;又被称为气泡排序或泡沫排序。升序时&#xff1a;它会遍历若干次需要排序的数列&#xff0c;每次遍历时&#xff0c;它都会从前往后依次的比较相邻两个数的大小&#xff1b;如果前者比后者大&#x…

黔院长 | 何为风邪?

中医上所说的风&#xff0c;也称风邪&#xff0c;是指受到外界侵犯&#xff08;外邪&#xff09;而感得风寒、风热、风湿等症状&#xff0c;导致人的免疫力下降。寒、湿、燥、暑、热等都属于外邪&#xff0c;多依附于风而入侵人体&#xff0c;因此风邪更多的是指一种致病因素。…

pythom导出mysql指定binlog文件

要求 要求本地有py环境和全局环境变量 先测试直接执行binlog命令执行命令 Windows 本地直接执行命令 # E:\output>E:\phpstudy_pro\Extensions\MySQL5.7.26\bin\mysqlbinlog binglog文件地址 # --no-defaults 不限制编码 # -h mysql链接地址 # -u mysql 链接名称 # -p m…

如何制作keil5的Device pack

概述&#xff1a; 作为一名嵌入式芯片相关行业人员&#xff0c;我们经常需要使用到Device pack, 比如STM32的pack如下图所示&#xff1a; 名词DFP&#xff1a; 设备家族包 DFP Pack组成&#xff1a; Boards (板级支持)Device &#xff08;芯片设备级支持&#xff09;Docum…

CI/CD 持续集成与持续交付(1)

git Git git使用 [rootserver1 ~]# yum install -y git [rootserver1 ~]# mkdir demo [rootserver1 ~]# cd demo/初始化版本库 [rootserver1 demo]# git init查看状态 [rootserver1 demo]# git status [rootserver1 demo]# git status -s #简化输出[rootserver1 demo]# echo…

第十一周任务总结

本周任务总结 本周物联网方面主要继续进行网关的二次开发与规则引擎实现设备联动的实现 非物联网方面主要复习了docker的使用与算法的学习 1.网关的二次开发&#xff0c;本周将实现debug调试输出的文件下载到了网关&#xff0c;但网关出了问题无法连接&#xff0c;最终跟客服…

SmartX 超融合 5.1 版本有哪些新特性和技术提升?

近日&#xff0c;SmartX 正式发布了超融合产品组合 SmartX HCI 5.1 版本&#xff0c;以全面升级的超融合软件、分布式块存储、容器管理与服务、软件定义的网络与安全等组件&#xff0c;为虚拟化和容器负载在计算、存储、网络和管理层面提供统一的架构和生产级别的能力支持。本期…

ArcGIS Maps SDK for JS:监听图层的visible属性

文章目录 1 问题描述2 解决方案3 拓展 1 问题描述 近期有这么一个需求。在 ArcGIS Maps SDK for JavaScript 中&#xff0c;使用图层的visible属性同步显示某个组件&#xff0c;即打开图层时显示组件&#xff0c;关闭图层时隐藏组件。 首先想到的是&#xff0c;通过点击图层列…

B站批量取消关注

找到关注页面&#xff1a; 右键检查或者按F12进入开发者界面 然后选console&#xff0c;在页面下面输入下面jQuery代码&#xff0c;然后按回车。复制粘贴两次这一页的博主就能全部取消大概20个 然后刷新页面&#xff0c;接着粘贴两边代码&#xff0c;循环如此即可。 $(".…

kubernetes集群编排——k8s高可用集群

实验环境 主机名 IP 角色 k8s1 192.168.92.11 harbor k8s2 192.168.92.12 control-plane k8s3 192.168.92.13 control-plane k8s4 192.168.92.14 control-plane k8s5 192.168.92.15 haproxy,pacemaker k8s6 192.168.92.16 haproxy,pacemaker k8s7 192.16…

duplicate复制数据库单个数据文件复制失败报错rman-03009 ora-03113

duplicate复制数据库单个数据文件复制失败报错rman-03009 ora-03113 搭建dg过程中&#xff0c;发现有一个数据文件在复制过程中没有复制过来&#xff0c;在备库数据文件目录找不到这个数据文件 处理方法&#xff1a; 第一步&#xff1a;主库备份86#数据文件 C:\Users\Admi…

【0235】修改私有内存(private memory)中的MyBEEntry时,st_changecount值前后变化

上一篇: 【0234】PgBackendStatus 记录当前postgres进程的活动状态 1. pg_stat_activity中xxx实时信息如何实现? 客户端(eg:psql)在连接上postmaster之后,postmaster守护进程会fork()一个后端进场(backend process),之后此客户端的所有操作、交互均有此对应的Backen…

实验七 状态机及键盘输入 chisel

题目 请设计一个区别两种特定时序的有限状态机FSM&#xff1a;该有限状态机有一个输入w和一个输出z。当w是4个连续的0或4个连续的1时&#xff0c;输出z1&#xff0c;否则z0&#xff0c;时序允许重叠。即&#xff1a;若w是连续的5个1时&#xff0c;则在第4个和第5个时钟之后&am…

Qt HTTP 摘要认证(海康球机摄像机ISAPI开发)

接到一个需求是开发下海康的球机,控制云台,给到我的是一个开发手册,当然了是海康的私有协议 ISAPI开发手册https://download.csdn.net/download/qq_37059136/88547425关于开发这块读文档就可以理解了,海康使用的是摘要认证,当然了海康已经给出使用范例 通过libcurl就可以直接连…

nodejs+vue杰和牧场管理系统的设计与实现-微信小程序-安卓-python-PHP-计算机毕业设计

系统涉及的对象是奶牛。 系统使用员工有管理员和普通员工。 管理员有修改的权限&#xff0c;普通员工没有。系统包含新闻功能&#xff0c;最好是有个后台管理&#xff0c;在后台输入新闻标题和内容&#xff0c;插入图片&#xff0c;在网页上就可以展示。最好再有个轮播图。 新闻…

使用Python进行二维图像的三维重建

2D图像的三维重建是从一组2D图像中创建对象或场景的三维模型的过程。这个技术广泛应用于计算机视觉、机器人技术和虚拟现实等领域。 在本文中&#xff0c;我们将解释如何使用Python执行从2D图像到三维重建的过程。我们将使用TempleRing数据集作为示例&#xff0c;逐步演示这个过…

SpringBoot-集成Kafka详解

SpringBoot集成Kafka 1、构建项目 1.1、引入依赖 <parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.2.5.RELEASE</version> </parent> <dependenci…

机器学习第7天:逻辑回归

文章目录 介绍 概率计算 逻辑回归的损失函数 单个实例的成本函数 整个训练集的成本函数 鸢尾花数据集上的逻辑回归 Softmax回归 Softmax回归数学公式 Softmax回归损失函数 调用代码 参数说明 结语 介绍 作用&#xff1a;使用回归算法进行分类任务 思想&#xff1a;…

某60区块链安全之整数溢出漏洞实战学习记录

区块链安全 文章目录 区块链安全整数溢出漏洞实战实验目的实验环境实验工具实验原理攻击过程分析合约源代码漏洞EXP利用 整数溢出漏洞实战 实验目的 学会使用python3的web3模块 学会以太坊整数溢出漏洞分析及利用 实验环境 Ubuntu18.04操作机 实验工具 python3 实验原理…

GEM5 Garnet DVFS / NoC DVFS教程:ruby.clk_domain ruby.voltage_domain

简介 gem5中的 NoC部分是Garnet实现的&#xff0c;但是Garnet并没有单独的时钟域&#xff0c;而是保持ruby一致&#xff0c;要做noc的DVFS&#xff0c;便是要改ruby的 改电压 #这里只是生成一个随便变量名&#xff0c;存一下值。改是和频率一起的 userssaved_voltage_domain…