(一)如何创建一个Servlet
1.继承 GenericServlet
代码:
public class ServletDemo1 extends GenericServlet{ @Override public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException { res.getOutputStream().write("Hello servlet!".getBytes()); } }
web.xml中配置
ServletDemo1 com.boom.servlet.ServletDemo1 1 ServletDemo1 /ServletDemo1
2.继承 HttpServlet
代码:
public class ServletDemo2 extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.getOutputStream().write("Hello HttpServlet!".getBytes()); } /** * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response) */ public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // TODO Auto-generated method stub doGet(request, response); } }
web.xml
ServletDemo2 ServletDemo2 com.boom.servlet.ServletDemo2 ServletDemo2 /ServletDemo2
代码:
public class ServletDemo3 extends HttpServlet { //servlet 方法只 调用一次 @Override public void init() throws ServletException { // TODO Auto-generated method stub super.init(); System.out.println("init"); } protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.getOutputStream().write("Hello HttpServlet!".getBytes()); } /** * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response) */ protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // TODO Auto-generated method stub doGet(request, response); } @Override public void destroy() { System.out.println("destroy"); } }
web.xml不用配置了
(三)线程安全问题代码:
/** * 线程安全出现在多个线程操作同一资源上,就是静态的使用要慎重 * @author Boom * */ public class Person { //如果不是静态变量的时候,当多个线程使用时用到的age是不同的,不会有线程安全 public int age; //如果是静态变量,因为静态变量在类加载的时候都会创建,每个线程都是用到同一个对象,当同一个对象被多个线程使用时,就会产生线程并发事件 // public static int age; //在开发中,用静态要小心,可能会造成内存奔溃 public List list = new ArrayList(); //public static List list = new ArrayList(); }
/** * 线程安全 * @author Boom * */ public class Demo { //假设100个线程跑这个方法,看age的状态 public static void main(String[] args) { Person person = new Person(); person.age++; //person.list.add("aaa"); System.out.println(person.age); } }
2.实现SingleThreadModel接口解决线程安全问题
代码:
/** * 在web开发中,我们不用同步代码块去解决并发事件,而是通过实现一个接口SingleThreadModel(不太建议),就是打个标记 * 这种接口叫做标记接口,同理的有序列化接口,就是标记这个类有特权 * @author Boom * Servlet就像一个网页,当出错了,我们就要抓起来 */ public class ServletDemo5 extends HttpServlet implements SingleThreadModel { /** * 线程安全问题 */ //在这里初始化数据会出现并发事件 int i=0; //子类在覆盖父类的方法,不能抛出比父类更多的异常 (子类要比父类强,形象的说就是父亲做东西抛出了异常,子类又要比父类强我们就不能在子类抛更多的异常) protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { i++; try { Thread.sleep(1000*4); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } //String.getBytes(); 把字符串输入到字节流中 response.getOutputStream().write((i+"").getBytes()); } protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // TODO Auto-generated method stub doGet(request, response); } }
3.用同步代码块synchronized(this){}解决线程安全问题
代码:
public class ServletDemo4 extends HttpServlet { /** * 线程安全问题 */ int i=0; //在这里初始化数据会出现并发事件 protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //假设100个人同时操作这个dOGet()方法 ,会不会出现并发问题 //在方法内部定义初始化不会出现线程并发事件 //int i=0; //同步代码块,单线程执行 //用线程锁解决线程并发问题,但是这种方法不行,如果一个线程正在访问一个资源,而另一个也要等第一个线程访问完才执行获取资源 synchronized(this){ i++; try { Thread.sleep(1000*4); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } //String.getBytes(); 把字符串输入到字节流中 response.getOutputStream().write((i+"").getBytes()); } } protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // TODO Auto-generated method stub doGet(request, response); } }
(四)ServletConfig
/** * ServletConfig * 在配置文件中定义数据,在java中获取(使用情况:在实际开发中,有些数据不适合在servlet中写死,这类数据就可以通过配置方式配置给servlet, * 例如:servlet采用哪个码表,servlet连接哪个库,servlet就配置哪个配置文件) * @author Boom * 其实,struts就是一个特殊的servlet */ public class ServletDemo6 extends HttpServlet { //方法一 /* private ServletConfig servletConfig; @Override public void init(ServletConfig config) throws ServletException { this.servletConfig=config; String value = servletConfig.getInitParameter("data"); System.out.println(value); }*/ protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //String value = servletConfig.getInitParameter("data"); 方法一 //方法二 String value = this.getServletConfig().getInitParameter("data");//得到指定的 Enumeration em = this.getServletConfig().getInitParameterNames(); while (em.hasMoreElements()) { String name = (String) em.nextElement(); String value1 = this.getServletConfig().getInitParameter(name); System.out.println(name+"="+value); } System.out.println(value); response.getOutputStream().write("Hello HttpServlet!".getBytes()); } protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // TODO Auto-generated method stub doGet(request, response); } }
(五)ServletContext
/** * ServletContext 以及ServletDemo8 多个servlet之间传值(相当于聊天室)示例 * @author Boom * ServletContext说的就是整个应用程序的范围 在多个servlet中共享数据 */ public class ServletDemo7 extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //得到ServletContext的方式一: ServletContext context = this.getServletConfig().getServletContext(); //得到ServletContext的方式二: //ServletContext context1 = this.getServletContext(); String data="aaa"; context.setAttribute("data",data); } public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); } }
(六)使用ServletContext 多个servlet之间传值
/** * 多个servlet之间传值(相当于聊天室) * @author Boom * */ public class ServletDemo8 extends HttpServlet { protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //应用场景 之前给每个servlet都配置数据连接,我们可以直接通过context域配置数据库连接 String value1 =this.getServletContext().getInitParameter("data1"); String value = (String) this.getServletContext().getAttribute("data"); System.out.println(value); } protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); } }
(七)Servlet中不适合对数据进行输出,我们要应用Servlet的转发
/** * Servlet中不适合对数据进行输出,我们要应用Servlet的转发 * @author Boom * ServletDemo9和ServletDemo10 */ public class ServletDemo9 extends HttpServlet { protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String value =this.getServletContext().getInitParameter("data1"); //Servlet数据输出比较麻烦,我们通过转发来实现 让jsp实现 // servlet的重定向是让他自己去做 // Servlet的转发是让我来帮他找人做 response.getOutputStream().write((""+value+"").getBytes()); } protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); } }
(八)同过servletcontext实现请求转发,每个web应用都有一个servletcontext
/** * 同过servletcontext实现请求转发,每个web应用都有一个servletcontext * Servlet的转发 ServletDemo9和ServletDemo10 * @author Boom * 转发对象 RequestDispatcher */ public class ServletDemo10 extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String data="aaaaa"; this.getServletContext().setAttribute("dt", data); //不能放在context域中,为什么呢?(涉及多线程问题,就是用的是同一对象,会覆盖数据) //把数据放到context域对象中,并转发给jsp去实现界面 RequestDispatcher rd= this.getServletContext().getRequestDispatcher("/1.jsp"); rd.forward(request, response); } public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); } }
(九)读取资源文件
1.通过ServletContext访问资源文件 db.propertis
/** * 读取资源文件 通过ServletContext访问资源文件 db.propertis * * @author Boom * */ public class ServletDemo11 extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { test5(); } public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); } //在项目的相对路径src下新建db.properties文件 public void test1() throws IOException { InputStream in = this.getServletContext().getResourceAsStream("/WEB-INF/classes/db.properties"); // 固定套路 (把流输出到properties中) Properties properties = new Properties(); properties.load(in); String url = properties.getProperty("url"); String username = properties.getProperty("username"); String password = properties.getProperty("password"); System.out.println(url); System.out.println(username); System.out.println(password); } //在com.boom.thread包下新建db.properties文件 public void test2() throws IOException { InputStream in = this.getServletContext().getResourceAsStream("/WEB-INF/classes/com/boom/thread/db.properties"); // 固定套路 (把流输出到properties中) Properties properties = new Properties(); properties.load(in); String url = properties.getProperty("url"); String username = properties.getProperty("username"); String password = properties.getProperty("password"); System.out.println(url); System.out.println(username); System.out.println(password); } //在WEB-INF下新建db.properties文件 public void test3() throws IOException { InputStream in = this.getServletContext().getResourceAsStream("/db.properties"); // 固定套路 (把流输出到properties中) Properties properties = new Properties(); properties.load(in); String url = properties.getProperty("url"); String username = properties.getProperty("username"); String password = properties.getProperty("password"); System.out.println(url); System.out.println(username); System.out.println(password); } //读取资源文件需要注意的问题(但是我们得在tomcat的bin文件考入文件db.properties,才能实现) 最好采用servletcontext来读取资源文件 public void test4() throws IOException { FileInputStream in = new FileInputStream("classes/db.properties"); // 固定套路 (把流输出到properties中) Properties properties = new Properties(); //map properties.load(in); String url = properties.getProperty("url"); String username = properties.getProperty("username"); String password = properties.getProperty("password"); System.out.println(url); System.out.println(username); System.out.println(password); } public void test5() throws IOException{ String path = this.getServletContext().getRealPath("/WEB-INF/classes/db.properties"); String filename=path.substring(path.lastIndexOf("\\")+1); System.out.println(filename); FileInputStream in=new FileInputStream(path); // 固定套路 (把流输出到properties中) Properties properties = new Properties(); //map properties.load(in); String url = properties.getProperty("url"); String username = properties.getProperty("username"); String password = properties.getProperty("password"); System.out.println(url); System.out.println(username); System.out.println(password); } }
2.如果读取资源文件的程序不是servlet的话,就只能通过类加载器去读了
代码:
新建一个UserDao
/** * 类装载器 * 如果读取资源文件的程序不是servlet的话,就只能通过类装载器去读了 * @author Boom * */ public class UserDao { //把东西放到预编译中,在类加载时就生成了,而且只有一次 private static Properties dbconfig = new Properties(); static{ try { //针对如果修改了配置文件中的数据,查看运行后的输出 方案一:无论文件中怎么改还是原来的 //以下代码虽然可以读取资源文件的数据,但是无法获取更新后的数据 InputStream in = UserDao.class.getClassLoader().getResourceAsStream("db.properties"); //方案二:修改后,数据也跟着修改了 //String path = UserDao.class.getClassLoader().getResource("db.properties").getPath(); //FileInputStream inputStream = new FileInputStream(path); //获取文件中的东西 dbconfig.load(in); } catch (IOException e) { //抛一个初始化错误 throw new ExceptionInInitializerError(e); } } //不能传入一个servletcontext对象,避免耦合 public void update() throws IOException { System.out.println(dbconfig.getProperty("url")); System.out.println(dbconfig.getProperty("username")); System.out.println(dbconfig.getProperty("password")); } public void find(){ } public void delete(){ } /** * 总结:读取资源文件 * 1.在servlet中,我们可以通过servletcontext去读取资源文件的数据 * 2.在其他类中,我们需要通过类加载器去读取资源文件的数据 * */ }
新建测试类
/** * 如果读取资源文件的程序不是servlet的话,就只能通过类加载器去读了 * @author Boom * */ public class ServletDemo12 extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { UserDao userdao =new UserDao(); userdao.update(); } public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); } }