SpringMVC和Servlet的区别与联系
Servlet:性能最好,处理Http请求的标准。
SpringMVC:开发效率高(好多共性的东西都封装好了,是对Servlet的封装,核心的DispatcherServlet最终继承自HttpServlet)
这两者的关系,就如同MyBatis和JDBC,一个性能好,一个开发效率高,是对另一个的封装。
接下来我们分别通过SpringMVC和Servlet实现一下用户登录的过程,体会一下他们的区别
Servlet实现登录
首先配置:web.xml
<?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">
<servlet>
<servlet-name>login</servlet-name>
<servlet-class>com.controller.LoginController</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>login</servlet-name>
<url-pattern>/login.do</url-pattern>
</servlet-mapping>
</web-app>
接下来实现Model层,查询数据库(顺便再来感受下JDBC编程的痛苦🤣)
User实体类
public class User {
private int id;
private String username;
private String pwd;
//省略get、set方法
//省略JDBC链接数据库的过程
public class UserDao extends BaseDao<User> {
@Override
public int insert(User user) {
return 0;
}
@Override
public int delete(User user) {
return 0;
}
@Override
public int update(User user) {
return 0;
}
@Override
public User select(User user) {
Connection connection = this.getConnection();
String sql = "select * from tb_user where username = ? and pwd = ?";
try {
PreparedStatement ps = connection.prepareStatement(sql);
ps.setString(1,user.getUsername());
ps.setString(2,user.getPwd());
ResultSet resultSet = ps.executeQuery();
while (resultSet.next()) {
User result = new User();
result.setId(resultSet.getInt("id"));
result.setUsername(resultSet.getString("username"));
return result;
}
} catch (SQLException e) {
e.printStackTrace();
} finally {
try {
connection.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
return null;
}
}
service层
public class UserService implements IUserService {
UserDao dao = new UserDao();
@Override
public boolean register(String username, String pwd) {
return false;
}
@Override
public User login(User user) {
User result = dao.select(user);
return result;
}
}
简易视图层:
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<form action="/web/login.do" method = "post">
用户名:<input type="text"name = "username"><br>
密 码:<input type="password"name = "password"><br>
<input type="submit" value="登录">
</form>
</body>
</html>
控制层
public class LoginController extends HttpServlet {
IUserService service = new UserService();
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
this.doPost(req, resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String username = req.getParameter("username");
String password = req.getParameter("password");
User user = new User();
user.setUsername(username);
user.setPwd(password);
User login = service.login(user);
if (login != null) {//如果查询到的值不为空,则表示登录成功
//正常业务这里会将用户信息保存在session中,然后重定向到登录成功的页面,这里简化操作,直接输出信息
System.out.println("登录成功,欢迎你:" + login.getUsername() );
} else {
System.out.println("登录失败");
}
}
}
接下来看看SpringMVC实现用户登录过程
首先配置web.xml
<web-app version="2.5"
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_2_5.xsd">
<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>
<!--所有的请求都过DispatcherServlet-->
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
Spring主要也是通过DispatcherServlet实现了Servlet这个接口,又叫前端控制器,来自前端的请求会先到达这里,它负责到后台去匹配合适的handler。DispatcherServlet的主要工作流程如下:
前端请求到达DispatcherServlet。
前端控制器请求HandlerMappering 查找Handler。
如果查找到存在的处理器,进一步去调用service和dao层
返回结果再到controller层,渲染具体的视图,返回结果给页面。
然后加载SpringMVC的配置文件: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"
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
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc.xsd ">
<!--扫描com.home.test包下的Controller-->
<context:component-scan base-package="com.home.test"></context:component-scan>
<mvc:annotation-driven></mvc:annotation-driven><!--mvc注解驱动-->
<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>
然后开始扫描UserController 这个类,找到login.do。这时是通过注解来找到自己所需要的方法。
控制层:
@Controller
@RequestMapping("/user")
public class UserController {
@Autowired
IUserService service;
@RequestMapping(value = "/login.do", method = {RequestMethod.GET})
public String login(User user) {
User result = service.login(user);
//登录是否成功就看result是否有返回值
if (result != null) {
return "redirect:/pages/success.html";//登录成功就重定向到成功页面
} else {
return "redirect:/pages/error.html";
}
}
}
model层,查询数据库(丢弃了老旧式的JDBC,使用MyBatis框架)
@Repository
public interface UserMapper {
User findUser(@Param("user") User 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>
service层
@Service
public class UserServiceImpl implements IUserService {
@Autowired
UserMapper mapper;
@Override
public User login(User user) {
User user1 = mapper.findUser(user);
return user1;
}
}
对比两个实现过程我们发现: 使用servlet的话需要每个请求都去在web.xml中配置一个servlet,并且在控制层创建一个Servlet,而且,每个Servlet只是完成了doGet、doPost方法,这就是大型的资源浪费啊。而SpringMVC中的DispatcherServlet他会拦截所有的请求,进一步去查找有没有合适的处理器,一个前端控制器就可以。
学习参考:
https://blog.csdn.net/cleble/article/details/78018859
https://www.cnblogs.com/haolnu/p/7294533.html