从servlet讲到SpringMVC

从Servlet讲到SpringMVC

1、MVC软件设计典范

Model(模型)——View(视图)——Controller(控制器)

之前Servlet的MVC设计模式其实是不太符合严格的MVC设计模式的,因为Controller控制器里不仅需要用servlet获取前端请求的参数,还要进行转发,而且有的时候servlet还要打开数据库流然后进行获取数据然后进行增删改查再返回,最后在JSP页面里还要用Java语句进行遍历或者赋值之类的,相当于很杂糅,控制器里既要进行模型层的操作,视图层还要进行控制器层的操作,就特别杂糅。

在这里插入图片描述

并且那个时候所有的压力基本上都在Contrller上,所以服务器端的压力特别大,后来有了新的SpringMVC就让用户端也分担小部分压力,同时也基本上实现了真正的前后端分离。

2、回顾Java Servlet

Servlet(Server Applet)是Java Servlet的简称,称为小服务程序或服务连接器,用Java编写的服务器端程序,具有独立于平台和协议的特性,主要功能在于交互式地浏览和生成数据,生成动态Web内容。

在JSP(Java Server Pages)里的Servlet:

在这里插入图片描述

所以如果我们有很多个页面或者很多种业务的话就需要N多个Servlet,并且没创建一个Servlet就还需要到web.xml里面去注册Servlet。

public class HelloServlet extends HttpServlet {
   @Override
   protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
       //取得参数
       String method = req.getParameter("method");
       if (method.equals("add")){
           req.getSession().setAttribute("msg","执行了add方法");
      }
       if (method.equals("delete")){
           req.getSession().setAttribute("msg","执行了delete方法");
      }
       //业务逻辑
       //视图跳转
       req.getRequestDispatcher("/WEB-INF/jsp/hello.jsp").forward(req,resp);
  }

   @Override
   protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
       doGet(req,resp);
  }
}

我们以前是在Servlet里面获取的HttpServletRequest对象然后用request.getParameter获取参数,最后再转发或者重定向到JSP页面。

而在SpringMVC里实质上就是加了一个最顶层的dispatcherServlet来获取用户请求,然后交给多个Controller来处理再响应给用户。

dispatcherServlet简单原理:

在这里插入图片描述

3、创建Maven项目并且集成Tomcat

我用的编译器是IDEA,IDEA集成Tomcat方法:https://www.cnblogs.com/weixinyu98/p/9822048.html

注意选择骨架的使用选webapp然后我们再手动导入SpringMVC需要的相关依赖:

在这里插入图片描述

创建完成:在这里插入图片描述

同时我们也需要创建src/main/resources资源文件夹用来放Spring和Mybatis的配置文件,还要创建src/main/java来放Java代码。创建好之后我们来启动Tomcat测试一下没有集成成功。

测试成功:

在这里插入图片描述

这时候我们就可以安心的来写自己的Java代码和配置文件了,起码不用担心Tomcat的问题了。

4、在pom.xml里引入相关依赖

因为我们需要跟Mybatis整合,所以需要mybatis和mybatis-spring依赖;如果需要Junit单元测试还需要Junit依赖;还有spring-webmvc依赖,这个依赖就自动包含了spring的绝大部分依赖,因为我们需要用servlet,所以还需要导入servlet的相关依赖,因为要前后端分离所以还需要导入jstl依赖;因为需要连接到数据库还需要MySQL驱动依赖

	<dependencies>
    <!--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>5.1.23</version>
    </dependency>

    <!--druid数据库连接池-->
    <dependency>
      <groupId>com.alibaba</groupId>
      <artifactId>druid</artifactId>
      <version>1.1.7</version>
    </dependency>

    <!--servlet-->
    <dependency>
      <groupId>javax.servlet</groupId>
      <artifactId>servlet-api</artifactId>
      <version>2.5</version>
    </dependency>
    <dependency>
      <groupId>javax.servlet</groupId>
      <artifactId>javax.servlet-api</artifactId>
      <version>4.0.1</version>
    </dependency>
    <dependency>
      <groupId>javax.servlet.jsp</groupId>
      <artifactId>jsp-api</artifactId>
      <version>2.2</version>
    </dependency>
    <dependency>
      <groupId>javax.servlet</groupId>
      <artifactId>jstl</artifactId>
      <version>1.2</version>
    </dependency>

    <!--Mybatis-->
    <dependency>
      <groupId>org.mybatis</groupId>
      <artifactId>mybatis</artifactId>
      <version>3.5.4</version>
    </dependency>
    <dependency>
      <groupId>org.mybatis</groupId>
      <artifactId>mybatis-spring</artifactId>
      <version>2.0.2</version>
    </dependency>

    <!--Spring-->
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-webmvc</artifactId>
      <version>5.1.9.RELEASE</version>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-jdbc</artifactId>
      <version>5.1.9.RELEASE</version>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-test</artifactId>
      <version>5.1.9.RELEASE</version>
      <scope>test</scope>
    </dependency>
  </dependencies>

