SpringMvc
常用注解
@RequestParams
value/name:请求参数中的名称
required:请求参数中是否必须提供此参数,默认值为true,表示必须提供,如果不提供将报错
@RequestMapping("/testRequestParam")
public String testRequestParam(@RequestParam("name") String uname) {
System.out.println(uname);
return "success";
}
@RequestBody
用于获取请求体内容,直接使用得到的是key=value&key=value....的结构
只适用于post方法(get方法没有请求体,参数都封装在地址栏上)
required:是否必须由请求体,默认是true,get方法请求方式会出错,如果取值为false,get请求得到null
@RequestMapping("/testRequestBody")
public String testRequestBody(@RequestBody String body, String uName) {
System.out.println(uName);
System.out.println(body);
return "success";
}
@PathVariable
1.作用:绑定url中的占位符,eg:/delete/{id},{id}就是占位符
2.属性
value:指定url中的占位符名称
3.Restful风格
请求路径一样,可以分局不同的请求方式去执行后台的不同的方法
restful风格的url优点:
结构清晰
符合标准
易于理解
扩展方便
@RequestMapping("/testPathVariable/{id}")
public String testPathVariable(@PathVariable("id") String ids) {
System.out.println(ids);
return "success";
}
@RequestHeader
获取请求头的值
value:提供消息头名称
required:是否必须有此消息头
@RequestMapping(value = "/testRequestHeader")
public String testRequestHeader(@RequestHeader(value = "Accept") String header){
System.out.println("执行了");
System.out.println(header);
return "success";
}
@CookieValue
用于指定cookie名称的值传入控制器方法参数
value:指定cookie的名称
required:是否必须有此cookie
@RequestMapping("/testCookieValue")
public String testCookieValue(@CookieValue(value ="JSESSIONID")String cookieValue){
System.out.println("cookieValue=>"+cookieValue);
return "success";
}
@SessionAttribute
作用
用于多次执行控制器方法间的参数共享
属性
value:用于指定存入的数据名称
type:用于指定存入的数据类型
@SessionAttributes({"msg"})//将添加的属性加入到session域中
public class AnnoController {
@RequestMapping("/testSessionAttribute")
public String testSessionAttribute(Model model){
//model会将值传到request域对象中
model.addAttribute("msg","haha");
return "success";
}
//获取session域中的属性
@RequestMapping("/getSessionAttribute")
public String getSessionAttribute(ModelMap modelMap){
String msg =(String) modelMap.get("msg");
System.out.println(msg);
return "success";
}
}
//清除
@RequestMapping("/delSessionAttribute")
public String delSessionAttribute(SessionStatus status){
System.out.println("delSessionAttribute");
status.setComplete();
return "success";
}
@ModelAttribute
1.位于方法上时
放在方法上时,该方法会在控制器的方法执行之前,先执行。它可以修饰没有返回值的方法,也可以修饰有具体返回值的方法
/**
*有返回值时
*/
@ModelAttribute
public Users showUser(){
System.out.println("test..modelAttribute");
Users users = new Users();
users.setDate(new Date());
return users;
}
/**
* 无返回值时
*/
@ModelAttribute
public void showUser2(String uName, Map<String,Users> map){
System.out.println("test..modelAttribute");
Users users = new Users();
users.setDate(new Date());
map.put("abc",users);
}
2.位于参数上时
value:用于获取数据的key,可以可以时pojo的属性名称,也可以时map结构中的key
应用场景:
当表单提交数据不是完整的实体类数据时,保证没有提交的数据的字段使用数据库对象原来的数据
@RequestMapping("/testModelAttribute")
public String testModelAttribute(@ModelAttribute("abc") Users users){
System.out.println(users);
return "success";
}
请求参数绑定
请求参数绑定
<!--请求参数绑定-->
<a href="param/testParam?username=df&&pwd=fe">请求参数的绑定</a>
@RequestMapping("testParam")
public String testParam(String username,String pwd) {
System.out.println("执行了....");
System.out.println("username=>"+username);
System.out.println("pwd=>"+pwd);
return "success";
}
请求参数绑定实体类
<%-- 将数据封装在实体类中--%>
<form action="param/saveAccount" method="post">
姓名:<input type="text" name="username"/><br><!--name属性的值必须跟实体类相对应-->
密码:<input type="password" name="pwd"><br>
金额:<input type="text" name="money"><br>
<!--引用类型-->
用户名:<input type="text" name="user.uName"><br>
年龄:<input type="text" name="user.uPwd"/><br>
<input type="submit" value="提交"><br>
</form>
@RequestMapping(value = "/saveAccount")
public String saveAccount(Account account){
System.out.println(account);
return "success";
}
自定义参数类型
<%--将数据封装在实体类中,类中存在list和map--%>
<form action="param/saveAccount" method="post">
用户名:<input type="text" name="list[0].uName"><br>
年龄:<input type="text" name="list[0].uPwd"><br>
用户名:<input type="text" name="map['one'].uName"><br>
年龄:<input type="text" name="map['one'].uPwd"><br>
<input type="submit">
</form>
@RequestMapping(value = "/saveUser")
public String save(Users users){
System.out.println(users);
return "success";
}
获取原生servletAPI
@RequestMapping("/testServlet")
public String testServlet(HttpServletRequest request, HttpServletResponse response) throws IOException {
System.out.println("request");
HttpSession session = request.getSession();
System.out.println(session);
ServletContext servletContext = session.getServletContext();
System.out.println(servletContext);
System.out.println(response);
return "success";
}
自定义类型转换
页面提交的任何数据都是string类型
请求时会自动类型转换:string->Integer/double/date
但遇到格式不同时,需要自定义类型转换
package com.zh.utils;
import org.springframework.core.convert.converter.Converter;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
/**
* 自定义类型转换:
* 把字符转换成日期
*/
public class StringToDateConverter implements Converter<String, Date> {
@Override
public Date convert(String source) {
// 判断
if (source==null){
throw new RuntimeException("请您传入数据");
}
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd");
try {
return df.parse(source);
} catch (ParseException e) {
throw new RuntimeException("数据类型转换出现错误");
}
}
}
<!--配置自定义类型转换器-->
<bean id="conversionService" class="org.springframework.context.support.ConversionServiceFactoryBean">
<property name="converters">
<set>
<bean class="com.zh.utils.StringToDateConverter"/>
</set>
</property>
</bean>
异常处理器
@Controller
@RequestMapping("/user")
public class UserController {
@RequestMapping("/testException")
public String testExceptions() throws Exception {
try {
//模拟异常
int a = 10 / 0;
} catch (Exception e) {
//打印异常信息
e.printStackTrace();
//抛出自定义提示信息
throw new SysException("查询所有用户出现错误....");
}
return "success";
}
}
1.编写自定义异常类
package com.zh.exception;
//自定义异常类
public class SysException extends Exception{
//存储提示信息
private String message;
@Override
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public SysException(String message) {
this.message = message;
}
public SysException() {
}
}
2.编写异常处理器
package com.zh.exception;
import org.springframework.web.servlet.HandlerExceptionResolver;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
//异常处理器
public class SysExceptionResolver implements HandlerExceptionResolver {
@Override
public ModelAndView resolveException(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception ex) {
//获取到异常对象
SysException e=null;
if (ex instanceof SysException){
e=(SysException)ex;
}else {
e=new SysException("系统正在维护");
}
//创建modelAndView
ModelAndView mv = new ModelAndView();
mv.addObject("errorMsg",e.getMessage());
mv.setViewName("error");
return mv;
}
}
3.配置异常处理器(跳转到提示页面)
<!--配置异常处理器-->
<bean id="sysExceptionResolver" class="com.zh.exception.SysExceptionResolver"></bean>
文件上传
1.传统方式文件上传
<form action="user/testFileUpLoad1" method="post" enctype="multipart/form-data">
请输入:<input type="text">
<!--name必须跟控制器方法参数一致-->
选择文件:<input type="file" name="upload"/><br/>
<input type="submit">
</form>
/**
* 传统方式文件上传:
* 文件上传的必要前提:
* 1.form表单的enctype取值必须时:multipart/form-data
* 默认值是:application/x-www.form-urlencoded
* 2.method必须为post请求
* 3.提供一个文本域
* 借助第三方组件实现文件上传
* commons-fileupload-1.3.1.jar
* commons-io-2.4.jar
*/
@RequestMapping("/testFileUpLoad1")
public String testFileUpLoad1(HttpServletRequest request) throws Exception {
System.out.println("javaweb方式执行文件上传");
//使用fileupload组件完成文件上
// 上传的位置
String path = request.getSession().getServletContext().getRealPath("/uploads/");
//判断该文件路径是否存在
File file = new File(path);
if (!file.exists()) {
file.mkdirs();
}
//解析request对象,获取上传文件项
DiskFileItemFactory factory = new DiskFileItemFactory();//磁盘文件项
ServletFileUpload upload = new ServletFileUpload(factory);
//解析request
List<FileItem> items = upload.parseRequest(request);
//遍历
for (FileItem item : items) {
System.out.println("item=>" + item);
//判断当前item对象是否是上传文件项
if (item.isFormField()) {
//普通文件项
} else {
//上传文件项
//获取上传文件名
String fileName = item.getName();
String uuid = UUID.randomUUID().toString().replace("-", "");
fileName = uuid + "_" + fileName;
//完成文件上传
System.out.println("fileName"+fileName);
item.write(new File(path, fileName));
//删除临时文件
item.delete();
}
}
return "success";
}
2.springmvc方式文件上传
<form action="user/testFileUpLoad2" method="post" enctype="multipart/form-data">
<!--name必须跟控制器方法参数一致-->
选择文件:<input type="file" name="upload"/><br/>
<input type="submit">
</form>
//springMvc方式文件上传
@RequestMapping("/testFileUpLoad2")
public String testFileUpLoad(HttpServletRequest request, MultipartFile upload) throws IOException {
System.out.println("springmvc执行文件上传");
// 上传的位置
String path = request.getSession().getServletContext().getRealPath("/uploads/");
//判断该文件路径是否存在
File file = new File(path);
if (!file.exists()) {
file.mkdirs();
}
String fileName = upload.getOriginalFilename();//获取文件名
String uuid = UUID.randomUUID().toString().replace("-", "");
fileName = uuid+"_"+fileName;
//完成文件上传
upload.transferTo(new File(path,fileName));
return "success";
}
3.跨服务器文件上传
<form action="user/testFileUpLoad3" method="post" enctype="multipart/form-data">
<!--name必须跟控制器方法参数一致-->
选择文件:<input type="file" name="upload"/><br/>
<input type="submit">
</form>
@RequestMapping("/testFileUpLoad3")
public String testFileUpLoad3(MultipartFile upload) throws IOException {
System.out.println("跨服务器文件上传");
//定义上传文件服务器路径
String path="http://persionzh.top:8080/images/";
//获取文件名
String fileName = upload.getOriginalFilename();//获取文件名
//将文件设为唯一值
String uuid = UUID.randomUUID().toString().replace("-", "");
fileName = uuid+"_"+fileName;
//创建客户端对象
Client client = Client.create();
//和图片服务器进行连接
WebResource webResource = client.resource(path + fileName);
//上传文件
webResource.put(upload.getBytes());
return "success";
}
Response
返回视图
@RequestMapping("/testString")
public String testString(Model model) {
User user = new User("hello", "nihao");
model.addAttribute("users", user);
return "success";
}
无返回值
@RequestMapping("/testVoid")
public void testVoid(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//转发:一次请求
// request.getRequestDispatcher("/WEB-INF/pages/success.jsp").forward(request,response);
//重定向:两次请求
// response.sendRedirect(request.getContextPath()+"/index.jsp");
// System.out.println(request.getContextPath());//获取虚拟路径/item2
//直接响应
//解决中文乱码
response.setCharacterEncoding("utf-8");
response.setContentType("text/html;charset=utf-8");
response.getWriter().print("你好");
return;
使用关键字进行转发/重定向
//使用关键字进行转发/重定向
@RequestMapping("/testForwardOrRequest")
public String testForwardOrRequest() {
//转发
return "forward:/WEB-INF/pages/success.jsp";
//重定向
// return "redirect:/index.jsp";//使用redirect时不需要加虚拟路径名
}
返回字符串
<script>
$(function () {
$("#btn").click(function () {
//发送ajax请求
$.ajax({
//编写json格式,设置属性和值
url: "response/testAjax",
contentType: "application/json;charset=UTF-8",
data:'{"uName":"zhtest","uPwd":"465456"}',
datatype: "json",
type: "post",
success: function (data) {
//data服务器端响应的json数据,进行解析
alert(data);
alert(data.uPwd);
alert(data.uName)
}
})
})
})
</script>
//模拟异步请求
@RequestMapping("/testAjax")
@ResponseBody
public User testAjax(@RequestBody User user) {//获取请求体
System.out.println("textajax执行了");
//客户端发送ajax的请求,传的是json字符串,后端把json字符串封装到user对象中
System.out.println("user=>" + user);
//做响应,模拟查询数据库
user.setuName("haha");
user.setuPwd("zfhjdji");
//响应;
return user;
}
ModelAndView
@RequestMapping("/testModelAndView")
public ModelAndView testModelAndView() {
User user = new User("zh", "23");
//创建modelAndView对象
ModelAndView mv = new ModelAndView();
//添加属性到request域,相当于model.addAttribute()
mv.addObject("users", user);
//跳转到指定视图,相当于return "success";
mv.setViewName("success");
return mv;
}
拦截器
@RequestMapping("/testInterception")
public String testInterception() {
System.out.println("testInterception方法执行了");
return "success";
}
1.编写拦截器类,实现HandleInterceptor接口
/**
* 自定义拦截器
*/
public class MyInterception implements HandlerInterceptor {
/**
* 预处理:controller方法执行前
* return true:放行,执行下一个拦截器,如果没有,执行controller中的方法
* return false不放行
*/
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("MyInterception执行了.....前1111");
//跳到指定页面
// request.getRequestDispatcher("/WEB-INF/pages/error.jsp").forward(request,response);
return true;
}
/**
* 后处理方法:controller方法执行后,success.jsp执行前
*/
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("MyInterception执行了.....后1111");
// request.getRequestDispatcher("/WEB-INF/pages/error.jsp").forward(request,response);
}
/**
* success.jsp页面执行后,该方法执行
*/
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
System.out.println("MyInterception执行了.....最后1111");
}
}
public class MyInterception2 implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("MyInterception执行了.....前2222");
return true;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("MyInterception执行了.....后2222");
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
System.out.println("MyInterception执行了.....最后2222");
}
}
2.配置拦截器
<!--配置拦截器-->
<mvc:interceptors>
<!-- 配置具体拦截器-->
<mvc:interceptor>
<!-- 要拦截的方法-->
<mvc:mapping path="/user/*"/>
<!-- 不要拦截的方法-->
<!-- <mvc:exclude-mapping path=""/>-->
<!--配置拦截器对象-->
<bean class="com.zh.interception.MyInterception"/>
</mvc:interceptor>
<!-- 配置第二个拦截器-->
<mvc:interceptor>
<mvc:mapping path="/user/**"/>
<bean class="com.zh.interception.MyInterception2"/>
</mvc:interceptor>
</mvc:interceptors>
静态资源过滤
<!-- 前端控制器,过滤静态资源-->
<mvc:resources mapping="/css/**" location="/css/"/>
<mvc:resources mapping="/images/**" location="/images/"/>
<mvc:resources mapping="/js/**" location="/js/"/>
<!--启用默认Servlet-->
<mvc:default-servlet-handler/>