springMVC
SpringMVC:前端控制器,映射器,适配器,控制器,试图解析器
前端控制器
前端控制器在web.xml中配置
<servlet>
<!-- 命名 -->
<servlet-name>springmvc</servlet-name>
<!-- 加载包中的前端控制器 -->
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<!-- 让服务器已启动就开始加载文件springMVC.xml,用的是contextConfigLocation这个属性 -->
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:springMVC.xml</param-value>
</init-param>
<!-- 启动加载 -->
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<!-- 对应上面的命名 -->
<servlet-name>springmvc</servlet-name>
<!-- 对文件进行拦截来执行上面的程序, "/"代表拦截所有的-->
<url-pattern>/</url-pattern>
</servlet-mapping>
两种映射器
<!-- 映射器 -->
<bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"></bean>
<!-- 映射器2 -->
<bean class=" org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
<property name="mappings">
<props>
<!-- 这里的值要和控制器中的id相对应 -->
<prop key="/text1">text</prop>
<prop key="/text1">text</prop>
</props>
</property>
</bean>
两种适配器
<!-- 适配器 要实现Controller接口-->
<bean class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter"></bean>
<!-- 适配器2 要实现 HttpRequestHandler接口 -->
<bean class=" org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter"></bean>
控制器
<!-- 控制器 -->
<bean class="com.hemi.controller.MyController" name="/text" id="text"></bean>
public class MyController implements org.springframework.web.servlet.mvc.Controller{
@Override
public ModelAndView handleRequest(HttpServletRequest req, HttpServletResponse resp) throws Exception {
String username = req.getParameter("username");
String password = req.getParameter("password");
// req.setAttribute("username", username);
// req.setAttribute("password", password);
ModelAndView view = new ModelAndView();
if("lisi".equals(username)&&"123".equals(password)){
view.setViewName("Hello.jsp");
}
else{
view.setViewName("login.jsp");
}
return view;
}
}
视图解析器
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"></bean>
视图解析器的配置前缀后缀
<!-- 视图解析器 -->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<!-- 前缀 -->
<property name="prefix" value="/"></property>
<!-- 后缀 -->
<property name="suffix" value=".jsp"></property>
</bean>
注解适配器和映射器
注解适配器和映射器要一起使用才有效
<!-- 扫描包 -->
<context:component-scan base-package="com.hemi.controller"></context:component-scan>
<!-- 配置注解 1-->
<!-- 配置映射器注解 -->
<bean class=" org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping "></bean>
<!-- 配置适配器注解 -->
<bean class=" org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter"></bean>
<!--配置注解2-->
<!-- 终极替换上面的注解 -->
<mvc:annotation-driven></mvc:annotation-driven>
Controller里使用注解
@Controller
public class TextControler{
@RequestMapping(show1)
public ModelAndView show1(){}
}
cotroller里面返回数据
ModleAndView类型返回值 返回值用一般用view保存使用 view.addObject方法(域对象也可以)
@RequestMapping("show1")
public ModelAndView show1(HttpServletRequest req){
String username = req.getParameter("username");
String password = req.getParameter("password");
ModelAndView view = new ModelAndView();
view.addObject("username", username);
view.addObject("password", password);
view.setViewName("Hello");
return view;
}
String类型返回值返回数据可以域对象,Modle以及ModleMap来保存数据
@RequestMapping("show2")
public String show2(Model model,HttpServletRequest req){
String username = req.getParameter("username");
String password = req.getParameter("password");
model.addAttribute("username", username);
model.addAttribute("password", password);
return "Hello";
}
void类型返回值要用域对象来保存数据
@RequestMapping("show3")
public void show3(HttpServletRequest req,HttpServletResponse resp){
String username = req.getParameter("username");
String password = req.getParameter("password");
req.setAttribute("username", username);
req.setAttribute("password", password);
try {
req.getRequestDispatcher("Hello.jsp").forward(req, resp);
} catch (ServletException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
参数绑定
简单参数绑定 pojo参数绑定,自定义类型
简单参数绑定:传入的数据和jsp中写入request中的数据参数相同,如果想用形参则使用注解@RequestParam("username")是取值 String name是取得别名
Pojo参数绑定:定义一个实体类和jsp中放入的数据类型相同,然后传入实体类可以获得参数
自定义类型: 创建一个转换类实现Converter<String, Date>接口 重写里面的方法进行转换,在springMVC.xml中配置将org.springframework.format.support.FormattingConversionServiceFactoryBean类引入里面注入转换类,在注解驱动的属性中用conversion-service将配置的类加载驱动中,在实体类需要转换类型的字段(日期)上面添加 @DateTimeFormat(pattern="yyyy-MM-dd")
自定义转换类:
public class DateConvert implements Converter<String, Date>{
@Override
public Date convert(String source) {
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
try {
return format.parse(source);
} catch (ParseException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
}
springMVC中配置
<mvc:annotation-driven conversion-service="conversionService">
</mvc:annotation-driven>
<bean id="conversionService" class="org.springframework.format.support.FormattingConversionServiceFactoryBean">
<property name="converters">
<list>
<bean class="com.hemi.controller.convert.DateConvert"></bean>
</list>
</property>
</bean>
User实体类中配置
private String username;
private String password;
@DateTimeFormat(pattern="yyyy-MM-dd")
private Date date;
控制器:
@RequestMapping("show4")
public String show4(Model model,User user){
model.addAttribute("user", user);
return "Hello";
}
}
参数绑定-数组,包装数据类型 list集合
login.jsp:
<form action="show5" method="post">
用户名:<input type="text" name="username"><br>
密码:<input type="password" name="password"> <br>
日期<input type="text" name="date"><br>
<!--传递list集合中装的是多个地址对象-->
<input type="text" placeholder="请输入地址" name="add[0].addres"><br>
<input type="text" placeholder="请输入编码" name="add[0].code"><br>
<input type="text" placeholder="请输入地址" name="add[1].addres"><br>
<input type="text" placeholder="请输入编码" name="add[1].code"><br>
<!--传递单个地址的实体对象-->
<input type="text" placeholder="请输入地址" name="add.addres"><br>
<input type="text" placeholder="请输入编码" name="add.code"><br>
<!--传递一个数组-->
<input type="checkbox" name="hobby" value="basketball">篮球<br>
<input type="checkbox" name="hobby" value="football">篮球<br>
<input type="checkbox" name="hobby" value="tennis">网球
<input type="submit" value="登录">
</form>
user类:
private String username;
private String password;
@DateTimeFormat(pattern="yyyy-MM-dd")
private Date date;
private List<Address> add;
private String[] hobby;
控制器:
@RequestMapping("show5")
public String show5(Model model,User user){
model.addAttribute("user", user);
return "Hello";
}
全局异常处理开发:
1、自定义异常类
2、自定义异常处理器实现 HandlerExceptionResolver接口
3、在springmvc配置文件中配置全局异常控制器
自定义异常类:
public class CustomException extends Exception{
private String msg;
public CustomException(String msg) {
super(msg);
this.msg = msg;
}
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
}
自定义异常处理器:
public class ExceptionHandler implements HandlerExceptionResolver{
@Override
public ModelAndView resolveException(HttpServletRequest req, HttpServletResponse resp, Object object,
Exception ex) {
CustomException customException=null;
if (ex instanceof CustomException) {
customException=(CustomException)ex;
}else{
customException=new CustomException("未知错误");
}
ModelAndView view = new ModelAndView();
view.addObject("error", customException);
view.setViewName("error");
return view;
}
}
springMVC的配置
<!-- 定义全局异常 -->
<bean class="com.hemi.exception.handler.ExceptionHandler"></bean>
静态资源的释放
在配置文件中进行配置
<!-- 静态资源释放-->
<mvc:resources location="/image/" mapping="/image/*.*"></mvc:resources>
文件上传的步骤
1、编写配置文件
<!-- 配置文件上传处理 -->
<bean id="multipartResolver"
class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<property name="defaultEncoding" value="utf-8"></property>
<property name="maxUploadSize" value="10485760000"></property>
<property name="maxInMemorySize" value="40960"></property>
</bean>
2、编写控制器
上传单个文件:
public String upload(MultipartFile file,HttpServletRequest req) throws IllegalStateException, IOException{
if(file==null){
return "uploadFile";
}
//取出文件名
String filename = file.getOriginalFilename();
//根据文件的虚拟入境找到真实入境
String path = req.getServletContext().getRealPath("/temp");
File file2 = new File(path);
if (!file2.exists()) {
//创建目录
file2.mkdirs();
}
//将传入的文件按照真实入境和文件名写出来
file.transferTo(new File(file2,filename));
return "success";
}
批量上传文件
@RequestMapping("/upload1")
public String upload1(MultipartFile[] file,HttpServletRequest req) throws IllegalStateException, IOException{
if (file.length==0) {
return "uploadFile";
}
for (MultipartFile multipartFile : file) {
String filename = multipartFile.getOriginalFilename();
String realPath = req.getServletContext().getRealPath("/team");
File file2 = new File(realPath);
if (!file2.exists()) {
file2.mkdirs();
}
multipartFile.transferTo(new File(file2,filename));
}
return "success";
}
3、编写前端表单页面
注意:把form表单的默认的enctype 类型改成 enctype="multipart/form-data"
<form action="upload" method="post" enctype="multipart/form-data">
请上传文件:<input type="file" name="file">
<br>
<input type="submit" value="upload">
</form>
<hr>
<form action="upload1" method="post" enctype="multipart/form-data">
请上传文件:<input type="file" name="file">
<br>
请上传文件:<input type="file" name="file">
<br>
<input type="submit" value="upload1">
</form>