您的位置:首页 > 编程语言 > Java开发

Spring学习笔记-C5-SpringMVC起步

2017-01-02 02:44 295 查看

Chapter05 SpringMVC起步

5.1 请求在SpringMVC组件之间的流转



请求发送

DispatcherServlet查询一个或多个HandlerMapping来确定请求的下一站。

按照HM查询结果,将请求转发到指定的Controller。

Controller返回ModelAndView给DispatcherServlet。

DispatcherServlet使用视图解析器ViewResolver将逻辑试图名匹配为一个特定的视图实现(一般是JSP)。

将Model传出给视图实现,渲染试图。

将渲染结果通过响应对象(Response)传递给客户端。

5.2 使用Java类来搭建SpringMVC

传统配置SpringMVC是用web.xml+Spring配置文件结合的方式。

但是如果你的容器支持Servlet3.0(Tomcat7及以上)

package chapter05;

import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;

/**
* 配置DispatcherServlet
* @author NikoBelic
* @create 30/12/2016 10:43
*/
public class SpittrWebInitializer extends AbstractAnnotationConfigDispatcherServletInitializer
{
/**
* 指定ContextLoaderListener配置类
* @Author NikoBelic
* @Date 30/12/2016 10:48
*/
@Override
protected Class<?>[] getRootConfigClasses()
{
return new Class<?>[]{RootConfig.class};
}

/**
* 指定SpringMVC配置类
* @Author NikoBelic
* @Date 30/12/2016 10:49
*/
@Override
protected Class<?>[] getServletConfigClasses()
{
return new Class<?>[]{WebConfig.class};
}

/**
* 将DispatcherServlet映射到 "/"
* @Author
* @Date 30/12/2016 10:44
*/
@Override
protected String[] getServletMappings() {
return new String[]{"/"};
}
}


/**
* 最小但可用的SpringMVC配置
* @author NikoBelic
* @create 30/12/2016 10:50
*/
@Configuration
@EnableWebMvc
@ComponentScan("chapter05")
public class WebConfig extends WebMvcConfigurerAdapter
{
@Bean
public ViewResolver viewResolver()
{
InternalResourceViewResolver resolver = new InternalResourceViewResolver();
resolver.setPrefix("/WEB-INF/views/");
resolver.setSuffix(".jsp");
resolver.setExposeContextBeansAsAttributes(true);
return resolver;
}
/**
* 配置静态资源的处理
* @Author NikoBelic
* @Date 30/12/2016 12:15
*/
@Override
public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer)
{
configurer.enable();
}
}



/** * 最小但可用的SpringMVC配置 * @author NikoBelic * @create 30/12/2016 10:50 */ @Configuration @EnableWebMvc @ComponentScan("chapter05") public class WebConfig extends WebMvcConfigurerAdapter { @Bean public ViewResolver viewResolver() { InternalResourceViewResolver resolver = new InternalResourceViewResolver(); resolver.setPrefix("/WEB-INF/views/"); resolver.setSuffix(".jsp"); resolver.setExposeContextBeansAsAttributes(true); return resolver; } /** * 配置静态资源的处理 * @Author NikoBelic * @Date 30/12/2016 12:15 */ @Override public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) { configurer.enable(); } }


Spring上下文的加载方式有两个,一个是使用SpringMVC的DispatcherServlet去加载(控制器、视图解析器、处理器映射器),另一个是用ContextLoaderListener加载(应用中的其他bean,例如Service、Dao)。

如果上程序所写,我们配置WebConfig类来加载SpringMVC需要的bean。配置RootConfig来加载剩余的bean。

5.2 编写基本的控制器

@Controller其实是包含@Component注解的,二者的功能是相同的,但是为了更加清晰的区分不同的组件,使用@Controller来标识这是一个SpringMVC的组件。

@RequestMapping可以加载类上,也可以加载在方法上,有一下几种情况:

1. 类有注解,方法有注解,那么HTTP访问路径为 http://IP:Port/Project/ControllerMapping/MethodMapping

2. 类无注解,方法有注解 http://IP:Port/Project/MethodMapping

3. 类有注解,方法无注解,那么只允许该Controller中只有一个Method,否则启动报错

我们一般使用方法1

@Controller
@RequestMapping("home")
public class HomeController
{
@RequestMapping(value = "list",method = RequestMethod.GET)
public String home()
{
return "home";
}
}


创建一个jsp页面

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Spittr</title>
</head>
<body>
<h1>Welcome to Spittr</h1>
<a href="<c:url value="/spittles"/>">Spittles</a>
<a href="<c:url value="/spitter/register"/>">Spittles</a>
</body>
</html>


