SpringMVC

SpringMVC:

  • controller:控制器
    • 获得表单数据
    • 调用业务逻辑
    • 转向指定页面
  • model:模型
    • 业务逻辑
    • 保存数据的状态
  • view:视图
    • 显示页面

SpringMVC优点:

  • 轻量级,简单易学
  • 高效,基于请求响应的MVC框架
  • 与 Spring 兼容性好,无缝集成
  • 约定优于配置
  • 功能强大:restful,数据验证,格式化等
  • 将业务逻辑,数据,显示分离,降低各个模块之间的耦合,

初识SpringMVC

Spring的web框架围绕DispatcherServlet调度Servlet设计。

HelloSpringMVC项目搭建,pom.xml中导入spring-webmvc,servlet-api,jstl-api,jstl的jar包

web.xml

	 <!--注册DispatcherServlet-->
    <servlet>
        <servlet-name>springmvc</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <!--关联一个springmvc的配置文件-->
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath:springmvc-servlet.xml</param-value>
        </init-param>
        <!--启动级别-->
        <load-on-startup>1</load-on-startup>

    </servlet>

    <!-- / 匹配所有的请求 (不包括.jsp)-->
    <!-- /* 匹配所有的请求 (包括.jsp)-->
    <servlet-mapping>
        <servlet-name>springmvc</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>

springmvc-servlet.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"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
      http://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"/>
    <bean class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter"/>

    <!--视图解析器,DispatcherServlet给它的ModelAndView-->
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" id="InternalResourceViewResolver">
        <!--前缀-->
        <property name="prefix" value="/WEB-INF/jsp/"/>
        <!--后缀-->
        <property name="suffix" value=".jsp"/>
    </bean>

    <!--Handler-->
    <bean id="/hello" class="com.zr.controller.HelloController"/>
    
</beans>

HelloController

//注意:导入org.springframework.web.servlet.mvc.Controller;
public class HelloController implements Controller {
    public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception {
        //模型和视图
        ModelAndView mv = new ModelAndView();

        //封装对象,放在ModelAndView中
        mv.addObject("msg","HelloSpringMVC!");
        //封装要跳转的视图
        mv.setViewName("hello");  ///WEB-INF/jsp/hello.jsp
        return mv;
    }
}

hello.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>

    ${msg}
    
</body>
</html>

注意:如果访问http://localhost:8080/hello出现404

选中自己的项目名,在WEB-INF下新建lib文件夹,点击+号,将项目的依赖添加到lib中,重启项目!!!

SpringMVC执行流程

  1. DispatcherServlet表示前置控制器,是整个SpringMVC控制的中心,用户发出请求,DispatcherServlet接收请求并拦截请求。
  2. HandlerMapping为处理器映射器,根据处理器请求url查找Handler,由DispatcherServlet调用。
  3. HandlerExecution表示具体的Handler,其主要作用是根据url查找控制器。
  4. HandlerExecution将解析后的信息传递给DispatcherServlet,如解析控制器映射等。
  5. HandlerAdapter表示处理器适配器,按特定的规则执行Handler。
  6. Handler让具体的Controller执行。
  7. Controller将执行的信息返回给HandlerAdapter,如ModelAndView。
  8. HandlerAdapter将视图逻辑名或模型传递给DispatcherServlet。
  9. DispatcherServlet调用视图解析器(ViewResolver)来解析HandlerAdapter传递的逻辑视图名。
  10. 视图解析器将解析的逻辑视图名传给DispatcherServlet。
  11. 视图渲染呈现给用户。

使用注解开发SpringMVC

控制器Controller

  • 控制器负责提供访问应用程序的行为,通常通过接口定义或注解定义两种方式实现。

  • 控制器负责解析用户的请求并将其转化为一个模型。

  • 在SpringMVC中一个控制器类可以包含多个方法。

web.xml

<!--  配置DispatcherServlet:这是SpringMVC的核心,请求分发器,前端控制器  -->
<servlet>
    <servlet-name>springmvc</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <!--    绑定spring的配置文件-->
    <init-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:springmvc-servlet.xml</param-value>
    </init-param>
    <!--    启动级别-->
    <load-on-startup>1</load-on-startup>
</servlet>

<!--SpringMVC中:
/:匹配所有的请求。不匹配jsp页面
/*:匹配所有的请求。匹配jsp页面
-->
<servlet-mapping>
    <servlet-name>springmvc</servlet-name>
    <url-pattern>/</url-pattern>
</servlet-mapping>

springmvc-servlet.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:mvc="http://www.springframework.org/schema/mvc"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        https://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        https://www.springframework.org/schema/context/spring-context.xsd
        http://www.springframework.org/schema/mvc
        https://www.springframework.org/schema/mvc/spring-mvc.xsd">

    <!--自动扫描包,让包下的注解生效,由IOC容器统一管理-->
    <context:component-scan base-package="com.zr.controller"/>
    <!--让SpringMVC不处理静态资源-->
    <mvc:default-servlet-handler/>

    <!--支持注解驱动
    在spring中使用@RequestMapping注解来完成映射关系,必须注册
    DefaultAnnotationHandlerMapping和AnnotationMethodHandlerAdapter
    这两个实例分别在类级别和方法级别处理
    annotation-driven帮助我们完成上述两个实例的注入
    -->
    <mvc:annotation-driven/>

    <!--视图解析器-->
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" id="internalResourceViewResolver">
        <property name="prefix" value="/WEB-INF/jsp/"/>
        <property name="suffix" value=".jsp"/>
    </bean>

</beans>

HelloController

@Controller
public class HelloController {

    @RequestMapping("/h1")
    public String hello(Model model){
        //封装数据
        model.addAttribute("msg","HelloSpringMVCAnnotation");

        return "hello"; //视图解析器处理
    }
}

hello.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
	${msg}
</body>
</html>

RestFul风格

概念:RestFul就是一个资源定位及资源操作的风格,不是标准也不是协议,只是一种风格,基于这个风格设计的软件可以更简洁,更有层次,更易于实现缓存等机制。

URL定义

资源:互联网所有的事物都可以被抽象为资源
资源操作:使用POST、DELETE、PUT、GET,使用不同方法对资源进行操作。
分别对应 添加、 删除、修改、查询。

传统方式操作资源

http://127.0.0.1/item/queryUser.action?id=1查询,GET
http://127.0.0.1/item/saveUser.action 新增,POST
http://127.0.0.1/item/updateUser.action 更新,POST
http://127.0.0.1/item/deleteUser.action?id=1 删除,GET或POST

使用RestFul操作资源:可以通过不同的请求实现不同的效果!

[http://127.0.0.1/item/zr 查询,GET
[http://127.0.0.1/item/ 新增,POST
[http://127.0.0.1/item/ 更新,PUT
[http://127.0.0.1/item/zr 删除,DELETE

学习测试

  1. 新建一个测试类RestFulController,在方法参数前面加@PathVariable注解,让方法参数的值对应绑定到一个URL模板变量上。

    @Controller
    public class RestFulController {
        @RequestMapping("/add/{a}/{b}")
        public String test(@PathVariable int a, @PathVariable int b, Model model){
            int res = a + b;
            model.addAttribute("msg","结果为"+res);
            return "test";  //test.jsp
        }
    }
    

请求地址相同,得到结果不同的情况

http://localhost:8080/add/3/4

http://localhost:8080/a.jsp

//@RequestMapping(value = "/add/{a}/{b}",method = RequestMethod.DELETE)
//@RequestMapping(value = "/add/{a}/{b}",method = RequestMethod.GET)
@GetMapping("/add/{a}/{b}")
public String test(@PathVariable int a, @PathVariable int b, Model model){
    int res = a + b;
    model.addAttribute("msg","结果1为"+res);
    return "test";
}

@PostMapping("/add/{a}/{b}")
public String test2(@PathVariable int a, @PathVariable int b, Model model){
    int res = a + b;
    model.addAttribute("msg","结果2为"+res);
    return "test";
}

web下a.jsp

<form action="/add/3/4" method="post">

    <input type="submit">
</form>

web/WEB-INF/jsp/test.jsp

<body>
${msg}
</body>

重定向和转发

ModelAndView:根据view的名字,和视图解析器跳转到指定的页面。

使用springmvc来实现转发和重定向—–无视图解析器

@Controller
public class ModelTest1 {

    @RequestMapping("/m1/t1")
    public String test(Model model){
        model.addAttribute("msg","ModelTest1");
        // return "/WEB-INF/jsp/test.jsp";
        //转发
        // return "forward:/index.jsp";
        //重定向
           return "redirect:/index.jsp";
    }

使用springmvc来实现转发和重定向—–有视图解析器

@Controller
public class HelloController {

    @RequestMapping("/h1")
    public String hello(Model model){
        //封装数据
        model.addAttribute("msg","HelloSpringMVCAnnotation");

        return "hello"; //视图解析器处理
    }
}

数据处理

User实体类

@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {
    private int id;
    private String name;
    private int age;
}

UserController类,使用@RequestParam(“***”)接收参数

@Controller
@RequestMapping("/user")
public class UserController {

    //localhost:8080/user/t1?name=***
    @RequestMapping("/t1")
    public String test1(@RequestParam("name") String name, Model model){
        //接收前端参数
        System.out.println("接收到前端的参数为"+name);
        //将结果传递给前端
        model.addAttribute("msg",name);
        //跳转视图
        return "test";
    }

    /*
    1.接收用户传递的参数,判断参数的名字,假设名字直接在方法上,就可以直接用
    2.假设传递的是一个对象User,匹配User对象的字段名

     */

    //http://localhost:8080/user/t2?id=1&name=zzzrrr&age=20
    //前端接受的是一个对象:id,name,age
    @RequestMapping("/t2")
    public String test2(User user){
        System.out.println(user);
        return "test";
    }

