版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/madongyu1259892936/article/details/79552037 </div>
<link rel="stylesheet" href="https://csdnimg.cn/release/phoenix/template/css/ck_htmledit_views-f57960eb32.css">
<link rel="stylesheet" href="https://csdnimg.cn/release/phoenix/template/css/ck_htmledit_views-f57960eb32.css">
<div class="htmledit_views" id="content_views">
Springmvc的处理流程
1、自定义注解
元注解
元注解就是用来解释我们自定义注解。结合我们xml文档的dtd.schemel约束
@Target:作用早我们的类上,变量上,方法,指定我们的注解是作用在什么目标上
(类上,变量上,方法)。
@Retention:用来描述我们自定义注解的生命周期
SOURCE:源文件,CLASS:编译时期
RUNTIME:运行时期(对照我们的Exception来比较理解)
@Documented:javadoc此类的工具的文档化,将其中的注释生成对应的API
自定义注解:
针对我们的springmvc
@Controller:控制类上的注解
@Service:标注该bean类是service层
@RequestMapping:映射请求地址
@Quallifier:注入bean类的功能
代码
1. 编写web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
version="3.0">
<servlet>
<servlet-name>MySpringMVC</servlet-name>
<servlet-class>com.dongyu.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>common.properties</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>MySpringMVC</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
</web-app>
2. 编写common.properties文件
scanPackage=com.dongyu
3. 编写自定义注解
/**
* 自定义控制层注解
* @author mama
*
*/
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Controller {
String value() default "";
}
/**
* 注入实例
* @author mama
*
*/
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Qualifier {
String value() default "";
}
/**
* 自定义方法注解
* @author mama
*
*/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface RequestMapping {
//表示访问该方法的url
String value() default "";
}
/**
* 自定义业务层注解
* @author mama
*
*/
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Service {
String value() default "";
}
4. 编写Controller层
@Controller("dongYu")
public class DongYuController {
@Qualifier("dongYuServiceImpl")
private DongYuService dongYuService;
@RequestMapping("insert")
public String insert(HttpServletRequest request,HttpServletResponse response,String url) {
dongYuService.insert(null);
return null;
}
@RequestMapping("delete")
public String delete(HttpServletRequest request,HttpServletResponse response,String url) {
dongYuService.delete(null);
return null;
}
@RequestMapping("update")
public String update(HttpServletRequest request,HttpServletResponse response,String url) {
dongYuService.update(null);
return null;
}
@RequestMapping("select")
public String select(HttpServletRequest request,HttpServletResponse response,String url) {
dongYuService.select(null);
return null;
}
}
5. 编写Service层
public interface DongYuService {
int insert(Map map);
int delete(Map map);
int update(Map map);
int select(Map map);
}
@Service("dongYuServiceImpl")
public class DongYuServiceImpl implements DongYuService{
public int insert(Map map) {
System.out.println("----------insert");
return 0;
}
public int delete(Map map) {
System.out.println("----------delete");
return 0;
}
public int update(Map map) {
System.out.println("----------update");
return 0;
}
public int select(Map map) {
System.out.println("----------select");
return 0;
}
}
6. 编写servlet
/**
* 核心控制类?
* @author mama
*
*/
@WebServlet("/DispatcherServlet")
public class DispatcherServlet extends HttpServlet{
private Properties properties = new Properties();
//将我们扫描的权限定类名放入集合类
private List<String> packeNames=new ArrayList<String>();
//定义一个注解属性i,对应各层对象实例Map
Map<String,Object> instanceMaps=new HashMap<String,Object>();
//请求url对应的method对象
Map<String,Object> hanlderMaps=new HashMap<String,Object>();
@Override
public void init(ServletConfig config) throws ServletException {
/**
* 扫描基础包上面的注解:com.dongyu
* 扫描基础包之后,拿到全限定名称? ---包名+类名称?
* com/dongyu/service/DongYuServiceImpl.java
* 替换上面类?/
* com.dongyu.service.DongYuServiceImpl.java
* 拿到实例
* 将实例注入各层bean变量
*/
/**
* 扫描全包
* 找到实例
* 通过我们的方法连接来拿到相应的处理类实例
*
*/
//1.加载配置文件
doLoadConfig(config.getInitParameter("contextConfigLocation"));
//2.初始化所有相关联的类,扫描用户设定的包下面所有的类
scanBase(properties.getProperty("scanPackage"));
try {
//3.拿到扫描到的类,通过反射机制,实例化,并且放到ioc容器中(k-v beanName-bean) beanName默认是首字母小写
filterAndInstance();
springIoc();
//4.初始化HandlerMapping(将url和method对应上)
halderMaps();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
/**
* 扫描配置文件
* @param initParameter
*/
private void doLoadConfig(String location) {
//把web.xml中的contextConfigLocation对应value值的文件加载到流里面
InputStream resourceAsStream = this.getClass().getClassLoader().getResourceAsStream(location);
try {
//用Properties文件加载文件里的内容
properties.load(resourceAsStream);
} catch (IOException e) {
e.printStackTrace();
}finally {
//关流
if(null!=resourceAsStream){
try {
resourceAsStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
/**
* 通过url找到相应的method对象进行处理
*/
private void halderMaps() throws Exception{
if(instanceMaps.size()<=0) {
return ;
}
//存的实例是有控制层和service�?
for (Map.Entry<String, Object> entry : instanceMaps.entrySet()) {
if(entry.getValue().getClass().isAnnotationPresent(Controller.class)) {
String baseURL=((Controller)entry.getValue().getClass().getAnnotation(Controller.class)).value();
Method[] controolerMethods = entry.getValue().getClass().getMethods();
for (Method controolerMethod : controolerMethods) {
if(controolerMethod.isAnnotationPresent(RequestMapping.class)) {
//在方法上游RequestMapping注解时,我们才做处理
String methodURL=((RequestMapping)controolerMethod.getAnnotation(RequestMapping.class)).value();
hanlderMaps.put("/"+baseURL+"/"+methodURL, controolerMethod);
}else {
continue;
}
}
}
}
}
/**
* 把实例注入到ioc容器中
* @throws Exception
* @throws IllegalArgumentException
*/
private void springIoc() throws IllegalArgumentException, Exception {
if(instanceMaps.size()<=0) {
return ;
}
for (Map.Entry<String, Object> entry : instanceMaps.entrySet()) {
Field[] fields = entry.getValue().getClass().getDeclaredFields();
for (Field field : fields) {
if(field.isAnnotationPresent(Qualifier.class)) {
//IOC注入
String value = ((Qualifier)field.getAnnotation(Qualifier.class)).value();
field.setAccessible(true);
field.set(entry.getValue(),instanceMaps.get(value));
}else {
continue;
}
}
}
}
/**
* 扫描全包的方法
*/
private void scanBase(String basePackage){
URL url=this.getClass().getClassLoader().getResource("/"+basePackage.replaceAll("\\.", "/"));
//拿到该路径下面的文件夹,以及文件
String pathFile = url.getFile();
//最终的目的是将这个路径封住成一个File
File file=new File(pathFile);
String[] files = file.list();
for (String path : files) {
//再次构造成一个file类
File eachFile=new File(pathFile+path);
if(eachFile.isDirectory()) {
//递归应用scanBase()
//System.out.println("扫描到的类"+basePackage+"."+eachFile.getName());
scanBase(basePackage+"."+eachFile.getName());
}else if (eachFile.isFile()) {
//表示扫描到的是一个实在文件?
System.out.println("扫描到的类"+basePackage+"."+eachFile.getName());
packeNames.add(basePackage+"."+eachFile.getName());
}
}
}
/**
* 将全包名称替换成一个路径
*/
private String replacePath(String path) {
return path.replaceAll("\\.", "/");
}
/**
* 拦截方法请求,然后在对应请求地址找到对应的handler实例
*/
private void filterAndInstance() throws Exception{
//判断集合里面是否有实例
if(packeNames.size()<=0) {
return;
}
for (String string : packeNames) {
Class ccName=Class.forName(string.replace(".class", ""));
if(ccName.isAnnotationPresent(Controller.class)) {
Object instance = ccName.newInstance();
//将实例装入Map key
Controller controllerAnController = (Controller)ccName.getAnnotation(Controller.class);
//通过注解对象拿到属性值 xml: key:beanID value:class=com.
String key=controllerAnController.value();
//通过注解的key找到对应的bean的实例
instanceMaps.put(key, instance);
}else if (ccName.isAnnotationPresent(Service.class)) {
Object instance = ccName.newInstance();
//将实例装入Map key
Service serviceAnController = (Service)ccName.getAnnotation(Service.class);
//通过注解对象拿到属性值 xml: key:beanID value:class=com.
String key=serviceAnController.value();
//通过注解的key找到对应的bean的实例
instanceMaps.put(key, instance);
}else {
//没有注解
continue;
}
}
}
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doPost(req, resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String uri=req.getRequestURI();
String projectNamePath = req.getContextPath();
//baseURL+methodURL
String path = uri.replace(projectNamePath, "");
//方法对象
Method method=(Method) hanlderMaps.get(path);
PrintWriter writer = resp.getWriter();
if(method==null) {
writer.write("您访问的地址不存在");
return;
}
//localhost:8080/springmvc/dongYu/insert
String className=uri.split("/")[2];
DongYuController dn=(DongYuController)instanceMaps.get(className);
try {
method.invoke(dn, new Object[] {req,resp,null});
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}