使用Tomcat启动服务后,项目会根据SpittrWebInitializer配置的信息加载相关的配置文件。



以上构建了一个最简单的一个请求结果展示,那么如果我们需要给前台界面返回一些数据,怎么做?

修改控制器

@Controller
@RequestMapping("home")
public class HomeController
{
@RequestMapping(value = "list",method = RequestMethod.GET)
public String home()
{
return "home";
}

@RequestMapping(value = "spittles",method = RequestMethod.GET)
public ModelAndView getSpittles(ModelAndView mv)
{
List<Spittle> spittleList = createSpittleList(10);
mv.setViewName("spittle");
mv.addObject("spittleList",spittleList);
return mv;
}

/**
* 模拟从数据库获取数据
* @Author NikoBelic
* @Date 31/12/2016 13:15
*/
private List<Spittle> createSpittleList(int count)
{
List<Spittle> spittles = new ArrayList<>();
for (int i = 0; i < count; i++)
{
spittles.add(new Spittle(i,"Spittle " + i ,new Date(),null,null));
}
return spittles;
}
}


创建JSP页面

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ page isELIgnored="false" %>
<%@ page session="false" %>
<html>
<head>
<title>Spittr</title>
</head>
<body>
<h1>Spittles</h1>
<table>
<thead>
<tr>
<td>Id</td>
<td>Message</td>
<td>Time</td>
</tr>
</thead>
<tbody>
<c:forEach items="${spittleList}" var="spittle">
<tr>
<td>${spittle.id}</td>
<td>${spittle.message}</td>
<td>${spittle.time}</td>
</tr>
</c:forEach>
</tbody>
</table>
</body>
</html




5.3 接受请求的输入

Controller中的方法接收参数的方式有很多

以分页请求为例。

Controller

@Controller
@RequestMapping("home")
public class HomeController
{
private static List<Spittle> spittleList;
private static final int PAGE_SIZE = 5;

static
{
spittleList = createSpittleList(Math.max(10, new Random().nextInt(100)));
System.out.println("随机生成数据:" + spittleList.size());
}

@RequestMapping(value = "list", method = RequestMethod.GET)
public String home()
{
return "home";
}

/**
* 获取Spittles
*
* @Author NikoBelic
* @Date 31/12/2016 22:22
*/
@RequestMapping(value = "spittles/{page}", method = RequestMethod.GET)
public ModelAndView getSpittles(@PathVariable int page, ModelAndView mv)
{
Map<String, Integer> pageInfo = getPageInfo(page, spittleList.size());
List<Spittle> pageSpittleList = spittleList.subList(pageInfo.get("start"), pageInfo.get("end"));
mv.setViewName("spittle");
mv.addObject("spittleList", pageSpittleList);
mv.addObject("totalPage", pageInfo.get("totalPage"));
mv.addObject("page", page);
return mv;
}

/**
* 模拟从数据库获取数据
*
* @Author NikoBelic
* @Date 31/12/2016 13:15
*/
private static List<Spittle> createSpittleList(int count)
{
List<Spittle> spittles = new ArrayList<>();
for (int i = 0; i < count; i++)
{
spittles.add(new Spittle(i, "Spittle " + i, new Date(), null, null));c
}
return spittles;
}

/**
* 分页工具
*
* @Author NikoBelic
* @Date 31/12/2016 23:39
*/
private Map<String, Integer> getPageInfo(int page, int totalRecord)
{
Map<String, Integer> pageInfo = new HashMap<>();
int start = (page - 1) * PAGE_SIZE; // 当前页起始index
int end;
int totalPage = (int) Math.ceil(totalRecord / (float) PAGE_SIZE);
if (page != totalPage)
end = start + PAGE_SIZE;
else
{
if (totalRecord % PAGE_SIZE != 0)
end = (totalPage - 1) * PAGE_SIZE + totalRecord % PAGE_SIZE;
else
end = start + PAGE_SIZE;
}
pageInfo.put("start", start);
pageInfo.put("end", end);
pageInfo.put("page", page);
pageInfo.put("totalPage", totalPage);
System.out.println("起始:" + start + ",结束:" + end + ",当前页:" + page + ",总页数:" + totalPage + ",总数据:" + totalRecord);
return pageInfo;
}
}