5、在web.xml里注册dispatcherServlet

因为SpringMVC的核心就是dispatcherServlet,所以我们就立马去web.xml里注册它,而且也只需要注册它一个Servlet

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
         version="4.0">

  <!--1.注册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:applicationContext.xml</param-value>
    </init-param>
    <!--启动级别-1,跟随服务器一起启动-->
    <load-on-startup>1</load-on-startup>
  </servlet>
  <!--
  /:匹配所有页面,不包括jsp页面(推荐)
  /*:匹配所有页面,包括jsp页面
  -->
  <servlet-mapping>
    <servlet-name>springmvc</servlet-name>
    <url-pattern>/</url-pattern>
  </servlet-mapping>
  <!--2.字符编码过滤器的Servlet-->
  <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-app>

还注册一个filter来过滤中文乱码。

6、我们依旧是对应数据表建立一个pojo类

以及有参、无参构造方法,toString()方法,getter和setter方法

在这里插入图片描述

其中数据表里uid自增

7、然后我们再写Mapper接口进行增删改查

UserMapper.java:

public interface UserMapper {
    //查询所有用户
    List<User> selectAllUser();
    //根据id查询用户
    User selectUserByUid(int id);
    //新增用户
    int insertUser(User user);
}

写了两个需求,分别是查询所有用户,根据id查询用户,新增用户

8、写mapper.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="cn.wqk.mapper.UserMapper">
    <select id="selectAllUser" resultType="User">
        SELECT
            uid,username,password,age
        FROM
            user
    </select>
    <select id="selectUserByUid" parameterType="integer" resultType="User">
        SELECT
            uid,username,password,age
        FROM
            user
        WHERE
            uid=#{uid}
    </select>
    <insert id="insertUser" parameterType="User" useGeneratedKeys="true" keyProperty="uid">
        INSERT INTO
            user
        (username,password,age)
        VALUES
        (#{username},#{password},#{age})
    </insert>
</mapper>

三个标签分别对应三个增删改查的要求。

9、Mybatis配置文件

<?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="cn.wqk.pojo" />
    </typeAliases>
    <!-- 配置Mapper映射文件地址 -->
    <mappers>
        <mapper class="cn.wqk.mapper.UserMapper"/>
    </mappers>
</configuration>

10、仍然是获取sqlSession对象

用spring-dao.xml配置文件来专注于获取SqlSession对象,当然在这之前,我们仍然需要我们的db.properties数据库连接配置文件

<?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
       http://www.springframework.org/schema/beans/spring-beans.xsd
       http://www.springframework.org/schema/context
       http://www.springframework.org/schema/context/spring-context.xsd">
    <!--引入db.properties文件-->
    <context:property-placeholder location="classpath:db.properties"/>
    <!--    1、dataSource-->
    <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
        <property name="driverClassName" value="${jdbc.driver}"/>
        <property name="url" value="${jdbc.url}"/>
        <property name="username" value="${jdbc.username}"/>
        <property name="password" value="${jdbc.password}"/>
    </bean>
    <!--    2、sqlSessionFactory-->
    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
        <property name="dataSource" ref="dataSource"/>
        <!--	引入mybatis配置文件	-->
        <property name="configLocation" value="classpath:mybatis-config.xml"/>
    </bean>
    <!--    3、sqlSession-->
    <bean id="sqlSession" class="org.mybatis.spring.SqlSessionTemplate">
        <constructor-arg index="0" ref="sqlSessionFactory"/>
    </bean>
</beans>

11、写Mapper接口的实现类,将他与SqlSession封装

public class UserMapperImpl extends SqlSessionDaoSupport implements UserMapper{
    @Override
    public List<User> selectAllUser() {
        return getSqlSession().getMapper(UserMapper.class).selectAllUser();
    }

    @Override
    public User selectUserByUid(int id) {
        return getSqlSession().getMapper(UserMapper.class).selectUserByUid(id);
    }

    @Override
    public int insertUser(User user) {
        return getSqlSession().getMapper(UserMapper.class).insertUser(user);
    }
}

依旧是需要将他的实现类去实现UserMapper接口并且继承SqlSessionDaoSupport,就会有getSqlSession()方法直接获取SqlSession对象了。

12、这个时候我们就需要一个spring-service.xml配置文件来专注于扫描并且获得pojo包、service包和UserMapper的实现

<?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
       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="cn.wqk.pojo"/>
    <context:component-scan base-package="cn.wqk.service"/>
    <bean id="UserMapper" class="cn.wqk.mapper.UserMapperImpl">
        <property name="sqlSessionFactory" ref="sqlSessionFactory"/>
    </bean>
</beans>

13、spring-mvc.xml配置文件来专注于配置springMVC相关东西

特别是这个视图解析器

<?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
       http://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="cn.wqk.controller"/>
   <!-- 让Spring MVC不处理静态资源 -->
   <mvc:default-servlet-handler />
   <!--
   支持mvc注解驱动
       在spring中一般采用@RequestMapping注解来完成映射关系
       要想使@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>

14、最后我们把spring-dao,spring-service,spring-mvc丢入到applicationContext容器里交给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/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">
    <import resource="classpath:spring-dao.xml"/>
    <import resource="classpath:spring-service.xml"/>
    <import resource="classpath:spring-mvc.xml"/>
</beans>

到这个时候我们的配置文件基本就配置完成了,以后任何的SpringMVC就可以直接使用这一套配置了,但是SpringMVC仍然是”配置地狱“,所以后面才有了SpringBoot来简化配置。

15、这个时候我们就进入最后一层面向用户的地方了,业务层service

写业务接口:

UserService.java:

public interface UserService {
    //查询所有用户但是只输出他们的用户名
    List<String> selectAllUsername();
    //根据id查询用户只输出名字
    String selectUsernameByUid(int uid);
}

因为Mapper只是对数据库进行增删改查,真正的业务不可能只是对数据进行简单的增删改查,还需要对增删改查的数据进行进一步封装,这就是业务service,比如分页之类的,上面两个需求就是将他们查询到的东西进行封装只输出名字,具体的要求得看公司的上级给你的要求是什么,然后你再自己进行封装。因为我们只需要返回一组名字,所以就返回泛型的String,下面同理。

16、实现service

public class UserServiceImpl implements UserService{
    @Autowired
    UserMapper userMapper;
    @Override
    public List<String> selectAllUsername() {
        List<User> userList = userMapper.selectAllUser();
        List<String> usernameList=new ArrayList<>();
        for (int i=0;i<userList.size();i++){
            usernameList.add(userList.get(i).getUsername());
        }
        return usernameList;
    }

    @Override
    public String selectUsernameByUid(int uid) {
        User user = userMapper.selectUserByUid(uid);
        String username=user.getUsername();
        return username;
    }
}

因为UserMapper被我们丢到了Spring容器里边,所以我们可以用@Autowired来自动装配他,而不是需要new一个。重写UserService的方法,就将查询到的数据进行进一步封装然后返回得到我们需要的数据。同时也可以写个Test来测试一下我们的Service有没有写正确。

17、我们创建一个jsp页面来测试一下

在WEB-INF下面创建一个jsp包,然后创建一个test.jsp:

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

用EL表达式${msg}来获取到我们返回的msg的值,也可以用JSTL来处理,甚至可以用HTML然后用JavaScript来获取数据返回给前端实现真正的前后端分离。

18、控制器controller

控制器就是SpringMVC的重中之重。

在src/main/java里创建cn.wqk.controller包专门存放controller

SpringMVC里控制器的几种实现方式以及Restful风格:

https://blog.youkuaiyun.com/weixin_45747080/article/details/106026230

我们先来写一个TestController试一下:

TestController.java:

@Controller
@RequestMapping("test")
public class TestController {
    @Autowired
    UserService userService;
    @RequestMapping("selectAllUsername")
    public String t1(Model model){
        List<String> stringList = userService.selectAllUsername();
        model.addAttribute("msg",stringList);
        return "test";
    }
    @RequestMapping("selectUsernameByUid")
    public String t2(@RequestParam("uid") int uid, Model model){
        String username = userService.selectUsernameByUid(uid);
        model.addAttribute("msg",username);
        return "test";
    }
}

因为我们需要用到自动装配UserService,所以请一定切记要在UserService和UserServiceImpl里加上@Service注解,然后我们就可以直接用@Autowired直接用了。

在这里插入图片描述

就相当于在地址栏请求http:/*********/test/selectAllUsername就会执行t1里面的方法,这个方法是调用了UserService里的selectAllUsername方法返回的是名字集合然后存到了msg这个对象里,执行完了之后就会返回到WEB/INF/test.sjp然后用EL表达式显示msg对象里的数据

在这里插入图片描述

在这里插入图片描述

同理请求selectUsernameByUid也是,只是需要传递一个Uid参数而已,我们也把他存到msg对象里,也返回到test.jsp就实现了jsp页面的复用。

19、测试

在这里插入图片描述

在这里插入图片描述

所以我们现在只需要把数据丢给前端,让前端帮我们用html或者Jsp渲染然后实现好看的页面,就真正做到了前后端分离!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值