乱码处理

在开发中,我们会经常遇到乱码问题,在Servlet阶段使用的是编写过滤器过滤。现在SpringMVC也给我们提供了一个过滤器,在xml中配置,然后重启服务器。

web下form.jsp

<body>
<form action="/e/t1" method="post">
    <input type="text" name="name">
    <input type="submit">

</form>
</body>

EncodingController

@Controller
public class EncodingController {
    @PostMapping("/e/t1")
    public String test1(String name, Model model){

        model.addAttribute("msg",name);
        System.out.println(name);
        return "test";
    }
}

编码过滤器

<!--配置SpringMVC的乱码过滤-->
<filter>
    <filter-name>encoding</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>encoding</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

JSON

什么是JSON:

  • JSON(JavaScript Object Notation,js对象标记)是一种轻量级数据交换格式
  • 采用完全独立于编程语言的文本格式来存储和表示数据
  • 易于人阅读和编写,同时也易于机器解析和生成,并有效提升网络传输速率
  • 对象表示为键值对,数据由逗号分隔
  • 花括号保存对象
  • 方括号保存数组
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script type="text/javascript">
        // 编写一个javascript对象
        var user = {
            name:"周周",
            age:"20",
            sex:"南"
        };
        // 将js对象转化为json对象
        var json = JSON.stringify(user);
        console.log(json);

        // json转化为javascript对象
        var js = JSON.parse(json);
        console.log(js)

        console.log(user);
    </script>
