菜鸟学SpringMVC之——SpringMVC入门

SpringMVC

引入

Spring 框架提供了构建 Web应用程序的全功能 MVC 模块。使用 Spring 可插入的 MVC 架构,从而在使用Spring进行WEB开发时,可以选择使用Spring的Spring MVC框架或集成其他MVC开发框架,如Struts1(现在一般不用),Struts 2(一般老项目使用)等。

SpringMVC的优点:

1、SpringMVC使用简单,学习成本低。学习难度小于Struts2,Struts2用不上的多余功能太多。

2、SpringMVC很容易就可以写出性能优秀的程序,Struts2要处处小心才可以写出性能优秀的程序(指MVC部分)

3、SpringMVC灵活性强。

先来看看以前的项目体系结构(Servlet):

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-pTQuquXA-1591687866191)(C:\Users\张澳琪\AppData\Roaming\Typora\typora-user-images\image-20200609145811694.png)]

首先用户的请求会到达 Servlet,然后根据请求调用相应的 Java Bean,并把所有的显示结果交给 JSP 去完成,这样的模式我们就称为 MVC 模式。

M 代表 模型(Model) :模型就是数据,dao、bean

V 代表 视图(View) : 就是网页, JSP,用来展示模型中的数据

C 代表 控制器(controller) 控制器的作用就是把不同的数据(Model),显示在不同的视图(View)上,Servlet 扮演的就是这样的角色。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-33w7wEb0-1591687866202)(C:\Users\张澳琪\AppData\Roaming\Typora\typora-user-images\image-20200606202422125.png)]

在以后的项目中,model层(从数据库中查找数据)可以被mybatis的mapper替换掉,service层可以被Spring处理。那么以后在Controller层中调用service时,就要用ApplicationContext来创建它。如果一个Controller创建一个它,那就要创建许多个ApplicationContext容器,太浪费了(我们发现以前我们的项目中,每一个Controller只是完成了doGet、doPost方法,大型的资源浪费。接下来我们看看用Spring管理Servlet。),所以这时就要将所有的容器共用一个。

在了解完SpringMVC后,可以去看看SpringMVC与Servlet的区别,有助于理解

在这里插入图片描述

接下来我们创建一个SpringMVC项目

先导入依赖的jar包

<dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-webmvc</artifactId>
      <version>5.2.5.RELEASE</version>
    </dependency>

    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-orm</artifactId>
      <version>5.2.5.RELEASE</version>
    </dependency>

    <dependency>
      <groupId>org.mybatis</groupId>
      <artifactId>mybatis-spring</artifactId>
      <version>2.0.4</version>
    </dependency>

    <dependency>
      <groupId>org.mybatis</groupId>
      <artifactId>mybatis</artifactId>
      <version>3.5.4</version>
    </dependency>

    <dependency>
      <groupId>mysql</groupId>
      <artifactId>mysql-connector-java</artifactId>
      <version>8.0.16</version>
    </dependency>

修改web.xml文件

<!DOCTYPE web-app PUBLIC
        "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
        "http://java.sun.com/dtd/web-app_2_3.dtd" >

<web-app>
<display-name>Archetype Created Web Application</display-name>

  <servlet>
    <servlet-name>springmvc</servlet-name>
    <!--DispatcherServlet,这个就是Spring给我们的用来启动web项目的容器启动器,它可以加载ApplicationContext-->
    <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>
    <!--启动项目时就启动Spring容器-->
    <load-on-startup>1</load-on-startup>
  </servlet>
  <servlet-mapping>
    <servlet-name>springmvc</servlet-name>
    <!--表示要拦截所有的请求,并交由Spring MVC的后台控制器来处理-->
    <url-pattern>/</url-pattern>
  </servlet-mapping>

</web-app>

这时就有了Spring容器了。

以前我们创建一个Servlet就要创建一个类继承HttpServlet了,这样太麻烦了。

上面DispatcherServlet已经为我们创建了Spring容器了,真正DispatcherServlet中获取到的所有请求都要交给Spring容器来检查它发给谁(转给那个真正处理业务的类,而这个类只要是Spring中的bean就行了)

