参数传递(View to Controller)
@RequestMapping映射请求
负责将不同请求映射到相对应的控制器上,具体包括四个方面的信息项,请求URL,请求参数,请求方法,请求头。
1)通过请求URL进行映射
package cn.jbit.web;
import org.apache.log4j.Logger;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
@Controller//对类标注使其成为一个可以处理HTTP请求的控制器
public class IndexController{
private Logger logger=Logger.getLogger(IndexController.class);
//对方法index()进行注解,也确定了index()方法对应的url是@RequestMapping后面紧跟的("index")
@RequestMapping("index")
public String index(@RequestParam String username){//绑定请求参数
logger.info("HELLO,"+username);
return "index";//返回index字符串,通过视图解析器转换为真正的View(/WEB-INF/jsp/index.jsp)
}
}
存在问题:不传入参数会报错。
注意:RequestMapping不仅可以注解在方法处,也可以注解在类上。
package cn.jbit.web;
import org.apache.log4j.Logger;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
@Controller//对类标注使其成为一个可以处理HTTP请求的控制器
@RequestMapping("index")
public class IndexController{
private Logger logger=Logger.getLogger(IndexController.class);
//对方法index()进行注解,也确定了index()方法对应的url是@RequestMapping后面紧跟的("index")
@RequestMapping("/index")
public String index(@RequestParam String username){
logger.info("HELLO,"+username);
return "index";//返回index字符串,通过视图解析器转换为真正的View(/WEB-INF/jsp/index.jsp)
}
}
此时的地址栏地址为:http://localhost:8080/SSM1/index/index?username=hh
这种方式可以便于业务的管理。
2)通过请求参数,请求方法进行映射
@RequestMapping还可以通过请求参数,请求方法来映射请求。通过多条件可以让映射更加精确。
package cn.jbit.web;
import org.apache.log4j.Logger;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
@Controller//对类标注使其成为一个可以处理HTTP请求的控制器
public class IndexController{
private Logger logger=Logger.getLogger(IndexController.class);
//value表示请求的url,method表示请求方法,params表示请求参数
@RequestMapping(value="index",method=RequestMethod.GET,params="username")
public String index(@RequestParam String username){
logger.info("HELLO,"+username);
return "index";
}
}
访问地址:http://localhost:8080/SSM1/index?username=hsh
注意:上述代码中,value表示请求的url,method表示请求方法(GET或者POST方法),params表示请求参数,三者条件都匹配才能进入方法index()。即url必须是index,method必须为get方法,params必须是username才行。
@RequestParam
之前的不传入参数会报错的问题没有解决,需要通过RequestParam解决。
通过@RequestParam注解指定其对应的请求参数。@RequestParam有三个参数:
1.value:参数名
2.required:是否必须,默认为true,表示必须包含参数名否则异常。
3.defaultValue:默认参数,一般不使用。
package cn.jbit.web;
import org.apache.log4j.Logger;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
@Controller//对类标注使其成为一个可以处理HTTP请求的控制器
public class IndexController{
private Logger logger=Logger.getLogger(IndexController.class);
@RequestMapping("index")
public String index(@RequestParam(value="username",required=false) String username){
logger.info("HELLO,"+username);
return "index";
}
}
此处required设置成false,则地址栏不输入username参数也不会报错,只是logger会显示空值。
参数传递(Controller to View)
SpringMVC提供了多种方式输出数据模型
1.ModelAndView
ModelAndView既包含视图信息又包含模型数据。
常用方法
1.添加模型数据
ModelAndView.addObject(String attributeName,Object attributeName)
第一个参数为key,第二个参数为Value,注意数据类型。
ModelAndView.addAllObject(Map<String,?> modelMap)
数据模型其实就是一个map对象,可以添加map对象到model中。
2.设置视图
void setView(View view)
指定具体视图对象
void setViewName(String viewName)
指定一个逻辑视图名,String类型
package cn.jbit.web;
import org.apache.log4j.Logger;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.servlet.ModelAndView;
@Controller//对类标注使其成为一个可以处理HTTP请求的控制器
public class IndexController{
private Logger logger=Logger.getLogger(IndexController.class);
@RequestMapping("index")
public ModelAndView index(@RequestParam(value="username",required=false) String username){
logger.info("HELLO,"+username);
ModelAndView mav=new ModelAndView();
//传模型数据
mav.addObject("name", username);
//添加视图
mav.setViewName("index");
return mav;
}
}
<%@ page language="java" contentType="text/html; charset=utf-8"
pageEncoding="utf-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Insert title here</title>
</head>
<body>
<h1>Hello,SpringMVC</h1>
${name}
</body>
</html>
2.Model
还可以使用SpringMVC提供的Model对象来完成数据传递,直接使用model对象入参,把数据模型username传入model中即可,model对象也是一个map类型的数据结构,对于key的指定可有可无,没有key时默认对象类型作为key,例如string(注意一定是小写不是大写)。
案例:
@Controller//对类标注使其成为一个可以处理HTTP请求的控制器
public class IndexController{
private Logger logger=Logger.getLogger(IndexController.class);
@RequestMapping("index")
public String index(@RequestParam(value="username",required=false) String username,Model model){
logger.info("HELLO,"+username);
model.addAttribute("name", username);//有key
model.addAttribute(username);//没有key
return "index";
}
}
<body>
<h1>Hello,SpringMVC</h1>
<h1>有key${name}</h1>
<h1>没有key${string}</h1> //注意,此处string一定是小写的
</body>
3.Map
和model入参方法类似,不过推荐使用model。
@Controller//对类标注使其成为一个可以处理HTTP请求的控制器
public class IndexController{
private Logger logger=Logger.getLogger(IndexController.class);
@RequestMapping("index")
public String index(@RequestParam(value="username",required=false) String username,Map<String,Object> map){
logger.info("HELLO,"+username);
map.put("name", username);
return "index";
}
}
4.@ModelAttribute
将入参的数据对象放到数据模型。
5.@SessionAttributes
将模型中的属性存入HttpSession中,以便在多个请求之间共享该属性。
单例模式:
单例模式即系统运行期间,有且仅有一个实例。
要满足三个点:
1.一个类仅有一个实例(最基本要求),需要类只能提供私有的构造器,保证不能随意创建该类的实例。
2.必须自行创造这个实例,自定义本类的私有(private)静态(static)对象,以便向外界提供时使用。
3.必须自行向这个系统提供这个实例。即必须提供一个静态共有方法(public static XX()),该方法创建或者获得它本身的私有对象并返回。
两种实现方法:
1.懒汉模式
对于懒汉模式,我们可以这样理解:该单例类非常懒,只有在自身需要的时候才会行动,从来不知道及早做好准备。它在需要对象的时候,才判断是否已有对象,如果没有就立即创建一个对象,然后返回,如果已有对象就不再创建,立即返回。
懒汉模式只在外部对象第一次请求实例的时候才去创建。
//类加载时不创建实例,调用getInstance()方法才能有实例。
public static synchronized ConfigManager getInstance(){//用到了同步锁保证线程安全
if(ConfigManager==null){
configManager=new ConfigManager();
}
return configManager;
}
2.饿汉模式
对于饿汉模式,我们可以这样理解:该单例类非常饿,迫切需要吃东西,所以它在类加载的时候就立即创建对象。
...
//类加载时直接初始化
Private static ConfigManager configManager =new ConfigManager();
//饿汉模式
public static ConfigManager getInstance(){
return configManager;
}
我们对比一下懒汉模式和饿汉模式的优缺点:
懒汉模式,它的特点是运行时获得对象的速度比较慢,但加载类的时候比较快。它在整个应用的生命周期只有一部分时间在占用资源。
饿汉模式,它的特点是加载类的时候比较慢,但运行时获得对象的速度比较快。它从加载到应用结束会一直占用资源。
饿汉模式优化(静态内部类):
要求其具备延迟加载的特性:
public class Singleton {
private static Singleton singleton;
private Singleton(){
//整个应用运行期间只执行一次的业务代码操作。如读取配置文件等。
}
public static class SingletonHelper{
private static final Singleton INSTANCE=new Singleton();
}
public static Singleton getInstance(){
singleton=SingletonHelper.INSTANCE;
return singleton;
}
public static Singleton test(){
return singleton;//调用test()未实例化singleton
}
}
public class Test12 {
public static void main(String[] args) {
System.out.println("Singleton.test()---->"+Singleton.test());
System.out.println("Singleton.getInstance()---->"+Singleton.getInstance());
}
//Singleton.test()---->null
//Singleton.getInstance()---->test.Singleton@1db9742
}
使用ServletAPI对象作为入参
如果我们需要HttpSession对象,就可以直接将HttpSession作为入参使用。
@RequestMapping(value="index",method=RequestMethod.POST)
public String doLogin(@RequestParam String userName,@RequestParam String upwd,HttpSession session,HttpServletRequest request){......}
静态资源文件的引用
由于DispatcherServlet请求映射为“/”,SpringMVC将捕获所以web容器的请求,也包括了静态资源的请求,由于找不到相应处理器,所以静态资源将无法访问。
这里采用<mvc:resources/>
标签来解决,首先为方便管理,将静态资源文件(js,css,images等)都放在统一目录下,例如”/WebRoot/statics”,这时在springmvc-servlet.xml中增加配置如下:
<mvc:resources mapping="/statics/**" location="/statics/"
mapping:将静态资源映射到指定路径(/statics)下
location:本地静态资源所在的目录
最后需要修改页面引用静态文件的目录路径,加上“/statics”。