Spring Web MVC
官方文檔的介紹:
The Spring Web model-view-controller (MVC) framework is designed around a DispatcherServlet that dispatches requests to handlers, with configurable handler mappings, view resolution, locale, time zone and theme resolution as well as support for uploading files. The default handler is based on the @Controller and @RequestMapping annotations, offering a wide range of flexible handling methods.
要想深入理解還需要多看官方文檔,多實(shí)踐操作才行,這里只是簡單的介紹哈,對我們?nèi)腴T來講只要了解這么多就能夠了。
Spring Web MVC最核心的幾個(gè)幾部份包括:
前端控制器:DispatcherServlet;
利用控制器:HandlerMapping(處理映照)、ViewResolver(視圖解析);
頁面控制器:ModelAndView
1般我們用到這幾個(gè)就能夠了,固然復(fù)雜的還要了解許多其他的。
下面我們來寫1個(gè)小例子:
新建1個(gè)項(xiàng)目,然后了加入以下的jar包:
新建HelloController.java
package cn.ailot.web;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
@RequestMapping("/spring")
public class HelloController{
@RequestMapping("/hello.form")
public String execute() throws Exception{
System.out.println("履行HelloController");
//這里返回的hello就是試圖解析器里面的hello.jsp頁面
return "hello";
}
}
然后在src文件夾下面新建1個(gè)名為sping-mvc.xml的文件,代碼以下:
<?xml version="1.0" encoding="UTF⑻"?>
<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"
xmlns:util="http://www.springframework.org/schema/util"
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
http://www.springframework.org/schema/util
http://www.springframework.org/schema/util/spring-util.xsd">
<!-- 開啟@RequestMapping注解映照 -->
<mvc:annotation-driven/>
<!--開啟組件掃描定義-->
<context:component-scan base-package="cn.ailot.web"></context:component-scan>
<!-- 定義視圖解析器ViewResolver -->
<bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/jsp/"></property>
<property name="suffix" value=".jsp"></property>
</bean>
</beans>
接下來配置web.xml文件:
<?xml version="1.0" encoding="UTF⑻"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0">
<display-name>springmvc</display-name>
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
<!-- 處理編碼問題 -->
<filter>
<filter-name>encodingFilter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF⑻</param-value>
</init-param>
</filter>
<!-- 加載sping配置文件 -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring-mvc.xml</param-value>
</context-param>
<servlet>
<servlet-name>springmvc</servlet-name>
<servlet-class>
org.springframework.web.servlet.DispatcherServlet
</servlet-class>
<!--啟動(dòng)容器的時(shí)候初始化改servlet-->
<load-on-startup>1</load-on-startup>
</servlet>
<!--servlet映照-->
<servlet-mapping>
<servlet-name>springmvc</servlet-name>
<url-pattern>*.form</url-pattern>
</servlet-mapping>
</web-app>
現(xiàn)在就能夠啟動(dòng)服務(wù)試試,看能否正常啟動(dòng),如果可以就表示配置沒錯(cuò)。
地址欄里輸入:http://localhost:8080/springmvc/spring/hello.form
會(huì)看到hello.jsp的內(nèi)容:
以上就是1個(gè)簡單的Spring MVC的例子。
下面我們來做1個(gè)登錄的案例,Sping MVC接受參數(shù)有好多種方法,最經(jīng)常使用到的有:
1、HttpServletRequest獲得;
2、@RequestParam注解;
3、封裝成實(shí)體參數(shù)。
下面我們來1個(gè)1個(gè)的實(shí)現(xiàn),
實(shí)體user.java
package cn.ailot.entity;
public class User {
private int id;
private String name;
private String pwd;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPwd() {
return pwd;
}
public void setPwd(String pwd) {
this.pwd = pwd;
}
}
接口UserDao.java
package cn.ailot.dao;
import cn.ailot.entity.User;
/**
* 用戶數(shù)據(jù)訪問接口
* @author litao
*
*/
public interface UserDao {
/**
* 根據(jù)用戶名查找系統(tǒng)用戶
* @param name
* @return
*/
public User findByName(String name);
}
異常捕獲:
用戶名或密碼錯(cuò):
NameOrPwdException.java
package cn.ailot.service;
public class NameOrPwdException extends Exception {
public NameOrPwdException(){}
public NameOrPwdException(String message){
super(message);
}
public NameOrPwdException(Throwable cause){
super(cause);
}
public NameOrPwdException(String message,Throwable cause){
super(message,cause);
}
}
空值異常:
NullParamException.java
package cn.ailot.service;
public class NullParamException extends Exception{
public NullParamException(){}
public NullParamException(String message){
super(message);
}
public NullParamException(String message,Throwable cause){
super(message,cause);
}
}
業(yè)務(wù)實(shí)現(xiàn)UserService.java
package cn.ailot.service;
import javax.annotation.Resource;
import org.springframework.stereotype.Service;
import cn.ailot.dao.UserDao;
import cn.ailot.entity.User;
@Service
public class UserService {
@Autowired
private UserDao userDao;
/**
* 登錄系統(tǒng)
* @throws NameOrPwdException
* @throws NullParamException
*/
public User login(String name,String pwd) throws NameOrPwdException, NullParamException{
if(name==null||name.equals("") || pwd == null|| pwd.equals("")){
throw new NullParamException("登錄參數(shù)不能為空!");
}
User user = userDao.findByName(name);
if(user != null && pwd.equals(user.getPwd())){
return user;
}
throw new NameOrPwdException("用戶名或密碼毛病");
}
}
配置數(shù)據(jù)庫連接:
db.properties
driver=com.mysql.jdbc.Driver
url=jdbc:mysql://127.0.0.1:3306/test
user=root
pwd=root
數(shù)據(jù)庫腳本:
-- ----------------------------
-- Table structure for users
-- ----------------------------
DROP TABLE IF EXISTS `users`;
CREATE TABLE `users` (
`id` varchar(10) NOT NULL,
`name` varchar(10) DEFAULT NULL,
`pwd` varchar(10) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-- ----------------------------
-- Records of users
-- ----------------------------
INSERT INTO `users` VALUES ('1', 'admin', 'admin');
spring-mvc.xml配置文件
<?xml version="1.0" encoding="UTF⑻"?>
<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"
xmlns:util="http://www.springframework.org/schema/util"
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
http://www.springframework.org/schema/util
http://www.springframework.org/schema/util/spring-util.xsd">
<!-- 實(shí)例化本地數(shù)據(jù)庫連接參數(shù) -->
<util:properties id="jdbcProps" location="classpath:db.properties"/>
<!-- 開啟@RequestMapping注解映照 -->
<mvc:annotation-driven/>
<!--開啟組件掃描定義-->
<context:component-scan base-package="cn.ailot"></context:component-scan>
<!-- 定義視圖解析器ViewResolver -->
<bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/jsp/"></property>
<property name="suffix" value=".jsp"></property>
</bean>
</beans>
創(chuàng)建數(shù)據(jù)庫連接:
package cn.ailot.dao;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
@Component
public class JdbcDataSource{
private String driver;
@Value("#{jdbcProps.url}")
private String url;
@Value("#{jdbcProps.user}")
private String user;
@Value("#{jdbcProps.pwd}")
private String pwd;
public String getDriver() {
return driver;
}
/*必須寫在set方法上,否則注入無效*/
@Value("#{jdbcProps.driver}")
public void setDriver(String driver) {
try{
Class.forName(driver);
this.driver = driver;
}catch(Exception e){
throw new RuntimeException(e);
}
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
public String getUser() {
return user;
}
public void setUser(String user) {
this.user = user;
}
public String getPwd() {
return pwd;
}
public void setPwd(String pwd) {
this.pwd = pwd;
}
public Connection getConnection() throws SQLException{
Connection conn = DriverManager.getConnection(url,user,pwd);
return conn;
}
public void close(Connection conn){
if(conn!=null){
try {
conn.close();
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}
}
}
}
履行數(shù)據(jù)庫操作:
MysqlUserDao.java
package cn.ailot.dao;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
import cn.ailot.entity.User;
@Repository("userDao") //必須指定Bean ID,否則默許加載的是mysqlUserDao
public class MysqlUserDao implements UserDao{
@Autowired
private JdbcDataSource dataSource;
/**
* 根據(jù)唯1用戶名查詢系統(tǒng)用戶,如果沒有找到用戶信息返回null
*/
@Override
public User findByName(String name) {
// TODO Auto-generated method stub
System.out.println("利用JDBC技術(shù)");
String sql = "select id,name,pwd from users where name=?";
Connection conn = null;
try {
conn = dataSource.getConnection();
PreparedStatement ps = conn.prepareStatement(sql);
ps.setString(1, name);
ResultSet rs = ps.executeQuery();
User user = null;
while(rs.next()){
user = new User();
user.setId(rs.getInt("id"));
user.setName(rs.getString("name"));
user.setPwd(rs.getString("pwd"));
}
rs.close();
ps.close();
return user;
} catch (Exception e) {
// TODO: handle exception
throw new RuntimeException(e);
}finally{
dataSource.close(conn);
}
}
}
接下來寫1個(gè)JUnit測試,
TestCase.java
package cn.ailot.test;
import java.util.Properties;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import cn.ailot.dao.JdbcDataSource;
import cn.ailot.entity.User;
import cn.ailot.service.UserService;
public class TestCase {
@Test
public void testUserService() throws Exception{
String cfg = "spring-mvc.xml";
ApplicationContext ac = new ClassPathXmlApplicationContext(cfg);
//打印加載的bean名稱
System.out.println(java.util.Arrays.toString(ac.getBeanDefinitionNames()));
Properties obj = ac.getBean("jdbcProps",Properties.class);
JdbcDataSource ds = ac.getBean("jdbcDataSource",JdbcDataSource.class);
System.out.println(obj);
System.out.println(ds);
System.out.println(ds.getConnection());
UserService service = ac.getBean("userService",UserService.class);
User user = service.login("admin", "admin");
System.out.println(user);
}
}
然后右鍵->Run As->JUnit Test
如果代碼無誤,會(huì)出現(xiàn)以下顯示:
接下就要構(gòu)建登錄的具體方法了(類似struts中的action):
LoginController.java
(同時(shí)寫了3種接受參數(shù)的方法)
package cn.ailot.controller;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import cn.ailot.entity.User;
import cn.ailot.service.NameOrPwdException;
import cn.ailot.service.NullParamException;
import cn.ailot.service.UserService;
@Controller
@RequestMapping("/login")
public class LoginController{
@Resource //要求sping注入資源userService
private UserService userService;
@RequestMapping("/login.form")
public String loginForm(){
//可以向表單傳遞1些參數(shù)
return "loginForm"; //映照到loginForm.jsp
}
/**
* 利用HttpServletRequest對象進(jìn)行傳參
* @param req
* @return
*/
@RequestMapping("/loginAction1.form")
//spring MVC自動(dòng)參數(shù)注入HttpServletRequest
public String checLogin1(HttpServletRequest req){
System.out.println("--方法1--");
//優(yōu)點(diǎn),直接簡潔,缺點(diǎn),需要自己處理數(shù)據(jù)類型轉(zhuǎn)換
String name = req.getParameter("name");
String pwd = req.getParameter("pwd");
System.out.println(name);
System.out.println(pwd);
try {
User user = userService.login(name, pwd);
//登錄成功將登錄信息保存到當(dāng)前會(huì)話中
req.getSession().setAttribute("user", user);
return "success"; //映照到登錄成功的success.jsp
} catch (NameOrPwdException e) {
// TODO: handle exception
e.printStackTrace();
req.setAttribute("message", e.getMessage());
return "loginForm"; //映照到登錄頁面loginForm.jsp
} catch (NullParamException e) {
// TODO: handle exception
e.printStackTrace();
req.setAttribute("message", e.getMessage());
return "redirect:login.form";//重定向
} catch (RuntimeException e){
e.printStackTrace();
req.setAttribute("message", e.getMessage());
return "error";
}
}
/**
* 使用@RequestParam注解獲得要求參數(shù)的值
* @param name
* @param pwd
* @param req
* @return
*/
@RequestMapping("/loginAction2.form")
public String checLogin2(
String name,
@RequestParam("pwd")String pwd, //映照表單屬性不同的參數(shù)
HttpServletRequest req){
System.out.println("--方法2--");
//優(yōu)點(diǎn),自動(dòng)轉(zhuǎn)換數(shù)據(jù)類型,缺點(diǎn),可能出現(xiàn)數(shù)據(jù)類型轉(zhuǎn)換異常
System.out.println(name);
System.out.println(pwd);
try {
User user = userService.login(name, pwd);
//登錄成功將登錄信息保存到當(dāng)前會(huì)話中
req.getSession().setAttribute("user", user);
return "success"; //映照到success.jsp
} catch (NameOrPwdException e) {
// TODO: handle exception
e.printStackTrace();
req.setAttribute("message", e.getMessage());
return "loginForm";
} catch (NullParamException e) {
// TODO: handle exception
e.printStackTrace();
req.setAttribute("message", e.getMessage());
return "loginForm";
} catch (RuntimeException e){
e.printStackTrace();
req.setAttribute("message", e.getMessage());
return "error";
}
}
/**
* 使用自動(dòng)機(jī)制封裝成實(shí)體參數(shù)的方式獲得要求參數(shù)的值
* @param user
* @param req
* @return
*/
@RequestMapping("/loginAction3.form")
public String checLogin3(User user,HttpServletRequest req){
System.out.println("--方法3--");
//自動(dòng)填充到bean對象
System.out.println(user);
try {
user = userService.login(user.getName(), user.getPwd());
//登錄成功將登錄信息保存到當(dāng)前會(huì)話中
req.getSession().setAttribute("user", user);
return "success"; //映照到success.jsp
} catch (NameOrPwdException e) {
// TODO: handle exception
e.printStackTrace();
req.setAttribute("message", e.getMessage());
return "loginForm";
} catch (NullParamException e) {
// TODO: handle exception
e.printStackTrace();
req.setAttribute("message", e.getMessage());
return "loginForm";
} catch (RuntimeException e){
e.printStackTrace();
req.setAttribute("message", e.getMessage());
return "error";
}
}
}
登錄頁面:
loginForm.jsp
<%@ page language="java" contentType="text/html; charset=UTF⑻"
pageEncoding="UTF⑻"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<!-- 獲得項(xiàng)目基本路徑 -->
<c:url var="base" value="/"></c:url>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF⑻">
<title>LoginForm</title>
<link rel="stylesheet" type="text/css" href="${base }css/style.css">
</head>
<body>
<h6>${message }</h6>
<%-- <h6>${next }</h6> --%>
<form method="post" action="${base }login/loginAction1.form">
<div>
<h2>登錄 loginAction1.form</h2>
<p><label>用戶</label><input type="text" name="name"></p>
<p><label>密碼</label><input type="password" name="pwd"></p>
<h3><input type="submit" value="登錄"></h3>
</div>
</form>
<form method="post" action="${base }login/loginAction2.form">
<div>
<h2>登錄 loginAction2.form</h2>
<p><label>用戶</label><input type="text" name="name"></p>
<p><label>密碼</label><input type="password" name="pwd"></p>
<h3><input type="submit" value="登錄"></h3>
</div>
</form>
<form method="post" action="${base }login/loginAction3.form">
<div>
<h2>登錄 loginAction3.form</h2>
<p><label>用戶</label><input type="text" name="name"></p>
<p><label>密碼</label><input type="password" name="pwd"></p>
<h3><input type="submit" value="登錄"></h3>
</div>
</form>
</body>
</html>
需要注意的是,這里我用到的是JSTL標(biāo)簽,所以在lib里面要引入jstl.jar、standard.jar這個(gè)兩個(gè)包。
樣式文件style.css
*{
margin:0;
padding:0;
}
h6{
text-align: center;
color: red;
padding:10px;
font-size:14px;
}
form{
padding:10px;
float:left;
}
form div{
border:1px gray solid;
width:320px;
padding:8px;
}
form p input{
widht:180px;
}
form h2 input {
text-align:center;
}
form h2{
background: black;
color:white;
padding:4px;
}
form p{
background:#ddd;
padding:4px 8px 0 8px;
}
form h3{
background: #ddd;
padding:8px;
}
在閱讀器里輸入http://localhost:8080/springmvc/login/login.form
運(yùn)行結(jié)果如圖所示:
添加登錄成功的頁面success.jsp
<%@ page language="java" contentType="text/html; charset=UTF⑻"
pageEncoding="UTF⑻"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<c:url var="base" value="/"></c:url>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF⑻">
<title>success</title>
<link rel="stylesheet" type="text/css" href="${base }css/style.css">
</head>
<body>
<center>
<h2>${user.name }登錄成功</h2>
</center>
</body>
</html>
輸入用戶名和密碼admin登錄就能夠看到登錄成功的界面。
源碼:下載地址