JSP

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ page isELIgnored="false" %>
<%@ page session="false" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Spittr</title>
</head>
<body>
<h1>Spittles</h1>
<table>
<thead>
<tr>
<td>Id</td>
<td>Message</td>
<td>Time</td>
</tr>
</thead>
<tbody>
<c:forEach items="${spittleList}" var="spittle">
<tr>
<td>${spittle.id}</td>
<td>${spittle.message}</td>
<td>${spittle.time}</td>
</tr>
</c:forEach>
</tbody>
</table>
<span><a href="${pageContext.request.contextPath}/home/spittles/1">首页</a></span>
<span><a href="${pageContext.request.contextPath}/home/spittles/<c:out value='${page-1}'/>"
<c:if test="${page <= 1}">
hidden="hidden"
</c:if>
>上一页</a></span>
<span>当前页:${page}</span>
<span><a href="${pageContext.request.contextPath}/home/spittles/<c:out value='${page+1}'/>"
<c:if test="${page >= totalPage}">
hidden="hidden"
</c:if>
>下一页</a></span>

<span><a href="${pageContext.request.contextPath}/home/spittles/${totalPage}">尾页</a></span>
</body>
</html>






5.4 处理表单

我们模拟一个用户注册情景

用户通过浏览器请求得到一个注册页面,通过注册页面完成注册后自动跳转到个人信息页面。

Controller

@Controller
@RequestMapping("spitter")
public class SpitterController
{
@Autowired
private SpitterDao spitterDao;

@RequestMapping(value = "register",method = RequestMethod.GET)
public String showRegisterForm()
{
return "register";
}

@RequestMapping(value ="register",method = RequestMethod.POST)
public String processRegister(Spitter spitter)
{
spitterDao.save(spitter);
return "redirect:/spitter/" + spitter.getUsername();
}

@RequestMapping(value ="{username}" ,method = RequestMethod.GET)
public String showSpitterProfile(@PathVariable String username,Model model)
{
Spitter spitter = spitterDao.findSpitterByUsername(username);
model.addAttribute("spitter",spitter);
return "profile";
}
}


注册表单信息

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ page isELIgnored="false" %>
<%@ page session="false" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>RegisterForm</title>
</head>
<body>
<h1>Register</h1>
<%--这里Form表单没有设置action,因此他会将请求提交到与展现时相同的URL路径上--%>
<form method="post">
Username:<input type="text" name="username"/><br/>
Password:<input type="password" name="password"/><br/>
FirstName:<input type="text" name="firstName"/><br/>
LastName:<input type="text" name="lastName"/><br/>
<input type="submit" value="Register"/>
</form>
</body>
</html>


个人信息

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ page isELIgnored="false" %>
<%@ page session="false" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Spittr</title>
</head>
<body>
<h1>Your Profile</h1>
${spitter.username}<br/>
${spitter.firstName} ${spitter.lastName}
</body>
</html>


Model

public class Spitter
{
String username;
String firstName;
String lastName;
String password;

public Spitter() {
}

public Spitter(String username, String firstName, String lastName, String password) {
this.username = username;
this.firstName = firstName;
this.lastName = lastName;
this.password = password;
}

public String getUsername() {
return username;
}

public void setUsername(String username) {
this.username = username;
}

public String getFirstName() {
return firstName;
}

public void setFirstName(String firstName) {
this.firstName = firstName;
}

public String getLastName() {
return lastName;
}

public void setLastName(String lastName) {
this.lastName = lastName;
}

public String getPassword() {
return password;
}

public void setPassword(String password) {
this.password = password;
}
}


Dao

@Repository
public class SpitterDao
{
private List<Spitter> spitterList;

public SpitterDao()
{
this.spitterList = new ArrayList<>();
System.out.println(spitterList);
}

public void save(Spitter spitter)
{
spitterList.add(spitter);
}

public Spitter findSpitterByUsername(String username)
{
for (Spitter spitter : spitterList)
{
if (spitter.getUsername().equals(username))
return spitter;
}
return null;
}
}


校验表单

注解描述
@AssertFalse所注解的元素必须是Boolean型,并且值为false
@AssertTrue所注解的元素必须是Boolean型,并且值为true
@DecimalMax必须是数字,且小于指定值
@DecimalMin必须是数字,且大于指定值
@Digits必须是数字,并且值必须有指定的位数
@Future必须是将来的一个日期
@Max必须是数字,且小于等于指定值
@Min必须是数字,且大于等于指定值
@NotNull值不能为null
@Null值必须为null
@Past必须是过去的一个日期
@Pattern值必须匹配给定的正则表达式
@Size值必须是String、集合、数组,并且长度必要符合给定的范围
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  spring spring mvc