</head>
<body>

</body>
</html>

Jackson的使用

Jackson 是当前用的比较广泛的,用来序列化和反序列化 json 的 Java 的开源框架。Jackson 是最流行的 json 解析器之一 。

Jackson 最常用的 API 就是基于”对象绑定” 的 ObjectMapper。

使用前pom.xml加入依赖

<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>xml
    <version>2.10.0</version>
</dependency>

web.xml

<!--  配置DispatcherServlet:这是SpringMVC的核心,请求分发器,前端控制器  -->
<servlet>
    <servlet-name>springmvc</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <!--    绑定spring的配置文件-->
    <init-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:springmvc-servlet.xml</param-value>
    </init-param>
    <!--    启动级别-->
    <load-on-startup>1</load-on-startup>
</servlet>

<!--SpringMVC中:
/:匹配所有的请求。不匹配jsp页面
/*:匹配所有的请求。匹配jsp页面
-->
<servlet-mapping>
    <servlet-name>springmvc</servlet-name>
    <url-pattern>/</url-pattern>
</servlet-mapping>

<!--配置SpringMVC的乱码过滤-->
<filter>
    <filter-name>encoding</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>encoding</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

springmvc-servlet.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:mvc="http://www.springframework.org/schema/mvc"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        https://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        https://www.springframework.org/schema/context/spring-context.xsd
        http://www.springframework.org/schema/mvc
        https://www.springframework.org/schema/mvc/spring-mvc.xsd">

    <!--自动扫描包,让包下的注解生效,由IOC容器统一管理-->
    <context:component-scan base-package="com.zr.controller"/>

    <!--解决json乱码-->
    <mvc:annotation-driven>
        <mvc:message-converters register-defaults="true">
            <bean class="org.springframework.http.converter.StringHttpMessageConverter">
                <constructor-arg value="UTF-8"/>
            </bean>
            <bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
                <property name="objectMapper">
                    <bean class="org.springframework.http.converter.json.Jackson2ObjectMapperFactoryBean">
                        <property name="failOnEmptyBeans" value="false"/>
                    </bean>
                </property>
            </bean>
        </mvc:message-converters>
    </mvc:annotation-driven>

    <!--视图解析器-->
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" id="internalResourceViewResolver">
        <property name="prefix" value="/WEB-INF/jsp/"/>
        <property name="suffix" value=".jsp"/>
    </bean>

</beans>

User类

@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {

    private String name;
    private int age;
    private String sex;

}

UserController

@RestController    //不会走视图解析器,
public class UserController {
    //注解解决json乱码 建议在xml中解决乱码
    // @RequestMapping(value = "/j1",produces = "application/json;charset=utf-8")
    @RequestMapping("/j1")
    //@ResponseBody  //不会走视图解析器,会直接返回一个字符串
    public String json1() throws JsonProcessingException {
        //jackson  ObjectMapper
        ObjectMapper mapper = new ObjectMapper();

        //创建一个对象
        User user = new User("周周",20,"南");

        String s = mapper.writeValueAsString(user);
        return s;
    }
}

返回一个json数组,返回格式化时间(方法加在UserController类中)

@RequestMapping("/j2")
public String json2() throws JsonProcessingException {

    ObjectMapper mapper = new ObjectMapper();

    List<User> list = new ArrayList<User>();

    User user1 = new User("周周1",20,"南");
    User user2 = new User("周周2",20,"南");
    User user3 = new User("周周3",20,"南");
    User user4 = new User("周周4",20,"南");

    list.add(user1);
    list.add(user2);
    list.add(user3);
    list.add(user4);
    String s = mapper.writeValueAsString(list);
    return s;
}

@RequestMapping("/j3")
public String json3() throws JsonProcessingException {
    ObjectMapper mapper = new ObjectMapper();

    //自定义日期的格式
    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    Date date = new Date();
    //return mapper.writeValueAsString(date);
    return mapper.writeValueAsString(sdf.format(date));
}

@RequestMapping("/j4")
public String json4() throws JsonProcessingException {
    ObjectMapper mapper = new ObjectMapper();
    //使用ObjectMapper  格式化输出
    mapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS,false);
    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

    mapper.setDateFormat(sdf);
    Date date = new Date();
    return mapper.writeValueAsString(date);
}

封装思想

工具类

public class JsonUtil {
    
    public static String getMapper(Object object,String dateFormat){
        ObjectMapper mapper = new ObjectMapper();
        //使用ObjectMapper  格式化输出
        mapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS,false);
        SimpleDateFormat sdf = new SimpleDateFormat(dateFormat);
        mapper.setDateFormat(sdf);
        try {
            return mapper.writeValueAsString(object);
        } catch (JsonProcessingException e) {
            e.printStackTrace();
        }
        return null;
    }
    public static String getMapper(Object object){
        return getMapper(object,"yyyy-MM-dd HH:mm:ss");

    }
}

测试工具类(方法加在UserController类中)

@RequestMapping("/j5")
public String json5() {
    Date date = new Date();
    return JsonUtil.getMapper(date,"yyyy-MM-dd HH:mm:ss");
}

@RequestMapping("/j6")
public String json6() {
    List<User> list = new ArrayList<User>();

    User user1 = new User("周周1",20,"南");
    User user2 = new User("周周2",20,"南");
    User user3 = new User("周周3",20,"南");
    User user4 = new User("周周4",20,"南");

    list.add(user1);
    list.add(user2);
    list.add(user3);
    list.add(user4);
    return JsonUtil.getMapper(list);
}

FastJson

FastJson是阿里巴巴开发的一款专门用于Java开发的包,可以方便的实现json对象与JavaBean对象de转换,实现JavaBean对象与json字符串的转换,实现json对象与json字符串的转换。

导包

<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>fastjson</artifactId>
    <version>1.2.74</version>
</dependency>

FastJson三个主要的类

  • JSONObject 代表json对象,JSONObject实现了Map接口
  • JSONArray 代表json数组对象,内部是由list接口中的方法完成操作
  • JSON代表 JSONObject 和 JSONArray的转化
@RequestMapping("/j7")
public String json7() {
    List<User> list = new ArrayList<User>();

    User user1 = new User("周周1",20,"南");
    User user2 = new User("周周2",20,"南");
    User user3 = new User("周周3",20,"南");
    User user4 = new User("周周4",20,"南");

    list.add(user1);
    list.add(user2);
    list.add(user3);
    list.add(user4);

      //java对象转json字符串
        String s = JSON.toJSONString(list);
        System.out.println(s);
        String s1 = JSON.toJSONString(user1);
        System.out.println("s1:  "+s1);

        //json字符串转java对象
        User s2 = JSON.parseObject(s1,User.class);
        System.out.println("s2:  "+s2.toString());

        //java对象转json对象
        JSONObject s3 = (JSONObject) JSON.toJSON(user2);
        System.out.println("s3:  "+s3.toJSONString());

        // json对象转java对象
        User s4 = JSON.toJavaObject(s3, User.class);
        System.out.println("s4:  "+s4);
        return "hello";
    }
}

整合SSM

新建maven一个项目ssmbuild

环境配置:

pom.xml中导入以下依赖和允许静态资源导出

<!--导入依赖 junit,数据库驱动,连接池,Servlet,jsp,mybatis,mybatis-spring,spring,lembok,spring-jdbc,jstl,standard等-->
<dependencies>
	......
</dependencies>
<!--静态资源导出-->
    <build>
        <resources>
            <resource>
                <directory>src/main/resources</directory>
                <includes>
                    <include>**/*.properties</include>
                    <include>**/*.xml</include>
                </includes>
                <filtering>false</filtering>
            </resource>
            <resource>
                <directory>src/main/java</directory>
                <includes>
                    <include>**/*.properties</include>
                    <include>**/*.xml</include>
                </includes>
                <filtering>false</filtering>
            </resource>
        </resources>
    </build>

database.properties

jdbc.driver=com.mysql.jdbc.Driver
#如果使用的是MySQL 8.0+,增加一个时区的配置
jdbc.url=jdbc:mysql://localhost:3306/ssmbuild?useSSL=false&useUnicode=true&characterEncoding=UTF-8
jdbc.username=root
jdbc.password=123456

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>
    <!--    配置数据源,交给spring去做-->
    <typeAliases>
        <package name="com.zr.pojo"/>
    </typeAliases>

    <mappers>
        <mapper class="com.zr.dao.BookMapper"/>
    </mappers>
</configuration>

spring-dao.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"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        https://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        https://www.springframework.org/schema/context/spring-context.xsd">

    <!--    关联数据库配置文件-->
    <context:property-placeholder location="classpath:database.properties"/>

    <!--连接池
    dbcp:手动化操作,不能自动连接
    c3p0:自动化操作,可以自动化加载配置文件,并且可以自动设置到对象中
    durid
    hikari
    -->
    <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
        <property name="driverClass" value="${jdbc.driver}"/>
        <property name="jdbcUrl" value="${jdbc.url}"/>
        <property name="user" value="${jdbc.username}"/>
        <property name="password" value="${jdbc.password}"/>

        <!--c3p0私有属性-->
        <property name="maxPoolSize" value="30"/>
        <property name="minPoolSize" value="10"/>
        <!--关闭连接后不自动commit-->
        <property name="autoCommitOnClose" value="false"/>
        <!--连接超时时间-->
        <property name="checkoutTimeout" value="10000"/>
        <!--连接失败,自动重连次数-->
        <property name="acquireRetryAttempts" value="2"/>
    </bean>

    <!--sqlSessionFactory-->
    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
        <property name="dataSource" ref="dataSource"/>
    <!--    绑定mybatis配置文件-->
        <property name="configLocation" value="classpath:mybatis-config.xml"/>
    </bean>

    <!--配置dao接口扫描包,动态的实现了dao接口注入到spring容器中-->
    <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
        <!--注入sqlSessionFactory-->
        <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/>
        <!--要扫描的dao包-->
        <property name="basePackage" value="com.zr.dao"/>
    </bean>
</beans>

spring-service.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"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        https://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        https://www.springframework.org/schema/context/spring-context.xsd">

<!--    扫描service下的包-->
    <context:component-scan base-package="com.zr.service"/>

    <!--将所有的业务类注入到spring,可以通过注解或者配置实现-->
    <bean id="BookServiceImpl" class="com.zr.service.BookServiceImpl">
        <property name="bookMapper" ref="bookMapper"/>
    </bean>

    <!--声明式事务配置-->
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <!--注入数据源-->
        <property name="dataSource" ref="dataSource"/>
    </bean>
</beans>

applicationContext.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"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        https://www.springframework.org/schema/beans/spring-beans.xsd">

    <import resource="classpath:spring-dao.xml"/>
    <import resource="classpath:spring-service.xml"/>

</beans>

BookMapper.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">

    <mapper namespace="com.zr.dao.BookMapper">
    
    <insert id="addBook" parameterType="Books">
        insert into books (bookName,bookCounts,detail) 
        values (#{bookName},#{bookCounts},#{detail});
    </insert>
    
    <delete id="deleteBookById" parameterType="int">
        delete from books where bookID=#{id};
    </delete>
    
    <update id="updateBook" parameterType="Books">
        update books set bookName=#{bookName},bookCounts=#{bookCounts},detail=#{detail}
         where bookID=#{bookID};
    </update>

    <select id="selectBookById" resultType="Books">
        select * from books where bookID=#{id};
    </select>

    <select id="selectAllBook" resultType="Books">
        select * from books;
    </select>
</mapper>

web.xml 【classpath:applicationContext.xml】bean的创建交给了applicationContext.xml

<!--DispatcherServlet-->
<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:applicationContext.xml</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
    <servlet-name>springmvc</servlet-name>
    <url-pattern>/</url-pattern>
</servlet-mapping>


<!--乱码过滤-->
<filter>
    <filter-name>encoding</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>encoding</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

<!--session-->
<session-config>
    <session-timeout>15</session-timeout>
</session-config>

实体类

@Data
@AllArgsConstructor
@NoArgsConstructor
public class Books {
    private int bookID;
    private String bookName;
    private int bookCounts;
    private String detail;
}

BookMapper

public interface BookMapper {
    //增加一本书
    int addBook(Books books);
    //删除一本书
    int deleteBookById(@Param("id") int id);
    //修改一本书
    int updateBook(Books books);
    //查询一本书
    Books selectBookById(@Param("id") int id);
    //查询全部
    List<Books> selectAllBook();
}

BookService

public interface BookService {
    //增加一本书
    int addBook(Books books);
    //删除一本书
    int deleteBookById(@Param("id") int id);
    //修改一本书
    int updateBook(Books books);
    //查询一本书
    Books selectBookById(@Param("id") int id);
    //查询全部
    List<Books> selectAllBook();
}

BookServiceImpl

public class BookServiceImpl implements BookService{
    //service调用dao层:组合dao层
    private BookMapper bookMapper;
    public void setBookMapper(BookMapper bookMapper) {
        this.bookMapper = bookMapper;
    }

    public int addBook(Books books) {
        return bookMapper.addBook(books);
    }

    public int deleteBookById(int id) {
        return bookMapper.deleteBookById(id);
    }

    public int updateBook(Books books) {
        return bookMapper.updateBook(books);
    }

    public Books selectBookById(int id) {
        return bookMapper.selectBookById(id);
    }

    public List<Books> selectAllBook() {
        return bookMapper.selectAllBook();
    }
}

Ajax

Ajax:异步,能在无需加载整个页面的情况下,更新部分网页的技术。

Ajax不是一种编程语言,而是一种用于创建更好更快以及交互性更强的Web应用程序的技术。

web.xml配置DispatcherServlet和encoding,spring-mvc.xml配置视图解析器,扫描包,支持注解驱动,静态资源支持

开启窗口

test.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>iframe测试体验页面无刷新</title>
    <script>
        function go() {
            var url = document.getElementById("url").value;
            document.getElementById("iframe1").src=url;
        }
    </script>
</head>
<body>
<div>
    <p>请输入地址:</p>
    <p>
        <input type="text" id="url" value="https://www.cnblogs.com/zhou-zr/">
        <input type="button" value="提交" onclick="go()">
    </p>
 </div>

<div>
    <iframe id="iframe1" style="width: 100%;height: 500px">

    </iframe>
</div>

</body>
</html>

Ajax的核心就是XMLHttpRequest。

Ajax异步加载数据

package com.zr.pojo;

@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {
    private int id;java
    private String name;
    private String sex;
}

AjaxController

package com.zr.controller;
@RestController
public class AjaxController {
    @RequestMapping("/t1")
    public String test(){
        return "hello";
    }

    @RequestMapping("/a")
    public void a1(String name, HttpServletResponse response) throws IOException {
        System.err.println("name--->>"+name);
        if ("zr".equals(name)){
            response.getWriter().println("true");
        }else {
            response.getWriter().println("false");
        }
    }
}

index.jsp

<head>
    <title>$Title$</title>
      <script src="https://apps.bdimg.com/libs/jquery/2.1.4/jquery.min.js"></script>
<%--      <script src="${pageContext.request.contextPath}/static/js/jquery-3.5.1.js"></script>--%>
    <script>
      function a(){
        $.ajax({
         url:"${pageContext.request.contextPath}/a",
            data:{"name":$("#username").val()},
            success:function (data) {
                alert(data);
            }
        })
      }

    </script>
  </head>
  <body>
<%--  失去焦点的时候,发送一个请求到后台--%>
  用户名:<input type="text" id="username" onblur="a()">
  </body>

test2.jsp

<html>
<head>
    <title>Title</title>
    <script src="https://apps.bdimg.com/libs/jquery/2.1.4/jquery.min.js"></script>
    <script>
        $(function () {
            $("#btn").click(function () {
                console.log("111");
                $.post("${pageContext.request.contextPath}/a2",function (data) {
                    // console.log(data);
                    var html="";
                    for (let i = 0; i < data.length; i++) {
                        html += "<tr>"+
                            "<td>"+ data[i].id+"</td>"+
                            "<td>"+ data[i].name+"</td>"+
                            "<td>"+ data[i].sex+"</td>"+
                            "</tr>"
                    }
                    $("#context").html(html)
                });
            })
        });
    </script>
</head>
<body>
<input type="button" value="加载数据" id="btn">
<table>
    <tr>
        <td>编号</td>
        <td>姓名</td>
        <td>性别</td>
    </tr>
    <tbody id="context">
    <%--    数据--%>

    </tbody>
</table>
</body>
</html>

AjaxController

@RequestMapping("/a2")
public List<User> a2(){
    List<User> userList = new ArrayList<User>();
    //添加数据
    userList.add(new User(1,"周zrr","南"));
    userList.add(new User(2,"周","南"));
    userList.add(new User(3,"周周周","南"));
    return userList;
}

Ajax验证用户名

login.jsp

<html>
<head>
    <title>Title</title>
    <script src="https://apps.bdimg.com/libs/jquery/2.1.4/jquery.min.js"></script>
<%--    <script src="${pageContext.request.contextPath}/static/js/jquery-3.5.1.js"></script>--%>
    <script>
        function a1() {
            $.ajax({
                url:"${pageContext.request.contextPath}/a3",
              data: {"name":$("#name").val()},
              success:function (data) {
                   // alert(data);
                  // console.log(data);
                  if (data.toString()==='ok'){
                      $("#userinfo").css("color","green");
                  }else {
                      $("#userinfo").css("color","red");
                  }
                  $("#userinfo").html(data);
              }
            })
        }
        function a2() {
            $.ajax({
                url:"${pageContext.request.contextPath}/a3",
                data:{"pwd":$("#pwd").val()},
                success:function (data) {
                    //alert(data);
                    // console.log(data);
                    if (data.toString()==='ok'){
                        $("#pwdinfo").css("color","green");
                    }else {
                        $("#pwdinfo").css("color","red");
                    }
                    $("#pwdinfo").html(data);
                }
            })
        }
    </script>
</head>
<body>
<p>
    用户名:<input type="text" id="name" onblur="a1()">
    <span id="userinfo"></span>
</p>
<p>
    密码:<input type="password" id="pwd" onblur="a2()">
    <span id="pwdinfo"></span>
</p>
</body>
</html>

AjaxController

@RequestMapping("/a3")
public String a3(String name,String pwd){
    String msg="";
    if (name!=null){
        //这些数据应该从数据库中查
        if ("admin".equals(name)){
            msg = "ok";
        }else {
            msg = "用户名输入错误";
        }
    }
    if (pwd!=null){
        if ("123456".equals(pwd)){
            msg = "ok";
        }else {
            msg = "密码有误";
        }
    }
    return msg;
}

拦截器

SpringMVC中的拦截器类似于Servlet中的过滤器filter,用于对处理器进行预处理和后处理,开发者可以定义拦截器来实现特定的功能。

过滤器和拦截器的区别:拦截器是Aop思想的具体应用。

过滤器

  • servlet规范中的一部分,任何java web工程都可以使用
  • 在url-pattern中配置/*后,可以对所有要请求的资源进行拦截

拦截器

  • 拦截器是SpringMVC框架自己的,只有使用了该框架才可以使用
  • 拦截器只会拦截访问控制器的方法,访问静态资源不会拦截

搭建环境测试

application.xml

<!--自动扫描包,让包下的注解生效,由IOC容器统一管理-->
<context:component-scan base-package="com.zr.controller"/>
<mvc:default-servlet-handler/>
<mvc:annotation-driven/>


<!--视图解析器-->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" id="internalResourceViewResolver">
    <property name="prefix" value="/WEB-INF/jsp/"/>
    <property name="suffix" value=".jsp"/>
</bean>

web.xml

<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:applicationContext.xml</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
    <servlet-name>springmvc</servlet-name>
    <url-pattern>/</url-pattern>
</servlet-mapping>

<filter>
    <filter-name>encoding</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>encoding</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

web下index.jsp

<body>
<h1>
  <a href="${pageContext.request.contextPath}/user/gologin">登录界面</a></h1>
<h1> <a href="${pageContext.request.contextPath}/user/main">首页</a></h1>
</body>

WEB-INF/jsp/login.jsp

<body>
<form action="${pageContext.request.contextPath}/user/login" method="post">
    用户名:<input type="text" name="username">
    密码:<input type="password" name="password">
    <input type="submit" value="提交">
</form>
</body>

WEB-INF/jsp/main.jsp

<body>
<%--在WEB_INF下的所有界面,只能通过servlet或controller访问--%>
<h1>首页</h1>
${username}
${pageContext.request.getSession("userinfo").getValue(username)}
<p>
    <a href="${pageContext.request.contextPath}/user/goOut">注销</a>
</p>
</body>

LoginController

package com.zr.controller;

@Controller
@RequestMapping("/user")
public class LoginController {
    @RequestMapping("/main")
    public String main(){
        return "main";
    }

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

    @RequestMapping("/login")
    public String login(String username, String password, HttpSession session, Model model){
        //把用户的信息存在Session中
        session.setAttribute("userInfo",username);
        model.addAttribute("username",username);
        System.out.println(model.getAttribute("username"));
        return "main";
    }

    @RequestMapping("/goOut")
    public String goOut(HttpSession session){
        //把用户的信息删除
        session.removeAttribute("userinfo");
        return "main";
    }
}

配置拦截器LoginIntercepter

public class LoginIntercepter implements HandlerInterceptor {
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.println("登录拦截器==========");
        HttpSession session = request.getSession();
        //放行的判断
        //登录页面要放行 包含login  即gologin和login
        if (request.getRequestURI().contains("login")){
            return true;
        }

        if (session.getAttribute("userinfo")!=null){
            return true;
        }

        //判断什么情况下没有登录
        System.out.println("返回登录页==========");
        request.getRequestDispatcher("/WEB-INF/jsp/login.jsp").forward(request,response);
        return false;
    }
}

配置到application.xml中

<!--拦截器配置-->
<mvc:interceptors>
    <mvc:interceptor>
        <!--包括这个请求下的所有请求-->
        <mvc:mapping path="/user/**"/>
        <bean class="com.zr.config.LoginIntercepter"/>
    </mvc:interceptor>
</mvc:interceptors>

文件上传

SpringMVC中配置CommonsMultipartResolver。

前端表单method设置为post,并将enctype设置为multipart/form-data。

对表单中enctype属性的详细说明:

  • application/x-www=form-urlencoded:默认方式,只处理表单域中的value属性值,采用这种编码方式的表单会将表单域中的值处理成URL编码方式。
  • multipart/form-data:这种编码方式会以二进制流的方式来处理表单数据,这种编码方式会把文件域指定文件的的内容也封装到请求参数中,不会对字符编码。
  • text/plain:除了把空格转化为 “+” 号外,其它字母都不做编码处理,这种方式适用直接通过表单发送文件。

在以上项目的pom文件中新增commons-fileupload,commons-io。

index.jsp

<body>

<form action="${pageContext.request.contextPath}/upload" enctype="multipart/form-data" method="post">
  <input type="file" name="file">
  <input type="submit" value="upload">
</form>
</body>

application.xml中增加文件上传配置

<!--文件上传配置-->
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
    <!--请求的编码格式,必须和jsp的pageEncoding的属性一致,以便正确读取表单内容,默认ISO-8859-1-->
    <property name="defaultEncoding" value="utf-8"/>
    <!--上传文件大小限制,单位是字节,10485760=10M-->
    <property name="maxUploadSize" value="10485760"/>
    <property name="maxInMemorySize" value="40960"/>
</bean>

controller

package com.zr.controller;

@RestController
public class FileController {
    //@RequestParam("file"),将name=file属性的文件封装成CommonsMultipartResolver对象
    //批量上传CommonsMultipartFile
    @RequestMapping("/upload")
    public String Fileupload(@RequestParam("file") CommonsMultipartFile file, HttpServletRequest request) throws IOException {
        //获取文件名
        String uploadFileName = file.getOriginalFilename();

        //如果文件名为空,直接回到首页
        if ("".equals(uploadFileName)){
            return "redirect:/index.jsp";
        }
        System.out.println("上传的文件名为:"+uploadFileName);

        //上传路径保存设置
        String path = request.getSession().getServletContext().getRealPath("/upload");
        //如果路径不存在,创建一个
        File realPath = new File(path);
        if (!realPath.exists()){
            realPath.mkdir();
        }
        System.out.println("上传文件保存地址为:"+realPath);

        InputStream is = file.getInputStream();
        OutputStream os = new FileOutputStream(new File(realPath,uploadFileName));

        //读取写出
        int len=0;
        byte[] buffer = new byte[1024];
        while ((len=is.read(buffer))!=-1){
            os.write(buffer,0,len);
            os.flush();
        }
        os.close();
        is.close();
        return "redirect:/index.jsp";
    }

}

上传方式二

@RequestMapping("/upload2")
    public String fileUpload2(@RequestParam("file") CommonsMultipartFile file, HttpServletRequest request) throws IOException {
        //上传路径设置
        String path = request.getSession().getServletContext().getRealPath("/upload");
        File realPath = new File(path);
        if (!realPath.exists()){
            realPath.mkdir();
        }
        //上传文件地址
        System.out.println("上传文件保存地址为:"+realPath);
        //通过 的方法直接写文件(注意)
        file.transferTo(new File(realPath+"/"+file.getOriginalFilename()));
        return "redirect:/index.jsp";
    }

下载文件

@RequestMapping("/downLoad")
public String downLoad(HttpServletResponse response,HttpServletRequest request) throws IOException {
    //要下载的图片地址
    String path = request.getSession().getServletContext().getRealPath("/upload");
    String fileName = "1.jpg";

    //设置respons响应头
    response.reset();//设置在页面不缓存,清空buffer
    response.setCharacterEncoding("utf-8");//字符编码
    response.setContentType("multipart/form-data");//二进制创数数据
    //设置响应头
    response.setHeader("Content-Disposition", "attachment;fileName=" + URLEncoder.encode(fileName, "UTF-8"));

    File file = new File(path, fileName);
    InputStream in = new FileInputStream(file);
    ServletOutputStream out = response.getOutputStream();
    //
    int len = 0;
    byte[] buffer = new byte[1024];
    while ((len = in.read(buffer)) != -1) {
        out.write(buffer, 0, len);
        out.flush();
    }
    out.close();
    in.close();
    return null;
}

版权声明:本文为zhou-zr原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://www.cnblogs.com/zhou-zr/p/14590292.html