下面这个类就相当于是一个大的Servlet,而里面的每个方法就是以前我们项目中的每一个Controller类

@Controller //将他放到Spring的IoC容器中了
@RequestMapping(value="/test")//请求映射地址
// http://www.jjjjj.com/test/test.do 这个请求中的test就是RequestMapping中配置的部分
public class TestController {
    
    

    @RequestMapping(value="/foo.do") //设置详细的请求就比如上面请求的test.do的部分
    public void foo() {
    
    //替代了之前的Servlet,之后这个类中的所有其他方法(加@RequestMapping后)都是一个Servlet接口了
        System.out.println("运行到这里了");
    }
}

这时只要我们前端的请求写对了,发送到了web.xml后与<url-pattern>/</url-pattern>匹配,匹配上了Tomcat就将这个请求给了DispatcherServlet,它里面有一个HandlerMapping,这个HandlerMapping关心的是发送来的请求和目标位置(真正要访问的内容)之间的关系。然后DispatcherServlet找到我们所有加有@Controller的bean,然后将请求与@RequestMapping的值依次匹配,匹配到对应的方法上,然后DispatcherServlet会通过反射调用匹配到的这个方法(比如请求为: http://localhost:8080/test/foo.do,则会匹配到配置@RequestMapping值为foo.do的方法上,即上面的foo()方法 ),这时请求就进入到了服务器。(这里描述的是SpringMVC的原理,后文会详细讲解)


这时又有一个疑问,原来的Servlet能控制是接受get请求或者post请求。SpringMVC怎么实现呢?看下面:

@Controller
@RequestMapping("/test")
public class TestController {
    
    
    @RequestMapping(value = "/doo.do", method = RequestMethod.POST)
    public void doo() {
    
    
        System.out.println("这里是doo");
    }
}

method = RequestMethod.POST表示可以接收post请求。

这时我们通过get访问,他会返回405错误,因为我们这里设置接收的是Post请求,而不支持get请求。

如果想让同一个请求get方法和post方法执行的逻辑不一样,那么就写两个方法,让他们的@RequestMapping的value值相同,但是method分别支持不同的请求就OK了。

但是原来的doGet,doPost方法中有两个参数 ,我们现在这个没有这两个参数,那么前端怎么传参呢?

给方法加形参就可以解决了(注意:形参名要和请求的key值相同,不过也可以通过@RequestParam来设置)

@RequestMapping(value = "/doo.do", method = {
    
    RequestMethod.GET})
    public void doo(String str) {
    
    //这时前端传来的参数名必须是str
        System.out.println("这里是doo:" + str);
    }

比如前端发送请求:localhost:8080/user/doo.do?str=zaq则这时控制台会输出:这里是doo:zaq。即可以获取到前端传来的参数了

@RequestMapping(value = "/doo.do", method = {
    
    RequestMethod.GET})
    public void doo(@RequestParam(value = "yyy",required = true, defaultValue = "我是一个小String") String str) {
    
    
        //这时如果前端传入的参数的key为yyy,则可以获取到前端传来的值,如果没传参或者参数的key值不是yyy,则默认值为:我是一个小String
        System.out.println("这里是doo:" + str);
    }

@RequestMapping(value = "/doo.do", method = {
    
    RequestMethod.GET})
    public void doo(@RequestParam(value = "yyy",required = true) String str) {
    
    
        //required属性表示是否必须传yyy这个值,如果没有设置默认值且required值为true,那么前端请求要是没传参或者传入的参数的key值不是yyy,那么就会有400错误
        System.out.println("这里是doo:" + str);
    }

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-IUTiwsMJ-1591687866211)(C:\Users\张澳琪\AppData\Roaming\Typora\typora-user-images\image-20200607082143072.png)]

现在再看看原来的接收前端传入的参数的过程,很麻烦

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-BwLwulPM-1591687866211)(C:\Users\张澳琪\AppData\Roaming\Typora\typora-user-images\image-20200607082355395.png)]

我们现在接收前端的参数就很简单了,如果接收到前端传来的一个一个字段,那我们先创建一个实体类,只要传来的参数与实体类的属性名一一对应,它就能将参数放到对象中。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-s9hzRS4m-1591687866212)(C:\Users\张澳琪\AppData\Roaming\Typora\typora-user-images\image-20200607082842953.png)]

@RequestMapping(value = "/test.do", method = {
    
    RequestMethod.GET})
    public void test(User user) {
    
    
        System.out.println("这里是test:" + user.getUsername() +","+ user.getPwd());
    }

在这里插入图片描述

有时候HttpServletRequest和HttpServletResponse这两个参数又很有用,必须加,怎么办?

先导入jar包

	<dependency>
      <groupId>javax.servlet</groupId>
      <artifactId>javax.servlet-api</artifactId>
      <version>4.0.1</version>
      <scope>provided</scope>
    </dependency>

这时就可以操作HttpServletRequest、HttpServletResponse了

@RequestMapping(value = "/test2.do", method = {
    
    RequestMethod.GET})
    public void test2(HttpServletRequest request, HttpServletResponse response) {
    
    
        System.out.println(request.getParameter("username"));

        try {
    
    
            response.setContentType("text/html; charset=utf8");
            response.getWriter().println("使用resp返回内容");
        } catch (IOException e) {
    
    
            e.printStackTrace();
        }
    }

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-vmUQZNWj-1591687866215)(C:\Users\张澳琪\AppData\Roaming\Typora\typora-user-images\image-20200607084124542.png)]


session怎么用呢?

@RequestMapping(value = "/test3.do", method = {
    
    RequestMethod.GET})
    public void test3(User user, HttpSession session) {
    
    
        System.out.println(session.getId());
    }

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-BIkqA0Jh-1591687866215)(C:\Users\张澳琪\AppData\Roaming\Typora\typora-user-images\image-20200607084350214.png)]

接下来用SpringMVC实现一个简单的登录过程

在这里插入图片描述

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

    @Autowired
    IUserService service;

    @RequestMapping(value = "/login.do", method = {
    
    RequestMethod.GET})
    public void login(User user) {
    
    
        User result = service.login(user);
        //登录是否成功就看result是否有返回值
        System.out.println("判断登录是否成功" + result.getId());
    }
}
@Repository
public interface UserMapper {
    
    
    User findUser(@Param("user") User user);
}
public interface IUserService {
    
    
    public User login(User user);
}
@Service //这时这个类就放进到了Spring的容器中
public class UserServiceImpl implements IUserService {
    
    

    @Autowired
    UserMapper mapper;

    @Override
    public User login(User user) {
    
    
        return mapper.findUser(user);
    }
}
<?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定义接口-->
<mapper namespace="com.home.test.mapper.UserMapper"> <!--namespace:绑定映射器-->

    <resultMap id="UserType" type="com.home.test.entity.User" autoMapping="false">
        <id property="id" column="id"></id>
        <result property="username" column="username"></result>
    </resultMap>
    <select id="findUser" resultMap="UserType">
        select * from tb_fans where username = #{user.username} and pwd=#{user.pwd}
    </select>
</mapper>

配置Spring的applicationContext.xml文件

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:context="http://www.springframework.org/schema/context"
       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
       http://www.springframework.org/schema/context
       http://www.springframework.org/schema/context/spring-context.xsd
">
    <context:component-scan base-package="com.home.test"></context:component-scan>

    <bean id="dataSource" class="org.apache.ibatis.datasource.pooled.PooledDataSource">
        <property name="driver" value="com.mysql.cj.jdbc.Driver"></property>
        <property name="url" value="jdbc:mysql://localhost:3306/db_foo?serverTimezone=UTC"></property>
        <property name="username" value="root"></property>
        <property name="password" value="zaq991221"></property>
    </bean>

    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
        <property name="dataSource" ref="dataSource"></property>
        <property name="mapperLocations" value="classpath:mapper/*.xml"></property>
    </bean>

    <bean id="mapperScanner" class="org.mybatis.spring.mapper.MapperScannerConfigurer">
        <property name="basePackage" value="com.home.test.mapper"></property>
    </bean>
</beans>

部分内容参考:https://www.jianshu.com/p/91a2d0a1e45a

Guess you like

Origin blog.csdn.net/ysf15609260848/article/details/106643489